Improve the is_tap method in Tapir::Parser and add some tests
[tapir.git] / lib / Tapir / Parser.pir
blobdfe0340d07d5e78cf9391caa1a7bb5a57807e3cd
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, 3
117     if $S0 == "ok " goto yes
119     $S0 = substr tapline, 0, 7
120     if $S0 == "not ok " goto yes
122     goto no
123     yes:
124         .return( 1 )
125     no:
126         .return( 0 )
127 .end
129 # parse_plan returns the expected number of tests given a plan line as a string
131 .sub parse_plan :method
132     .param string plan_line
133     .local pmc plan_parts
134     # yes, a numeric
135     .local num num_expected_tests
137     $I0 = length plan_line
138     if $I0 < 4 goto plan_error
140     # this needs to take into account TAP Versions
141     $S0 = substr plan_line, 0, 3
142     unless $S0 == "1.." goto plan_error
144     plan_parts = new 'FixedPMCArray'
145     plan_parts = 2
147     split plan_parts, "..", plan_line
148     num_expected_tests  = plan_parts[1]
150     $I1 = num_expected_tests
151     unless $I1 == num_expected_tests goto plan_error
152     .return (num_expected_tests)
153   plan_error:
154     # this indicates an invalid plan
155     .return (-1)
156 .end
159 # Local Variables:
160 #   mode: pir
161 #   fill-column: 100
162 # End:
163 # vim: expandtab shiftwidth=4 ft=pir: