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 185a836560218051fe9e2f5b19e71cbc78117f56
parent e428190321cfca618139c6ec5c10ab935deb1c21
Author: gearsix <gearsix@tuta.io>
Date:   Mon, 15 Mar 2021 15:52:43 +0000

added result validation to template_test.go; bugfixes in template.go

Diffstat:
Msrc/data_test.go | 4++--
Msrc/template.go | 10+++++++---
Msrc/template_test.go | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 98 insertions(+), 17 deletions(-)

diff --git a/src/data_test.go b/src/data_test.go @@ -83,7 +83,7 @@ func TestLoadData(t *testing.T) { 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) @@ -97,7 +97,7 @@ func TestLoadData(t *testing.T) { if d, e = LoadData("ebrgji", strings.NewReader(goodJson)); e == nil || len(d) > 0 { t.Errorf("invalid data language passed: %s, %s", d, e) } - + return } diff --git a/src/template.go b/src/template.go @@ -21,7 +21,7 @@ func LoadTemplateFile(root string, partials ...string) (t Template, e error) { if len(root) == 0 { return nil, fmt.Errorf("no root tempslate specified") } - + if stat, err := os.Stat(root); err != nil { return nil, err } else if stat.IsDir() { @@ -38,6 +38,8 @@ func LoadTemplateFile(root string, partials ...string) (t Template, e error) { 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 @@ -47,10 +49,12 @@ func LoadTemplateFile(root string, partials ...string) (t Template, e error) { if gohmpl, e = hmpl.ParseFiles(root); e == nil { for _, p := range partials { ptype := getTemplateType(p) - if ptype == "tmpl" || ptype == "gotmpl" { + 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 @@ -64,7 +68,7 @@ func LoadTemplateFile(root string, partials ...string) (t Template, e error) { func ExecuteTemplate(t Template, d Data) (result bytes.Buffer, err error) { tv := reflect.ValueOf(t) tt := reflect.TypeOf(t) - + if tt.String() == "*template.Template" { // tmpl or hmpl rval := tv.MethodByName("Execute").Call([]reflect.Value{ reflect.ValueOf(&result), reflect.ValueOf(&d), diff --git a/src/template_test.go b/src/template_test.go @@ -2,18 +2,22 @@ package main import ( "bytes" + "path/filepath" + "reflect" "strings" "testing" ) -const tmplRootGood = "{{ .example1 }} {{ template \"tmplPartialGood\" . }}" -const tmplPartialGood = "{{range .data}} .example2 {{ end }}" -const tmplRootBad = "{{ example1 }} {{{ template \"partial\" . }}" +const tmplRootGood = "root {{ template \"tmplPartialGood.tmpl\" . }}" +const tmplPartialGood = "partial" +const tmplResult = "root partial" +const tmplRootBad = "{{ example }}} {{{ template \"partial\" . }}" const tmplPartialBad = "{{{ .example }}" -const hmplRootGood = "<!DOCTYPE html><html>{{ .example1 }} {{ template \"hmplPartialGood\" . }}</html>" -const hmplPartialGood = "{{range .data}}<b>.example2</b>{{ end }}" -const hmplRootBad = "{{ example1 }} {{{ template \"partial\" . }}" +const hmplRootGood = "<!DOCTYPE html><html><p>root {{ template \"hmplPartialGood.hmpl\" . }}</p></html>" +const hmplPartialGood = "<b>partial</b>" +const hmplResult = "<!DOCTYPE html><html><p>root <b>partial</b></p></html>" +const hmplRootBad = "{{ example }} {{{ template \"partial\" . }}" const hmplPartialBad = "<b>{{{ .example2 }}</b>" func TestLoadTemplateFile(t *testing.T) { @@ -56,8 +60,55 @@ func TestLoadTemplateFile(t *testing.T) { } for _, root := range gr { // good root, good partials - if _, e := LoadTemplateFile(root, gp...); e != nil { + if template, e := LoadTemplateFile(root, gp...); 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) + } } } for _, root := range gr { // good root, bad partials @@ -80,30 +131,56 @@ func TestLoadTemplateFile(t *testing.T) { func TestExecuteTemplate(t *testing.T) { var e error var sd, gd, d Data + var tmplr, tmplp, hmplr, hmplp string var tmpl, hmpl Template var results bytes.Buffer + tdir := t.TempDir() - if gd, e = LoadData("json", strings.NewReader(goodJson1)); e != nil { + tmplr = tdir + "/tmplRootGood.gotmpl" + if e = writeTestFile(tmplr, tmplRootGood); e != nil { + t.Skip("setup failure:", e) + } + tmplp = tdir + "/tmplPartialGood.tmpl" + if e = writeTestFile(tmplp, tmplPartialGood); e != nil { t.Skip("setup failure:", e) } - if d, e = LoadData("json", strings.NewReader(goodJson2)); e != nil { + hmplr = tdir + "/hmplRootGood.gohmpl" + if e = writeTestFile(hmplr, hmplRootGood); e != nil { t.Skip("setup failure:", e) } + hmplp = tdir + "/hmplPartialGood.hmpl" + if e = writeTestFile(hmplp, hmplPartialGood); e != nil { + t.Skip("setup failure:", e) + } + + if gd, e = LoadData("json", strings.NewReader(goodJson)); e != nil { + t.Skip("setup failure:", e) + } + if d, e = LoadData("yaml", strings.NewReader(goodYaml)); e != nil { + t.Skip("setup failure:", e) + } + if d, e = LoadData("toml", strings.NewReader(goodToml)); e != nil { + t.Skip("setup failure:", e) + } + data := make([]Data, 1) data = append(data, d) sd = GenerateSuperData("", data, gd) - if tmpl, e = LoadTemplateFile(tmplRootGood, tmplPartialGood); e != nil { + if tmpl, e = LoadTemplateFile(tmplr, tmplp); e != nil { t.Skip("setup failure:", e) } - if hmpl, e = LoadTemplateFile(hmplRootGood, hmplPartialGood); e != nil { + if hmpl, e = LoadTemplateFile(hmplr, hmplp); e != nil { 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) } - t.Log(results) }