2016-04-04 15:41:05 +08:00
|
|
|
//
|
|
|
|
// Blackfriday Markdown Processor
|
|
|
|
// Available at http://github.com/russross/blackfriday
|
|
|
|
//
|
|
|
|
// Copyright © 2011 Russ Ross <russ@russross.com>.
|
|
|
|
// Distributed under the Simplified BSD License.
|
|
|
|
// See README.md for details.
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// Helper functions for unit testing
|
|
|
|
//
|
|
|
|
|
|
|
|
package blackfriday
|
|
|
|
|
|
|
|
import (
|
2019-01-21 16:05:15 +08:00
|
|
|
"fmt"
|
2016-04-04 15:41:05 +08:00
|
|
|
"io/ioutil"
|
|
|
|
"path/filepath"
|
|
|
|
"regexp"
|
2019-01-21 16:05:15 +08:00
|
|
|
"strings"
|
2016-04-04 15:41:05 +08:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2016-04-04 16:18:50 +08:00
|
|
|
type TestParams struct {
|
2017-02-02 15:35:10 +08:00
|
|
|
extensions Extensions
|
|
|
|
referenceOverride ReferenceOverrideFunc
|
2016-04-04 16:18:50 +08:00
|
|
|
HTMLFlags
|
|
|
|
HTMLRendererParameters
|
|
|
|
}
|
|
|
|
|
2016-04-04 18:13:57 +08:00
|
|
|
func execRecoverableTestSuite(t *testing.T, tests []string, params TestParams, suite func(candidate *string)) {
|
|
|
|
// Catch and report panics. This is useful when running 'go test -v' on
|
|
|
|
// the integration server. When developing, though, crash dump is often
|
|
|
|
// preferable, so recovery can be easily turned off with doRecover = false.
|
|
|
|
var candidate string
|
|
|
|
const doRecover = true
|
|
|
|
if doRecover {
|
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
suite(&candidate)
|
|
|
|
}
|
|
|
|
|
2016-04-04 19:00:26 +08:00
|
|
|
func runMarkdown(input string, params TestParams) string {
|
2016-04-05 19:18:32 +08:00
|
|
|
params.HTMLRendererParameters.Flags = params.HTMLFlags
|
|
|
|
renderer := NewHTMLRenderer(params.HTMLRendererParameters)
|
2017-06-06 04:42:05 +08:00
|
|
|
return string(Run([]byte(input), WithRenderer(renderer),
|
2017-02-02 15:35:10 +08:00
|
|
|
WithExtensions(params.extensions),
|
|
|
|
WithRefOverride(params.referenceOverride)))
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
|
2016-07-16 05:03:02 +08:00
|
|
|
// doTests runs full document tests using MarkdownCommon configuration.
|
|
|
|
func doTests(t *testing.T, tests []string) {
|
|
|
|
doTestsParam(t, tests, TestParams{
|
2017-02-02 15:35:10 +08:00
|
|
|
extensions: CommonExtensions,
|
2016-07-16 05:03:02 +08:00
|
|
|
HTMLRendererParameters: HTMLRendererParameters{
|
2016-11-25 03:48:48 +08:00
|
|
|
Flags: CommonHTMLFlags,
|
2016-07-16 05:03:02 +08:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-04-04 15:41:05 +08:00
|
|
|
func doTestsBlock(t *testing.T, tests []string, extensions Extensions) {
|
2016-04-04 19:00:26 +08:00
|
|
|
doTestsParam(t, tests, TestParams{
|
2017-02-02 15:35:10 +08:00
|
|
|
extensions: extensions,
|
|
|
|
HTMLFlags: UseXHTML,
|
2016-04-04 19:00:26 +08:00
|
|
|
})
|
2016-04-04 17:18:06 +08:00
|
|
|
}
|
|
|
|
|
2016-04-04 19:00:26 +08:00
|
|
|
func doTestsParam(t *testing.T, tests []string, params TestParams) {
|
2016-04-04 18:13:57 +08:00
|
|
|
execRecoverableTestSuite(t, tests, params, func(candidate *string) {
|
|
|
|
for i := 0; i+1 < len(tests); i += 2 {
|
|
|
|
input := tests[i]
|
|
|
|
*candidate = input
|
|
|
|
expected := tests[i+1]
|
2016-04-04 19:00:26 +08:00
|
|
|
actual := runMarkdown(*candidate, params)
|
2016-04-04 18:13:57 +08:00
|
|
|
if actual != expected {
|
|
|
|
t.Errorf("\nInput [%#v]\nExpected[%#v]\nActual [%#v]",
|
2016-04-05 15:00:34 +08:00
|
|
|
*candidate, expected, actual)
|
2016-04-04 18:13:57 +08:00
|
|
|
}
|
2016-04-04 15:41:05 +08:00
|
|
|
|
2016-04-04 18:13:57 +08:00
|
|
|
// now test every substring to stress test bounds checking
|
|
|
|
if !testing.Short() {
|
|
|
|
for start := 0; start < len(input); start++ {
|
|
|
|
for end := start + 1; end <= len(input); end++ {
|
|
|
|
*candidate = input[start:end]
|
2016-04-04 19:00:26 +08:00
|
|
|
runMarkdown(*candidate, params)
|
2016-04-04 18:13:57 +08:00
|
|
|
}
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-04 18:13:57 +08:00
|
|
|
})
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func doTestsInline(t *testing.T, tests []string) {
|
2016-04-04 16:18:50 +08:00
|
|
|
doTestsInlineParam(t, tests, TestParams{})
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func doLinkTestsInline(t *testing.T, tests []string) {
|
|
|
|
doTestsInline(t, tests)
|
|
|
|
|
|
|
|
prefix := "http://localhost"
|
|
|
|
params := HTMLRendererParameters{AbsolutePrefix: prefix}
|
|
|
|
transformTests := transformLinks(tests, prefix)
|
2016-04-04 16:18:50 +08:00
|
|
|
doTestsInlineParam(t, transformTests, TestParams{
|
|
|
|
HTMLRendererParameters: params,
|
|
|
|
})
|
|
|
|
doTestsInlineParam(t, transformTests, TestParams{
|
2016-08-10 12:26:37 +08:00
|
|
|
HTMLFlags: UseXHTML,
|
2016-04-04 16:18:50 +08:00
|
|
|
HTMLRendererParameters: params,
|
|
|
|
})
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func doSafeTestsInline(t *testing.T, tests []string) {
|
2016-04-04 16:18:50 +08:00
|
|
|
doTestsInlineParam(t, tests, TestParams{HTMLFlags: Safelink})
|
2016-04-04 15:41:05 +08:00
|
|
|
|
|
|
|
// All the links in this test should not have the prefix appended, so
|
|
|
|
// just rerun it with different parameters and the same expectations.
|
|
|
|
prefix := "http://localhost"
|
|
|
|
params := HTMLRendererParameters{AbsolutePrefix: prefix}
|
|
|
|
transformTests := transformLinks(tests, prefix)
|
2016-04-04 16:18:50 +08:00
|
|
|
doTestsInlineParam(t, transformTests, TestParams{
|
|
|
|
HTMLFlags: Safelink,
|
|
|
|
HTMLRendererParameters: params,
|
|
|
|
})
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
|
2016-04-04 16:18:50 +08:00
|
|
|
func doTestsInlineParam(t *testing.T, tests []string, params TestParams) {
|
2017-02-02 15:35:10 +08:00
|
|
|
params.extensions |= Autolink | Strikethrough
|
2016-04-04 19:00:26 +08:00
|
|
|
params.HTMLFlags |= UseXHTML
|
|
|
|
doTestsParam(t, tests, params)
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func transformLinks(tests []string, prefix string) []string {
|
|
|
|
newTests := make([]string, len(tests))
|
|
|
|
anchorRe := regexp.MustCompile(`<a href="/(.*?)"`)
|
|
|
|
imgRe := regexp.MustCompile(`<img src="/(.*?)"`)
|
|
|
|
for i, test := range tests {
|
|
|
|
if i%2 == 1 {
|
|
|
|
test = anchorRe.ReplaceAllString(test, `<a href="`+prefix+`/$1"`)
|
|
|
|
test = imgRe.ReplaceAllString(test, `<img src="`+prefix+`/$1"`)
|
|
|
|
}
|
|
|
|
newTests[i] = test
|
|
|
|
}
|
|
|
|
return newTests
|
|
|
|
}
|
|
|
|
|
|
|
|
func doTestsReference(t *testing.T, files []string, flag Extensions) {
|
2017-02-02 15:35:10 +08:00
|
|
|
params := TestParams{extensions: flag}
|
2016-04-04 18:13:57 +08:00
|
|
|
execRecoverableTestSuite(t, files, params, func(candidate *string) {
|
|
|
|
for _, basename := range files {
|
|
|
|
filename := filepath.Join("testdata", basename+".text")
|
|
|
|
inputBytes, err := ioutil.ReadFile(filename)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
input := string(inputBytes)
|
2016-04-04 15:41:05 +08:00
|
|
|
|
2016-04-04 18:13:57 +08:00
|
|
|
filename = filepath.Join("testdata", basename+".html")
|
|
|
|
expectedBytes, err := ioutil.ReadFile(filename)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
expected := string(expectedBytes)
|
2016-04-04 15:41:05 +08:00
|
|
|
|
2016-04-04 19:00:26 +08:00
|
|
|
actual := string(runMarkdown(input, params))
|
2016-04-04 18:13:57 +08:00
|
|
|
if actual != expected {
|
2018-09-05 05:36:14 +08:00
|
|
|
t.Errorf("\n" + doTestDiff(basename, expected, actual))
|
2016-04-04 18:13:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// now test every prefix of every input to check for
|
|
|
|
// bounds checking
|
|
|
|
if !testing.Short() {
|
|
|
|
start, max := 0, len(input)
|
|
|
|
for end := start + 1; end <= max; end++ {
|
|
|
|
*candidate = input[start:end]
|
2016-04-04 19:00:26 +08:00
|
|
|
runMarkdown(*candidate, params)
|
2016-04-04 18:13:57 +08:00
|
|
|
}
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
|
|
|
}
|
2016-04-04 18:13:57 +08:00
|
|
|
})
|
2016-04-04 15:41:05 +08:00
|
|
|
}
|
2018-09-05 05:36:14 +08:00
|
|
|
|
|
|
|
func doTestDiff(name, expected, actual string) string {
|
2019-01-21 16:05:15 +08:00
|
|
|
expectedLines := strings.Split(expected, "\n")
|
|
|
|
actualLines := strings.Split(actual, "\n")
|
|
|
|
d := "file: " + name + "\n"
|
|
|
|
for i, line := range expectedLines {
|
|
|
|
// Allow the actualLines indexing to panic because we're in tests where
|
|
|
|
// that's okay and we probably want to know about it if this input is wrong
|
|
|
|
// somehow.
|
|
|
|
if line != actualLines[i] {
|
|
|
|
d += fmt.Sprintf(`
|
|
|
|
line: %d
|
|
|
|
|
|
|
|
-%s
|
|
|
|
+%s
|
|
|
|
`, i, line, actualLines[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-05 05:36:14 +08:00
|
|
|
return d
|
|
|
|
}
|