cmark

My personal build of CMark ✏️

Commit
d042b7cf47390039fe9d04c9e41cc272263a25db
Parent
45a2e3a387909a73857f00612225aebda1d1f5b1
Author
John MacFarlane <jgm@berkeley.edu>
Date

Added (still commented-out) pathological tests to test.js.

Diffstat

1 file changed, 126 insertions, 62 deletions

Status File Name N° Changes Insertions Deletions
Modified js/test.js 188 126 62
diff --git a/js/test.js b/js/test.js
@@ -11,6 +11,21 @@ var escSeq = function(s) {
         return this;
     };
 };
+
+var repeat = function(pattern, count) {
+    if (count < 1) {
+        return '';
+    }
+    var result = '';
+    while (count > 1) {
+        if (count & 1) {
+            result += pattern;
+        }
+        count >>= 1, pattern += pattern;
+    }
+    return result + pattern;
+};
+
 var cursor = {
     write: function (s) {
         process.stdout.write(s);
@@ -25,74 +40,123 @@ var cursor = {
 var writer = new commonmark.HtmlRenderer();
 var reader = new commonmark.DocParser();
 
-var passed = 0;
-var failed = 0;
+var results = {
+    passed: 0,
+    failed: 0
+};
 
 var showSpaces = function(s) {
-  var t = s;
-  return t.replace(/\t/g, '→')
-    .replace(/ /g, '␣');
+    var t = s;
+    return t.replace(/\t/g, '→')
+        .replace(/ /g, '␣');
 };
 
-fs.readFile('spec.txt', 'utf8', function(err, data) {
-  if (err) {
-    return console.log(err);
-  }
-  var i;
-  var examples = [];
-  var current_section = "";
-  var example_number = 0;
-  var tests = data
-    .replace(/\r\n?/g, "\n") // Normalize newlines for platform independence
-    .replace(/^<!-- END TESTS -->(.|[\n])*/m, '');
-
-  tests.replace(/^\.\n([\s\S]*?)^\.\n([\s\S]*?)^\.$|^#{1,6} *(.*)$/gm,
-        function(_, markdownSubmatch, htmlSubmatch, sectionSubmatch){
-          if (sectionSubmatch) {
-            current_section = sectionSubmatch;
-          } else {
-            example_number++;
-            examples.push({markdown: markdownSubmatch,
-                           html: htmlSubmatch,
-                           section: current_section,
-                           number: example_number});
-          }
-      });
-
-  current_section = "";
-
-  console.time("Elapsed time");
-
-  for (i = 0; i < examples.length; i++) {
-    var example = examples[i];
-    if (example.section !== current_section) {
-      if (current_section !== '') {
+var pathologicalTest = function(testcase, results) {
+    cursor.write(testcase.name + ' ');
+    console.time('  elapsed time');
+    var actual = writer.render(reader.parse(testcase.input));
+    if (actual === testcase.expected) {
+        cursor.green().write('✓\n').reset();
+        results.passed += 1;
+    } else {
+        cursor.red().write('✘\n');
+        cursor.cyan();
+        cursor.write('=== markdown ===============\n');
+        cursor.write(showSpaces(testcase.input));
+        cursor.write('=== expected ===============\n');
+        cursor.write(showSpaces(testcase.expected));
+        cursor.write('=== got ====================\n');
+        cursor.write(showSpaces(actual));
         cursor.write('\n');
-      }
-      current_section = example.section;
-      cursor.reset().write(current_section).reset().write('  ');
+        cursor.reset();
+        results.failed += 1;
     }
-    var actual = writer.render(reader.parse(example.markdown.replace(/→/g, '\t')));
-    if (actual === example.html) {
-      passed++;
-      cursor.green().write('✓').reset();
-    } else {
-      failed++;
-      cursor.write('\n');
-
-      cursor.red().write('✘ Example ' + example.number + '\n');
-      cursor.cyan();
-      cursor.write('=== markdown ===============\n');
-      cursor.write(showSpaces(example.markdown));
-      cursor.write('=== expected ===============\n');
-      cursor.write(showSpaces(example.html));
-      cursor.write('=== got ====================\n');
-      cursor.write(showSpaces(actual));
-      cursor.reset();
+    console.timeEnd('  elapsed time');
+};
+
+fs.readFile('spec.txt', 'utf8', function(err, data) {
+    if (err) {
+        return console.log(err);
+    }
+    var i;
+    var examples = [];
+    var current_section = "";
+    var example_number = 0;
+    var tests = data
+            .replace(/\r\n?/g, "\n") // Normalize newlines for platform independence
+            .replace(/^<!-- END TESTS -->(.|[\n])*/m, '');
+
+    tests.replace(/^\.\n([\s\S]*?)^\.\n([\s\S]*?)^\.$|^#{1,6} *(.*)$/gm,
+                  function(_, markdownSubmatch, htmlSubmatch, sectionSubmatch){
+                      if (sectionSubmatch) {
+                          current_section = sectionSubmatch;
+                      } else {
+                          example_number++;
+                          examples.push({markdown: markdownSubmatch,
+                                         html: htmlSubmatch,
+                                         section: current_section,
+                                         number: example_number});
+                      }
+                  });
+
+    current_section = "";
+
+    cursor.write('Spec tests:\n\n');
+    console.time("Elapsed time");
+
+    for (i = 0; i < examples.length; i++) {
+        var example = examples[i];
+        if (example.section !== current_section) {
+            if (current_section !== '') {
+                cursor.write('\n');
+            }
+            current_section = example.section;
+            cursor.reset().write(current_section).reset().write('  ');
+        }
+        var actual = writer.render(reader.parse(example.markdown.replace(/→/g, '\t')));
+        if (actual === example.html) {
+            results.passed++;
+            cursor.green().write('✓').reset();
+        } else {
+            results.failed++;
+            cursor.write('\n');
+
+            cursor.red().write('✘ Example ' + example.number + '\n');
+            cursor.cyan();
+            cursor.write('=== markdown ===============\n');
+            cursor.write(showSpaces(example.markdown));
+            cursor.write('=== expected ===============\n');
+            cursor.write(showSpaces(example.html));
+            cursor.write('=== got ====================\n');
+            cursor.write(showSpaces(actual));
+            cursor.reset();
+        }
     }
-  }
-  cursor.write('\n' + passed.toString() + ' tests passed, ' +
-      failed.toString() + ' failed.\n');
+    cursor.write('\n');
+    console.timeEnd("Elapsed time");
+/*
+    // pathological cases
+    cursor.write('\nPathological cases:\n');
 
-  console.timeEnd("Elapsed time");
+    var cases = [
+        { name: 'U+0000 in input',
+          input: 'abc\u0000xyz\u0000\n',
+          expected: '<p>abc\ufffdxyz\ufffd</p>\n' },
+        { name: 'nested strong emph 10000 deep',
+          input: repeat('*a **a ', 10000) + 'b' + repeat(' a** a*', 10000),
+          expected: '<p>' + repeat('<em>a <strong>a ', 10000) + 'b' +
+          repeat(' a</strong> a</em>', 10000) + '</p>\n' },
+        { name: 'nested brackets 10000 deep',
+          input: repeat('[', 10000) + 'a' + repeat(']', 10000),
+          expected: '<p>' + repeat('[', 10000) + 'a' + repeat(']', 10000) +
+          '</p>\n' },
+    ];
+
+    for (var i = 0; i < cases.length; i++) {
+        pathologicalTest(cases[i], results);
+    }
+    cursor.write('\n');
+*/
+    cursor.write('\n' + results.passed.toString() + ' tests passed, ' +
+                 results.failed.toString() + ' failed.\n');
 });