...

Source file src/github.com/russross/blackfriday/v2/helpers_test.go

Documentation: github.com/russross/blackfriday/v2

     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  
    14  package blackfriday
    15  
    16  import (
    17  	"fmt"
    18  	"io/ioutil"
    19  	"path/filepath"
    20  	"regexp"
    21  	"strings"
    22  	"testing"
    23  )
    24  
    25  type TestParams struct {
    26  	extensions        Extensions
    27  	referenceOverride ReferenceOverrideFunc
    28  	HTMLFlags
    29  	HTMLRendererParameters
    30  }
    31  
    32  func execRecoverableTestSuite(t *testing.T, tests []string, params TestParams, suite func(candidate *string)) {
    33  	// Catch and report panics. This is useful when running 'go test -v' on
    34  	// the integration server. When developing, though, crash dump is often
    35  	// preferable, so recovery can be easily turned off with doRecover = false.
    36  	var candidate string
    37  	const doRecover = true
    38  	if doRecover {
    39  		defer func() {
    40  			if err := recover(); err != nil {
    41  				t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err)
    42  			}
    43  		}()
    44  	}
    45  	suite(&candidate)
    46  }
    47  
    48  func runMarkdown(input string, params TestParams) string {
    49  	params.HTMLRendererParameters.Flags = params.HTMLFlags
    50  	renderer := NewHTMLRenderer(params.HTMLRendererParameters)
    51  	return string(Run([]byte(input), WithRenderer(renderer),
    52  		WithExtensions(params.extensions),
    53  		WithRefOverride(params.referenceOverride)))
    54  }
    55  
    56  // doTests runs full document tests using MarkdownCommon configuration.
    57  func doTests(t *testing.T, tests []string) {
    58  	doTestsParam(t, tests, TestParams{
    59  		extensions: CommonExtensions,
    60  		HTMLRendererParameters: HTMLRendererParameters{
    61  			Flags: CommonHTMLFlags,
    62  		},
    63  	})
    64  }
    65  
    66  func doTestsBlock(t *testing.T, tests []string, extensions Extensions) {
    67  	doTestsParam(t, tests, TestParams{
    68  		extensions: extensions,
    69  		HTMLFlags:  UseXHTML,
    70  	})
    71  }
    72  
    73  func doTestsParam(t *testing.T, tests []string, params TestParams) {
    74  	execRecoverableTestSuite(t, tests, params, func(candidate *string) {
    75  		for i := 0; i+1 < len(tests); i += 2 {
    76  			input := tests[i]
    77  			*candidate = input
    78  			expected := tests[i+1]
    79  			actual := runMarkdown(*candidate, params)
    80  			if actual != expected {
    81  				t.Errorf("\nInput   [%#v]\nExpected[%#v]\nActual  [%#v]",
    82  					*candidate, expected, actual)
    83  			}
    84  
    85  			// now test every substring to stress test bounds checking
    86  			if !testing.Short() {
    87  				for start := 0; start < len(input); start++ {
    88  					for end := start + 1; end <= len(input); end++ {
    89  						*candidate = input[start:end]
    90  						runMarkdown(*candidate, params)
    91  					}
    92  				}
    93  			}
    94  		}
    95  	})
    96  }
    97  
    98  func doTestsInline(t *testing.T, tests []string) {
    99  	doTestsInlineParam(t, tests, TestParams{})
   100  }
   101  
   102  func doLinkTestsInline(t *testing.T, tests []string) {
   103  	doTestsInline(t, tests)
   104  
   105  	prefix := "http://localhost"
   106  	params := HTMLRendererParameters{AbsolutePrefix: prefix}
   107  	transformTests := transformLinks(tests, prefix)
   108  	doTestsInlineParam(t, transformTests, TestParams{
   109  		HTMLRendererParameters: params,
   110  	})
   111  	doTestsInlineParam(t, transformTests, TestParams{
   112  		HTMLFlags:              UseXHTML,
   113  		HTMLRendererParameters: params,
   114  	})
   115  }
   116  
   117  func doSafeTestsInline(t *testing.T, tests []string) {
   118  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Safelink})
   119  
   120  	// All the links in this test should not have the prefix appended, so
   121  	// just rerun it with different parameters and the same expectations.
   122  	prefix := "http://localhost"
   123  	params := HTMLRendererParameters{AbsolutePrefix: prefix}
   124  	transformTests := transformLinks(tests, prefix)
   125  	doTestsInlineParam(t, transformTests, TestParams{
   126  		HTMLFlags:              Safelink,
   127  		HTMLRendererParameters: params,
   128  	})
   129  }
   130  
   131  func doTestsInlineParam(t *testing.T, tests []string, params TestParams) {
   132  	params.extensions |= Autolink | Strikethrough
   133  	params.HTMLFlags |= UseXHTML
   134  	doTestsParam(t, tests, params)
   135  }
   136  
   137  func transformLinks(tests []string, prefix string) []string {
   138  	newTests := make([]string, len(tests))
   139  	anchorRe := regexp.MustCompile(`<a href="/(.*?)"`)
   140  	imgRe := regexp.MustCompile(`<img src="/(.*?)"`)
   141  	for i, test := range tests {
   142  		if i%2 == 1 {
   143  			test = anchorRe.ReplaceAllString(test, `<a href="`+prefix+`/$1"`)
   144  			test = imgRe.ReplaceAllString(test, `<img src="`+prefix+`/$1"`)
   145  		}
   146  		newTests[i] = test
   147  	}
   148  	return newTests
   149  }
   150  
   151  func doTestsReference(t *testing.T, files []string, flag Extensions) {
   152  	params := TestParams{extensions: flag}
   153  	execRecoverableTestSuite(t, files, params, func(candidate *string) {
   154  		for _, basename := range files {
   155  			filename := filepath.Join("testdata", basename+".text")
   156  			inputBytes, err := ioutil.ReadFile(filename)
   157  			if err != nil {
   158  				t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
   159  				continue
   160  			}
   161  			input := string(inputBytes)
   162  
   163  			filename = filepath.Join("testdata", basename+".html")
   164  			expectedBytes, err := ioutil.ReadFile(filename)
   165  			if err != nil {
   166  				t.Errorf("Couldn't open '%s', error: %v\n", filename, err)
   167  				continue
   168  			}
   169  			expected := string(expectedBytes)
   170  
   171  			actual := string(runMarkdown(input, params))
   172  			if actual != expected {
   173  				t.Errorf("\n" + doTestDiff(basename, expected, actual))
   174  			}
   175  
   176  			// now test every prefix of every input to check for
   177  			// bounds checking
   178  			if !testing.Short() {
   179  				start, max := 0, len(input)
   180  				for end := start + 1; end <= max; end++ {
   181  					*candidate = input[start:end]
   182  					runMarkdown(*candidate, params)
   183  				}
   184  			}
   185  		}
   186  	})
   187  }
   188  
   189  func doTestDiff(name, expected, actual string) string {
   190  	expectedLines := strings.Split(expected, "\n")
   191  	actualLines := strings.Split(actual, "\n")
   192  	d := "file: " + name + "\n"
   193  	for i, line := range expectedLines {
   194  		// Allow the actualLines indexing to panic because we're in tests where
   195  		// that's okay and we probably want to know about it if this input is wrong
   196  		// somehow.
   197  		if line != actualLines[i] {
   198  			d += fmt.Sprintf(`
   199  line: %d
   200  
   201  -%s
   202  +%s
   203  `, i, line, actualLines[i])
   204  		}
   205  	}
   206  
   207  	return d
   208  }
   209  

View as plain text