blob: f89eaa6ce3cfbc8b08c80dec0aea51e52005bd3b [file] [log] [blame]
// 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 (
"fmt"
"testing"
)
const dumpErrors = true
type numberTest struct {
text string
isInt bool
isUint bool
isFloat bool
imaginary bool
int64
uint64
float64
}
var numberTests = []numberTest{
// basics
{"0", true, true, true, false, 0, 0, 0},
{"-0", true, true, true, false, 0, 0, 0}, // check that -0 is a uint.
{"73", true, true, true, false, 73, 73, 73},
{"-73", true, false, true, false, -73, 0, -73},
{"+73", true, false, true, false, 73, 0, 73},
{"100", true, true, true, false, 100, 100, 100},
{"1e9", true, true, true, false, 1e9, 1e9, 1e9},
{"-1e9", true, false, true, false, -1e9, 0, -1e9},
{"-1.2", false, false, true, false, 0, 0, -1.2},
{"1e19", false, true, true, false, 0, 1e19, 1e19},
{"-1e19", false, false, true, false, 0, 0, -1e19},
{"4i", false, false, true, true, 0, 0, 4},
// funny bases
{"0123", true, true, true, false, 0123, 0123, 0123},
{"-0x0", true, true, true, false, 0, 0, 0},
{"0xdeadbeef", true, true, true, false, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef},
// some broken syntax
{text: "+-2"},
{text: "0x123."},
{text: "1e."},
{text: "0xi."},
}
func TestNumberParse(t *testing.T) {
for _, test := range numberTests {
n, err := newNumber(test.text)
ok := test.isInt || test.isUint || test.isFloat
if ok && err != nil {
t.Errorf("unexpected error for %q", test.text)
continue
}
if !ok && err == nil {
t.Errorf("expected error for %q", test.text)
continue
}
if !ok {
continue
}
if n.imaginary != test.imaginary {
t.Errorf("imaginary incorrect for %q; should be %t", test.text, test.imaginary)
}
if test.isInt {
if !n.isInt {
t.Errorf("expected integer for %q", test.text)
}
if n.int64 != test.int64 {
t.Errorf("int64 for %q should be %d is %d", test.text, test.int64, n.int64)
}
} else if n.isInt {
t.Errorf("did not expect integer for %q", test.text)
}
if test.isUint {
if !n.isUint {
t.Errorf("expected unsigned integer for %q", test.text)
}
if n.uint64 != test.uint64 {
t.Errorf("uint64 for %q should be %d is %d", test.text, test.uint64, n.uint64)
}
} else if n.isUint {
t.Errorf("did not expect unsigned integer for %q", test.text)
}
if test.isFloat {
if !n.isFloat {
t.Errorf("expected float for %q", test.text)
}
if n.float64 != test.float64 {
t.Errorf("float64 for %q should be %g is %g", test.text, test.float64, n.float64)
}
} else if n.isFloat {
t.Errorf("did not expect float for %q", test.text)
}
}
}
func num(s string) *numberNode {
n, err := newNumber(s)
if err != nil {
panic(err)
}
return n
}
type parseTest struct {
name string
input string
ok bool
result string
}
const (
noError = true
hasError = false
)
var parseTests = []parseTest{
{"empty", "", noError,
`[]`},
{"spaces", " \t\n", noError,
`[(text: " \t\n")]`},
{"text", "some text", noError,
`[(text: "some text")]`},
{"emptyMeta", "{{}}", noError,
`[(action: [])]`},
{"simple command", "{{hello}}", noError,
`[(action: [(command: [I=hello])])]`},
{"multi-word command", "{{hello world}}", noError,
`[(action: [(command: [I=hello I=world])])]`},
{"multi-word command with number", "{{hello 80}}", noError,
`[(action: [(command: [I=hello N=80])])]`},
{"multi-word command with string", "{{hello `quoted text`}}", noError,
"[(action: [(command: [I=hello S=`quoted text`])])]"},
{"pipeline", "{{hello|world}}", noError,
`[(action: [(command: [I=hello]) (command: [I=world])])]`},
{"simple range", "{{range .x}}hello{{end}}", noError,
`[({{range F=.x}} [(text: "hello")])]`},
{"nested range", "{{range .x}}hello{{range .y}}goodbye{{end}}{{end}}", noError,
`[({{range F=.x}} [(text: "hello")({{range F=.y}} [(text: "goodbye")])])]`},
{"range with else", "{{range .x}}true{{else}}false{{end}}", noError,
`[({{range F=.x}} [(text: "true")] {{else}} [(text: "false")])]`},
// Errors.
{"unclosed action", "hello{{range", hasError, ""},
{"not a field", "hello{{range x}}{{end}}", hasError, ""},
{"missing end", "hello{{range .x}}", hasError, ""},
{"missing end after else", "hello{{range .x}}{{else}}", hasError, ""},
}
func TestParse(t *testing.T) {
for _, test := range parseTests {
tmpl := New(test.name)
err := tmpl.Parse(test.input)
switch {
case err == nil && !test.ok:
t.Errorf("%q: expected error; got none", test.name)
continue
case err != nil && test.ok:
t.Errorf("%q: unexpected error: %v", test.name, err)
continue
case err != nil && !test.ok:
// expected error, got one
if dumpErrors {
fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
}
continue
}
result := tmpl.root.String()
if result != test.result {
t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result)
}
}
}