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 renderer := NewHTMLRenderer(params.HTMLRendererParameters)
48 return string(Markdown([]byte(input), renderer, params.Options))
49}
50
51// doTests runs full document tests using MarkdownCommon configuration.
52func doTests(t *testing.T, tests []string) {
53 doTestsParam(t, tests, TestParams{
54 Options: DefaultOptions,
55 HTMLRendererParameters: HTMLRendererParameters{
56 Flags: CommonHTMLFlags,
57 },
58 })
59}
60
61func doTestsBlock(t *testing.T, tests []string, extensions Extensions) {
62 doTestsParam(t, tests, TestParams{
63 Options: Options{Extensions: extensions},
64 HTMLFlags: UseXHTML,
65 })
66}
67
68func doTestsParam(t *testing.T, tests []string, params TestParams) {
69 execRecoverableTestSuite(t, tests, params, func(candidate *string) {
70 for i := 0; i+1 < len(tests); i += 2 {
71 input := tests[i]
72 *candidate = input
73 expected := tests[i+1]
74 actual := runMarkdown(*candidate, params)
75 if actual != expected {
76 t.Errorf("\nInput [%#v]\nExpected[%#v]\nActual [%#v]",
77 *candidate, expected, actual)
78 }
79
80 // now test every substring to stress test bounds checking
81 if !testing.Short() {
82 for start := 0; start < len(input); start++ {
83 for end := start + 1; end <= len(input); end++ {
84 *candidate = input[start:end]
85 runMarkdown(*candidate, params)
86 }
87 }
88 }
89 }
90 })
91}
92
93func doTestsInline(t *testing.T, tests []string) {
94 doTestsInlineParam(t, tests, TestParams{})
95}
96
97func doLinkTestsInline(t *testing.T, tests []string) {
98 doTestsInline(t, tests)
99
100 prefix := "http://localhost"
101 params := HTMLRendererParameters{AbsolutePrefix: prefix}
102 transformTests := transformLinks(tests, prefix)
103 doTestsInlineParam(t, transformTests, TestParams{
104 HTMLRendererParameters: params,
105 })
106 doTestsInlineParam(t, transformTests, TestParams{
107 HTMLFlags: UseXHTML,
108 HTMLRendererParameters: params,
109 })
110}
111
112func doSafeTestsInline(t *testing.T, tests []string) {
113 doTestsInlineParam(t, tests, TestParams{HTMLFlags: Safelink})
114
115 // All the links in this test should not have the prefix appended, so
116 // just rerun it with different parameters and the same expectations.
117 prefix := "http://localhost"
118 params := HTMLRendererParameters{AbsolutePrefix: prefix}
119 transformTests := transformLinks(tests, prefix)
120 doTestsInlineParam(t, transformTests, TestParams{
121 HTMLFlags: Safelink,
122 HTMLRendererParameters: params,
123 })
124}
125
126func doTestsInlineParam(t *testing.T, tests []string, params TestParams) {
127 params.Options.Extensions |= Autolink
128 params.Options.Extensions |= Strikethrough
129 params.HTMLFlags |= UseXHTML
130 doTestsParam(t, tests, params)
131}
132
133func transformLinks(tests []string, prefix string) []string {
134 newTests := make([]string, len(tests))
135 anchorRe := regexp.MustCompile(`<a href="/(.*?)"`)
136 imgRe := regexp.MustCompile(`<img src="/(.*?)"`)
137 for i, test := range tests {
138 if i%2 == 1 {
139 test = anchorRe.ReplaceAllString(test, `<a href="`+prefix+`/$1"`)
140 test = imgRe.ReplaceAllString(test, `<img src="`+prefix+`/$1"`)
141 }
142 newTests[i] = test
143 }
144 return newTests
145}
146
147func doTestsReference(t *testing.T, files []string, flag Extensions) {
148 params := TestParams{Options: Options{Extensions: flag}}
149 execRecoverableTestSuite(t, files, params, func(candidate *string) {
150 for _, basename := range files {
151 filename := filepath.Join("testdata", basename+".text")
152 inputBytes, err := ioutil.ReadFile(filename)
153 if err != nil {
154 t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
155 continue
156 }
157 input := string(inputBytes)
158
159 filename = filepath.Join("testdata", basename+".html")
160 expectedBytes, err := ioutil.ReadFile(filename)
161 if err != nil {
162 t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
163 continue
164 }
165 expected := string(expectedBytes)
166
167 actual := string(runMarkdown(input, params))
168 if actual != expected {
169 t.Errorf("\n [%#v]\nExpected[%#v]\nActual [%#v]",
170 basename+".text", expected, actual)
171 }
172
173 // now test every prefix of every input to check for
174 // bounds checking
175 if !testing.Short() {
176 start, max := 0, len(input)
177 for end := start + 1; end <= max; end++ {
178 *candidate = input[start:end]
179 runMarkdown(*candidate, params)
180 }
181 }
182 }
183 })
184}