1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
package tfjson
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"path/filepath"
"reflect"
"strings"
"testing"
)
const testFixtureDir = "testdata"
const testGoldenPlanFileName = "plan.json"
const testGoldenSchemasFileName = "schemas.json"
func testParse(t *testing.T, filename string, typ reflect.Type) {
entries, err := ioutil.ReadDir(testFixtureDir)
if err != nil {
t.Fatalf("err: %s", err)
}
for _, e := range entries {
if !e.IsDir() {
continue
}
t.Run(e.Name(), func(t *testing.T) {
expected, err := ioutil.ReadFile(filepath.Join(testFixtureDir, e.Name(), filename))
if err != nil {
t.Fatal(err)
}
parsed := reflect.New(typ).Interface()
dec := json.NewDecoder(bytes.NewBuffer(expected))
dec.DisallowUnknownFields()
if err = dec.Decode(parsed); err != nil {
t.Fatal(err)
}
actual, err := json.Marshal(parsed)
if err != nil {
t.Fatal(err)
}
// Add a newline at the end
actual = append(actual, byte('\n'))
if err := testDiff(actual, expected); err != nil {
t.Fatal(err)
}
})
}
}
func TestParsePlan(t *testing.T) {
testParse(t, testGoldenPlanFileName, reflect.TypeOf(Plan{}))
}
func TestParseSchemas(t *testing.T) {
testParse(t, testGoldenSchemasFileName, reflect.TypeOf(ProviderSchemas{}))
}
func testDiff(out, gld []byte) error {
var b strings.Builder // holding long error message
// compare lengths
if len(out) != len(gld) {
fmt.Fprintf(&b, "\nlength changed: len(output) = %d, len(golden) = %d", len(out), len(gld))
}
// compare contents
line := 1
offs := 1
for i := 0; i < len(out) && i < len(gld); i++ {
ch := out[i]
if ch != gld[i] {
fmt.Fprintf(&b, "\noutput:%d:%d: %s", line, i-offs+1, lineAt(out, offs))
fmt.Fprintf(&b, "\ngolden:%d:%d: %s", line, i-offs+1, lineAt(gld, offs))
fmt.Fprintf(&b, "\n\n")
break
}
if ch == '\n' {
line++
offs = i + 1
}
}
if b.Len() > 0 {
return errors.New(b.String())
}
return nil
}
func lineAt(text []byte, offs int) []byte {
i := offs
for i < len(text) && text[i] != '\n' {
i++
}
return text[offs:i]
}
|