all repos — grayfriday @ 3cc9341a191a43bae67e2d91d812a40f61d124a2

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	extensions        Extensions
 25	referenceOverride ReferenceOverrideFunc
 26	HTMLFlags
 27	HTMLRendererParameters
 28}
 29
 30func execRecoverableTestSuite(t *testing.T, tests []string, params TestParams, suite func(candidate *string)) {
 31	// Catch and report panics. This is useful when running 'go test -v' on
 32	// the integration server. When developing, though, crash dump is often
 33	// preferable, so recovery can be easily turned off with doRecover = false.
 34	var candidate string
 35	const doRecover = true
 36	if doRecover {
 37		defer func() {
 38			if err := recover(); err != nil {
 39				t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err)
 40			}
 41		}()
 42	}
 43	suite(&candidate)
 44}
 45
 46func runMarkdown(input string, params TestParams) string {
 47	params.HTMLRendererParameters.Flags = params.HTMLFlags
 48	renderer := NewHTMLRenderer(params.HTMLRendererParameters)
 49	return string(Markdown([]byte(input), WithRenderer(renderer),
 50		WithExtensions(params.extensions),
 51		WithRefOverride(params.referenceOverride)))
 52}
 53
 54// doTests runs full document tests using MarkdownCommon configuration.
 55func doTests(t *testing.T, tests []string) {
 56	doTestsParam(t, tests, TestParams{
 57		extensions: CommonExtensions,
 58		HTMLRendererParameters: HTMLRendererParameters{
 59			Flags: CommonHTMLFlags,
 60		},
 61	})
 62}
 63
 64func doTestsBlock(t *testing.T, tests []string, extensions Extensions) {
 65	doTestsParam(t, tests, TestParams{
 66		extensions: extensions,
 67		HTMLFlags:  UseXHTML,
 68	})
 69}
 70
 71func doTestsParam(t *testing.T, tests []string, params TestParams) {
 72	execRecoverableTestSuite(t, tests, params, func(candidate *string) {
 73		for i := 0; i+1 < len(tests); i += 2 {
 74			input := tests[i]
 75			*candidate = input
 76			expected := tests[i+1]
 77			actual := runMarkdown(*candidate, params)
 78			if actual != expected {
 79				t.Errorf("\nInput   [%#v]\nExpected[%#v]\nActual  [%#v]",
 80					*candidate, expected, actual)
 81			}
 82
 83			// now test every substring to stress test bounds checking
 84			if !testing.Short() {
 85				for start := 0; start < len(input); start++ {
 86					for end := start + 1; end <= len(input); end++ {
 87						*candidate = input[start:end]
 88						runMarkdown(*candidate, params)
 89					}
 90				}
 91			}
 92		}
 93	})
 94}
 95
 96func doTestsInline(t *testing.T, tests []string) {
 97	doTestsInlineParam(t, tests, TestParams{})
 98}
 99
100func doLinkTestsInline(t *testing.T, tests []string) {
101	doTestsInline(t, tests)
102
103	prefix := "http://localhost"
104	params := HTMLRendererParameters{AbsolutePrefix: prefix}
105	transformTests := transformLinks(tests, prefix)
106	doTestsInlineParam(t, transformTests, TestParams{
107		HTMLRendererParameters: params,
108	})
109	doTestsInlineParam(t, transformTests, TestParams{
110		HTMLFlags:              UseXHTML,
111		HTMLRendererParameters: params,
112	})
113}
114
115func doSafeTestsInline(t *testing.T, tests []string) {
116	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Safelink})
117
118	// All the links in this test should not have the prefix appended, so
119	// just rerun it with different parameters and the same expectations.
120	prefix := "http://localhost"
121	params := HTMLRendererParameters{AbsolutePrefix: prefix}
122	transformTests := transformLinks(tests, prefix)
123	doTestsInlineParam(t, transformTests, TestParams{
124		HTMLFlags:              Safelink,
125		HTMLRendererParameters: params,
126	})
127}
128
129func doTestsInlineParam(t *testing.T, tests []string, params TestParams) {
130	params.extensions |= Autolink | 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{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}