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 'Test/Builder.pir'
64 load_bytecode 'PGE.pbc'
65 load_bytecode 'PGE/Dumper.pbc'
66 .include "iglobals.pasm"
68 # Variable declarations, initializations
69 .local pmc test # the test harness object.
70 test = new [ 'Test'; 'Builder' ]
72 .local pmc todo_tests # keys indicate test file; values test number.
73 todo_tests = new 'Hash'
75 .local pmc skip_tests # keys indicate tests ID; values reasons.
76 skip_tests = new 'Hash'
78 .local string test_dir # the directory containing tests
81 .local pmc test_files # values are test file names to run.
82 test_files = new 'ResizablePMCArray'
84 # populate the list of test files
85 push test_files, 'sprintf_tests'
88 .local pmc file_iterator # iterate over list of files..
89 file_iterator = new 'Iterator', test_files
91 .local int test_number # the number of the test we're running
94 # these vars are in the loops below
95 .local string test_line # one line of one test file, a single test
96 .local int ok # is this a passing test?
99 .local string template # the sprintf template
100 .local string data # the data to format with the template
101 .local string expected # expected result of this test
102 .local string description # user-facing description of the test
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, '<'
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 ) = 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?
172 $I0 = exists skip_tests[test_name]
173 unless $I0 goto not_skip
174 $P0 = skip_tests[test_name]
175 $I0 = exists $P0[local_test_number]
176 unless $I0 goto not_skip
177 $S0 = $P0[local_test_number]
183 actual = 'sprintf'(template, data)
185 unless_null actual, sprintf_ok
186 $P1 = new 'Exception'
187 $P1[0] = 'sprintf error'
191 if expected == actual goto is_ok
192 description .= ' actual: >'
193 description .= actual
198 $S0 = substr expected, 0, 1
199 if $S0 != "/" goto eh_bad_line
200 substr expected, 0, 1, ''
201 substr expected, -1, 1, ''
203 $I0 = index $S1, expected
204 if $I0 == -1 goto is_nok
214 $I0 = exists todo_tests[test_name]
215 unless $I0 goto not_todo
216 $P0 = todo_tests[test_name]
217 $I0 = exists $P0[local_test_number]
218 unless $I0 goto not_todo
219 test.'todo'(ok,description)
222 test.'ok'(ok,description)
234 print "Unable to open '"
240 .local string message
241 get_results '0,0', exception, message
242 $I0 = index message, 'is not a valid sprintf format'
243 if $I0 == -1 goto other_error
244 $I0 = index expected, ' INVALID'
245 if $I0 == -1 goto bad_error
253 $S0 = "Test not formatted properly!"
261 .param pmc args :slurpy
264 $S1 = sprintf $S0, args
270 # set todo information
272 .local pmc todo_tests # keys indicate test file; values test number
273 todo_tests = new 'Hash'
276 todo_info = new 'Hash'
278 .local string test_file
281 test_file = 'sprintf_tests'
283 todo_info[64] = 'undecided perl5 vs. posix behavior'
284 todo_info[153] = '%hf should be rejected'
285 todo_info[187] = '%h alone is invalid'
286 todo_info[191] = '%l alone is invalid'
287 todo_info[223] = '%v alone is invalid, but a valid parrot extension'
288 todo_info[304] = 'undecided'
289 todo_info[305] = 'undecided'
290 todo_info[306] = 'undecided'
293 todo_tests[test_file] = todo_info
298 todo_info = new 'Hash'
302 if $I0 > $I1 goto end_loop
311 # set skip information
313 .local pmc skip_tests # keys indicate test file; values test number
314 skip_tests = new 'Hash'
317 skip_info = new 'Hash'
319 .local string test_file
322 test_file = 'sprintf_tests'
323 skip_info[5] = 'parrot extension (%B)'
324 skip_info[7] = 'perl5-specific extension (%D)'
325 skip_info[9] = 'perl5-specific extension (%F)'
326 skip_info[16] = 'parrot extension (%H)'
327 skip_info[20] = 'parrot extension (%L)'
328 skip_info[23] = 'perl5-specific extension (%O)'
329 skip_info[24] = 'parrot extension (%P)'
330 skip_info[27] = 'parrot extension (%S)'
331 skip_info[29] = 'perl5-specific extension (%U)'
333 $S0 = 'perl5-specific extension (%v...)'
338 skip_info[114] = 'harness needs support for * modifier'
339 skip_info[144] = 'perl5 expresssion as test value'
340 skip_info[131] = 'harness needs support for * modifier'
341 skip_info[141] = 'harness needs support for * modifier'
342 skip_info[161] = 'harness needs support for * modifier'
343 skip_info[166] = 'harness needs support for * modifier'
344 skip_info[193] = 'perl5-specific test'
345 skip_info[200] = 'perl5-specific test'
346 skip_info[201] = 'perl5-specific test'
347 skip_info[202] = 'parrot extension (%p)'
348 skip_info[204] = 'parrot extension (%r)'
349 skip_info[210] = 'harness needs support for * modifier'
350 skip_info[214] = 'harness needs support for * modifier'
351 skip_info[233] = 'harness needs support for * modifier'
352 skip_info[234] = 'perl5-specific extension (%v...)'
353 skip_info[235] = 'perl5-specific extension (%v...)'
355 $S0 = 'perl5-specific test'
360 $S0 = 'perl5-specific extension (%v...)'
365 skip_info[307] = 'perl5-specific extension (%v...)'
366 skip_info[308] = 'perl5-specific extension (%v...)'
368 skip_tests[test_file] = skip_info
373 skip_info = new 'Hash'
377 if $I0 > $I1 goto end_loop
378 if $S0 != '' goto set_skip_info
379 $S0 = 'unknown reason'
391 .param string record # the data record
393 .local string template # the sprintf template
394 .local string data # the data to format with the template
395 .local string expected # expected result of this test
396 .local string description # user-facing description of the test
398 # NOTE: there can be multiple tabs between entries, so skip until
400 # remove the trailing newline from record
402 $P1 = split "\t", record
403 $I0 = elements $P1 # length of array
404 .local int tab_number
407 if tab_number >= $I0 goto bad_line
408 template = $P1[tab_number]
410 if template == '' goto get_template
412 if tab_number >= $I0 goto bad_line
413 data = $P1[tab_number]
415 if data == '' goto get_data
418 if tab_number >= $I0 goto empty_expected
419 expected = $P1[tab_number]
421 if expected == '' goto get_expected
422 ## FIXME: description handling
424 if tab_number >= $I0 goto no_desc
425 description = $P1[tab_number]
427 if description == '' goto get_description
430 # substr description, -1, 1, ''
434 .return ( template, data, expected, description )
441 $P1 = new 'Exception'
442 $P1[0] = 'invalid data format'
447 .sub 'build_test_desc'
449 .param string testname
455 desc = concat $S0, desc
461 # The following tests are not currently run, for the reasons stated:
467 >%.0f< >1.5< >2< >Standard vague: no rounding rules<
468 >%.0f< >2.5< >2< >Standard vague: no rounding rules<
478 # vim: expandtab shiftwidth=4 ft=pir: