hcl/printer/printer_test.go

142 lines
2.7 KiB
Go
Raw Normal View History

package printer
2015-10-03 00:30:57 +00:00
import (
2015-10-25 14:51:18 +00:00
"bytes"
"errors"
"flag"
2015-10-25 13:08:09 +00:00
"fmt"
2015-10-25 14:51:18 +00:00
"io/ioutil"
"path/filepath"
2015-10-03 00:30:57 +00:00
"testing"
"github.com/fatih/hcl/parser"
2015-10-03 00:30:57 +00:00
)
2015-10-25 14:51:18 +00:00
var update = flag.Bool("update", false, "update golden files")
2015-10-25 14:51:18 +00:00
const (
dataDir = "testdata"
)
2015-10-03 00:30:57 +00:00
2015-10-25 14:51:18 +00:00
type entry struct {
source, golden string
2015-10-03 00:30:57 +00:00
}
2015-10-25 14:51:18 +00:00
// Use go test -update to create/update the respective golden files.
var data = []entry{
{"complexhcl.input", "complexhcl.golden"},
2015-10-25 18:18:46 +00:00
{"list.input", "list.golden"},
2015-10-25 22:34:41 +00:00
{"comment.input", "comment.golden"},
2015-10-03 00:30:57 +00:00
}
2015-10-25 14:51:18 +00:00
func TestFiles(t *testing.T) {
for _, e := range data {
source := filepath.Join(dataDir, e.source)
golden := filepath.Join(dataDir, e.golden)
check(t, source, golden)
}
2015-10-03 00:30:57 +00:00
}
2015-10-25 14:51:18 +00:00
func check(t *testing.T, source, golden string) {
src, err := ioutil.ReadFile(source)
if err != nil {
t.Error(err)
return
}
res, err := format(src)
if err != nil {
t.Error(err)
return
}
// update golden files if necessary
if *update {
if err := ioutil.WriteFile(golden, res, 0644); err != nil {
t.Error(err)
}
return
}
2015-10-03 00:30:57 +00:00
2015-10-25 14:51:18 +00:00
// get golden
gld, err := ioutil.ReadFile(golden)
if err != nil {
t.Error(err)
return
}
2015-10-03 00:30:57 +00:00
2015-10-25 14:51:18 +00:00
// formatted source and golden must be the same
if err := diff(source, golden, res, gld); err != nil {
t.Error(err)
return
}
2015-10-03 00:30:57 +00:00
}
2015-10-25 14:51:18 +00:00
// diff compares a and b.
func diff(aname, bname string, a, b []byte) error {
var buf bytes.Buffer // holding long error message
// compare lengths
if len(a) != len(b) {
fmt.Fprintf(&buf, "\nlength changed: len(%s) = %d, len(%s) = %d", aname, len(a), bname, len(b))
}
// compare contents
line := 1
offs := 1
for i := 0; i < len(a) && i < len(b); i++ {
ch := a[i]
if ch != b[i] {
fmt.Fprintf(&buf, "\n%s:%d:%d: %s", aname, line, i-offs+1, lineAt(a, offs))
fmt.Fprintf(&buf, "\n%s:%d:%d: %s", bname, line, i-offs+1, lineAt(b, offs))
fmt.Fprintf(&buf, "\n\n")
break
}
if ch == '\n' {
line++
offs = i + 1
}
}
if buf.Len() > 0 {
return errors.New(buf.String())
}
return nil
2015-10-03 00:30:57 +00:00
}
2015-10-25 14:51:18 +00:00
// format parses src, prints the corresponding AST, verifies the resulting
// src is syntactically correct, and returns the resulting src or an error
// if any.
func format(src []byte) ([]byte, error) {
// parse src
node, err := parser.Parse(src)
2015-10-03 00:30:57 +00:00
if err != nil {
2015-10-25 14:51:18 +00:00
return nil, fmt.Errorf("parse: %s\n%s", err, src)
2015-10-03 00:30:57 +00:00
}
2015-10-25 14:51:18 +00:00
var buf bytes.Buffer
cfg := &Config{}
if err := cfg.Fprint(&buf, node); err != nil {
2015-10-25 14:51:18 +00:00
return nil, fmt.Errorf("print: %s", err)
}
// make sure formatted output is syntactically correct
res := buf.Bytes()
if _, err := parser.Parse(src); err != nil {
return nil, fmt.Errorf("parse: %s\n%s", err, src)
2015-10-03 00:30:57 +00:00
}
2015-10-25 13:08:09 +00:00
2015-10-25 14:51:18 +00:00
return res, nil
}
// lineAt returns the line in text starting at offset offs.
func lineAt(text []byte, offs int) []byte {
i := offs
for i < len(text) && text[i] != '\n' {
i++
}
return text[offs:i]
2015-10-03 00:30:57 +00:00
}