blob: a5de3774a2688f8b15c9e65663dba3745ded4ca9 [file] [log] [blame]
// Copyright 2009 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 printer
import (
"bytes"
"flag"
"io/ioutil"
"go/ast"
"go/parser"
"path"
"testing"
)
const (
dataDir = "testdata"
tabwidth = 8
)
var update = flag.Bool("update", false, "update golden files")
func lineString(text []byte, i int) string {
i0 := i
for i < len(text) && text[i] != '\n' {
i++
}
return string(text[i0:i])
}
type checkMode uint
const (
export checkMode = 1 << iota
rawFormat
)
func check(t *testing.T, source, golden string, mode checkMode) {
// parse source
prog, err := parser.ParseFile(source, nil, nil, parser.ParseComments)
if err != nil {
t.Error(err)
return
}
// filter exports if necessary
if mode&export != 0 {
ast.FileExports(prog) // ignore result
prog.Comments = nil // don't print comments that are not in AST
}
// determine printer configuration
cfg := Config{Tabwidth: tabwidth}
if mode&rawFormat != 0 {
cfg.Mode |= RawFormat
}
// format source
var buf bytes.Buffer
if _, err := cfg.Fprint(&buf, prog); err != nil {
t.Error(err)
}
res := buf.Bytes()
// update golden files if necessary
if *update {
if err := ioutil.WriteFile(golden, res, 0644); err != nil {
t.Error(err)
}
return
}
// get golden
gld, err := ioutil.ReadFile(golden)
if err != nil {
t.Error(err)
return
}
// compare lengths
if len(res) != len(gld) {
t.Errorf("len = %d, expected %d (= len(%s))", len(res), len(gld), golden)
}
// compare contents
for i, line, offs := 0, 1, 0; i < len(res) && i < len(gld); i++ {
ch := res[i]
if ch != gld[i] {
t.Errorf("%s:%d:%d: %s", source, line, i-offs+1, lineString(res, offs))
t.Errorf("%s:%d:%d: %s", golden, line, i-offs+1, lineString(gld, offs))
t.Error()
return
}
if ch == '\n' {
line++
offs = i + 1
}
}
}
type entry struct {
source, golden string
mode checkMode
}
// Use gotest -update to create/update the respective golden files.
var data = []entry{
entry{"empty.input", "empty.golden", 0},
entry{"comments.input", "comments.golden", 0},
entry{"comments.input", "comments.x", export},
entry{"linebreaks.input", "linebreaks.golden", 0},
entry{"expressions.input", "expressions.golden", 0},
entry{"expressions.input", "expressions.raw", rawFormat},
entry{"declarations.input", "declarations.golden", 0},
entry{"statements.input", "statements.golden", 0},
}
func Test(t *testing.T) {
for _, e := range data {
source := path.Join(dataDir, e.source)
golden := path.Join(dataDir, e.golden)
check(t, source, golden, e.mode)
// TODO(gri) check that golden is idempotent
//check(t, golden, golden, e.mode);
}
}