printer: implement file tests

This commit is contained in:
Fatih Arslan 2015-10-25 17:51:18 +03:00
parent 2ea5683566
commit 0fc42b65df
4 changed files with 205 additions and 64 deletions

View File

@ -111,18 +111,14 @@ func writeBlank(buf io.ByteWriter, indent int) {
} }
func indent(buf []byte) []byte { func indent(buf []byte) []byte {
splitted := bytes.Split(buf, []byte{newline}) var res []byte
newBuf := make([]byte, len(splitted)) bol := true
for i, s := range splitted { for _, c := range buf {
s = append(s, 0) if bol && c != '\n' {
copy(s[1:], s[0:]) res = append(res, []byte{tab}...)
s[0] = tab
newBuf = append(newBuf, s...)
if i != len(splitted)-1 {
newBuf = append(newBuf, newline)
} }
res = append(res, c)
bol = c == '\n'
} }
return res
return newBuf
} }

View File

@ -1,73 +1,137 @@
package printer package printer
import ( import (
"bytes"
"errors"
"flag"
"fmt" "fmt"
"os" "io/ioutil"
"path/filepath"
"testing" "testing"
"github.com/fatih/hcl/parser" "github.com/fatih/hcl/parser"
) )
var listHCL = `foo = ["fatih", "arslan"]` var update = flag.Bool("update", false, "update golden files")
var listHCL2 = `foo = [
"fatih",
"arslan",
]`
var complexHcl = `// This comes from Terraform, as a test const (
variable "foo" { dataDir = "testdata"
default = "bar" )
description = "bar"
type entry struct {
source, golden string
} }
provider "aws" { // Use go test -update to create/update the respective golden files.
access_key = "foo" var data = []entry{
secret_key = "bar" {"complexhcl.input", "complexhcl.golden"},
} }
provider "do" { func TestFiles(t *testing.T) {
api_key = "${var.foo}" for _, e := range data {
source := filepath.Join(dataDir, e.source)
golden := filepath.Join(dataDir, e.golden)
check(t, source, golden)
}
} }
resource "aws_security_group" "firewall" { func check(t *testing.T, source, golden string) {
count = 5 src, err := ioutil.ReadFile(source)
}
resource aws_instance "web" {
ami = "${var.foo}"
security_groups = [
"foo",
"${aws_security_group.firewall.foo}"
]
network_interface {
device_index = 0
description = "Main network interface"
}
}
resource "aws_instance" "db" {
security_groups = "${aws_security_group.firewall.*.id}"
VPC = "foo"
depends_on = ["aws_instance.web"]
}
output "web_ip" {
value = "${aws_instance.web.private_ip}"
}
`
func TestPrint(t *testing.T) {
node, err := parser.Parse([]byte(complexHcl))
// node, err := parser.Parse([]byte(listHCL2))
if err != nil { if err != nil {
t.Fatal(err)
}
if err := Fprint(os.Stdout, node); err != nil {
t.Error(err) t.Error(err)
return
} }
fmt.Println("") 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
}
// get golden
gld, err := ioutil.ReadFile(golden)
if err != nil {
t.Error(err)
return
}
// formatted source and golden must be the same
if err := diff(source, golden, res, gld); err != nil {
t.Error(err)
return
}
}
// 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
}
// 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)
if err != nil {
return nil, fmt.Errorf("parse: %s\n%s", err, src)
}
var buf bytes.Buffer
if err := Fprint(&buf, node); err != nil {
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)
}
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]
} }

39
printer/testdata/complexhcl.golden vendored Normal file
View File

@ -0,0 +1,39 @@
variable "foo" = {
default = "bar"
description = "bar"
}
provider "aws" = {
access_key = "foo"
secret_key = "bar"
}
provider "do" = {
api_key = "${var.foo}"
}
resource "aws_security_group" "firewall" = {
count = 5
}
resource aws_instance "web" = {
ami = "${var.foo}"
security_groups = [
"foo",
"${aws_security_group.firewall.foo}",
]
network_interface = {
device_index = 0
description = "Main network interface"
}
}
resource "aws_instance" "db" = {
security_groups = "${aws_security_group.firewall.*.id}"
VPC = "foo"
depends_on = [ "aws_instance.web"]
}
output "web_ip" = {
value = "${aws_instance.web.private_ip}"
}

42
printer/testdata/complexhcl.input vendored Normal file
View File

@ -0,0 +1,42 @@
// This comes from Terraform, as a test
variable "foo" {
default = "bar"
description = "bar"
}
provider "aws" {
access_key = "foo"
secret_key = "bar"
}
provider "do" {
api_key = "${var.foo}"
}
resource "aws_security_group" "firewall" {
count = 5
}
resource aws_instance "web" {
ami = "${var.foo}"
security_groups = [
"foo",
"${aws_security_group.firewall.foo}"
]
network_interface {
device_index = 0
description = "Main network interface"
}
}
resource "aws_instance" "db" {
security_groups = "${aws_security_group.firewall.*.id}"
VPC = "foo"
depends_on = ["aws_instance.web"]
}
output "web_ip" {
value = "${aws_instance.web.private_ip}"
}