Add myself to credits.
[tapir.git] / t / harness.pir
blobbe31a1d9ef1c362e2e488d4022b8ba3e701aa40e
1 # Copyright (C) 2009, Jonathan "Duke" Leto <jonathan@leto.net>
4 .sub version
5     say "Tapir version 0.01"
6     exit 0
7 .end
9 .sub help
10     say <<"HELP"
12 Tapir is a TAP test harness. There are different ways to run it, depending on
13 your preferences and build, but this should always work:
15         parrot t/harness.pir t/*.t
17 If you have created binary "fakecutable" (this requires a working compiler in
18 your PATH) then you can use Tapir like this:
20         ./tapir t/*.t
22 Currently supported arguments:
23     -v                  Print the output of each test file
24     --verbose
26     --version           Print out the current Tapir version
28     -e
29     --exec=program      Use a given program to execute test scripts
30                         i.e. ./tapir --exec=perl t/*.t to run Perl tests
31     -h
32     --help              This message
34 HELP
35     exit 0
36 .end
38 .sub _parse_opts
39     .param pmc argv
40     .local pmc getopts, opts
41     load_bytecode "Getopt/Obj.pbc"
42     getopts = new ['Getopt';'Obj']
43     getopts."notOptStop"(1)
44     push getopts, "exec|e:s"
45     push getopts, "verbose|v"
46     push getopts, "version"
47     push getopts, "help|h"
48     opts = getopts."get_options"(argv)
49     .return(opts)
50 .end
52 .sub _find_max_file_length
53     .param pmc files
54     .local int numfiles
55     .local int maxlength
56     numfiles = files
57     maxlength = 0
58     $I0 = -1
59   loop_top:
60     inc $I0
61     if $I0 > numfiles goto loop_bottom
62     $S0 = files[$I0]
63     $I1 = length $S0
64     if $I1 <= maxlength goto loop_top
65     maxlength = $I1
66     goto loop_top
67   loop_bottom:
68     .return(maxlength)
69 .end
71 .sub _print_elipses
72     .param string filename
73     .param int maxlength
74     .local int namelength
75     .local int lengthdiff
76     namelength = length filename
77     lengthdiff = maxlength - namelength
78     $I0 = lengthdiff + 2
79     $S0 = repeat ".", $I0
80     print " "
81     print $S0
82     print " "
83 .end
85 .sub main :main
86     .param pmc argv
87     .local pmc opts
88     .local string exec, verbose
89     .local int argc
90     .local num start_time, end_time
92     start_time  = time
93     $S0  = shift argv  # get rid of harness.pir in the args list
95     argc = elements argv
96     if argc > 0 goto load_libs
97     help()
99   load_libs:
100     load_bytecode 'lib/Tapir/Parser.pbc'
101     load_bytecode 'lib/Tapir/Stream.pbc'
104     # parse command line args
105     opts    = _parse_opts(argv)
106     exec    = opts["exec"]
107     $S1     = opts["version"]
108     $S2     = opts["help"]
109     verbose = opts["verbose"]
111     unless $S2 goto check_version
112     help()
114   check_version:
115     unless $S1 goto make_parser
116     version()
118   make_parser:
119     .local pmc tapir, klass
120     klass = newclass [ 'Tapir'; 'Parser' ]
121     tapir = klass.'new'()
123     .local pmc stream, qx_data
124     .local int i
125     .local string file
126     .local string output
127     .local int success, exit_code
128     .local int total_files, failing_files, failing_tests, tests
129     .local int namelength
131     namelength = _find_max_file_length(argv)
132     i = 0
133     failing_files = 0
134     failing_tests = 0
135     total_files   = 0
136     tests         = 0
137   loop:
138     file = argv[i]
139     unless file goto done
140     inc total_files
141     print file
142     _print_elipses(file, namelength)
144     # we assume the test is PIR unless given an --exec flag
145     # how to do proper shebang-line detection?
146     .local string exec_cmd
147     exec_cmd = 'parrot'
148     unless exec goto run_cmd
149     exec_cmd = exec
150   run_cmd:
151     qx_data   = qx(exec_cmd,file)
152     output    = qx_data[0]
153     exit_code = qx_data[1]
154     unless verbose goto parse
155     print output
156   parse:
157     stream    = tapir.'parse_tapstream'(output, exit_code)
158     success   = stream.'is_pass'()
159     unless success goto fail
160     print "passed "
162     $I0 = stream.'total'() # includes todo tests
163     print $I0
164     tests += $I0
165     say " tests"
167     unless exit_code goto redo
168     # all tests passed but file had non-zero exit code
169     inc failing_files
171     goto redo
172   fail:
173     print "failed "
174     $I0 = stream.'get_fail'()
175     print $I0
176     inc failing_files
177     failing_tests += $I0
178     $S1 = stream.'total'()
179     $S0 = "/" . $S1
180     print $S0
181     print " tests"
182     $I1 = stream.'get_exit_code'()
183     unless $I1 goto newline
184     print ", exit code = "
185     say $I1
186     goto redo
187  newline:
188     print "\n"
189  redo:
190     inc i
191     goto loop
193  done:
194     if failing_files goto print_fail
195     print "PASSED "
196     print tests
197     print " test(s) in "
198     print total_files
199     print " files"
200     goto over
201   print_fail:
202     print "FAILED "
203     print failing_tests
204     print " test(s) in "
205     print failing_files
206     print "/"
207     print total_files
208     print " files"
209   over:
210     end_time = time
211     $N1 = end_time - start_time
212     print " ("
213     $P0 = new 'FixedPMCArray'
214     $P0 = 1
215     $P0[0] = $N1
216     $S1 = sprintf "%.4f", $P0
217     print $S1
218     say " seconds)"
219     $I0 = failing_files != 0
220     exit $I0
221 .end
223 .sub 'qx'
224     .param pmc command_and_args :slurpy
226     .local string cmd
227     cmd = join ' ', command_and_args
229     .local pmc pipe
230     pipe = new ['FileHandle']
231     pipe.'open'(cmd, 'rp')
232     unless pipe goto pipe_open_error
234     .local pmc output
235     pipe.'encoding'('utf8')
236     output = pipe.'readall'()
237     pipe.'close'()
239     .local pmc exit_status
240     $I0 = pipe.'exit_status'()
241     exit_status = box $I0
243     find_dynamic_lex $P0, '$!'
244     if null $P0 goto skip_exit_status
245     store_dynamic_lex '$!', exit_status
246   skip_exit_status:
248     # hack
249     $P0 = new 'FixedPMCArray'
250     $P0 = 2
251     $P0[0] = output
252     $P0[1] = exit_status
253     .return ($P0)
255   pipe_open_error:
256     $S0  = 'Unable to execute "'
257     $S0 .= cmd
258     $S0 .= '"'
259     die $S0
260 .end
262 # Local Variables:
263 #   mode: pir
264 #   fill-column: 100
265 # End:
266 # vim: expandtab shiftwidth=4 ft=pir: