2 # Copyright (C) 2006-2008, Parrot Foundation.
7 t/op/sprintf.t -- sprintf tests
11 % prove t/op/sprintf.t
15 These tests are based on C<sprintf> tests from perl 5.9.4.
17 Tests C<sprintf>, excluding handling of 64-bit integers or long
18 doubles (if supported), of machine-specific short and long
19 integers, machine-specific floating point exceptions (infinity,
20 not-a-number, etc.), of the effects of locale, and of features
21 specific to multi-byte characters (under the utf8 pragma and such).
23 Individual tests are stored in the F<sprintf_tests> file in the same
24 directory; There is one test per line. In each test, there are three
29 =item * printf template
31 =item * data to be formatted (as a parrot expression)
33 =item * expected result of formatting
37 Optional fields contain a comment.
39 Each field is separated by one or more tabs. If formatting requires more than
40 one data item (for example, if variable field widths are used), the Parrot
41 data expression should return a reference to an array having the requisite
42 number of elements. Even so, subterfuge is sometimes required:
43 see tests for C<%n> and C<%p>.
45 =head1 XXX: FIXME: TODO:
47 Tests that are expected to fail on a certain OS can be marked as such
48 by trailing the comment with a C<skip:> section. Skips are tags separated
49 by space consisting of a C<$^O> optionally trailed with C<:osvers>. In the
50 latter case, all os-levels below that are expected to fail. A special
51 tag C<all> is allowed for todo tests that should fail on any system.
53 %G 1234567e96 1.23457E+102 exponent too big skip: os390
54 %.0f -0.1 -0 C library bug: no minus skip: VMS
55 %d 4 1 4 != 1 skip: all
60 .const int TESTS = 308
63 load_bytecode 'Test/Builder.pbc'
64 .include "iglobals.pasm"
65 .include "sysinfo.pasm"
67 # Variable declarations, initializations
68 .local pmc test # the test harness object.
69 test = new [ 'Test'; 'Builder' ]
71 .local pmc todo_tests # keys indicate test file; values test number.
72 todo_tests = new 'Hash'
74 .local pmc skip_tests # keys indicate tests ID; values reasons.
75 skip_tests = new 'Hash'
77 .local string test_dir # the directory containing tests
80 .local pmc test_files # values are test file names to run.
81 test_files = new 'ResizablePMCArray'
83 # populate the list of test files
84 push test_files, 'sprintf_tests'
87 .local pmc file_iterator # iterate over list of files..
88 file_iterator = iter test_files
90 .local int test_number # the number of the test we're running
93 # these vars are in the loops below
94 .local string test_line # one line of one test file, a single test
95 .local int ok # is this a passing test?
98 .local string template # the sprintf template
99 .local string data # the data to format with the template
100 .local string expected # expected result of this test
101 .local string description # user-facing description of the test
102 .local int skip_it # skip this test on this platform?
103 .local string actual # actual result of the test
105 todo_tests = 'set_todo_info'()
106 skip_tests = 'set_skip_info'()
108 # how many tests to run?
109 # XXX: this should be summed automatically from test_files data
110 # until then, it's set to no plan
114 unless file_iterator goto end_outer_loop
115 .local string test_name # file name of the current test file
116 test_name = shift file_iterator
118 .local string test_file # full name of the current test file
119 test_file = test_dir . test_name
121 .local int local_test_number # local test number in test file
122 local_test_number = 0
125 .local pmc file_handle # currently open file
126 file_handle = open test_file, 'r'
128 unless file_handle goto bad_file
130 # loop over the file, one at a time.
133 # read in the file one line at a time...
134 $I0 = file_handle.'eof'()
137 test_line = readline file_handle
139 # skip lines without tabs, and comment lines
140 $I0 = index test_line, "\t"
141 if $I0 == -1 goto loop
142 $I0 = index test_line, '#'
143 if $I0 == 0 goto loop
145 inc local_test_number
149 ( template, data, expected, description, skip_it ) = parse_data( test_line )
152 # prepend test filename and line number to description
153 description = 'build_test_desc'( description, template )
156 data_hash = new 'Hash'
158 data_hash['2**32-1'] = 0xffffffff
160 data_hash['2**38'] = $N0
161 data_hash["'string'"] = 'string'
163 $I0 = exists data_hash[data]
164 unless $I0 goto got_data
165 data = data_hash[data]
168 # data = backslash_escape (data)
169 # expected = backslash_escape (expected)
171 # Should this test be skipped?
173 $S0 .= ' (skipped on this platform)'
174 if skip_it goto must_skip
175 $I0 = exists skip_tests[test_name]
176 unless $I0 goto not_skip
177 $P0 = skip_tests[test_name]
178 $I0 = exists $P0[local_test_number]
179 unless $I0 goto not_skip
180 $S0 = $P0[local_test_number]
187 actual = 'sprintf'(template, data)
189 unless_null actual, sprintf_ok
190 $P1 = new 'Exception'
191 $P1[0] = 'sprintf error'
195 if expected == actual goto is_ok
196 description .= ' actual: >'
197 description .= actual
199 description .= ' expected: >'
200 description .= expected
205 $S0 = substr expected, 0, 1
206 if $S0 != "/" goto eh_bad_line
207 substr expected, 0, 1, ''
208 substr expected, -1, 1, ''
210 $I0 = index $S1, expected
211 if $I0 == -1 goto is_nok
221 $I0 = exists todo_tests[test_name]
222 unless $I0 goto not_todo
223 $P0 = todo_tests[test_name]
224 $I0 = exists $P0[local_test_number]
225 unless $I0 goto not_todo
226 test.'todo'(ok,description)
229 test.'ok'(ok,description)
241 print "Unable to open '"
247 .local string message
248 get_results '0', exception
250 $I0 = index message, 'is not a valid sprintf format'
251 if $I0 == -1 goto other_error
252 $I0 = index expected, ' INVALID'
253 if $I0 == -1 goto bad_error
261 $S0 = "Test not formatted properly!"
269 .param pmc args :slurpy
272 $S1 = sprintf $S0, args
278 # set todo information
280 .local pmc todo_tests # keys indicate test file; values test number
281 todo_tests = new 'Hash'
284 todo_info = new 'Hash'
286 jmpstack = new 'ResizableIntegerArray'
288 .local string test_file
290 local_branch jmpstack, reset_todo_info
291 test_file = 'sprintf_tests'
293 todo_info[64] = 'undecided perl5 vs. posix behavior'
294 todo_info[153] = '%hf should be rejected'
295 todo_info[187] = '%h alone is invalid'
296 todo_info[191] = '%l alone is invalid'
297 todo_info[223] = '%v alone is invalid, but a valid parrot extension'
298 todo_info[304] = 'undecided'
299 todo_info[305] = 'undecided'
300 todo_info[306] = 'undecided'
303 todo_tests[test_file] = todo_info
308 todo_info = new 'Hash'
309 local_return jmpstack
312 if $I0 > $I1 goto end_loop
317 local_return jmpstack
321 # set skip information
323 .local pmc skip_tests # keys indicate test file; values test number
324 skip_tests = new 'Hash'
327 skip_info = new 'Hash'
329 jmpstack = new 'ResizableIntegerArray'
331 .local string test_file
333 local_branch jmpstack, reset_skip_info
334 test_file = 'sprintf_tests'
335 skip_info[5] = 'parrot extension (%B)'
336 skip_info[7] = 'perl5-specific extension (%D)'
337 skip_info[9] = 'perl5-specific extension (%F)'
338 skip_info[16] = 'parrot extension (%H)'
339 skip_info[20] = 'parrot extension (%L)'
340 skip_info[23] = 'perl5-specific extension (%O)'
341 skip_info[24] = 'parrot extension (%P)'
342 skip_info[27] = 'parrot extension (%S)'
343 skip_info[29] = 'perl5-specific extension (%U)'
345 $S0 = 'perl5-specific extension (%v...)'
348 local_branch jmpstack, set_skip_loop
350 skip_info[114] = 'harness needs support for * modifier'
351 skip_info[144] = 'perl5 expresssion as test value'
352 skip_info[131] = 'harness needs support for * modifier'
353 skip_info[141] = 'harness needs support for * modifier'
354 skip_info[161] = 'harness needs support for * modifier'
355 skip_info[166] = 'harness needs support for * modifier'
356 skip_info[193] = 'perl5-specific test'
357 skip_info[200] = 'perl5-specific test'
358 skip_info[201] = 'perl5-specific test'
359 skip_info[202] = 'parrot extension (%p)'
360 skip_info[204] = 'parrot extension (%r)'
361 skip_info[210] = 'harness needs support for * modifier'
362 skip_info[214] = 'harness needs support for * modifier'
363 skip_info[233] = 'harness needs support for * modifier'
364 skip_info[234] = 'perl5-specific extension (%v...)'
365 skip_info[235] = 'perl5-specific extension (%v...)'
366 skip_info[300] = 'harness needs support for * modifier'
368 $S0 = 'perl5-specific test'
371 local_branch jmpstack, set_skip_loop
373 $S0 = 'perl5-specific extension (%v...)'
376 local_branch jmpstack, set_skip_loop
378 skip_info[307] = 'perl5-specific extension (%v...)'
379 skip_info[308] = 'perl5-specific extension (%v...)'
381 skip_tests[test_file] = skip_info
386 skip_info = new 'Hash'
387 local_return jmpstack
390 if $I0 > $I1 goto end_loop
391 if $S0 != '' goto set_skip_info
392 $S0 = 'unknown reason'
399 local_return jmpstack
404 .param string record # the data record
406 .local string template # the sprintf template
407 .local string data # the data to format with the template
408 .local string expected # expected result of this test
409 .local string description # user-facing description of the test
410 .local int skip_it # skip this test on this platform
413 # NOTE: there can be multiple tabs between entries, so skip until
415 # remove the trailing newline from record
417 $P1 = split "\t", record
418 $I0 = elements $P1 # length of array
419 .local int tab_number
422 if tab_number >= $I0 goto bad_line
423 template = $P1[tab_number]
425 if template == '' goto get_template
427 if tab_number >= $I0 goto bad_line
428 data = $P1[tab_number]
430 if data == '' goto get_data
433 if tab_number >= $I0 goto empty_expected
434 expected = $P1[tab_number]
436 if expected == '' goto get_expected
437 ## FIXME: description handling
439 if tab_number >= $I0 goto no_desc
440 description = $P1[tab_number]
442 if description == '' goto get_description
444 ( description, skip_it ) = find_skip_in_description( description )
447 # substr description, -1, 1, ''
451 .return ( template, data, expected, description, skip_it )
458 $P1 = new 'Exception'
459 $P1[0] = 'invalid data format'
464 .sub 'find_skip_in_description'
465 .param string description
468 parts = split ' skip: ', description
471 if $I0 > 1 goto check_os
472 .return( description, 0 )
475 description = shift parts
477 .local string skip_list
478 skip_list = shift parts
481 skip_os = split ' ', skip_list
487 osname = sysinfo .SYSINFO_PARROT_OS
490 unless it goto iter_end
491 .local string os_name
493 eq os_name, osname, skip_it
496 .return( description, 0 )
499 .return( description, 1 )
503 .sub 'build_test_desc'
505 .param string testname
511 desc = concat $S0, desc
517 # The following tests are not currently run, for the reasons stated:
523 >%.0f< >1.5< >2< >Standard vague: no rounding rules<
524 >%.0f< >2.5< >2< >Standard vague: no rounding rules<
534 # vim: expandtab shiftwidth=4 ft=pir: