aboutsummaryrefslogtreecommitdiff
path: root/runtests.pl
blob: 370b43c939b8a6d8f214064043f99b777e0f943f (plain)
  1. #!/usr/bin/env perl
  2. use 5.006;
  3. use warnings;
  4. use strict;
  5. use utf8;
  6. use Term::ANSIColor;
  7. use IO::Handle;
  8. use IPC::Open2;
  9. $|++;
  10. my $usage="runtests.pl PROGRAM SPEC\nSet ANSI_COLORS_DISABLED=1 if you redirect to a file.\nSet PATT='...' to restrict tests to sections matching a regex.\n";
  11. my $PROG=$ARGV[0];
  12. my $SPEC=$ARGV[1];
  13. my $PATT=$ENV{'PATT'};
  14. if (!(defined $PROG && defined $SPEC)) {
  15. print STDERR $usage;
  16. exit 1;
  17. }
  18. my $passed = 0;
  19. my $failed = 0;
  20. my $skipped = 0;
  21. # Markdown implementations vary on insignificant whitespace.
  22. # Some leave blanks between block elements, others don't.
  23. # This function tries to normalize the output so it can be
  24. # compared with our test. tidy takes two arguments: the
  25. # string containing the actual output, and a pathname of the
  26. # file to which the tidied output is to be saved.
  27. sub tidy
  28. {
  29. my $inpre = 0;
  30. my $out = "";
  31. my $outfh;
  32. open($outfh, '>', \$out);
  33. for (split /^/, $_[0]) {
  34. if (/<pre/) {
  35. $inpre = 1;
  36. } elsif (/<\/pre/) {
  37. $inpre = 0;
  38. }
  39. if ($inpre) {
  40. print $outfh $_;
  41. } else {
  42. # remove leading spaces
  43. s/^ *//;
  44. # remove trailing spaces
  45. s/ *$//;
  46. # collapse consecutive spaces
  47. s/ */ /;
  48. # collapse space before /> in tag
  49. s/ *\/>/\/>/;
  50. # skip blank line
  51. if (/^$/) {
  52. next;
  53. }
  54. print $outfh $_;
  55. }
  56. }
  57. close $outfh;
  58. return $out;
  59. }
  60. sub dotest
  61. {
  62. my $markdown = $_[0];
  63. my $html = $_[1];
  64. my $testname = $_[2];
  65. my $actual = "";
  66. # We use → to indicate tab and ␣ space in the spec
  67. $markdown =~ s/→/\t/g;s/␣/ /g;
  68. $html =~ s/→/\t/g;s/␣/ /g;
  69. open2(my $out, my $in, $PROG);
  70. print $in $markdown;
  71. close $in;
  72. flush $out;
  73. $actual = do { local $/; <$out>; };
  74. close $out;
  75. $html = &tidy($html);
  76. $actual = &tidy($actual);
  77. $actual =~ s/\&#39;/'/;
  78. if ($actual eq $html) {
  79. print colored("✓", "green");
  80. return 1;
  81. } else {
  82. print colored("\n$testname", "red");
  83. print "\n";
  84. print color "cyan";
  85. print "=== markdown ===============\n";
  86. print $markdown;
  87. print "=== expected ===============\n";
  88. print $html;
  89. print "=== got ====================\n";
  90. print $actual;
  91. print color "black";
  92. return 0;
  93. }
  94. }
  95. my $stage = 0;
  96. my $markdown = "";
  97. my $html = "";
  98. my $example = 0;
  99. my $linenum = 0;
  100. my $exampleline = 0;
  101. my @secnums = ();
  102. my $secheading;
  103. open(SPEC, "< $SPEC");
  104. while (<SPEC>) {
  105. $linenum++;
  106. if (/^\.$/) {
  107. $stage = ($stage + 1) % 3;
  108. if ($stage == 1) {
  109. $exampleline = $linenum;
  110. }
  111. if ($stage == 0) {
  112. $example++;
  113. if (!$PATT || $secheading =~ /$PATT/) {
  114. if (&dotest($markdown, $html,
  115. "Example $example (line $exampleline)")) {
  116. $passed++;
  117. } else {
  118. $failed++;
  119. }
  120. } else {
  121. $skipped++;
  122. }
  123. $markdown = "";
  124. $html = "";
  125. }
  126. } elsif ($stage == 0 && $_ =~ /^<!-- END TESTS -->/) {
  127. last;
  128. } elsif ($stage == 0 && $_ =~ /^(#+) +(.*)/) {
  129. my $seclevel = length($1);
  130. $secheading = $2;
  131. if ($#secnums == $seclevel - 1) {
  132. $secnums[$#secnums]++;
  133. } elsif ($#secnums > $seclevel - 1) {
  134. @secnums = @secnums[0..($seclevel - 1)];
  135. $secnums[$#secnums]++;
  136. } else {
  137. while ($#secnums < $seclevel - 1) {
  138. push(@secnums, 1);
  139. }
  140. }
  141. if (!$PATT || $secheading =~ /$PATT/) {
  142. print ("\n", join(".", @secnums) . " " . $secheading, " ");
  143. }
  144. } elsif ($stage == 1) {
  145. $markdown .= $_;
  146. } elsif ($stage == 2) {
  147. $html .= $_;
  148. }
  149. }
  150. print "\n";
  151. print STDERR colored("$passed tests passed, $failed failed, $skipped skipped.", "bold");
  152. print STDERR "\n";
  153. exit $failed;