106 lines
2.5 KiB
Go
106 lines
2.5 KiB
Go
package hatmill_test
|
|
|
|
import (
|
|
"bytes"
|
|
"html/template"
|
|
"io"
|
|
"testing"
|
|
|
|
h "git.codemonkeysoftware.net/b/hatmill"
|
|
he "git.codemonkeysoftware.net/b/hatmill/element"
|
|
)
|
|
|
|
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 = `<!DOCTYPE html><html><head><title>{{.Title}}</title></head>` +
|
|
`<body>{{range .Persons}}<div><h1>{{.Name}}</h1>` +
|
|
`<ul>{{range .FavoriteAnimals}}<li>{{ . }}</li>{{end}}</ul>` +
|
|
`</div>{{end}}</body></html>`
|
|
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)
|
|
}
|