From c301f6b6c6c3c870bc7a56334c3fd1d42356b736 Mon Sep 17 00:00:00 2001
From: John MacFarlane
Date: Sat, 29 Nov 2014 11:00:48 -0800
Subject: Moved testing programs to test/.
Added test/CMakeLists.txt.
---
CMakeLists.txt | 22 +---
pathological_tests.py | 82 ------------
spec_tests.py | 308 ---------------------------------------------
test/CMakeLists.txt | 24 ++++
test/pathological_tests.py | 82 ++++++++++++
test/spec_tests.py | 308 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 415 insertions(+), 411 deletions(-)
delete mode 100644 pathological_tests.py
delete mode 100755 spec_tests.py
create mode 100644 test/CMakeLists.txt
create mode 100644 test/pathological_tests.py
create mode 100755 test/spec_tests.py
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e4c870..be75c5e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,28 +15,8 @@ set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_
add_subdirectory(src)
add_subdirectory(api_test)
add_subdirectory(man)
-
enable_testing()
-
-# To get verbose output: cmake --build build --target "test" -- ARGS='-V'
-add_test(spectest_library
- python "${CMAKE_SOURCE_DIR}/spec_tests.py" "--no-normalize" "--spec"
- "${CMAKE_SOURCE_DIR}/spec.txt" "--library-dir" "${CMAKE_BINARY_DIR}/src"
-)
-add_test(pathological_tests_library
- python "${CMAKE_SOURCE_DIR}/pathological_tests.py"
- "--library-dir" "${CMAKE_BINARY_DIR}/src"
-)
-add_test(NAME api_test COMMAND api_test)
-if (WIN32)
- file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/src WIN_DLL_DIR)
- set_tests_properties(api_test PROPERTIES
- ENVIRONMENT "PATH=${WIN_DLL_DIR};$ENV{PATH}"
- )
-endif(WIN32)
-add_test(spectest_executable
- python "${CMAKE_SOURCE_DIR}/spec_tests.py" "--no-normalize" "--spec" "${CMAKE_SOURCE_DIR}/spec.txt" "--program" "${CMAKE_BINARY_DIR}/src/cmark"
-)
+add_subdirectory(test)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
diff --git a/pathological_tests.py b/pathological_tests.py
deleted file mode 100644
index 999a467..0000000
--- a/pathological_tests.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from ctypes import CDLL, c_char_p, c_long
-from subprocess import *
-import re
-import argparse
-import sys
-import platform
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser(description='Run cmark tests.')
- parser.add_argument('--program', dest='program', nargs='?', default=None,
- help='program to test')
- parser.add_argument('--library-dir', dest='library_dir', nargs='?',
- default=None, help='directory containing dynamic library')
- args = parser.parse_args(sys.argv[1:])
-
-if not args.program:
- sysname = platform.system()
- libname = "libcmark"
- if sysname == 'Darwin':
- libname += ".dylib"
- elif sysname == 'Windows':
- libname += ".dll"
- else:
- libname += ".so"
- if args and args.library_dir:
- libpath = args.library_dir + "/" + libname
- else:
- libpath = "build/src/" + libname
- cmark = CDLL(libpath)
-
- markdown = cmark.cmark_markdown_to_html
- markdown.restype = c_char_p
- markdown.argtypes = [c_char_p, c_long]
-
-def md2html(text, prog):
- if prog:
- p1 = Popen(prog.split(), stdout=PIPE, stdin=PIPE, stderr=PIPE)
- [result, err] = p1.communicate(input=text)
- return [p1.returncode, result, err]
- else:
- return [0, markdown(text, len(text)), '']
-
-pathological = {
- "nested strong emph":
- (("*a **a " * 100000) + "b" + (" a** a*" * 100000),
- "" + ("a a " * 100000) + "b" +
- (" a a" * 100000) + "
"),
- "nested brackets":
- (("[" * 50000) + "a" + ("]" * 50000),
- "" + ("[" * 50000) + "a" + ("]" * 50000) + "
")
- }
-
-whitespace_re = re.compile('/s+/')
-passed = 0
-errored = 0
-failed = 0
-
-print "Testing pathological cases:"
-for description in pathological:
- print description
- (inp, expected) = pathological[description]
- [rc, actual, err] = md2html(inp, args.program)
- if rc != 0:
- errored += 1
- print description
- print "program returned error code %d" % rc
- print(err)
- elif whitespace_re.sub(' ', actual.rstrip()) == expected.rstrip():
- passed += 1
- else:
- print description, 'failed'
- print(actual)
- failed += 1
-
-print "%d passed, %d failed, %d errored" % (passed, failed, errored)
-if (failed == 0 and errored == 0):
- exit(0)
-else:
- exit(1)
diff --git a/spec_tests.py b/spec_tests.py
deleted file mode 100755
index 6e0d4cc..0000000
--- a/spec_tests.py
+++ /dev/null
@@ -1,308 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from ctypes import CDLL, c_char_p, c_long
-import sys
-import platform
-from difflib import unified_diff
-from subprocess import *
-import argparse
-from HTMLParser import HTMLParser, HTMLParseError
-from htmlentitydefs import name2codepoint
-import re
-import cgi
-import json
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser(description='Run cmark tests.')
- parser.add_argument('--program', dest='program', nargs='?', default=None,
- help='program to test')
- parser.add_argument('--spec', dest='spec', nargs='?', default='spec.txt',
- help='path to spec')
- parser.add_argument('--pattern', dest='pattern', nargs='?',
- default=None, help='limit to sections matching regex pattern')
- parser.add_argument('--library-dir', dest='library_dir', nargs='?',
- default=None, help='directory containing dynamic library')
- parser.add_argument('--no-normalize', dest='normalize',
- action='store_const', const=False, default=True,
- help='do not normalize HTML')
- parser.add_argument('--dump-tests', dest='dump_tests',
- action='store_const', const=True, default=False,
- help='dump tests in JSON format')
- parser.add_argument('--debug-normalization', dest='debug_normalization',
- action='store_const', const=True,
- default=False, help='filter stdin through normalizer for testing')
- args = parser.parse_args(sys.argv[1:])
-
-if not (args.program or args.dump_tests or args.debug_normalization):
- sysname = platform.system()
- libname = "libcmark"
- if sysname == 'Darwin':
- libname += ".dylib"
- elif sysname == 'Windows':
- libname += ".dll"
- else:
- libname += ".so"
- if args and args.library_dir:
- libpath = args.library_dir + "/" + libname
- else:
- libpath = "build/src/" + libname
- cmark = CDLL(libpath)
-
- markdown = cmark.cmark_markdown_to_html
- markdown.restype = c_char_p
- markdown.argtypes = [c_char_p, c_long]
-
-def md2html(text, prog):
- if prog:
- p1 = Popen(prog.split(), stdout=PIPE, stdin=PIPE, stderr=PIPE)
- [result, err] = p1.communicate(input=text)
- return [p1.returncode, result, err]
- else:
- return [0, markdown(text, len(text)), '']
-
-# Normalization code, adapted from
-# https://github.com/karlcow/markdown-testsuite/
-significant_attrs = ["alt", "href", "src", "title"]
-whitespace_re = re.compile('/s+/')
-class MyHTMLParser(HTMLParser):
- def __init__(self):
- HTMLParser.__init__(self)
- self.last = "starttag"
- self.in_pre = False
- self.output = u""
- self.last_tag = ""
- def handle_data(self, data):
- after_tag = self.last == "endtag" or self.last == "starttag"
- after_block_tag = after_tag and self.is_block_tag(self.last_tag)
- if after_tag and self.last_tag == "br":
- data = data.lstrip('\n')
- data = whitespace_re.sub(' ', data)
- if after_block_tag and not self.in_pre:
- if self.last == "starttag":
- data = data.lstrip()
- elif self.last == "endtag":
- data = data.strip()
- self.output += data
- self.last = "data"
- def handle_endtag(self, tag):
- if tag == "pre":
- self.in_pre = False
- if self.is_block_tag(tag):
- self.output = self.output.rstrip()
- self.output += "" + tag + ">"
- self.last_tag = tag
- self.last = "endtag"
- def handle_starttag(self, tag, attrs):
- if tag == "pre":
- self.in_pre = True
- self.output += "<" + tag
- # For now we don't strip out 'extra' attributes, because of
- # raw HTML test cases.
- # attrs = filter(lambda attr: attr[0] in significant_attrs, attrs)
- if attrs:
- attrs.sort()
- for (k,v) in attrs:
- self.output += " " + k
- if v != None:
- self.output += ("=" + '"' + cgi.escape(v,quote=True) + '"')
- self.output += ">"
- self.last_tag = tag
- self.last = "starttag"
- def handle_startendtag(self, tag, attrs):
- """Ignore closing tag for self-closing """
- self.handle_starttag(tag, attrs)
- self.last_tag = tag
- self.last = "endtag"
- def handle_comment(self, data):
- self.output += ''
- self.last = "comment"
- def handle_decl(self, data):
- self.output += ''
- self.last = "decl"
- def unknown_decl(self, data):
- self.output += ''
- self.last = "decl"
- def handle_pi(self,data):
- self.output += '' + data + '>'
- self.last = "pi"
- def handle_entityref(self, name):
- try:
- c = unichr(name2codepoint[name])
- except KeyError:
- c = None
- self.output_char(c, '&' + name + ';')
- self.last = "ref"
- def handle_charref(self, name):
- try:
- if name.startswith("x"):
- c = unichr(int(name[1:], 16))
- else:
- c = unichr(int(name))
- except ValueError:
- c = None
- self.output_char(c, '&' + name + ';')
- self.last = "ref"
- # Helpers.
- def output_char(self, c, fallback):
- if c == u'<':
- self.output += "<"
- elif c == u'>':
- self.output += ">"
- elif c == u'&':
- self.output += "&"
- elif c == u'"':
- self.output += """
- elif c == None:
- self.output += fallback
- else:
- self.output += c
-
- def is_block_tag(self,tag):
- return (tag in ['article', 'header', 'aside', 'hgroup', 'blockquote',
- 'hr', 'iframe', 'body', 'li', 'map', 'button', 'object', 'canvas',
- 'ol', 'caption', 'output', 'col', 'p', 'colgroup', 'pre', 'dd',
- 'progress', 'div', 'section', 'dl', 'table', 'td', 'dt',
- 'tbody', 'embed', 'textarea', 'fieldset', 'tfoot', 'figcaption',
- 'th', 'figure', 'thead', 'footer', 'tr', 'form', 'ul',
- 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'video', 'script', 'style'])
-
-def normalize_html(html):
- r"""
- Return normalized form of HTML which ignores insignificant output
- differences:
-
- * Multiple inner whitespaces are collapsed to a single space (except
- in pre tags).
- * Outer whitespace (outside block-level tags) is removed.
- * Self-closing tags are converted to open tags.
- * Attributes are sorted and lowercased.
- * References are converted to unicode, except that '<', '>', '&', and
- '&' are rendered using entities.
- """
- html_chunk_re = re.compile("(\|\<[^>]*\>|[^<]+)")
- try:
- parser = MyHTMLParser()
- # We work around HTMLParser's limitations parsing CDATA
- # by breaking the input into chunks and passing CDATA chunks
- # through verbatim.
- for chunk in re.finditer(html_chunk_re, html):
- if chunk.group(0)[:8] == "" + ("a a " * 100000) + "b" +
+ (" a a" * 100000) + "
"),
+ "nested brackets":
+ (("[" * 50000) + "a" + ("]" * 50000),
+ "" + ("[" * 50000) + "a" + ("]" * 50000) + "
")
+ }
+
+whitespace_re = re.compile('/s+/')
+passed = 0
+errored = 0
+failed = 0
+
+print "Testing pathological cases:"
+for description in pathological:
+ print description
+ (inp, expected) = pathological[description]
+ [rc, actual, err] = md2html(inp, args.program)
+ if rc != 0:
+ errored += 1
+ print description
+ print "program returned error code %d" % rc
+ print(err)
+ elif whitespace_re.sub(' ', actual.rstrip()) == expected.rstrip():
+ passed += 1
+ else:
+ print description, 'failed'
+ print(actual)
+ failed += 1
+
+print "%d passed, %d failed, %d errored" % (passed, failed, errored)
+if (failed == 0 and errored == 0):
+ exit(0)
+else:
+ exit(1)
diff --git a/test/spec_tests.py b/test/spec_tests.py
new file mode 100755
index 0000000..6e0d4cc
--- /dev/null
+++ b/test/spec_tests.py
@@ -0,0 +1,308 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from ctypes import CDLL, c_char_p, c_long
+import sys
+import platform
+from difflib import unified_diff
+from subprocess import *
+import argparse
+from HTMLParser import HTMLParser, HTMLParseError
+from htmlentitydefs import name2codepoint
+import re
+import cgi
+import json
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description='Run cmark tests.')
+ parser.add_argument('--program', dest='program', nargs='?', default=None,
+ help='program to test')
+ parser.add_argument('--spec', dest='spec', nargs='?', default='spec.txt',
+ help='path to spec')
+ parser.add_argument('--pattern', dest='pattern', nargs='?',
+ default=None, help='limit to sections matching regex pattern')
+ parser.add_argument('--library-dir', dest='library_dir', nargs='?',
+ default=None, help='directory containing dynamic library')
+ parser.add_argument('--no-normalize', dest='normalize',
+ action='store_const', const=False, default=True,
+ help='do not normalize HTML')
+ parser.add_argument('--dump-tests', dest='dump_tests',
+ action='store_const', const=True, default=False,
+ help='dump tests in JSON format')
+ parser.add_argument('--debug-normalization', dest='debug_normalization',
+ action='store_const', const=True,
+ default=False, help='filter stdin through normalizer for testing')
+ args = parser.parse_args(sys.argv[1:])
+
+if not (args.program or args.dump_tests or args.debug_normalization):
+ sysname = platform.system()
+ libname = "libcmark"
+ if sysname == 'Darwin':
+ libname += ".dylib"
+ elif sysname == 'Windows':
+ libname += ".dll"
+ else:
+ libname += ".so"
+ if args and args.library_dir:
+ libpath = args.library_dir + "/" + libname
+ else:
+ libpath = "build/src/" + libname
+ cmark = CDLL(libpath)
+
+ markdown = cmark.cmark_markdown_to_html
+ markdown.restype = c_char_p
+ markdown.argtypes = [c_char_p, c_long]
+
+def md2html(text, prog):
+ if prog:
+ p1 = Popen(prog.split(), stdout=PIPE, stdin=PIPE, stderr=PIPE)
+ [result, err] = p1.communicate(input=text)
+ return [p1.returncode, result, err]
+ else:
+ return [0, markdown(text, len(text)), '']
+
+# Normalization code, adapted from
+# https://github.com/karlcow/markdown-testsuite/
+significant_attrs = ["alt", "href", "src", "title"]
+whitespace_re = re.compile('/s+/')
+class MyHTMLParser(HTMLParser):
+ def __init__(self):
+ HTMLParser.__init__(self)
+ self.last = "starttag"
+ self.in_pre = False
+ self.output = u""
+ self.last_tag = ""
+ def handle_data(self, data):
+ after_tag = self.last == "endtag" or self.last == "starttag"
+ after_block_tag = after_tag and self.is_block_tag(self.last_tag)
+ if after_tag and self.last_tag == "br":
+ data = data.lstrip('\n')
+ data = whitespace_re.sub(' ', data)
+ if after_block_tag and not self.in_pre:
+ if self.last == "starttag":
+ data = data.lstrip()
+ elif self.last == "endtag":
+ data = data.strip()
+ self.output += data
+ self.last = "data"
+ def handle_endtag(self, tag):
+ if tag == "pre":
+ self.in_pre = False
+ if self.is_block_tag(tag):
+ self.output = self.output.rstrip()
+ self.output += "" + tag + ">"
+ self.last_tag = tag
+ self.last = "endtag"
+ def handle_starttag(self, tag, attrs):
+ if tag == "pre":
+ self.in_pre = True
+ self.output += "<" + tag
+ # For now we don't strip out 'extra' attributes, because of
+ # raw HTML test cases.
+ # attrs = filter(lambda attr: attr[0] in significant_attrs, attrs)
+ if attrs:
+ attrs.sort()
+ for (k,v) in attrs:
+ self.output += " " + k
+ if v != None:
+ self.output += ("=" + '"' + cgi.escape(v,quote=True) + '"')
+ self.output += ">"
+ self.last_tag = tag
+ self.last = "starttag"
+ def handle_startendtag(self, tag, attrs):
+ """Ignore closing tag for self-closing """
+ self.handle_starttag(tag, attrs)
+ self.last_tag = tag
+ self.last = "endtag"
+ def handle_comment(self, data):
+ self.output += ''
+ self.last = "comment"
+ def handle_decl(self, data):
+ self.output += ''
+ self.last = "decl"
+ def unknown_decl(self, data):
+ self.output += ''
+ self.last = "decl"
+ def handle_pi(self,data):
+ self.output += '' + data + '>'
+ self.last = "pi"
+ def handle_entityref(self, name):
+ try:
+ c = unichr(name2codepoint[name])
+ except KeyError:
+ c = None
+ self.output_char(c, '&' + name + ';')
+ self.last = "ref"
+ def handle_charref(self, name):
+ try:
+ if name.startswith("x"):
+ c = unichr(int(name[1:], 16))
+ else:
+ c = unichr(int(name))
+ except ValueError:
+ c = None
+ self.output_char(c, '&' + name + ';')
+ self.last = "ref"
+ # Helpers.
+ def output_char(self, c, fallback):
+ if c == u'<':
+ self.output += "<"
+ elif c == u'>':
+ self.output += ">"
+ elif c == u'&':
+ self.output += "&"
+ elif c == u'"':
+ self.output += """
+ elif c == None:
+ self.output += fallback
+ else:
+ self.output += c
+
+ def is_block_tag(self,tag):
+ return (tag in ['article', 'header', 'aside', 'hgroup', 'blockquote',
+ 'hr', 'iframe', 'body', 'li', 'map', 'button', 'object', 'canvas',
+ 'ol', 'caption', 'output', 'col', 'p', 'colgroup', 'pre', 'dd',
+ 'progress', 'div', 'section', 'dl', 'table', 'td', 'dt',
+ 'tbody', 'embed', 'textarea', 'fieldset', 'tfoot', 'figcaption',
+ 'th', 'figure', 'thead', 'footer', 'tr', 'form', 'ul',
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'video', 'script', 'style'])
+
+def normalize_html(html):
+ r"""
+ Return normalized form of HTML which ignores insignificant output
+ differences:
+
+ * Multiple inner whitespaces are collapsed to a single space (except
+ in pre tags).
+ * Outer whitespace (outside block-level tags) is removed.
+ * Self-closing tags are converted to open tags.
+ * Attributes are sorted and lowercased.
+ * References are converted to unicode, except that '<', '>', '&', and
+ '&' are rendered using entities.
+ """
+ html_chunk_re = re.compile("(\|\<[^>]*\>|[^<]+)")
+ try:
+ parser = MyHTMLParser()
+ # We work around HTMLParser's limitations parsing CDATA
+ # by breaking the input into chunks and passing CDATA chunks
+ # through verbatim.
+ for chunk in re.finditer(html_chunk_re, html):
+ if chunk.group(0)[:8] == "