2 # Copyright (C) 2006-2008, The Perl 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 'config.pir'
64 load_bytecode 'Test/Builder.pir'
65 load_bytecode 'PGE.pbc'
66 load_bytecode 'PGE/Dumper.pbc'
67 .include "iglobals.pasm"
69 # Variable declarations, initializations
70 .local pmc test # the test harness object.
71 test = new [ 'Test'; 'Builder' ]
73 .local pmc todo_tests # keys indicate test file; values test number.
74 todo_tests = new 'Hash'
76 .local pmc skip_tests # keys indicate tests ID; values reasons.
77 skip_tests = new 'Hash'
79 .local string test_dir # the directory containing tests
82 .local pmc test_files # values are test file names to run.
83 test_files = new 'ResizablePMCArray'
85 # populate the list of test files
86 push test_files, 'sprintf_tests'
89 .local pmc file_iterator # iterate over list of files..
90 file_iterator = new 'Iterator', test_files
92 .local int test_number # the number of the test we're running
95 # these vars are in the loops below
96 .local string test_line # one line of one test file, a single test
97 .local int ok # is this a passing test?
100 .local string template # the sprintf template
101 .local string data # the data to format with the template
102 .local string expected # expected result of this test
103 .local string description # user-facing description of the test
104 .local int skip_it # skip this test on this platform?
105 .local string actual # actual result of the test
107 todo_tests = 'set_todo_info'()
108 skip_tests = 'set_skip_info'()
110 # how many tests to run?
111 # XXX: this should be summed automatically from test_files data
112 # until then, it's set to no plan
116 unless file_iterator goto end_outer_loop
117 .local string test_name # file name of the current test file
118 test_name = shift file_iterator
120 .local string test_file # full name of the current test file
121 test_file = test_dir . test_name
123 .local int local_test_number # local test number in test file
124 local_test_number = 0
127 .local pmc file_handle # currently open file
128 file_handle = open test_file, '<'
130 unless file_handle goto bad_file
132 # loop over the file, one at a time.
135 # read in the file one line at a time...
136 $I0 = file_handle.'eof'()
139 test_line = readline file_handle
141 # skip lines without tabs, and comment lines
142 $I0 = index test_line, "\t"
143 if $I0 == -1 goto loop
144 $I0 = index test_line, '#'
145 if $I0 == 0 goto loop
147 inc local_test_number
151 ( template, data, expected, description, skip_it ) = parse_data( test_line )
154 # prepend test filename and line number to description
155 description = 'build_test_desc'( description, template )
158 data_hash = new 'Hash'
160 data_hash['2**32-1'] = 0xffffffff
162 data_hash['2**38'] = $N0
163 data_hash["'string'"] = 'string'
165 $I0 = exists data_hash[data]
166 unless $I0 goto got_data
167 data = data_hash[data]
170 # data = backslash_escape (data)
171 # expected = backslash_escape (expected)
173 # Should this test be skipped?
175 $S0 .= ' (skipped on this platform)'
176 if skip_it goto must_skip
177 $I0 = exists skip_tests[test_name]
178 unless $I0 goto not_skip
179 $P0 = skip_tests[test_name]
180 $I0 = exists $P0[local_test_number]
181 unless $I0 goto not_skip
182 $S0 = $P0[local_test_number]
189 actual = 'sprintf'(template, data)
191 unless_null actual, sprintf_ok
192 $P1 = new 'Exception'
193 $P1[0] = 'sprintf error'
197 if expected == actual goto is_ok
198 description .= ' actual: >'
199 description .= actual
204 $S0 = substr expected, 0, 1
205 if $S0 != "/" goto eh_bad_line
206 substr expected, 0, 1, ''
207 substr expected, -1, 1, ''
209 $I0 = index $S1, expected
210 if $I0 == -1 goto is_nok
220 $I0 = exists todo_tests[test_name]
221 unless $I0 goto not_todo
222 $P0 = todo_tests[test_name]
223 $I0 = exists $P0[local_test_number]
224 unless $I0 goto not_todo
225 test.'todo'(ok,description)
228 test.'ok'(ok,description)
240 print "Unable to open '"
246 .local string message
247 get_results '0,0', exception, message
248 $I0 = index message, 'is not a valid sprintf format'
249 if $I0 == -1 goto other_error
250 $I0 = index expected, ' INVALID'
251 if $I0 == -1 goto bad_error
259 $S0 = "Test not formatted properly!"
267 .param pmc args :slurpy
270 $S1 = sprintf $S0, args
276 # set todo information
278 .local pmc todo_tests # keys indicate test file; values test number
279 todo_tests = new 'Hash'
282 todo_info = new 'Hash'
284 .local string test_file
287 test_file = 'sprintf_tests'
289 todo_info[64] = 'undecided perl5 vs. posix behavior'
290 todo_info[153] = '%hf should be rejected'
291 todo_info[187] = '%h alone is invalid'
292 todo_info[191] = '%l alone is invalid'
293 todo_info[223] = '%v alone is invalid, but a valid parrot extension'
294 todo_info[304] = 'undecided'
295 todo_info[305] = 'undecided'
296 todo_info[306] = 'undecided'
299 todo_tests[test_file] = todo_info
304 todo_info = new 'Hash'
308 if $I0 > $I1 goto end_loop
317 # set skip information
319 .local pmc skip_tests # keys indicate test file; values test number
320 skip_tests = new 'Hash'
323 skip_info = new 'Hash'
325 .local string test_file
328 test_file = 'sprintf_tests'
329 skip_info[5] = 'parrot extension (%B)'
330 skip_info[7] = 'perl5-specific extension (%D)'
331 skip_info[9] = 'perl5-specific extension (%F)'
332 skip_info[16] = 'parrot extension (%H)'
333 skip_info[20] = 'parrot extension (%L)'
334 skip_info[23] = 'perl5-specific extension (%O)'
335 skip_info[24] = 'parrot extension (%P)'
336 skip_info[27] = 'parrot extension (%S)'
337 skip_info[29] = 'perl5-specific extension (%U)'
339 $S0 = 'perl5-specific extension (%v...)'
344 skip_info[114] = 'harness needs support for * modifier'
345 skip_info[144] = 'perl5 expresssion as test value'
346 skip_info[131] = 'harness needs support for * modifier'
347 skip_info[141] = 'harness needs support for * modifier'
348 skip_info[161] = 'harness needs support for * modifier'
349 skip_info[166] = 'harness needs support for * modifier'
350 skip_info[193] = 'perl5-specific test'
351 skip_info[200] = 'perl5-specific test'
352 skip_info[201] = 'perl5-specific test'
353 skip_info[202] = 'parrot extension (%p)'
354 skip_info[204] = 'parrot extension (%r)'
355 skip_info[210] = 'harness needs support for * modifier'
356 skip_info[214] = 'harness needs support for * modifier'
357 skip_info[233] = 'harness needs support for * modifier'
358 skip_info[234] = 'perl5-specific extension (%v...)'
359 skip_info[235] = 'perl5-specific extension (%v...)'
360 skip_info[300] = 'harness needs support for * modifier'
362 $S0 = 'perl5-specific test'
367 $S0 = 'perl5-specific extension (%v...)'
372 skip_info[307] = 'perl5-specific extension (%v...)'
373 skip_info[308] = 'perl5-specific extension (%v...)'
375 skip_tests[test_file] = skip_info
380 skip_info = new 'Hash'
384 if $I0 > $I1 goto end_loop
385 if $S0 != '' goto set_skip_info
386 $S0 = 'unknown reason'
398 .param string record # the data record
400 .local string template # the sprintf template
401 .local string data # the data to format with the template
402 .local string expected # expected result of this test
403 .local string description # user-facing description of the test
404 .local int skip_it # skip this test on this platform
407 # NOTE: there can be multiple tabs between entries, so skip until
409 # remove the trailing newline from record
411 $P1 = split "\t", record
412 $I0 = elements $P1 # length of array
413 .local int tab_number
416 if tab_number >= $I0 goto bad_line
417 template = $P1[tab_number]
419 if template == '' goto get_template
421 if tab_number >= $I0 goto bad_line
422 data = $P1[tab_number]
424 if data == '' goto get_data
427 if tab_number >= $I0 goto empty_expected
428 expected = $P1[tab_number]
430 if expected == '' goto get_expected
431 ## FIXME: description handling
433 if tab_number >= $I0 goto no_desc
434 description = $P1[tab_number]
436 if description == '' goto get_description
438 ( description, skip_it ) = find_skip_in_description( description )
441 # substr description, -1, 1, ''
445 .return ( template, data, expected, description, skip_it )
452 $P1 = new 'Exception'
453 $P1[0] = 'invalid data format'
457 .sub 'find_skip_in_description'
458 .param string description
461 parts = split ' skip: ', description
464 if $I0 > 1 goto check_os
465 .return( description, 0 )
468 description = shift parts
470 .local string skip_list
471 skip_list = shift parts
474 skip_os = split ' ', skip_list
477 iter = new 'Iterator', skip_os
483 osname = config['osname']
486 unless iter goto iter_end
487 .local string os_name
489 eq os_name, osname, skip_it
492 .return( description, 0 )
495 .return( description, 1 )
499 .sub 'build_test_desc'
501 .param string testname
507 desc = concat $S0, desc
513 # The following tests are not currently run, for the reasons stated:
519 >%.0f< >1.5< >2< >Standard vague: no rounding rules<
520 >%.0f< >2.5< >2< >Standard vague: no rounding rules<
530 # vim: expandtab shiftwidth=4 ft=pir: