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 }