github.com/dahs81/otto@v0.2.1-0.20160126165905-6400716cf085/appfile/file_hcl_test.go (about)

     1  package appfile
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"flag"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/hcl/hcl/printer"
    13  )
    14  
    15  var update = flag.Bool("update", false, "update golden files")
    16  
    17  func TestFileHCL(t *testing.T) {
    18  	cases := []struct {
    19  		Input, Output string
    20  	}{
    21  		{"basic.hcl", "basic.golden"},
    22  	}
    23  
    24  	for _, tc := range cases {
    25  		source, _ := filepath.Abs(filepath.Join("./test-fixtures", tc.Input))
    26  		output, _ := filepath.Abs(filepath.Join("./test-fixtures", tc.Output))
    27  		check(t, source, output, *update)
    28  	}
    29  }
    30  
    31  func check(t *testing.T, source, golden string, update bool) {
    32  	actual, err := ParseFile(source)
    33  	if err != nil {
    34  		t.Error(err)
    35  		return
    36  	}
    37  
    38  	res, err := format(actual)
    39  	if err != nil {
    40  		t.Error(err)
    41  		return
    42  	}
    43  
    44  	// update golden files if necessary
    45  	if update {
    46  		if err := ioutil.WriteFile(golden, res, 0644); err != nil {
    47  			t.Error(err)
    48  		}
    49  		return
    50  	}
    51  
    52  	// get golden
    53  	gld, err := ioutil.ReadFile(golden)
    54  	if err != nil {
    55  		t.Error(err)
    56  		return
    57  	}
    58  
    59  	// formatted source and golden must be the same
    60  	if err := diff(source, golden, res, gld); err != nil {
    61  		t.Error(err)
    62  		return
    63  	}
    64  }
    65  
    66  // diff compares a and b.
    67  func diff(aname, bname string, a, b []byte) error {
    68  	var buf bytes.Buffer // holding long error message
    69  
    70  	// compare lengths
    71  	if len(a) != len(b) {
    72  		fmt.Fprintf(&buf, "\nlength changed: len(%s) = %d, len(%s) = %d", aname, len(a), bname, len(b))
    73  	}
    74  
    75  	// compare contents
    76  	line := 1
    77  	offs := 1
    78  	for i := 0; i < len(a) && i < len(b); i++ {
    79  		ch := a[i]
    80  		if ch != b[i] {
    81  			fmt.Fprintf(&buf, "\n%s:%d:%d: %s", aname, line, i-offs+1, lineAt(a, offs))
    82  			fmt.Fprintf(&buf, "\n%s:%d:%d: %s", bname, line, i-offs+1, lineAt(b, offs))
    83  			fmt.Fprintf(&buf, "\n\n")
    84  			break
    85  		}
    86  		if ch == '\n' {
    87  			line++
    88  			offs = i + 1
    89  		}
    90  	}
    91  
    92  	if buf.Len() > 0 {
    93  		return errors.New(buf.String())
    94  	}
    95  	return nil
    96  }
    97  
    98  // format parses src, prints the corresponding AST, verifies the resulting
    99  // src is syntactically correct, and returns the resulting src or an error
   100  // if any.
   101  func format(f *File) ([]byte, error) {
   102  	var buf bytes.Buffer
   103  	if err := printer.Fprint(&buf, f.HCL()); err != nil {
   104  		return nil, fmt.Errorf("print: %s", err)
   105  	}
   106  
   107  	// make sure formatted output is syntactically correct
   108  	res := buf.Bytes()
   109  	/*
   110  		if _, err := Parse(bytes.NewReader(res)); err != nil {
   111  			return nil, fmt.Errorf("parse: %s\n%s", err, f.Path)
   112  		}
   113  	*/
   114  
   115  	return res, nil
   116  }
   117  
   118  // lineAt returns the line in text starting at offset offs.
   119  func lineAt(text []byte, offs int) []byte {
   120  	i := offs
   121  	for i < len(text) && text[i] != '\n' {
   122  		i++
   123  	}
   124  	return text[offs:i]
   125  }