dati

A Go library/binary to parse & execute data against template langauges.
git clone git://src.gearsix.net/dati
Log | Files | Refs | Atom | README | LICENSE

commit f00fbc8da49516bdd8c37cdfc2b986f9ace64dc6
parent 185a836560218051fe9e2f5b19e71cbc78117f56
Author: gearsix <gearsix@tuta.io>
Date:   Wed, 17 Mar 2021 12:44:48 +0000

big refactor & tidyup

- added go.mod & go.sum files
- big refactors to reduce cyclomatic complexity
- fix to sortFileDataModified
- some linting
- some comment doc
- some gofmt
- fixed some ineffassigns

Diffstat:
Ago.mod | 8++++++++
Ago.sum | 8++++++++
Msrc/data.go | 49++++++++++++++++++++++++++++++-------------------
Msrc/data_test.go | 250+++++++++++++++++++++++++------------------------------------------------------
Msrc/suti.go | 3++-
Msrc/template.go | 72++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/template_test.go | 170++++++++++++++++++++++++++++++++-----------------------------------------------
7 files changed, 240 insertions(+), 320 deletions(-)

diff --git a/go.mod b/go.mod @@ -0,0 +1,8 @@ +module git.gearsix.net/suti + +go 1.16 + +require ( + github.com/pelletier/go-toml v1.8.1 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b +) diff --git a/go.sum b/go.sum @@ -0,0 +1,8 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/data.go b/src/data.go @@ -21,6 +21,20 @@ func getDataType(path string) string { return strings.TrimPrefix(filepath.Ext(path), ".") } +func loadGlobPaths(paths ...string) []string { + for p, path := range paths { + if strings.Contains(path, "*") { + if glob, e := filepath.Glob(path); e == nil { + paths = append(paths, glob...) + paths = append(paths[:p], paths[p+1:]...) + } else { + warn("error parsing glob '%s': %s", path, e) + } + } + } + return paths +} + // LoadData reads all data from `in` and loads it in the format set in `lang`. func LoadData(lang string, in io.Reader) (d Data, e error) { var fbuf []byte @@ -45,14 +59,15 @@ func LoadData(lang string, in io.Reader) (d Data, e error) { // LoadDataFile loads all the data from the file found at `path` into the the // format of that files file extension (e.g. "x.json" will be loaded as a json). -func LoadDataFile(path string) (Data, error) { - if f, e := os.Open(path); e != nil { +func LoadDataFile(path string) (d Data, e error) { + var f *os.File + if f, e = os.Open(path); e != nil { warn("could not load data file '%s' (%s)", path, e) - return nil, e } else { defer f.Close() - return LoadData(getDataType(path), f) + d, e = LoadData(getDataType(path), f) } + return } // LoadDataFiles loads all files in `paths` recursively and sorted them in @@ -64,19 +79,9 @@ func LoadDataFiles(order string, paths ...string) []Data { loaded := make(map[string]Data) - for p, path := range paths { - if strings.Contains(path, "*") { - if glob, e := filepath.Glob(path); e == nil { - paths = append(paths, glob...) - paths = append(paths[:p], paths[p+1:]...) - } else { - warn("error parsing glob '%s': %s", path, err) - } - } - } + paths = loadGlobPaths(paths...) for _, path := range paths { - err = nil stat, err = os.Stat(path) if err == nil { if stat.IsDir() { @@ -86,12 +91,15 @@ func LoadDataFiles(order string, paths ...string) []Data { if d, e = LoadDataFile(p); e == nil { loaded[p] = d } else { - warn("skipping data file '%s': %s", p, e) + warn("skipping data file '%s' (%s)", p, e) e = nil } } return e }) + if err != nil { + warn("error loading files in %s (%s)", path, err) + } } else if d, err = LoadDataFile(path); err == nil { loaded[path] = d } else { @@ -134,7 +142,7 @@ func sortFileData(data map[string]Data, order string) []Data { func sortFileDataFilename(direction string, data map[string]Data) []Data { sorted := make([]Data, 0, len(data)) fnames := make([]string, 0, len(data)) - for fpath, _ := range data { + for fpath := range data { fnames = append(fnames, filepath.Base(fpath)) } sort.Strings(fnames) @@ -162,7 +170,7 @@ func sortFileDataFilename(direction string, data map[string]Data) []Data { func sortFileDataModified(direction string, data map[string]Data) []Data { sorted := make([]Data, 0, len(data)) stats := make(map[string]os.FileInfo) - for fpath, _ := range data { + for fpath := range data { if stat, err := os.Stat(fpath); err != nil { warn("failed to stat %s (%s)", fpath, err) } else { @@ -186,11 +194,14 @@ func sortFileDataModified(direction string, data map[string]Data) []Data { for _, t := range modtimes { for fpath, stat := range stats { - if t == stat.ModTime() { + if stat.ModTime() == t { sorted = append(sorted, data[fpath]) + delete(stats, fpath) + break } } } + return sorted } diff --git a/src/data_test.go b/src/data_test.go @@ -7,215 +7,126 @@ import ( "os" "strings" "testing" + "time" ) -const goodJson = `{"json":0}` -const goodJson2 = `{"json":1}` -const goodYaml = `yaml: 0 -` -const goodToml = `toml = 0 -` -const badData = `{"json"!:2:]}}` +var good = map[string]string{ + "json": `{"json":0}`, + "yaml": `yaml: 0 +`, + "toml": `toml = 0 +`, +} -func writeTestFile(path string, Data string) (e error) { - var f *os.File +const badData = `{"json"!:2:]}}` - if f, e = os.Create(path); e != nil { - return +func writeTestFile(t *testing.T, path string, Data string) { + f, e := os.Create(path) + defer f.Close() + if e != nil { + t.Skipf("setup failure: %s", e) } - if _, e = f.WriteString(Data); e != nil { - return + _, e = f.WriteString(Data) + if e != nil { + t.Skipf("setup failure: %s", e) } - f.Close() return } -func TestLoadData(t *testing.T) { - var d Data - var e error +func validateData(t *testing.T, d Data, e error, lang string) { var b []byte - // json - if d, e = LoadData("json", strings.NewReader(goodJson)); e != nil { + if e != nil { t.Error(e) - } else if len(d) == 0 { + } + if len(d) == 0 { t.Error("no data loaded") - } else { - if b, e = json.Marshal(d); e != nil { - t.Error(e) - } else if string(b) != goodJson { - t.Errorf("incorrect json: %s does not match %s", b, goodJson) - } } - if d, e = LoadData("json", strings.NewReader(badData)); e == nil || len(d) > 0 { - t.Error("bad json passed") + + switch lang { + case "json": + b, e = json.Marshal(d) + case "yaml": + b, e = yaml.Marshal(d) + case "toml": + b, e = toml.Marshal(d) } - // yaml - if d, e = LoadData("yaml", strings.NewReader(goodYaml)); e != nil { + if e != nil { t.Error(e) - } else if len(d) == 0 { - t.Error("no data loaded") - } else { - if b, e = yaml.Marshal(d); e != nil { - t.Error(e) - } else if string(b) != goodYaml { - t.Errorf("incorrect yaml: %s does not match %s", b, goodYaml) - } } - if d, e = LoadData("yaml", strings.NewReader(badData)); e == nil || len(d) > 0 { - t.Error("bad yaml passed") + if string(b) != good[lang] { + t.Errorf("incorrect %s: %s does not match %s", lang, b, good[lang]) } +} - // toml - if d, e = LoadData("toml", strings.NewReader(goodToml)); e != nil { - t.Error(e) - } else if len(d) == 0 { - t.Error("no data loaded") - } else { - if b, e = toml.Marshal(d); e != nil { - t.Error(e) - } else if string(b) != goodToml { - t.Errorf("incorrect toml: %s does not match %s", b, goodToml) +func TestLoadData(t *testing.T) { + var d Data + var e error + + for lang, data := range good { + d, e = LoadData(lang, strings.NewReader(data)) + validateData(t, d, e, lang) + + if d, e = LoadData(lang, strings.NewReader(badData)); e == nil || len(d) > 0 { + t.Errorf("bad %s passed", lang) } - } - if d, e = LoadData("toml", strings.NewReader(badData)); e == nil || len(d) > 0 { - t.Error("bad toml passed") - } - // misc - if d, e = LoadData("json", strings.NewReader("")); e != nil { - t.Errorf("empty file failed for json: %s, %s", d, e) - } - if d, e = LoadData("yaml", strings.NewReader("")); e != nil { - t.Errorf("empty file failed for yaml: %s, %s", d, e) - } - if d, e = LoadData("toml", strings.NewReader("")); e != nil { - t.Errorf("empty file failed toml: %s, %s", d, e) + if d, e = LoadData(lang, strings.NewReader("")); e != nil { + t.Errorf("empty file failed for json: %s, %s", d, e) + } } - if d, e = LoadData("ebrgji", strings.NewReader(goodJson)); e == nil || len(d) > 0 { + + if d, e = LoadData("invalid", strings.NewReader("shouldn't pass")); e == nil || len(d) > 0 { t.Errorf("invalid data language passed: %s, %s", d, e) } return } +func validateFileData(t *testing.T, d []Data, dlen int, orderedLangs ...string) { + if dlen != len(orderedLangs) { + t.Errorf("invalid orderedLangs length (%d should be %d)", len(orderedLangs), dlen) + } + + if len(d) != dlen { + t.Errorf("invalid data length (%d should be %d)", len(d), dlen) + } + + for i, lang := range orderedLangs { + validateData(t, d[i], nil, lang) + } +} + func TestLoadDataFiles(t *testing.T) { - var e error var p []string - var b []byte var d []Data tdir := t.TempDir() - p = append(p, tdir+"/good.json") - if e = writeTestFile(p[len(p)-1], goodJson); e != nil { - t.Skip("setup failure:", e) - } p = append(p, tdir+"/1.yaml") - if e = writeTestFile(p[len(p)-1], goodYaml); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, p[len(p)-1], good["yaml"]) + time.Sleep(100 * time.Millisecond) + p = append(p, tdir+"/good.json") + writeTestFile(t, p[len(p)-1], good["json"]) + time.Sleep(100 * time.Millisecond) p = append(p, tdir+"/good.toml") - if e = writeTestFile(p[len(p)-1], goodToml); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, p[len(p)-1], good["toml"]) + time.Sleep(100 * time.Millisecond) p = append(p, tdir+"/bad.json") - if e = writeTestFile(p[len(p)-1], badData); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, p[len(p)-1], badData) d = LoadDataFiles("filename", tdir) - if len(d) == len(p) { - t.Error("bad.json passed") - } else if len(d) == 0 { - t.Error("no data loaded") - } else { - if b, e = yaml.Marshal(d[0]); e != nil { - t.Error(e) - } else if string(b) != goodYaml { - t.Error("data returned out of order") - } - if b, e = json.Marshal(d[1]); e != nil { - t.Error(e) - } else if string(b) != goodJson { - t.Error("data returned out of order") - } - if b, e = toml.Marshal(d[2]); e != nil { - t.Error(e) - } else if string(b) != goodToml { - t.Error("data returned out of order") - } - } + validateFileData(t, d, len(p)-1, "yaml", "json", "toml") d = LoadDataFiles("filename-desc", tdir+"/*") - if len(d) == len(p) { - t.Error("bad.json passed") - } else if len(d) == 0 { - t.Error("no data loaded") - } else { - if b, e = toml.Marshal(d[0]); e != nil { - t.Error(e) - } else if string(b) != goodToml { - t.Error("data returned out of order") - } - if b, e = json.Marshal(d[1]); e != nil { - t.Error(e) - } else if string(b) != goodJson { - t.Error("data returned out of order") - } - if b, e = yaml.Marshal(d[2]); e != nil { - t.Error(e) - } else if string(b) != goodYaml { - t.Error("data returned out of order") - } - } + validateFileData(t, d, len(p)-1, "toml", "json", "yaml") d = LoadDataFiles("modified", p...) - if len(d) == len(p) { - t.Error("bad.json passed") - } else if len(d) == 0 { - t.Error("no data loaded") - } else { - if b, e = json.Marshal(d[0]); e != nil { - t.Error(e) - } else if string(b) != goodJson { - t.Error("data returned out of order") - } - if b, e = yaml.Marshal(d[1]); e != nil { - t.Error(e) - } else if string(b) != goodYaml { - t.Error("data returned out of order") - } - if b, e = toml.Marshal(d[2]); e != nil { - t.Error(e) - } else if string(b) != goodToml { - t.Error("data returned out of order") - } - } + validateFileData(t, d, len(p)-1, "yaml", "json", "toml") d = LoadDataFiles("modified-desc", p...) - if len(d) == len(p) { - t.Error("bad.json passed") - } else if len(d) == 0 { - t.Error("no data loaded") - } else { - if b, e = toml.Marshal(d[0]); e != nil { - t.Error(e) - } else if string(b) != goodToml { - t.Error("data returned out of order") - } - if b, e = yaml.Marshal(d[1]); e != nil { - t.Error(e) - } else if string(b) != goodYaml { - t.Error("data returned out of order") - } - if b, e = json.Marshal(d[2]); e != nil { - t.Error(e) - } else if string(b) != goodJson { - t.Error("data returned out of order") - } - } + validateFileData(t, d, len(p)-1, "toml", "json", "yaml") } func TestGenerateSuperData(t *testing.T) { @@ -225,17 +136,17 @@ func TestGenerateSuperData(t *testing.T) { var d []Data var sd Data - if data, e = LoadData("json", strings.NewReader(goodJson)); e == nil { + if data, e = LoadData("json", strings.NewReader(good["json"])); e == nil { gd = append(gd, data) } else { t.Skip("setup failure:", e) } - if data, e = LoadData("json", strings.NewReader(goodJson)); e == nil { + if data, e = LoadData("json", strings.NewReader(good["json"])); e == nil { // test duplicate gd = append(gd, data) } else { t.Skip("setup failure:", e) } - if data, e = LoadData("yaml", strings.NewReader(goodYaml)); e == nil { + if data, e = LoadData("yaml", strings.NewReader(good["yaml"])); e == nil { d = append(d, data) } else { t.Skip("setup failure:", e) @@ -260,23 +171,22 @@ func TestMergeData(t *testing.T) { var d []Data var m Data - if m, e = LoadData("json", strings.NewReader(goodJson)); e == nil { + if m, e = LoadData("json", strings.NewReader(good["json"])); e == nil { d = append(d, m) } else { t.Skip("setup failure:", e) } - if m, e = LoadData("json", strings.NewReader(goodJson2)); e == nil { + if m, e = LoadData("json", strings.NewReader(good["json"])); e == nil { d = append(d, m) } else { t.Skip("setup failure:", e) } - if m, e = LoadData("yaml", strings.NewReader(goodYaml)); e == nil { + if m, e = LoadData("yaml", strings.NewReader(good["yaml"])); e == nil { d = append(d, m) } else { t.Skip("setup failure:", e) } - m = nil m = MergeData(d...) if m["json"] == nil || m["yaml"] == nil { t.Error("missing global keys") diff --git a/src/suti.go b/src/suti.go @@ -7,6 +7,8 @@ import ( "strings" ) +// Options provides all the different variables that need to be set by the +// user calling suti. type Options struct { RootPath string PartialPaths []string @@ -21,7 +23,6 @@ var options Options func warn(msg string, args ...interface{}) { fmt.Println("WARNING", strings.TrimSuffix(fmt.Sprintf(msg, args...), "\n")) - return } func init() { diff --git a/src/template.go b/src/template.go @@ -11,12 +11,52 @@ import ( tmpl "text/template" ) +// Template is a generic interace container for any template type type Template interface{} func getTemplateType(path string) string { return strings.TrimPrefix(filepath.Ext(path), ".") } +func loadTemplateFileTmpl(root string, partials ...string) (t Template, e error) { + var gotmpl *tmpl.Template + if gotmpl, e = tmpl.ParseFiles(root); e == nil { + for _, p := range partials { + ptype := getTemplateType(p) + if ptype == "tmpl" || ptype == "gotmpl" { + if gotmpl, e = gotmpl.ParseFiles(p); e != nil { + warn("failed to parse partial '%s': %s", p, e) + } + } else { + warn("skipping partial '%s': non-matching filetype", p) + } + } + t = gotmpl + } + return +} + +func loadTemplateFileHmpl(root string, partials ...string) (t Template, e error) { + var gohmpl *hmpl.Template + if gohmpl, e = hmpl.ParseFiles(root); e == nil { + for _, p := range partials { + ptype := getTemplateType(p) + if ptype == "hmpl" || ptype == "gohmpl" { + if gohmpl, e = gohmpl.ParseFiles(p); e != nil { + warn("failed to parse partial '%s': %s", p, e) + } + } else { + warn("skipping partial '%s': non-matching filetype", p) + } + } + t = gohmpl + } + return +} + +// LoadTemplateFile loads a Template from file `root`. All files in `partials` +// that have the same template type (identified by file extension) are also +// parsed and associated with the parsed root template. func LoadTemplateFile(root string, partials ...string) (t Template, e error) { if len(root) == 0 { return nil, fmt.Errorf("no root tempslate specified") @@ -30,41 +70,17 @@ func LoadTemplateFile(root string, partials ...string) (t Template, e error) { ttype := getTemplateType(root) if ttype == "tmpl" || ttype == "gotmpl" { - var gotmpl *tmpl.Template - if gotmpl, e = tmpl.ParseFiles(root); e == nil { - for _, p := range partials { - ptype := getTemplateType(p) - if ptype == "tmpl" || ptype == "gotmpl" { - if gotmpl, e = gotmpl.ParseFiles(p); e != nil { - warn("failed to parse partial '%s': %s", p, e) - } - } else { - warn("skipping partial '%s': non-matching filetype", p) - } - } - t = gotmpl - } + t, e = loadTemplateFileTmpl(root, partials...) } else if ttype == "hmpl" || ttype == "gohmpl" { - var gohmpl *hmpl.Template - if gohmpl, e = hmpl.ParseFiles(root); e == nil { - for _, p := range partials { - ptype := getTemplateType(p) - if ptype == "hmpl" || ptype == "gohmpl" { - if gohmpl, e = gohmpl.ParseFiles(p); e != nil { - warn("failed to parse partial '%s': %s", p, e) - } - } else { - warn("skipping partial '%s': non-matching filetype", p) - } - } - t = gohmpl - } + t, e = loadTemplateFileHmpl(root, partials...) } else { e = fmt.Errorf("'%s' is not a supported template language", ttype) } return } +// ExecuteTemplate executes `t` against `d`. Reflection is used to determine +// the template type and call it's execution fuction. func ExecuteTemplate(t Template, d Data) (result bytes.Buffer, err error) { tv := reflect.ValueOf(t) tt := reflect.TypeOf(t) diff --git a/src/template_test.go b/src/template_test.go @@ -20,95 +20,63 @@ const hmplResult = "<!DOCTYPE html><html><p>root <b>partial</b></p></html>" const hmplRootBad = "{{ example }} {{{ template \"partial\" . }}" const hmplPartialBad = "<b>{{{ .example2 }}</b>" +func validateTemplateFile(t *testing.T, template Template, root string, partials ...string) { + types := map[string]string{ + "tmpl": "*template.Template", + "gotmpl": "*template.Template", + "hmpl": "*template.Template", + "gohmpl": "*template.Template", + } + if reflect.TypeOf(template).String() != types[getTemplateType(root)] { + t.Error("invalid template loaded") + } + + var rv []reflect.Value + for _, p := range partials { + p = filepath.Base(p) + rv := reflect.ValueOf(template).MethodByName("Lookup").Call([]reflect.Value{ + reflect.ValueOf(p), + }) + if rv[0].IsNil() { + t.Errorf("missing defined template '%s'", p) + rv = reflect.ValueOf(template).MethodByName("DefinedTemplates").Call([]reflect.Value{}) + t.Log(rv) + } + } + rv = reflect.ValueOf(template).MethodByName("Name").Call([]reflect.Value{}) + if rv[0].String() != filepath.Base(root) { + t.Errorf("invalid template name: %s does not match %s", + rv[0].String(), filepath.Base(root)) + } +} + func TestLoadTemplateFile(t *testing.T) { - var e error var gr, gp, br, bp []string tdir := t.TempDir() gr = append(gr, tdir+"/goodRoot.tmpl") - if e = writeTestFile(gr[0], tmplRootGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, gr[0], tmplRootGood) gp = append(gp, tdir+"/goodPartial.gotmpl") - if e = writeTestFile(gp[0], tmplPartialGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, gp[0], tmplPartialGood) br = append(br, tdir+"/badRoot.tmpl") - if e = writeTestFile(br[0], tmplRootBad); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, br[0], tmplRootBad) bp = append(bp, tdir+"/badPartial.gotmpl") - if e = writeTestFile(bp[0], tmplPartialBad); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, bp[0], tmplPartialBad) gr = append(gr, tdir+"/goodRoot.hmpl") - if e = writeTestFile(gr[1], hmplRootGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, gr[1], hmplRootGood) gp = append(gp, tdir+"/goodPartial.gohmpl") - if e = writeTestFile(gp[1], hmplPartialGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, gp[1], hmplPartialGood) br = append(br, tdir+"/badRoot.hmpl") - if e = writeTestFile(br[1], hmplRootBad); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, br[1], hmplRootBad) bp = append(bp, tdir+"/badPartial.gohmpl") - if e = writeTestFile(bp[1], hmplPartialBad); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, bp[1], hmplPartialBad) - for _, root := range gr { // good root, good partials - if template, e := LoadTemplateFile(root, gp...); e != nil { + for g, root := range gr { // good root, good partials + if template, e := LoadTemplateFile(root, gp[g]); e != nil { t.Error(e) } else { - ttype := getTemplateType(root) - if ttype == "tmpl" || ttype == "gotmpl" { - ttype = reflect.TypeOf(template).String() - if ttype != "*template.Template" { - t.Errorf("invalid tempate type parsed: %s should be *template.Template", ttype) - } - rv := reflect.ValueOf(template).MethodByName("Lookup").Call([]reflect.Value{ - reflect.ValueOf("goodRoot.tmpl"), - }) - if rv[0].IsNil() { - t.Error("missing defined templates") - } - rv = reflect.ValueOf(template).MethodByName("Lookup").Call([]reflect.Value{ - reflect.ValueOf("goodPartial.gotmpl"), - }) - if rv[0].IsNil() { - t.Error("missing defined templates") - } - rv = reflect.ValueOf(template).MethodByName("Name").Call([]reflect.Value{}) - if rv[0].String() != filepath.Base(root) { - t.Errorf("invalid template name: %s does not match %s", rv[0].String(), filepath.Base(root)) - } - } else if ttype == "hmpl" || ttype == "gohmpl" { - ttype = reflect.TypeOf(template).String() - if ttype != "*template.Template" { - t.Errorf("invalid tempate type parsed: %s should be *template.Template", ttype) - } - rv := reflect.ValueOf(template).MethodByName("Lookup").Call([]reflect.Value{ - reflect.ValueOf("goodRoot.hmpl"), - }) - if rv[0].IsNil() { - t.Error("missing defined templates") - } - rv = reflect.ValueOf(template).MethodByName("Lookup").Call([]reflect.Value{ - reflect.ValueOf("goodPartial.gohmpl"), - }) - if rv[0].IsNil() { - t.Error("missing defined templates") - } - rv = reflect.ValueOf(template).MethodByName("Name").Call([]reflect.Value{}) - if rv[0].String() != filepath.Base(root) { - t.Errorf("invalid template name: %s does not match %s", rv[0].String(), filepath.Base(root)) - } - } else { - t.Errorf("test broken: invalid template type written (%s)", root) - } + validateTemplateFile(t, template, root, gp[g]) } } for _, root := range gr { // good root, bad partials @@ -128,44 +96,47 @@ func TestLoadTemplateFile(t *testing.T) { } } +func validateExecuteTemplate(t *testing.T, results string, expect string, e error) { + if e != nil { + t.Error(e) + } + if results != expect { + t.Errorf("invalid results: %s should match %s", results, expect) + } +} + func TestExecuteTemplate(t *testing.T) { var e error - var sd, gd, d Data + var sd, data Data + var gd, d []Data var tmplr, tmplp, hmplr, hmplp string var tmpl, hmpl Template var results bytes.Buffer tdir := t.TempDir() tmplr = tdir + "/tmplRootGood.gotmpl" - if e = writeTestFile(tmplr, tmplRootGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, tmplr, tmplRootGood) tmplp = tdir + "/tmplPartialGood.tmpl" - if e = writeTestFile(tmplp, tmplPartialGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, tmplp, tmplPartialGood) hmplr = tdir + "/hmplRootGood.gohmpl" - if e = writeTestFile(hmplr, hmplRootGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, hmplr, hmplRootGood) hmplp = tdir + "/hmplPartialGood.hmpl" - if e = writeTestFile(hmplp, hmplPartialGood); e != nil { - t.Skip("setup failure:", e) - } + writeTestFile(t, hmplp, hmplPartialGood) - if gd, e = LoadData("json", strings.NewReader(goodJson)); e != nil { + if data, e = LoadData("json", strings.NewReader(good["json"])); e != nil { t.Skip("setup failure:", e) } - if d, e = LoadData("yaml", strings.NewReader(goodYaml)); e != nil { + gd = append(gd, data) + if data, e = LoadData("yaml", strings.NewReader(good["yaml"])); e != nil { t.Skip("setup failure:", e) } - if d, e = LoadData("toml", strings.NewReader(goodToml)); e != nil { + d = append(d, data) + if data, e = LoadData("toml", strings.NewReader(good["toml"])); e != nil { t.Skip("setup failure:", e) } + d = append(d, data) - data := make([]Data, 1) - data = append(data, d) - sd = GenerateSuperData("", data, gd) + sd = GenerateSuperData("", d, gd...) if tmpl, e = LoadTemplateFile(tmplr, tmplp); e != nil { t.Skip("setup failure:", e) } @@ -173,14 +144,9 @@ func TestExecuteTemplate(t *testing.T) { t.Skip("setup failure:", e) } - if results, e = ExecuteTemplate(tmpl, sd); e != nil { - t.Error(e) - } else if results.String() != tmplResult { - t.Errorf("invalid results: %s should match %s", results.String(), tmplResult) - } - if results, e = ExecuteTemplate(hmpl, sd); e != nil { - t.Error(e) - } else if results.String() != hmplResult { - t.Errorf("invalid results: %s should match %s", results.String(), hmplResult) - } + results, e = ExecuteTemplate(tmpl, sd) + validateExecuteTemplate(t, results.String(), tmplResult, e) + + results, e = ExecuteTemplate(hmpl, sd) + validateExecuteTemplate(t, results.String(), hmplResult, e) }