Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 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 | |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 5 | package parse |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 6 | |
| 7 | import ( |
Rob Pike | 64228e3 | 2011-07-06 17:46:36 +1000 | [diff] [blame] | 8 | "flag" |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 9 | "fmt" |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 10 | "reflect" |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 11 | "testing" |
| 12 | ) |
| 13 | |
Rob Pike | 64228e3 | 2011-07-06 17:46:36 +1000 | [diff] [blame] | 14 | var debug = flag.Bool("debug", false, "show the errors produced by the tests") |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 15 | |
| 16 | type numberTest struct { |
| 17 | text string |
| 18 | isInt bool |
| 19 | isUint bool |
| 20 | isFloat bool |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 21 | isComplex bool |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 22 | int64 |
| 23 | uint64 |
| 24 | float64 |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 25 | complex128 |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 26 | } |
| 27 | |
| 28 | var numberTests = []numberTest{ |
| 29 | // basics |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 30 | {"0", true, true, true, false, 0, 0, 0, 0}, |
| 31 | {"-0", true, true, true, false, 0, 0, 0, 0}, // check that -0 is a uint. |
| 32 | {"73", true, true, true, false, 73, 73, 73, 0}, |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 33 | {"073", true, true, true, false, 073, 073, 073, 0}, |
| 34 | {"0x73", true, true, true, false, 0x73, 0x73, 0x73, 0}, |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 35 | {"-73", true, false, true, false, -73, 0, -73, 0}, |
| 36 | {"+73", true, false, true, false, 73, 0, 73, 0}, |
| 37 | {"100", true, true, true, false, 100, 100, 100, 0}, |
| 38 | {"1e9", true, true, true, false, 1e9, 1e9, 1e9, 0}, |
| 39 | {"-1e9", true, false, true, false, -1e9, 0, -1e9, 0}, |
| 40 | {"-1.2", false, false, true, false, 0, 0, -1.2, 0}, |
| 41 | {"1e19", false, true, true, false, 0, 1e19, 1e19, 0}, |
| 42 | {"-1e19", false, false, true, false, 0, 0, -1e19, 0}, |
| 43 | {"4i", false, false, false, true, 0, 0, 0, 4i}, |
| 44 | {"-1.2+4.2i", false, false, false, true, 0, 0, 0, -1.2 + 4.2i}, |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 45 | {"073i", false, false, false, true, 0, 0, 0, 73i}, // not octal! |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 46 | // complex with 0 imaginary are float (and maybe integer) |
| 47 | {"0i", true, true, true, true, 0, 0, 0, 0}, |
| 48 | {"-1.2+0i", false, false, true, true, 0, 0, -1.2, -1.2}, |
| 49 | {"-12+0i", true, false, true, true, -12, 0, -12, -12}, |
| 50 | {"13+0i", true, true, true, true, 13, 13, 13, 13}, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 51 | // funny bases |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 52 | {"0123", true, true, true, false, 0123, 0123, 0123, 0}, |
| 53 | {"-0x0", true, true, true, false, 0, 0, 0, 0}, |
| 54 | {"0xdeadbeef", true, true, true, false, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0}, |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 55 | // character constants |
| 56 | {`'a'`, true, true, true, false, 'a', 'a', 'a', 0}, |
| 57 | {`'\n'`, true, true, true, false, '\n', '\n', '\n', 0}, |
| 58 | {`'\\'`, true, true, true, false, '\\', '\\', '\\', 0}, |
| 59 | {`'\''`, true, true, true, false, '\'', '\'', '\'', 0}, |
| 60 | {`'\xFF'`, true, true, true, false, 0xFF, 0xFF, 0xFF, 0}, |
| 61 | {`'パ'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0}, |
| 62 | {`'\u30d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0}, |
| 63 | {`'\U000030d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0}, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 64 | // some broken syntax |
| 65 | {text: "+-2"}, |
| 66 | {text: "0x123."}, |
| 67 | {text: "1e."}, |
| 68 | {text: "0xi."}, |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 69 | {text: "1+2."}, |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 70 | {text: "'x"}, |
| 71 | {text: "'xx'"}, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | func TestNumberParse(t *testing.T) { |
| 75 | for _, test := range numberTests { |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 76 | // If fmt.Sscan thinks it's complex, it's complex. We can't trust the output |
| 77 | // because imaginary comes out as a number. |
| 78 | var c complex128 |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 79 | typ := itemNumber |
| 80 | if test.text[0] == '\'' { |
Rob Pike | fc1f0bd | 2011-07-14 13:15:55 +1000 | [diff] [blame] | 81 | typ = itemCharConstant |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 82 | } else { |
| 83 | _, err := fmt.Sscan(test.text, &c) |
| 84 | if err == nil { |
| 85 | typ = itemComplex |
| 86 | } |
| 87 | } |
| 88 | n, err := newNumber(test.text, typ) |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 89 | ok := test.isInt || test.isUint || test.isFloat || test.isComplex |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 90 | if ok && err != nil { |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 91 | t.Errorf("unexpected error for %q: %s", test.text, err) |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 92 | continue |
| 93 | } |
| 94 | if !ok && err == nil { |
| 95 | t.Errorf("expected error for %q", test.text) |
| 96 | continue |
| 97 | } |
| 98 | if !ok { |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 99 | if *debug { |
| 100 | fmt.Printf("%s\n\t%s\n", test.text, err) |
| 101 | } |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 102 | continue |
| 103 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 104 | if n.IsComplex != test.isComplex { |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 105 | t.Errorf("complex incorrect for %q; should be %t", test.text, test.isComplex) |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 106 | } |
| 107 | if test.isInt { |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 108 | if !n.IsInt { |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 109 | t.Errorf("expected integer for %q", test.text) |
| 110 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 111 | if n.Int64 != test.int64 { |
| 112 | t.Errorf("int64 for %q should be %d Is %d", test.text, test.int64, n.Int64) |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 113 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 114 | } else if n.IsInt { |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 115 | t.Errorf("did not expect integer for %q", test.text) |
| 116 | } |
| 117 | if test.isUint { |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 118 | if !n.IsUint { |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 119 | t.Errorf("expected unsigned integer for %q", test.text) |
| 120 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 121 | if n.Uint64 != test.uint64 { |
| 122 | t.Errorf("uint64 for %q should be %d Is %d", test.text, test.uint64, n.Uint64) |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 123 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 124 | } else if n.IsUint { |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 125 | t.Errorf("did not expect unsigned integer for %q", test.text) |
| 126 | } |
| 127 | if test.isFloat { |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 128 | if !n.IsFloat { |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 129 | t.Errorf("expected float for %q", test.text) |
| 130 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 131 | if n.Float64 != test.float64 { |
| 132 | t.Errorf("float64 for %q should be %g Is %g", test.text, test.float64, n.Float64) |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 133 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 134 | } else if n.IsFloat { |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 135 | t.Errorf("did not expect float for %q", test.text) |
| 136 | } |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 137 | if test.isComplex { |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 138 | if !n.IsComplex { |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 139 | t.Errorf("expected complex for %q", test.text) |
| 140 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 141 | if n.Complex128 != test.complex128 { |
| 142 | t.Errorf("complex128 for %q should be %g Is %g", test.text, test.complex128, n.Complex128) |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 143 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 144 | } else if n.IsComplex { |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 145 | t.Errorf("did not expect complex for %q", test.text) |
| 146 | } |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 147 | } |
| 148 | } |
| 149 | |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 150 | type parseTest struct { |
| 151 | name string |
| 152 | input string |
| 153 | ok bool |
| 154 | result string |
| 155 | } |
| 156 | |
| 157 | const ( |
| 158 | noError = true |
| 159 | hasError = false |
| 160 | ) |
| 161 | |
| 162 | var parseTests = []parseTest{ |
| 163 | {"empty", "", noError, |
| 164 | `[]`}, |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 165 | {"comment", "{{/*\n\n\n*/}}", noError, |
| 166 | `[]`}, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 167 | {"spaces", " \t\n", noError, |
| 168 | `[(text: " \t\n")]`}, |
| 169 | {"text", "some text", noError, |
| 170 | `[(text: "some text")]`}, |
Rob Pike | 8d538c6 | 2011-07-07 10:56:33 +1000 | [diff] [blame] | 171 | {"emptyAction", "{{}}", hasError, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 172 | `[(action: [])]`}, |
Rob Pike | 81592c2 | 2011-06-28 23:04:08 +1000 | [diff] [blame] | 173 | {"field", "{{.X}}", noError, |
| 174 | `[(action: [(command: [F=[X]])])]`}, |
Rob Pike | 5b16582 | 2011-07-05 16:02:34 +1000 | [diff] [blame] | 175 | {"simple command", "{{printf}}", noError, |
| 176 | `[(action: [(command: [I=printf])])]`}, |
Rob Pike | e7030e7 | 2011-07-11 10:01:15 +1000 | [diff] [blame] | 177 | {"$ invocation", "{{$}}", noError, |
Rob Pike | 7b79b3b | 2011-07-11 15:23:38 +1000 | [diff] [blame] | 178 | "[(action: [(command: [V=[$]])])]"}, |
Rob Pike | e7030e7 | 2011-07-11 10:01:15 +1000 | [diff] [blame] | 179 | {"variable invocation", "{{with $x := 3}}{{$x 23}}{{end}}", noError, |
Rob Pike | fc1f0bd | 2011-07-14 13:15:55 +1000 | [diff] [blame] | 180 | "[({{with [V=[$x]] := [(command: [N=3])]}} [(action: [(command: [V=[$x] N=23])])])]"}, |
Rob Pike | 7b79b3b | 2011-07-11 15:23:38 +1000 | [diff] [blame] | 181 | {"variable with fields", "{{$.I}}", noError, |
| 182 | "[(action: [(command: [V=[$ I]])])]"}, |
Rob Pike | 5b16582 | 2011-07-05 16:02:34 +1000 | [diff] [blame] | 183 | {"multi-word command", "{{printf `%d` 23}}", noError, |
| 184 | "[(action: [(command: [I=printf S=`%d` N=23])])]"}, |
| 185 | {"pipeline", "{{.X|.Y}}", noError, |
| 186 | `[(action: [(command: [F=[X]]) (command: [F=[Y]])])]`}, |
Rob Pike | c705701 | 2011-07-17 13:31:59 +1000 | [diff] [blame] | 187 | {"pipeline with decl", "{{$x := .X|.Y}}", noError, |
| 188 | `[(action: [V=[$x]] := [(command: [F=[X]]) (command: [F=[Y]])])]`}, |
Rob Pike | b8c6642 | 2011-07-08 17:54:16 +1000 | [diff] [blame] | 189 | {"declaration", "{{.X|.Y}}", noError, |
| 190 | `[(action: [(command: [F=[X]]) (command: [F=[Y]])])]`}, |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 191 | {"simple if", "{{if .X}}hello{{end}}", noError, |
| 192 | `[({{if [(command: [F=[X]])]}} [(text: "hello")])]`}, |
| 193 | {"if with else", "{{if .X}}true{{else}}false{{end}}", noError, |
| 194 | `[({{if [(command: [F=[X]])]}} [(text: "true")] {{else}} [(text: "false")])]`}, |
Rob Pike | 81592c2 | 2011-06-28 23:04:08 +1000 | [diff] [blame] | 195 | {"simple range", "{{range .X}}hello{{end}}", noError, |
| 196 | `[({{range [(command: [F=[X]])]}} [(text: "hello")])]`}, |
| 197 | {"chained field range", "{{range .X.Y.Z}}hello{{end}}", noError, |
| 198 | `[({{range [(command: [F=[X Y Z]])]}} [(text: "hello")])]`}, |
| 199 | {"nested range", "{{range .X}}hello{{range .Y}}goodbye{{end}}{{end}}", noError, |
| 200 | `[({{range [(command: [F=[X]])]}} [(text: "hello")({{range [(command: [F=[Y]])]}} [(text: "goodbye")])])]`}, |
| 201 | {"range with else", "{{range .X}}true{{else}}false{{end}}", noError, |
| 202 | `[({{range [(command: [F=[X]])]}} [(text: "true")] {{else}} [(text: "false")])]`}, |
| 203 | {"range over pipeline", "{{range .X|.M}}true{{else}}false{{end}}", noError, |
| 204 | `[({{range [(command: [F=[X]]) (command: [F=[M]])]}} [(text: "true")] {{else}} [(text: "false")])]`}, |
| 205 | {"range []int", "{{range .SI}}{{.}}{{end}}", noError, |
| 206 | `[({{range [(command: [F=[SI]])]}} [(action: [(command: [{{<.>}}])])])]`}, |
Rob Pike | bf9531f | 2011-07-11 11:46:22 +1000 | [diff] [blame] | 207 | {"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError, |
| 208 | `[({{range [(command: [F=[SI] N=1 N=-3.2i B=true B=false N='a'])]}} [])]`}, |
Rob Pike | 3987b91 | 2011-07-10 07:32:01 +1000 | [diff] [blame] | 209 | {"template", "{{template `x`}}", noError, |
Rob Pike | 7aa1a1a | 2011-07-13 15:58:31 +1000 | [diff] [blame] | 210 | `[{{template "x"}}]`}, |
| 211 | {"template with arg", "{{template `x` .Y}}", noError, |
| 212 | `[{{template "x" [(command: [F=[Y]])]}}]`}, |
Rob Pike | 13f8897 | 2011-07-04 15:15:47 +1000 | [diff] [blame] | 213 | {"with", "{{with .X}}hello{{end}}", noError, |
| 214 | `[({{with [(command: [F=[X]])]}} [(text: "hello")])]`}, |
| 215 | {"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError, |
| 216 | `[({{with [(command: [F=[X]])]}} [(text: "hello")] {{else}} [(text: "goodbye")])]`}, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 217 | // Errors. |
| 218 | {"unclosed action", "hello{{range", hasError, ""}, |
Rob Pike | e7030e7 | 2011-07-11 10:01:15 +1000 | [diff] [blame] | 219 | {"unmatched end", "{{end}}", hasError, ""}, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 220 | {"missing end", "hello{{range .x}}", hasError, ""}, |
| 221 | {"missing end after else", "hello{{range .x}}{{else}}", hasError, ""}, |
Rob Pike | 5b16582 | 2011-07-05 16:02:34 +1000 | [diff] [blame] | 222 | {"undefined function", "hello{{undefined}}", hasError, ""}, |
Rob Pike | e7030e7 | 2011-07-11 10:01:15 +1000 | [diff] [blame] | 223 | {"undefined variable", "{{$x}}", hasError, ""}, |
| 224 | {"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""}, |
Rob Pike | 41efecf | 2011-07-13 13:21:18 +1000 | [diff] [blame] | 225 | {"variable undefined in template", "{{template $v}}", hasError, ""}, |
Rob Pike | 7b79b3b | 2011-07-11 15:23:38 +1000 | [diff] [blame] | 226 | {"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""}, |
Rob Pike | 7aa1a1a | 2011-07-13 15:58:31 +1000 | [diff] [blame] | 227 | {"template with field ref", "{{template .X}}", hasError, ""}, |
| 228 | {"template with var", "{{template $v}}", hasError, ""}, |
Rob Pike | fc1f0bd | 2011-07-14 13:15:55 +1000 | [diff] [blame] | 229 | {"invalid punctuation", "{{printf 3, 4}}", hasError, ""}, |
| 230 | {"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""}, |
| 231 | {"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""}, |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 232 | } |
| 233 | |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 234 | var builtins = map[string]reflect.Value{ |
| 235 | "printf": reflect.ValueOf(fmt.Sprintf), |
| 236 | } |
| 237 | |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 238 | func TestParse(t *testing.T) { |
| 239 | for _, test := range parseTests { |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 240 | tmpl, err := New(test.name).Parse(test.input, builtins) |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 241 | switch { |
| 242 | case err == nil && !test.ok: |
| 243 | t.Errorf("%q: expected error; got none", test.name) |
| 244 | continue |
| 245 | case err != nil && test.ok: |
| 246 | t.Errorf("%q: unexpected error: %v", test.name, err) |
| 247 | continue |
| 248 | case err != nil && !test.ok: |
| 249 | // expected error, got one |
Rob Pike | 64228e3 | 2011-07-06 17:46:36 +1000 | [diff] [blame] | 250 | if *debug { |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 251 | fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err) |
| 252 | } |
| 253 | continue |
| 254 | } |
Rob Pike | c66917d | 2011-08-09 15:42:53 +1000 | [diff] [blame^] | 255 | result := tmpl.Root.String() |
Rob Pike | cd7826e | 2011-06-23 09:27:28 +1000 | [diff] [blame] | 256 | if result != test.result { |
| 257 | t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result) |
| 258 | } |
| 259 | } |
| 260 | } |