Out of order tests are now detected
[tapir.git] / lib / Tapir / Parser.pir
blob948c507e369dd89c20462161c46c2c5d5ead62d8
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, num_lines
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     num_lines = 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 >= num_lines goto done
49     curr_line = tap_lines[i]
51     .local int need_to_bail
52     need_to_bail = self.'bail_if_necessary'(curr_line)
53     if need_to_bail goto done
55     .local int is_tap
56     is_tap = self.'is_tap'(curr_line)
57     unless is_tap goto unrecognized
59     split parts, "ok ", curr_line
61     prefix        = parts[0]
62     reported_test = parts[1]
64     if prefix == 'not ' goto fail_or_todo
66     if reported_test == curr_test goto pass_or_skip
67     # out of order test
68     ordered = 0
70     goto pass_or_skip
72   unrecognized: # doesn't look like TAP, just ignore
73     inc i
74     goto loop
76   pass_or_skip:
77     split parts, "# ", curr_line
78     $S0 = parts[1]
79     $S0 = substr $S0, 0, 4
80     downcase $S0
81     if $S0 != "skip" goto passz
82     # it is a SKIP test!
83     inc skip
84     inc i
85     inc curr_test
86     goto loop
87   fail_or_todo:
88     split parts, "# ", curr_line
89     $S0 = parts[1]
90     $S0 = substr $S0, 0, 4
91     downcase $S0
92     if $S0 != "todo" goto failz
93     # it is a TODO test!
94     inc todo
95     inc curr_test
96     inc i
97     goto loop
98   failz:
99     inc fail
100     inc curr_test
101     inc i
102     goto loop
103   passz:
104     inc pass
105     inc i
106     inc curr_test
107     goto loop
109   done:
110     stream = new [ 'Tapir'; 'Stream' ]
111     stream.'set_ordered'(ordered)
112     stream.'set_pass'(pass)
113     stream.'set_fail'(fail)
114     stream.'set_todo'(todo)
115     stream.'set_skip'(skip)
116     stream.'set_plan'(plan)
117     stream.'set_exit_code'(exit_code)
118     .return (stream)
119 .end
121 .sub is_tap :method
122     .param string tapline
123     $S0 = substr tapline, 0, 3
124     if $S0 == "ok " goto yes
126     $S0 = substr tapline, 0, 7
127     if $S0 == "not ok " goto yes
129     no:
130         .return( 0 )
131     yes:
132         .return( 1 )
133 .end
135 # parse_plan returns the expected number of tests given a plan line as a string
137 .sub parse_plan :method
138     .param string plan_line
139     .local pmc plan_parts
140     # yes, a numeric
141     .local num num_expected_tests
143     $I0 = length plan_line
144     if $I0 < 4 goto plan_error
146     # this needs to take into account TAP Versions
147     $S0 = substr plan_line, 0, 3
148     unless $S0 == "1.." goto plan_error
150     plan_parts = new 'FixedPMCArray'
151     plan_parts = 2
153     split plan_parts, "..", plan_line
154     num_expected_tests  = plan_parts[1]
156     $I1 = num_expected_tests
157     unless $I1 == num_expected_tests goto plan_error
158     .return (num_expected_tests)
159   plan_error:
160     # this indicates an invalid plan
161     .return (-1)
162 .end
165 # Local Variables:
166 #   mode: pir
167 #   fill-column: 100
168 # End:
169 # vim: expandtab shiftwidth=4 ft=pir: