2 # Copyright (C) 2001-2008, The Perl Foundation.
7 t/compilers/pge/perl6regex/01-regex.t -- Basic Perl6Regex tests
11 These tests are based on L<http://dev.perl.org/perl6/doc/design/syn/S05.html>.
12 Individual tests are stored in the C<rx_*> files in the same directory;
13 There is one test per line: each test consists of the following
14 columns (separated by one *or more* tabs):
20 The Perl 6 regex to test.
24 The string that will be matched against the pattern. Use '' to indicate
29 The expected result of the match. Either C<y> for a successful match, C<n>
30 for a failed one. Otherwise the output is expected to begin and end with
33 This result is used in one of two ways: If an exception is thrown by the
34 match, the result must be contained in the exception's message. If the match
35 succeeds, then the message must be contained in a dump of the match object.
39 A unique test identifier. This allows us to track TODO/SKIP information in
40 *this* file instead of the associated test file, which lets us easily
41 share the tests across implementations of perl6's regex engine.
45 Description of the test.
51 % prove t/compilers/pge/01-regex.t
55 .const string TESTS = 'no_plan'
58 load_bytecode 'Test/Builder.pir'
59 load_bytecode 'PGE.pbc'
60 load_bytecode 'PGE/Dumper.pbc'
61 load_bytecode 'String/Utils.pbc'
62 .include "iglobals.pasm"
64 # Variable declarations, initializations
65 .local pmc test # the test harness object.
66 test = new [ 'Test'; 'Builder' ]
68 .local string test_dir # the directory containing tests
69 test_dir = 't/compilers/pge/perl6regex/'
71 .local pmc test_files # values are test file names to run.
72 test_files = new 'ResizablePMCArray'
74 # populate the list of test files
75 push test_files, 'rx_metachars'
76 push test_files, 'rx_quantifiers'
77 push test_files, 'rx_backtrack'
78 push test_files, 'rx_charclass'
79 push test_files, 'rx_subrules'
80 push test_files, 'rx_lookarounds'
81 push test_files, 'rx_captures'
82 push test_files, 'rx_modifiers'
83 push test_files, 'rx_syntax'
85 .local pmc interp # a handle to our interpreter object.
89 config = interp[.IGLOBALS_CONFIG_HASH]
91 .local int has_icu # flag indicating presense of icu
92 has_icu = config['has_icu']
94 .local pmc file_iterator # iterate over list of files..
95 file_iterator = new 'Iterator', test_files
97 .local int test_number # the number of the test we're running
100 # these vars are in the loops below
101 .local pmc file_handle # currently open file.
102 .local string test_file # name of the current test file
103 .local string test_line # one line of one test file, a single test
104 .local int ok # is this a passing test?
106 # for any given test:
107 .local int skiptest # if the test is '# skip'
108 .local int todotest # if the test is '# todo'
109 .local string reason # reason for todo/skip
110 .local pmc rule # the rule
111 .local pmc match # the match
112 .local string pattern # the regexp
113 .local string target # this string to match against the regex
114 .local string result # expected result of this test. (y/n/...)
115 .local string description # user-facing description of the test.
117 # how many tests to run?
118 # XXX: this should be summed automatically from test_files data
119 # until then, it's set to no plan
124 unless file_iterator goto end_outer_loop
125 .local string test_name
126 test_name = shift file_iterator
127 # local test number in test file
128 .local int local_test_number
129 local_test_number = 0
131 # local line number in test file
132 .local int local_line_number
133 local_line_number = 0
135 # append the test directory and filename
136 test_file = test_dir . test_name
139 file_handle = open test_file, '<'
140 $S0 = typeof file_handle
141 if $S0 == 'Undef' goto bad_file
148 # loop over the file, one at a time.
150 # read in the file one line at a time...
151 $I0 = file_handle.'eof'()
154 test_line = readline file_handle
155 inc local_line_number
157 # if this line is not a comment, try a test
158 $S0 = substr test_line, 0, 1
159 if $S0 != '#' goto parse_test
162 # line is a comment, if no :pge<...> then skip comment
163 $I0 = index test_line, ':pge<'
164 if $I0 == -1 goto loop
166 # extract out the reason for skip or todo
168 $I1 = index test_line, '>', $I0
170 reason = substr test_line, $I0, $I1
172 # determine skip/todo
173 $P0 = split ' ', test_line
175 if $S0 == 'skip' goto comment_skip
176 if $S0 == 'todo' goto comment_todo
177 if $S0 == 'trace' goto comment_trace
191 # skip lines without tabs
192 $I0 = index test_line, "\t"
193 if $I0 == -1 goto loop
195 inc local_test_number
199 ( pattern, target, result, description ) = parse_data( test_line )
202 # prepend test filename and line number to description
203 description = 'build_test_desc'( description, test_name, local_line_number )
205 if target != "''" goto got_target
209 target = 'backslash_escape'( target )
210 result = 'backslash_escape'( result )
212 # Should this test be skipped?
213 unless skiptest goto not_skip
214 test.'skip'(1, reason)
219 match = 'match_perl6regex'( pattern, target )
222 if match goto matched
224 if result == 'n' goto is_ok
225 if result == 'y' goto is_nok
229 if result == 'y' goto is_ok
230 if result == 'n' goto is_nok
234 $S1 = match.'dump_str'('mob', ' ', '')
237 $S0 = substr result, 0, 1
238 if $S0 != "/" goto bad_line
239 substr result, 0, 1, ''
240 substr result, -1, 1, ''
242 $I0 = index $S1, result
243 if $I0 == -1 goto is_nok
253 unless todotest goto not_todo
254 test.'todo'(ok, description, reason)
257 test.'ok'(ok, description)
269 print "Unable to open '"
275 .local string message
276 get_results '0,0', exception, message
279 $S0 = substr result, 0, 1
280 if $S0 != "/" goto bad_error
281 substr result, 0, 1, ''
282 substr result, -1, 1, ''
283 $I0 = index message, result
284 if $I0 == -1 goto bad_error
291 $S0 = "Test not formatted properly!"
295 $S0 = "Test not formatted properly!"
302 .param string test_line # the data record
304 .local pmc rule # the rule
305 .local pmc match # the match
306 .local string pattern # the regexp
307 .local string target # this string to match against the regex
308 .local string result # expected result of this test. (y/n/...)
309 .local string description # user-facing description of the test.
311 # NOTE: there can be multiple tabs between entries, so skip until
313 # remove the trailing newline from record
316 $P1 = split "\t", test_line
317 $I0 = elements $P1 # length of array
318 .local int tab_number
321 if tab_number >= $I0 goto bad_line
322 pattern = $P1[tab_number]
325 if tab_number >= $I0 goto bad_line
326 target = $P1[tab_number]
328 if target == '' goto get_target
330 if tab_number >= $I0 goto bad_line
331 result = $P1[tab_number]
333 if result == '' goto get_result
335 if tab_number >= $I0 goto bad_line
336 description = $P1[tab_number]
338 if description == '' goto get_description
341 .return ( pattern, target, result, description )
344 $P1 = new 'Exception'
345 $P1 = 'invalid data format'
350 .sub 'build_test_desc'
352 .param string test_name
353 .param string local_test_number
358 $S0 .= local_test_number
361 desc = concat $S0, desc
367 .sub 'match_perl6regex'
368 .param string pattern
373 .local pmc p6rule # the perl6 regex compiler
374 p6rule = compreg 'PGE::Perl6Regex'
377 rule = p6rule(pattern)
379 unless_null rule, match_it
380 $P1 = new 'Exception'
390 # given a 2 digit string, convert to appropriate chr() value.
394 $S0 = substr hex, 0, 1
395 $S1 = substr hex, 1, 1
409 # given a single digit hex value, return it's int value.
414 if $I0 < 48 goto bad_digit
415 if $I0 > 57 goto non_numeric
419 if $I0 < 65 goto bad_digit
420 if $I0 > 70 goto not_capital
421 $I0 -= 55 # A is ascii 65, so reset to zero, add 10 for hex..
424 if $I0 < 97 goto bad_digit
425 if $I0 > 102 goto bad_digit
426 $I0 -= 87 # a is ascii 97, so reset to zero, add 10 for hex..
430 $P1 = new 'Exception'
431 $P1 = 'invalid hex digit'
436 .sub backslash_escape
440 $I0 = index target, '\n'
441 if $I0 == -1 goto target2
442 substr target, $I0, 2, "\n"
445 $I0 = index target, '\r'
446 if $I0 == -1 goto target3
447 substr target, $I0, 2, "\r"
450 $I0 = index target, '\e'
451 if $I0 == -1 goto target4
452 substr target, $I0, 2, "\e"
455 $I0 = index target, '\t'
456 if $I0 == -1 goto target5
457 substr target, $I0, 2, "\t"
460 $I0 = index target, '\f'
461 if $I0 == -1 goto target6
462 substr target, $I0, 2, "\f"
465 # handle \xHH, hex escape.
467 $I0 = index target, '\x'
468 if $I0 == -1 goto target7
471 $P0 = get_hll_global ['String';'Utils'], 'convert_digits_to_string'
472 ($S0, $I2) = $P0(target, 'x', $I1)
473 $S3 = substr target, $I1, $I2
475 substr target, $I0, $I2, $S0
481 =head1 BUGS AND LIMITATIONS
483 Note that while our job would be easier if we could use regular expressions
484 in here, but we want to avoid any dependency on the thing we're testing.
486 Need to add in test ids, to avoid the precarious line numbering.
494 # vim: expandtab shiftwidth=4 ft=pir: