github.com/valyala/quicktemplate@v1.7.0/parser/parser_test.go (about) 1 package parser 2 3 import ( 4 "bytes" 5 "go/format" 6 "io/ioutil" 7 "os" 8 "testing" 9 10 "github.com/valyala/quicktemplate" 11 ) 12 13 func TestParsePackageName(t *testing.T) { 14 // empty template 15 testParseSuccess(t, ``) 16 17 // No package name 18 testParseSuccess(t, `foobar`) 19 20 // explicit package name 21 testParseSuccess(t, `{% package foobar %}`) 22 23 // package name with imports 24 testParseSuccess(t, `Package: {% 25 package foobar 26 %} 27 import 28 {% import "aa/bb/cc" %} 29 yet another import 30 {% import ( 31 "xxx.com/aaa" 32 ) %}`) 33 34 // invalid package name 35 testParseFailure(t, `{% package foo bar %}`) 36 testParseFailure(t, `{% package "foobar" %}`) 37 testParseFailure(t, `{% package x(foobar) %}`) 38 39 // multiple package names 40 testParseFailure(t, `{% package foo %}{% package bar %}`) 41 42 // package name not at the top of the template 43 testParseFailure(t, `{% import "foo" %}{% package bar %}`) 44 testParseFailure(t, `{% func foo() %}{% endfunc %}{% package bar %}`) 45 testParseFailure(t, `{% func foo() %}{% package bar %}{% endfunc %}`) 46 } 47 48 func TestParseOutputFunc(t *testing.T) { 49 // func without args 50 testParseSuccess(t, `{% func f() %}{%= f() %}{% endfunc %}`) 51 testParseSuccess(t, `{% func f() %}{%= x.y.f() %}{% endfunc %}`) 52 53 // func with args 54 testParseSuccess(t, `{% func f() %}{%= f(1, "foo", bar) %}{% endfunc %}`) 55 testParseSuccess(t, `{% func f() %}{%= x.y.f(1, "foo", bar) %}{% endfunc %}`) 56 57 // html modifier (=h) 58 testParseSuccess(t, `{% func f() %}{%=h f(1, "foo", bar) %}{% endfunc %}`) 59 testParseSuccess(t, `{% func f() %}{%=h x.y.f(1, "foo", bar) %}{% endfunc %}`) 60 61 // urlencode modifier (=u) 62 testParseSuccess(t, `{% func f() %}{%=u f(1, "foo", bar) %}{% endfunc %}`) 63 testParseSuccess(t, `{% func f() %}{%=u x.y.f(1, "foo", bar) %}{% endfunc %}`) 64 testParseSuccess(t, `{% func f() %}{%=uh f(1, "foo", bar) %}{% endfunc %}`) 65 testParseSuccess(t, `{% func f() %}{%=uh x.y.f(1, "foo", bar) %}{% endfunc %}`) 66 67 // quoted json string modifier (=q) 68 testParseSuccess(t, `{% func f() %}{%=q f(1, "foo", bar) %}{% endfunc %}`) 69 testParseSuccess(t, `{% func f() %}{%=q x.y.f(1, "foo", bar) %}{% endfunc %}`) 70 testParseSuccess(t, `{% func f() %}{%=qh f(1, "foo", bar) %}{% endfunc %}`) 71 testParseSuccess(t, `{% func f() %}{%=qh x.y.f(1, "foo", bar) %}{% endfunc %}`) 72 73 // unquoted json string modifier (=j) 74 testParseSuccess(t, `{% func f() %}{%=j f(1, "foo", bar) %}{% endfunc %}`) 75 testParseSuccess(t, `{% func f() %}{%=j x.y.f(1, "foo", bar) %}{% endfunc %}`) 76 testParseSuccess(t, `{% func f() %}{%=jh f(1, "foo", bar) %}{% endfunc %}`) 77 testParseSuccess(t, `{% func f() %}{%=jh x.y.f(1, "foo", bar) %}{% endfunc %}`) 78 79 // unknown modifier 80 testParseFailure(t, `{% func f() %}{%=w f(1, "foo", bar) %}{% endfunc %}`) 81 testParseFailure(t, `{% func f() %}{%=ww x.y.f(1, "foo", bar) %}{% endfunc %}`) 82 testParseFailure(t, `{% func f() %}{%=wwh f(1, "foo", bar) %}{% endfunc %}`) 83 testParseFailure(t, `{% func f() %}{%=wh x.y.f(1, "foo", bar) %}{% endfunc %}`) 84 } 85 86 func TestParseCat(t *testing.T) { 87 // relative paths 88 testParseSuccess(t, `{% func a() %}{% cat "parser.go" %}{% endfunc %}`) 89 testParseSuccess(t, `{% func a() %}{% cat "./parser.go" %}{% endfunc %}`) 90 testParseSuccess(t, `{% func a() %}{% cat "../parser/parser.go" %}{% endfunc %}`) 91 92 // multi-cat 93 testParseSuccess(t, `{% func a() %}{% cat "parser.go" %}{% cat "./parser.go" %}{% endfunc %}`) 94 95 // non-existing file 96 testParseFailure(t, `{% func a() %}{% cat "non-existing-file.go" %}{% endfunc %}`) 97 98 // non-const string 99 testParseFailure(t, `{% func a() %}{% cat "foobar"+".baz" %}{% endfunc %}`) 100 testParseFailure(t, `{% func a() %}{% cat foobar %}{% endfunc %}`) 101 } 102 103 func TestParseUnexpectedValueAfterTag(t *testing.T) { 104 // endfunc 105 testParseSuccess(t, "{% func a() %}{% endfunc %}") 106 testParseFailure(t, "{% func a() %}{% endfunc foo bar %}") 107 108 // endfor 109 testParseSuccess(t, "{% func a() %}{% for %}{% endfor %}{% endfunc %}") 110 testParseFailure(t, "{% func a() %}{% for %}{% endfor foo bar %}{% endfunc %}") 111 112 // endif 113 testParseSuccess(t, "{% func a() %}{% if true %}{% endif %}{% endfunc %}") 114 testParseFailure(t, "{% func a() %}{% if true %}{% endif foo bar %}{% endfunc %}") 115 116 // endswitch 117 testParseSuccess(t, "{% func a() %}{% switch %}{% case true %}{% endswitch %}{% endfunc %}") 118 testParseFailure(t, "{% func a() %}{% switch %}{% case true %}{% endswitch foobar %}{% endfunc %}") 119 120 // else 121 testParseSuccess(t, "{% func a() %}{% if true %}{% else %}{% endif %}{% endfunc %}") 122 testParseFailure(t, "{% func a() %}{% if true %}{% else foo bar %}{% endif %}{% endfunc %}") 123 124 // return 125 testParseSuccess(t, "{% func a() %}{% return %}{% endfunc %}") 126 testParseFailure(t, "{% func a() %}{% return foobar %}{% endfunc %}") 127 128 // break 129 testParseSuccess(t, "{% func a() %}{% for %}{% break %}{% endfor %}{% endfunc %}") 130 testParseFailure(t, "{% func a() %}{% for %}{% break foobar %}{% endfor %}{% endfunc %}") 131 132 // default 133 testParseSuccess(t, "{% func a() %}{% switch %}{% default %}{% endswitch %}{% endfunc %}") 134 testParseFailure(t, "{% func a() %}{% switch %}{% default foobar %}{% endswitch %}{% endfunc %}") 135 } 136 137 func TestParseFPrecFailure(t *testing.T) { 138 // negative precision 139 testParseFailure(t, "{% func a()%}{%f.-1 1.2 %}{% endfunc %}") 140 141 // non-numeric precision 142 testParseFailure(t, "{% func a()%}{%f.foo 1.2 %}{% endfunc %}") 143 144 // more than one dot 145 testParseFailure(t, "{% func a()%}{%f.1.234 1.2 %}{% endfunc %}") 146 testParseFailure(t, "{% func a()%}{%f.1.foo 1.2 %}{% endfunc %}") 147 } 148 149 func TestParseFPrecSuccess(t *testing.T) { 150 // no precision 151 testParseSuccess(t, "{% func a()%}{%f 1.2 %}{% endfunc %}") 152 testParseSuccess(t, "{% func a()%}{%f= 1.2 %}{% endfunc %}") 153 154 // precision set 155 testParseSuccess(t, "{% func a()%}{%f.1 1.234 %}{% endfunc %}") 156 testParseSuccess(t, "{% func a()%}{%f.10= 1.234 %}{% endfunc %}") 157 158 // missing precision 159 testParseSuccess(t, "{% func a()%}{%f. 1.234 %}{% endfunc %}") 160 testParseSuccess(t, "{% func a()%}{%f.= 1.234 %}{% endfunc %}") 161 } 162 163 func TestParseSwitchCaseSuccess(t *testing.T) { 164 // single-case switch 165 testParseSuccess(t, "{%func a()%}{%switch n%}{%case 1%}aaa{%endswitch%}{%endfunc%}") 166 167 // multi-case switch 168 testParseSuccess(t, "{%func a()%}{%switch%}\n\t {%case foo()%}\nfoobar{%case bar()%}{%endswitch%}{%endfunc%}") 169 170 // default statement 171 testParseSuccess(t, "{%func a()%}{%switch%}{%default%}{%endswitch%}{%endfunc%}") 172 173 // switch with break 174 testParseSuccess(t, "{%func a()%}{%switch n%}{%case 1%}aaa{%break%}ignore{%endswitch%}{%endfunc%}") 175 176 // switch on a type 177 // See https://github.com/valyala/quicktemplate/issues/77 178 testParseSuccess(t, "{%func a()%}{%switch a.(type) %}{% case []string %}aaa{%case int%}bbb{%endswitch%}{%endfunc%}") 179 180 // complex switch 181 testParseSuccess(t, `{%func f()%}{% for %} 182 {%switch foo() %} 183 The text before the first case 184 is converted into a comment 185 {%case "foobar" %} 186 {% switch %} 187 {% case bar() %} 188 aaaa{% break %} 189 ignore this line 190 {% case baz() %} 191 bbbb 192 {% endswitch %} 193 {% case "aaa" %} 194 {% for i := 0; i < 10; i++ %} 195 foobar 196 {% endfor %} 197 {% case "qwe", "sdfdf" %} 198 aaaa 199 {% return %} 200 {% case "www" %} 201 break from the switch 202 {% break %} 203 {% default %} 204 foobar 205 {%endswitch%} 206 {% if 42 == 2 %} 207 break for the loop 208 {% break %} 209 ignore this 210 {% endif %} 211 {% endfor %}{%endfunc%}`) 212 } 213 214 func TestParseSwitchCaseFailure(t *testing.T) { 215 // missing endswitch 216 testParseFailure(t, "{%func a()%}{%switch%}{%endfunc%}") 217 218 // empty switch 219 testParseFailure(t, "{%func f()%}{%switch%}{%endswitch%}{%endfunc%}") 220 221 // case outside switch 222 testParseFailure(t, "{%func f()%}{%case%}{%endfunc%}") 223 224 // the first tag inside switch is non-case 225 testParseFailure(t, "{%func f()%}{%switch%}{%return%}{%endswitch%}{%endfunc%}") 226 testParseFailure(t, "{%func F()%}{%switch%}{%break%}{%endswitch%}{%endfunc%}") 227 testParseFailure(t, "{%func f()%}{%switch 1%}{%return%}{%case 1%}aaa{%endswitch%}{%endfunc%}") 228 229 // empty case 230 testParseFailure(t, "{%func f()%}{%switch%}{%case%}aaa{%endswitch%}{%endfunc%}") 231 232 // multiple default statements 233 testParseFailure(t, "{%func f()%}{%switch%}{%case%}aaa{%default%}bbb{%default%}{%endswitch%}{%endfunc%}") 234 } 235 236 func TestParseBreakContinueReturn(t *testing.T) { 237 testParseSuccess(t, `{% func a() %}{% for %}{% continue %}{% break %}{% return %}{% endfor %}{% endfunc %}`) 238 testParseSuccess(t, `{% func a() %}{% for %} 239 {% if f1() %}{% continue %}skip this{%s "and this" %}{% endif %} 240 {% if f2() %}{% break %}{% for %}{% endfor %}skip this{% endif %} 241 {% if f3() %}{% return %}foo{% if f4() %}{% for %}noop{% endfor %}{% endif %}bar skip this{% endif %} 242 text 243 {% endfor %}{% endfunc %}`) 244 } 245 246 func TestParseOutputTagSuccess(t *testing.T) { 247 // identifier 248 testParseSuccess(t, "{%func a()%}{%s foobar %}{%endfunc%}") 249 250 // method call 251 testParseSuccess(t, "{%func a()%}{%s foo.bar.baz(a, b, &A{d:e}) %}{%endfunc%}") 252 253 // inline function call 254 testParseSuccess(t, "{%func f()%}{%s func() string { return foo.bar(baz, aaa) }() %}{%endfunc%}") 255 256 // map 257 testParseSuccess(t, `{%func f()%}{%v map[int]string{1:"foo", 2:"bar"} %}{%endfunc%}`) 258 259 // jsons-safe string 260 testParseSuccess(t, `{% func f() %}{%j "foo\nbar" %}{%endfunc%}`) 261 262 // url-encoded string 263 testParseSuccess(t, `{% func A() %}{%u "fooab" %}{%endfunc%}`) 264 } 265 266 func TestParseOutputTagFailure(t *testing.T) { 267 // empty tag 268 testParseFailure(t, "{%func f()%}{%s %}{%endfunc%}") 269 270 // multiple arguments 271 testParseFailure(t, "{%func f()%}{%s a, b %}{%endfunc%}") 272 273 // invalid code 274 testParseFailure(t, "{%func f()%}{%s f(a, %}{%endfunc%}") 275 testParseFailure(t, "{%func f()%}{%s Foo{Bar:1 %}{%endfunc%}") 276 277 // unsupported code 278 testParseFailure(t, "{%func f()%}{%s if (a) {} %}{%endfunc%}") 279 testParseFailure(t, "{%func f()%}{%s for {} %}{%endfunc%}") 280 } 281 282 func TestParseTemplateCodeSuccess(t *testing.T) { 283 // empty code 284 testParseSuccess(t, "{% code %}") 285 testParseSuccess(t, "{% func f() %}{% code %}{% endfunc %}") 286 287 // comment 288 testParseSuccess(t, `{% code // foobar %}`) 289 testParseSuccess(t, `{% func f() %}{% code // foobar %}{% endfunc %}`) 290 testParseSuccess(t, `{% code 291 // foo 292 // bar 293 %}`) 294 testParseSuccess(t, `{% func f() %}{% code 295 // foo 296 // bar 297 %}{% endfunc %}`) 298 testParseSuccess(t, `{% 299 code 300 /* 301 foo 302 bar 303 */ 304 %}`) 305 testParseSuccess(t, `{% func f() %}{% 306 code 307 /* 308 foo 309 bar 310 */ 311 %}{% endfunc %}`) 312 313 testParseSuccess(t, `{% code var a int %}`) 314 testParseSuccess(t, `{% func f() %}{% code var a int %}{% endfunc %}`) 315 testParseSuccess(t, `{% func f() %}{% code a := 0 %}{% endfunc %}`) 316 testParseSuccess(t, `{% func f() %}{% code type A struct{} %}{% endfunc %}`) 317 318 // declarations 319 testParseSuccess(t, `{%code 320 // comment 321 type Foo struct {} 322 var b = &Foo{} 323 324 func (f *Foo) Bar() {} 325 326 // yet another comment 327 func Bar(baz int) string { 328 return fmt.Sprintf("%d", baz) 329 } 330 %}`) 331 } 332 333 func TestParseTemplateCodeFailure(t *testing.T) { 334 // import inside the code 335 testParseFailure(t, `{% code import "foo" %}`) 336 337 // incomplete code 338 testParseFailure(t, `{% code type A struct { %}`) 339 testParseFailure(t, `{% code func F() { %}`) 340 341 // invalid code 342 testParseFailure(t, `{%code { %}`) 343 testParseFailure(t, `{%code {} %}`) 344 testParseFailure(t, `{%code ( %}`) 345 testParseFailure(t, `{%code () %}`) 346 } 347 348 func TestParseImportSuccess(t *testing.T) { 349 // single line import 350 testParseSuccess(t, `{% import "github.com/foo/bar" %}`) 351 352 // multiline import 353 testParseSuccess(t, `{% import ( 354 "foo" 355 xxx "bar/baz/aaa" 356 357 "yyy.com/zzz" 358 ) %}`) 359 360 // multiple imports 361 testParseSuccess(t, `{% import "foo" %} 362 baaas 363 {% import ( 364 "bar" 365 "baasd" 366 ) 367 %} 368 sddf 369 `) 370 } 371 372 func TestParseImportFailure(t *testing.T) { 373 // empty import 374 testParseFailure(t, `{%import %}`) 375 376 // invalid import 377 testParseFailure(t, `{%import foo %}`) 378 379 // non-import code 380 testParseFailure(t, `{%import {"foo"} %}`) 381 testParseFailure(t, `{%import "foo" 382 type A struct {} 383 %}`) 384 testParseFailure(t, `{%import type a struct{} %}`) 385 } 386 387 func TestParseFailure(t *testing.T) { 388 // unknown tag 389 testParseFailure(t, "{% foobar %}") 390 391 // unexpected tag outside func 392 testParseFailure(t, "aaa{% for %}bbb{%endfor%}") 393 testParseFailure(t, "{% return %}") 394 testParseFailure(t, "{% break %}") 395 testParseFailure(t, "{% if 1==1 %}aaa{%endif%}") 396 testParseFailure(t, "{%s abc %}") 397 testParseFailure(t, "{%v= aaaa(xx) %}") 398 testParseFailure(t, "{%= a() %}") 399 400 // import after func and/or code 401 testParseFailure(t, `{%code var i = 0 %}{%import "fmt"%}`) 402 testParseFailure(t, `{%func f()%}{%endfunc%}{%import "fmt"%}`) 403 404 // missing endfunc 405 testParseFailure(t, "{%func a() %}aaaa") 406 407 // empty func name 408 testParseFailure(t, "{% func () %}aaa{% endfunc %}") 409 testParseFailure(t, "{% func (a int, b string) %}aaa{% endfunc %}") 410 411 // empty func arguments 412 testParseFailure(t, "{% func aaa %}aaa{% endfunc %}") 413 414 // func with anonymous argument 415 testParseFailure(t, "{% func a(x int, string) %}{%endfunc%}") 416 417 // func with incorrect arguments' list 418 testParseFailure(t, "{% func x(foo, bar) %}{%endfunc%}") 419 testParseFailure(t, "{% func x(foo bar baz) %}{%endfunc%}") 420 421 // empty if condition 422 testParseFailure(t, "{% func a() %}{% if %}aaaa{% endif %}{% endfunc %}") 423 424 // else with content 425 testParseFailure(t, "{% func a() %}{% if 3 == 4%}aaaa{% else if 3 == 5 %}bug{% endif %}{% endfunc %}") 426 427 // missing endif 428 testParseFailure(t, "{%func a() %}{%if foo %}aaa{% endfunc %}") 429 430 // missing endfor 431 testParseFailure(t, "{%func a()%}{%for %}aaa{%endfunc%}") 432 433 // break outside for 434 testParseFailure(t, "{%func a()%}{%break%}{%endfunc%}") 435 436 // invalid if condition 437 testParseFailure(t, "{%func a()%}{%if a = b %}{%endif%}{%endfunc%}") 438 testParseFailure(t, "{%func f()%}{%if a { %}{%endif%}{%endfunc%}") 439 440 // invalid for 441 testParseFailure(t, "{%func a()%}{%for a = b %}{%endfor%}{%endfunc%}") 442 testParseFailure(t, "{%func f()%}{%for { %}{%endfor%}{%endfunc%}") 443 444 // invalid code inside func 445 testParseFailure(t, "{%func f()%}{%code } %}{%endfunc%}") 446 testParseFailure(t, "{%func f()%}{%code { %}{%endfunc%}") 447 448 // interface inside func 449 testParseFailure(t, "{%func f()%}{%interface A { Foo() } %}{%endfunc%}") 450 451 // interface without name 452 testParseFailure(t, "{%interface { Foo() } %}") 453 454 // empty interface 455 testParseFailure(t, "{% interface Foo {} %}") 456 457 // invalid interface 458 testParseFailure(t, "{%interface aaaa %}") 459 testParseFailure(t, "{%interface aa { Foo() %}") 460 461 // unnamed method 462 testParseFailure(t, "{%func (s *S) () %}{%endfunc%}") 463 464 // empty method arguments 465 testParseFailure(t, "{%func (s *S) Foo %}{%endfunc %}") 466 467 // method with return values 468 testParseFailure(t, "{%func (s *S) Foo() string %}{%endfunc%}") 469 testParseFailure(t, "{%func (s *S) Bar() (int, string) %}{%endfunc%}") 470 } 471 472 func TestParserSuccess(t *testing.T) { 473 // empty template 474 testParseSuccess(t, "") 475 476 // template without code and funcs 477 testParseSuccess(t, "foobar\nbaz") 478 479 // template with code 480 testParseSuccess(t, "{%code var a struct {}\nconst n = 123%}") 481 482 // import 483 testParseSuccess(t, `{%import "foobar"%}`) 484 testParseSuccess(t, `{% import ( 485 "foo" 486 "bar" 487 )%}`) 488 testParseSuccess(t, `{%import "foo"%}{%import "bar"%}`) 489 490 // func 491 testParseSuccess(t, "{%func a()%}{%endfunc%}") 492 493 // func with with condition 494 testParseSuccess(t, "{%func a(x bool)%}{%if x%}foobar{%endif%}{%endfunc%}") 495 496 // func with complex arguments 497 testParseSuccess(t, "{%func f(h1, h2 func(x, y int) string, d int)%}{%endfunc%}") 498 499 // for 500 testParseSuccess(t, "{%func a()%}{%for%}aaa{%endfor%}{%endfunc%}") 501 502 // return 503 testParseSuccess(t, "{%func a()%}{%return%}{%endfunc%}") 504 505 // nested for 506 testParseSuccess(t, "{%func a()%}{%for i := 0; i < 10; i++ %}{%for j := 0; j < i; j++%}aaa{%endfor%}{%endfor%}{%endfunc%}") 507 508 // plain containing arbitrary tags 509 testParseSuccess(t, "{%func f()%}{%plain%}This {%endfunc%} is ignored{%endplain%}{%endfunc%}") 510 511 // comment with arbitrary tags 512 testParseSuccess(t, "{%func f()%}{%comment%}This {%endfunc%} is ignored{%endcomment%}{%endfunc%}") 513 514 // complex if 515 testParseSuccess(t, "{%func a()%}{%if n, err := w.Write(p); err != nil %}{%endif%}{%endfunc%}") 516 517 // complex for 518 testParseSuccess(t, "{%func a()%}{%for i, n := 0, len(s); i < n && f(i); i++ %}{%endfor%}{%endfunc%}") 519 520 // complex code inside func 521 testParseSuccess(t, `{%func f()%}{%code 522 type A struct{} 523 var aa []A 524 for i := 0; i < 10; i++ { 525 aa = append(aa, &A{}) 526 if i == 42 { 527 break 528 } 529 } 530 return 531 %}{%endfunc%}`) 532 533 // break inside for loop 534 testParseSuccess(t, `{%func f()%}{%for%} 535 {% if a() %} 536 {% break 537 %} 538 {% 539 else 540 %} 541 {% return %} 542 {% endif %} 543 {%endfor%}{%endfunc%}`) 544 545 // interface 546 testParseSuccess(t, "{%interface Foo { Bar()\nBaz() } %}") 547 testParseSuccess(t, "{%iface Foo { Bar()\nBaz() } %}") 548 549 // method 550 testParseSuccess(t, "{%func (s *S) Foo(bar, baz string) %}{%endfunc%}") 551 } 552 553 func testParseFailure(t *testing.T, str string) { 554 r := bytes.NewBufferString(str) 555 w := &bytes.Buffer{} 556 if err := Parse(w, r, "qtc-test.qtpl", "memory"); err == nil { 557 t.Fatalf("expecting error when parsing %q", str) 558 } 559 } 560 561 func testParseSuccess(t *testing.T, str string) { 562 r := bytes.NewBufferString(str) 563 w := &bytes.Buffer{} 564 if err := Parse(w, r, "qtc-test.qtpl", "memory"); err != nil { 565 t.Fatalf("unexpected error when parsing %q: %s", str, err) 566 } 567 } 568 569 func TestParseFile(t *testing.T) { 570 currDir, err := os.Getwd() 571 if err != nil { 572 t.Fatalf("cannot obtain current directory: %s", err) 573 } 574 if err := os.Chdir("../testdata/qtc"); err != nil { 575 t.Fatalf("cannot change directory to `../testdata/qtc`: %s", err) 576 } 577 defer func() { 578 if err := os.Chdir(currDir); err != nil { 579 t.Fatalf("cannot change directory to %q: %s", currDir, err) 580 } 581 }() 582 583 filename := "test.qtpl" 584 f, err := os.Open(filename) 585 if err != nil { 586 t.Fatalf("cannot open file %q: %s", filename, err) 587 } 588 defer f.Close() 589 590 w := quicktemplate.AcquireByteBuffer() 591 if err := Parse(w, f, "test.qtpl", "qtc"); err != nil { 592 t.Fatalf("unexpected error: %s", err) 593 } 594 code, err := format.Source(w.B) 595 if err != nil { 596 t.Fatalf("unexpected error: %s", err) 597 } 598 quicktemplate.ReleaseByteBuffer(w) 599 600 expectedFilename := filename + ".expected" 601 expectedCode, err := ioutil.ReadFile(expectedFilename) 602 if err != nil { 603 t.Fatalf("unexpected error: %s", err) 604 } 605 606 if !bytes.Equal(code, expectedCode) { 607 if err := ioutil.WriteFile(filename+".generated", code, 0644); err != nil { 608 t.Fatal(err) 609 } 610 t.Fatalf("unexpected code:\n%q\nexpected:\n%q", code, expectedCode) 611 } 612 } 613 614 func TestParseNoLineComments(t *testing.T) { 615 const str = "foobar\nbaz" 616 r := bytes.NewBufferString(str) 617 w := &bytes.Buffer{} 618 if err := ParseNoLineComments(w, r, "qtc-test.qtpl", "memory"); err != nil { 619 t.Fatalf("unexpected error when parsing %q: %s", str, err) 620 } 621 if bytes.Contains(w.Bytes(), []byte("//line")) { 622 t.Fatal("unexpected line comment") 623 } 624 }