test_helpers.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
23func runMarkdownBlockWithRenderer(input string, extensions Extensions, renderer Renderer) string {
24 return string(Markdown([]byte(input), renderer, extensions))
25}
26
27func runMarkdownBlock(input string, extensions Extensions) string {
28 renderer := HTMLRenderer(UseXHTML, extensions, "", "")
29 return runMarkdownBlockWithRenderer(input, extensions, renderer)
30}
31
32func runnerWithRendererParameters(parameters HTMLRendererParameters) func(string, Extensions) string {
33 return func(input string, extensions Extensions) string {
34 renderer := HTMLRendererWithParameters(UseXHTML, extensions, "", "", parameters)
35 return runMarkdownBlockWithRenderer(input, extensions, renderer)
36 }
37}
38
39func doTestsBlock(t *testing.T, tests []string, extensions Extensions) {
40 doTestsBlockWithRunner(t, tests, extensions, runMarkdownBlock)
41}
42
43func doTestsBlockWithRunner(t *testing.T, tests []string, extensions Extensions, runner func(string, Extensions) string) {
44 // catch and report panics
45 var candidate string
46 defer func() {
47 if err := recover(); err != nil {
48 t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err)
49 }
50 }()
51
52 for i := 0; i+1 < len(tests); i += 2 {
53 input := tests[i]
54 candidate = input
55 expected := tests[i+1]
56 actual := runner(candidate, extensions)
57 if actual != expected {
58 t.Errorf("\nInput [%#v]\nExpected[%#v]\nActual [%#v]",
59 candidate, expected, actual)
60 }
61
62 // now test every substring to stress test bounds checking
63 if !testing.Short() {
64 for start := 0; start < len(input); start++ {
65 for end := start + 1; end <= len(input); end++ {
66 candidate = input[start:end]
67 _ = runMarkdownBlock(candidate, extensions)
68 }
69 }
70 }
71 }
72}
73
74func runMarkdownInline(input string, opts Options, htmlFlags HTMLFlags, params HTMLRendererParameters) string {
75 opts.Extensions |= Autolink
76 opts.Extensions |= Strikethrough
77
78 htmlFlags |= UseXHTML
79
80 renderer := HTMLRendererWithParameters(htmlFlags, opts.Extensions, "", "", params)
81
82 return string(MarkdownOptions([]byte(input), renderer, opts))
83}
84
85func doTestsInline(t *testing.T, tests []string) {
86 doTestsInlineParam(t, tests, Options{}, 0, HTMLRendererParameters{})
87}
88
89func doLinkTestsInline(t *testing.T, tests []string) {
90 doTestsInline(t, tests)
91
92 prefix := "http://localhost"
93 params := HTMLRendererParameters{AbsolutePrefix: prefix}
94 transformTests := transformLinks(tests, prefix)
95 doTestsInlineParam(t, transformTests, Options{}, 0, params)
96 doTestsInlineParam(t, transformTests, Options{}, CommonHtmlFlags, params)
97}
98
99func doSafeTestsInline(t *testing.T, tests []string) {
100 doTestsInlineParam(t, tests, Options{}, Safelink, HTMLRendererParameters{})
101
102 // All the links in this test should not have the prefix appended, so
103 // just rerun it with different parameters and the same expectations.
104 prefix := "http://localhost"
105 params := HTMLRendererParameters{AbsolutePrefix: prefix}
106 transformTests := transformLinks(tests, prefix)
107 doTestsInlineParam(t, transformTests, Options{}, Safelink, params)
108}
109
110func doTestsInlineParam(t *testing.T, tests []string, opts Options, htmlFlags HTMLFlags, params HTMLRendererParameters) {
111 // catch and report panics
112 var candidate string
113 defer func() {
114 if err := recover(); err != nil {
115 t.Errorf("\npanic while processing [%#v] (%v)\n", candidate, err)
116 }
117 }()
118
119 for i := 0; i+1 < len(tests); i += 2 {
120 input := tests[i]
121 candidate = input
122 expected := tests[i+1]
123 actual := runMarkdownInline(candidate, opts, htmlFlags, params)
124 if actual != expected {
125 t.Errorf("\nInput [%#v]\nExpected[%#v]\nActual [%#v]",
126 candidate, expected, actual)
127 }
128
129 // now test every substring to stress test bounds checking
130 if !testing.Short() {
131 for start := 0; start < len(input); start++ {
132 for end := start + 1; end <= len(input); end++ {
133 candidate = input[start:end]
134 _ = runMarkdownInline(candidate, opts, htmlFlags, params)
135 }
136 }
137 }
138 }
139}
140
141func transformLinks(tests []string, prefix string) []string {
142 newTests := make([]string, len(tests))
143 anchorRe := regexp.MustCompile(`<a href="/(.*?)"`)
144 imgRe := regexp.MustCompile(`<img src="/(.*?)"`)
145 for i, test := range tests {
146 if i%2 == 1 {
147 test = anchorRe.ReplaceAllString(test, `<a href="`+prefix+`/$1"`)
148 test = imgRe.ReplaceAllString(test, `<img src="`+prefix+`/$1"`)
149 }
150 newTests[i] = test
151 }
152 return newTests
153}
154
155func runMarkdownReference(input string, flag Extensions) string {
156 renderer := HTMLRenderer(0, flag, "", "")
157 return string(Markdown([]byte(input), renderer, flag))
158}
159
160func doTestsReference(t *testing.T, files []string, flag Extensions) {
161 // catch and report panics
162 var candidate string
163 defer func() {
164 if err := recover(); err != nil {
165 t.Errorf("\npanic while processing [%#v]\n", candidate)
166 }
167 }()
168
169 for _, basename := range files {
170 filename := filepath.Join("testdata", basename+".text")
171 inputBytes, err := ioutil.ReadFile(filename)
172 if err != nil {
173 t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
174 continue
175 }
176 input := string(inputBytes)
177
178 filename = filepath.Join("testdata", basename+".html")
179 expectedBytes, err := ioutil.ReadFile(filename)
180 if err != nil {
181 t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
182 continue
183 }
184 expected := string(expectedBytes)
185
186 // fmt.Fprintf(os.Stderr, "processing %s ...", filename)
187 actual := string(runMarkdownReference(input, flag))
188 if actual != expected {
189 t.Errorf("\n [%#v]\nExpected[%#v]\nActual [%#v]",
190 basename+".text", expected, actual)
191 }
192 // fmt.Fprintf(os.Stderr, " ok\n")
193
194 // now test every prefix of every input to check for
195 // bounds checking
196 if !testing.Short() {
197 start, max := 0, len(input)
198 for end := start + 1; end <= max; end++ {
199 candidate = input[start:end]
200 // fmt.Fprintf(os.Stderr, " %s %d:%d/%d\n", filename, start, end, max)
201 _ = runMarkdownReference(candidate, flag)
202 }
203 }
204 }
205}