package hatmill_test import ( "bytes" h "gitlab.codemonkeysoftware.net/b/hatmill" he "gitlab.codemonkeysoftware.net/b/hatmill/element" "html/template" "io" "testing" ) type benchPerson struct { Name string FavoriteAnimals []string } type benchModel struct { Title string Persons []benchPerson } var benchData = benchModel{ Title: "People I know", Persons: []benchPerson{ {Name: "Malter Witty", FavoriteAnimals: []string{"porpoise"}}, {Name: "Perry Moppins", FavoriteAnimals: []string{"penguin"}}, {Name: "Ralbus Fumblemore", FavoriteAnimals: []string{"owl", "cat", "toad"}}, {Name: "Wuce Brayne", FavoriteAnimals: []string{"bat", "robin"}}, }, } type testingT interface { Helper() Error(args ...interface{}) } func checkError(t testingT, err error) { t.Helper() if err != nil { t.Error(err) } } func stdHtmlTemplate(t testingT) func(testingT, io.Writer, benchModel) { // hatmill does not pretty-print its output, so neither must we here. const tpl = `{{.Title}}` + `{{range .Persons}}

{{.Name}}

` + `` + `
{{end}}` compiled, err := template.New("page").Parse(tpl) checkError(t, err) return func(t testingT, w io.Writer, model benchModel) { checkError(t, compiled.Execute(w, model)) } } func hatmillTemplate(t testingT, w io.Writer, model benchModel) { var personHtml h.Terms for _, p := range model.Persons { var animalHtml h.Terms for _, a := range p.FavoriteAnimals { animalHtml = append(animalHtml, he.Li()(h.Text(a))) } personHtml = append(personHtml, he.Div()( he.H1()(h.Text(p.Name)), he.Ul()(animalHtml), )) } html := he.Html()( he.Head()( he.Title()(h.Text(model.Title)), ), he.Body()(personHtml), ) _, err := h.WriteDocument(w, html) checkError(t, err) } func TestBenchmarkEquivalence(t *testing.T) { var stdHtmlOutput bytes.Buffer stdHtmlTemplate(t)(t, &stdHtmlOutput, benchData) var hatmillOutput bytes.Buffer hatmillTemplate(t, &hatmillOutput, benchData) if stdHtmlOutput.String() != hatmillOutput.String() { t.Fatalf("Output does not match\nhtml/template: %s\nhatmill: %s", &stdHtmlOutput, &hatmillOutput) } } func doBenchmark(b *testing.B, tpl func(testingT, io.Writer, benchModel)) { var buf bytes.Buffer for i := 0; i < b.N; i++ { buf.Reset() tpl(b, &buf, benchData) } } func BenchmarkStdHtmlTemplate(b *testing.B) { doBenchmark(b, stdHtmlTemplate(b)) } func BenchmarkHatmill(b *testing.B) { doBenchmark(b, hatmillTemplate) }