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