blob: 04b64355de3d3a28e6a07ab3a8c46e06318ea2ca [file] [log] [blame]
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"io/ioutil"
"net/http/httptest"
"os"
"path"
"path/filepath"
"regexp"
"testing"
"time"
"rsc.io/rf/diff"
)
func TestGolden(t *testing.T) {
start := time.Now()
h, err := NewHandler("../../_content")
if err != nil {
t.Fatal(err)
}
total := time.Since(start)
t.Logf("Load %v\n", total)
root := "../../testdata/golden"
err = filepath.Walk(root, func(name string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
name = filepath.ToSlash(name[len(root)+1:])
switch name {
case "index.xml",
"categories/index.html",
"categories/index.xml",
"learn/index.xml",
"series/index.html",
"series/index.xml",
"series/case-studies/index.html",
"series/case-studies/index.xml",
"series/use-cases/index.html",
"series/use-cases/index.xml",
"sitemap.xml",
"solutions/google/index.xml",
"solutions/index.xml",
"tags/index.html",
"tags/index.xml":
t.Logf("%s <- SKIP\n", name)
return nil
}
want, err := ioutil.ReadFile(filepath.Join(root, name))
if err != nil {
t.Fatal(err)
}
start := time.Now()
r := httptest.NewRequest("GET", "/"+name, nil)
resp := httptest.NewRecorder()
resp.Body = new(bytes.Buffer)
h.ServeHTTP(resp, r)
for nredir := 0; resp.Code/10 == 30; nredir++ {
if nredir > 10 {
t.Fatalf("%s <- redirect loop!", name)
}
r.URL.Path = resp.Result().Header.Get("Location")
resp = httptest.NewRecorder()
resp.Body = new(bytes.Buffer)
h.ServeHTTP(resp, r)
}
if resp.Code != 200 {
t.Fatalf("GET %s <- %d, want 200", r.URL, resp.Code)
}
have := resp.Body.Bytes()
total += time.Since(start)
if path.Ext(name) == ".html" {
have = canonicalize(have)
want = canonicalize(want)
if !bytes.Equal(have, want) {
d, err := diff.Diff("hugo", want, "newgo", have)
if err != nil {
panic(err)
}
t.Fatalf("%s: diff:\n%s", name, d)
}
t.Logf("%s <- OK!\n", name)
return nil
}
if !bytes.Equal(have, want) {
t.Fatalf("%s: wrong bytes", name)
}
return nil
})
t.Logf("total %v", total)
if err != nil {
t.Fatal(err)
}
}
// canonicalize trims trailing spaces and tabs at the ends of lines,
// removes blank lines, and removes leading spaces before HTML tags.
// This gives us a little more leeway in cases where it is difficult
// to match Hugo's whitespace heuristics exactly or where we are
// refactoring templates a little which changes spacing in inconsequential ways.
func canonicalize(data []byte) []byte {
data = bytes.ReplaceAll(data, []byte("<li>"), []byte("<li>\n"))
data = bytes.ReplaceAll(data, []byte("</p>"), []byte("</p>\n"))
data = bytes.ReplaceAll(data, []byte("</ul>"), []byte("</ul>\n"))
data = regexp.MustCompile(`(<(img|hr)([^<>]*[^ <>])?) */>`).ReplaceAll(data, []byte("$1>")) // <img/> to <img>
lines := bytes.Split(data, []byte("\n"))
for i, line := range lines {
lines[i] = bytes.Trim(line, " \t")
}
var out [][]byte
for _, line := range lines {
if len(line) > 0 {
out = append(out, line)
}
}
return bytes.Join(out, []byte("\n"))
}