Almost-working out of order test detection
[tapir.git] / lib / Tapir / Parser.pir
blob3ea9ee12ed6199f1e73891a0095368ddec7b99fc
1 # Copyright (C) 2009, Jonathan "Duke" Leto
3 =head1 AUTHOR
5 Written and maintained by Jonathan "Duke" Leto C<< jonathan@leto.net >>.
7 =cut
9 .namespace [ 'Tapir'; 'Parser' ]
11 .sub bail_if_necessary :method
12     .param string line
13     $S0 = substr line, 0, 9
14     if $S0 == 'Bail out!' goto bail_out
15     .return(0)
16   bail_out:
17     .return(1)
18 .end
20 .sub parse_tapstream :method
21     .param string tap
22     .param int exit_code :optional
23     .local string curr_line
24     .local pmc plan, pass, fail, skip, todo
25     .local int i, curr_test, reported_test, ordered
26     .local pmc tap_lines, parts, klass, stream
28     i         = 0
29     curr_test = 1
30     ordered   = 1
31     fail      = new 'Integer'
32     skip      = new 'Integer'
33     todo      = new 'Integer'
34     pass      = new 'Integer'
35     plan      = new 'Integer'
36     tap_lines = new 'ResizablePMCArray'
37     parts     = new 'ResizablePMCArray'
39     split tap_lines, "\n", tap
40     $I0 = tap_lines
42     .local string plan_line
43     plan_line = tap_lines[0]
44     plan      = self.'parse_plan'(plan_line)
46     .local string prefix
47   loop:
48     if i >= $I0 goto done
49     curr_line = tap_lines[i]
50     $I1 = self.'bail_if_necessary'(curr_line)
51     if $I1 goto done
53     $I1 = self.'is_tap'(curr_line)
54     unless $I1 goto unrecognized
56     split parts, "ok ", curr_line
58     prefix        = parts[0]
59     reported_test = parts[1]
61     if prefix == 'not ' goto fail_or_todo
63     if reported_test == curr_test goto pass_or_skip
64     # out of order test
65     ordered = 0
67   unrecognized: # doesn't look like TAP, just ignore
68     inc i
69     goto loop
70   pass_or_skip:
71     split parts, "# ", curr_line
72     $S0 = parts[1]
73     $S0 = substr $S0, 0, 4
74     downcase $S0
75     if $S0 != "skip" goto passz
76     # it is a SKIP test!
77     inc skip
78     inc i
79     inc curr_test
80     goto loop
81   fail_or_todo:
82     split parts, "# ", curr_line
83     $S0 = parts[1]
84     $S0 = substr $S0, 0, 4
85     downcase $S0
86     if $S0 != "todo" goto failz
87     # it is a TODO test!
88     inc todo
89     inc curr_test
90     inc i
91     goto loop
92   failz:
93     inc fail
94     inc curr_test
95     inc i
96     goto loop
97   passz:
98     inc pass
99     inc i
100     inc curr_test
101     goto loop
103   done:
104     stream = new [ 'Tapir'; 'Stream' ]
105     stream.'set_pass'(pass)
106     stream.'set_fail'(fail)
107     stream.'set_todo'(todo)
108     stream.'set_skip'(skip)
109     stream.'set_plan'(plan)
110     stream.'set_exit_code'(exit_code)
111     .return (stream)
112 .end
114 .sub is_tap :method
115     .param string tapline
116     $S0 = substr tapline, 0, 2
117     if $S0 == "ok" goto yes
119     $S0 = substr tapline, 0, 5
120     if $S0 == "not ok" goto yes
121     yes:
122         .return( 1 )
123     no:
124         .return( 0 )
125 .end
127 # parse_plan returns the expected number of tests given a plan line as a string
129 .sub parse_plan :method
130     .param string plan_line
131     .local pmc plan_parts
132     # yes, a numeric
133     .local num num_expected_tests
135     $I0 = length plan_line
136     if $I0 < 4 goto plan_error
138     # this needs to take into account TAP Versions
139     $S0 = substr plan_line, 0, 3
140     unless $S0 == "1.." goto plan_error
142     plan_parts = new 'FixedPMCArray'
143     plan_parts = 2
145     split plan_parts, "..", plan_line
146     num_expected_tests  = plan_parts[1]
148     $I1 = num_expected_tests
149     unless $I1 == num_expected_tests goto plan_error
150     .return (num_expected_tests)
151   plan_error:
152     # this indicates an invalid plan
153     .return (-1)
154 .end
157 # Local Variables:
158 #   mode: pir
159 #   fill-column: 100
160 # End:
161 # vim: expandtab shiftwidth=4 ft=pir: