all repos — grayfriday @ ff2d79c2cb08e0b410143e26f71a0e80e49d5b20

blackfriday fork with a few changes

helpers_test.go (view raw)

  1//
  2// Blackfriday Markdown Processor
  3// Available at http://github.com/russross/blackfriday
  4//
  5// Copyright © 2011 Russ Ross <russ@russross.com>.
  6// Distributed under the Simplified BSD License.
  7// See README.md for details.
  8//
  9
 10//
 11// Helper functions for unit testing
 12//
 13
 14package blackfriday
 15
 16import (
 17	"io/ioutil"
 18	"path/filepath"
 19	"regexp"
 20	"testing"
 21)
 22
 23type TestParams struct {
 24	Options
 25	HTMLFlags
 26	HTMLRendererParameters
 27}
 28
 29func execRecoverableTestSuite(t *testing.T, tests []string, params TestParams, suite func(candidate *string)) {
 30	// Catch and report panics. This is useful when running 'go test -v' on
 31	// the integration server. When developing, though, crash dump is often
 32	// preferable, so recovery can be easily turned off with doRecover = false.
 33	var candidate string
 34	const doRecover = true
 35	if doRecover {
 36		defer func() {
 37			if err := recover(); err != nil {
 38				t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err)
 39			}
 40		}()
 41	}
 42	suite(&candidate)
 43}
 44
 45func runMarkdown(input string, params TestParams) string {
 46	params.HTMLRendererParameters.Flags = params.HTMLFlags
 47	params.HTMLRendererParameters.Extensions = params.Options.Extensions
 48	renderer := NewHTMLRenderer(params.HTMLRendererParameters)
 49	return string(Markdown([]byte(input), renderer, params.Options))
 50}
 51
 52// doTests runs full document tests using MarkdownCommon configuration.
 53func doTests(t *testing.T, tests []string) {
 54	doTestsParam(t, tests, TestParams{
 55		Options: DefaultOptions,
 56		HTMLRendererParameters: HTMLRendererParameters{
 57			Flags:      CommonHTMLFlags,
 58			Extensions: CommonExtensions,
 59		},
 60	})
 61}
 62
 63func doTestsBlock(t *testing.T, tests []string, extensions Extensions) {
 64	doTestsParam(t, tests, TestParams{
 65		Options:   Options{Extensions: extensions},
 66		HTMLFlags: UseXHTML,
 67	})
 68}
 69
 70func doTestsParam(t *testing.T, tests []string, params TestParams) {
 71	execRecoverableTestSuite(t, tests, params, func(candidate *string) {
 72		for i := 0; i+1 < len(tests); i += 2 {
 73			input := tests[i]
 74			*candidate = input
 75			expected := tests[i+1]
 76			actual := runMarkdown(*candidate, params)
 77			if actual != expected {
 78				t.Errorf("\nInput   [%#v]\nExpected[%#v]\nActual  [%#v]",
 79					*candidate, expected, actual)
 80			}
 81
 82			// now test every substring to stress test bounds checking
 83			if !testing.Short() {
 84				for start := 0; start < len(input); start++ {
 85					for end := start + 1; end <= len(input); end++ {
 86						*candidate = input[start:end]
 87						runMarkdown(*candidate, params)
 88					}
 89				}
 90			}
 91		}
 92	})
 93}
 94
 95func doTestsInline(t *testing.T, tests []string) {
 96	doTestsInlineParam(t, tests, TestParams{})
 97}
 98
 99func doLinkTestsInline(t *testing.T, tests []string) {
100	doTestsInline(t, tests)
101
102	prefix := "http://localhost"
103	params := HTMLRendererParameters{AbsolutePrefix: prefix}
104	transformTests := transformLinks(tests, prefix)
105	doTestsInlineParam(t, transformTests, TestParams{
106		HTMLRendererParameters: params,
107	})
108	doTestsInlineParam(t, transformTests, TestParams{
109		HTMLFlags:              CommonHTMLFlags,
110		HTMLRendererParameters: params,
111	})
112}
113
114func doSafeTestsInline(t *testing.T, tests []string) {
115	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Safelink})
116
117	// All the links in this test should not have the prefix appended, so
118	// just rerun it with different parameters and the same expectations.
119	prefix := "http://localhost"
120	params := HTMLRendererParameters{AbsolutePrefix: prefix}
121	transformTests := transformLinks(tests, prefix)
122	doTestsInlineParam(t, transformTests, TestParams{
123		HTMLFlags:              Safelink,
124		HTMLRendererParameters: params,
125	})
126}
127
128func doTestsInlineParam(t *testing.T, tests []string, params TestParams) {
129	params.Options.Extensions |= Autolink
130	params.Options.Extensions |= Strikethrough
131	params.HTMLFlags |= UseXHTML
132	doTestsParam(t, tests, params)
133}
134
135func transformLinks(tests []string, prefix string) []string {
136	newTests := make([]string, len(tests))
137	anchorRe := regexp.MustCompile(`<a href="/(.*?)"`)
138	imgRe := regexp.MustCompile(`<img src="/(.*?)"`)
139	for i, test := range tests {
140		if i%2 == 1 {
141			test = anchorRe.ReplaceAllString(test, `<a href="`+prefix+`/$1"`)
142			test = imgRe.ReplaceAllString(test, `<img src="`+prefix+`/$1"`)
143		}
144		newTests[i] = test
145	}
146	return newTests
147}
148
149func doTestsReference(t *testing.T, files []string, flag Extensions) {
150	params := TestParams{Options: Options{Extensions: flag}}
151	execRecoverableTestSuite(t, files, params, func(candidate *string) {
152		for _, basename := range files {
153			filename := filepath.Join("testdata", basename+".text")
154			inputBytes, err := ioutil.ReadFile(filename)
155			if err != nil {
156				t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
157				continue
158			}
159			input := string(inputBytes)
160
161			filename = filepath.Join("testdata", basename+".html")
162			expectedBytes, err := ioutil.ReadFile(filename)
163			if err != nil {
164				t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
165				continue
166			}
167			expected := string(expectedBytes)
168
169			actual := string(runMarkdown(input, params))
170			if actual != expected {
171				t.Errorf("\n    [%#v]\nExpected[%#v]\nActual  [%#v]",
172					basename+".text", expected, actual)
173			}
174
175			// now test every prefix of every input to check for
176			// bounds checking
177			if !testing.Short() {
178				start, max := 0, len(input)
179				for end := start + 1; end <= max; end++ {
180					*candidate = input[start:end]
181					runMarkdown(*candidate, params)
182				}
183			}
184		}
185	})
186}