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