// 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, 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);
}
}
|