blob: fa952d21d0e02b18cfa3ed707c649a4af32a211e [file] [log] [blame]
// Copyright 2022 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 comment
import (
"bytes"
"encoding/json"
"fmt"
"path/filepath"
"strings"
"testing"
"golang.org/x/tools/txtar"
"golang.org/x/website/internal/backport/diff"
)
func TestTestdata(t *testing.T) {
files, _ := filepath.Glob("testdata/*.txt")
if len(files) == 0 {
t.Fatalf("no testdata")
}
var p Parser
p.Words = map[string]string{
"italicword": "",
"linkedword": "https://example.com/linkedword",
}
p.LookupPackage = func(name string) (importPath string, ok bool) {
if name == "comment" {
return "go/doc/comment", true
}
return DefaultLookupPackage(name)
}
p.LookupSym = func(recv, name string) (ok bool) {
if recv == "Parser" && name == "Parse" ||
recv == "" && name == "Doc" ||
recv == "" && name == "NoURL" {
return true
}
return false
}
stripDollars := func(b []byte) []byte {
// Remove trailing $ on lines.
// They make it easier to see lines with trailing spaces,
// as well as turning them into lines without trailing spaces,
// in case editors remove trailing spaces.
return bytes.ReplaceAll(b, []byte("$\n"), []byte("\n"))
}
for _, file := range files {
t.Run(filepath.Base(file), func(t *testing.T) {
var pr Printer
a, err := txtar.ParseFile(file)
if err != nil {
t.Fatal(err)
}
if len(a.Comment) > 0 {
err := json.Unmarshal(a.Comment, &pr)
if err != nil {
t.Fatalf("unmarshalling top json: %v", err)
}
}
if len(a.Files) < 1 || a.Files[0].Name != "input" {
t.Fatalf("first file is not %q", "input")
}
d := p.Parse(string(stripDollars(a.Files[0].Data)))
for _, f := range a.Files[1:] {
want := stripDollars(f.Data)
for len(want) >= 2 && want[len(want)-1] == '\n' && want[len(want)-2] == '\n' {
want = want[:len(want)-1]
}
var out []byte
switch f.Name {
default:
t.Fatalf("unknown output file %q", f.Name)
case "dump":
out = dump(d)
case "gofmt":
out = pr.Comment(d)
case "html":
out = pr.HTML(d)
case "markdown":
out = pr.Markdown(d)
case "text":
out = pr.Text(d)
}
if string(out) != string(want) {
t.Errorf("%s: %s", file, diff.Diff(f.Name, want, "have", out))
}
}
})
}
}
func dump(d *Doc) []byte {
var out bytes.Buffer
dumpTo(&out, 0, d)
return out.Bytes()
}
func dumpTo(out *bytes.Buffer, indent int, x interface{}) {
switch x := x.(type) {
default:
fmt.Fprintf(out, "?%T", x)
case *Doc:
fmt.Fprintf(out, "Doc")
dumpTo(out, indent+1, x.Content)
if len(x.Links) > 0 {
dumpNL(out, indent+1)
fmt.Fprintf(out, "Links")
dumpTo(out, indent+2, x.Links)
}
fmt.Fprintf(out, "\n")
case []*LinkDef:
for _, def := range x {
dumpNL(out, indent)
dumpTo(out, indent, def)
}
case *LinkDef:
fmt.Fprintf(out, "LinkDef Used:%v Text:%q URL:%s", x.Used, x.Text, x.URL)
case []Block:
for _, blk := range x {
dumpNL(out, indent)
dumpTo(out, indent, blk)
}
case *Heading:
fmt.Fprintf(out, "Heading")
dumpTo(out, indent+1, x.Text)
case *List:
fmt.Fprintf(out, "List ForceBlankBefore=%v ForceBlankBetween=%v", x.ForceBlankBefore, x.ForceBlankBetween)
dumpTo(out, indent+1, x.Items)
case []*ListItem:
for _, item := range x {
dumpNL(out, indent)
dumpTo(out, indent, item)
}
case *ListItem:
fmt.Fprintf(out, "Item Number=%q", x.Number)
dumpTo(out, indent+1, x.Content)
case *Paragraph:
fmt.Fprintf(out, "Paragraph")
dumpTo(out, indent+1, x.Text)
case *Code:
fmt.Fprintf(out, "Code")
dumpTo(out, indent+1, x.Text)
case []Text:
for _, t := range x {
dumpNL(out, indent)
dumpTo(out, indent, t)
}
case Plain:
if !strings.Contains(string(x), "\n") {
fmt.Fprintf(out, "Plain %q", string(x))
} else {
fmt.Fprintf(out, "Plain")
dumpTo(out, indent+1, string(x))
}
case Italic:
if !strings.Contains(string(x), "\n") {
fmt.Fprintf(out, "Italic %q", string(x))
} else {
fmt.Fprintf(out, "Italic")
dumpTo(out, indent+1, string(x))
}
case string:
for _, line := range strings.SplitAfter(x, "\n") {
if line != "" {
dumpNL(out, indent)
fmt.Fprintf(out, "%q", line)
}
}
case *Link:
fmt.Fprintf(out, "Link %q", x.URL)
dumpTo(out, indent+1, x.Text)
case *DocLink:
fmt.Fprintf(out, "DocLink pkg:%q, recv:%q, name:%q", x.ImportPath, x.Recv, x.Name)
dumpTo(out, indent+1, x.Text)
}
}
func dumpNL(out *bytes.Buffer, n int) {
out.WriteByte('\n')
for i := 0; i < n; i++ {
out.WriteByte('\t')
}
}