#!./parrot # Copyright (C) 2001-2010, Parrot Foundation. =head1 NAME t/op/string.t - Parrot Strings =head1 SYNOPSIS % prove t/op/string.t =head1 DESCRIPTION Tests Parrot string registers and operations. =cut .include 'except_types.pasm' .sub main :main .include 'test_more.pir' set_s_s_sc() test_clone() clone_null() test_length_i_s() zero_length_substr() chopn_with_clone() chopn_oob_values() three_argument_chopn() three_argument_chopn__oob_values() substr_tests() neg_substr_offset() exception_substr_null_string() exception_substr_oob() exception_substr_oob_neg() len_greater_than_strlen() len_greater_than_strlen_neg_offset() replace_w_rep_eq_length() replace_w_replacement_gt_length() replace_w_replacement_lt_length() replace_vs_hash() replace__offset_at_end_of_string() exception_replace__offset_past_end_of_string() replace_neg_offset_repl_eq_length() replace_neg_offset_repl_gt_length() replace_neg_offset_repl_lt_length() exception_replace_neg_offset_out_of_string() replace_length_gt_strlen() replace_length_gt_strlen_neg_offset() replace_only_substr() three_arg_substr() exception_substr__pos_offset_zero_length_string() substr_offset_zero_zero_length_string() exception_substr_offset_one_zero_length_string() exception_substr_neg_offset_zero_length_string() exception_substr_oob_utf8() zero_length_substr_zero_length_string() zero_length_substr_zero_length_string() three_arg_substr_zero_length_string() replace_zero_length_string() four_arg_substr_replace_zero_length_string() concat_s_s_sc_null_onto_null() concat_s_sc_repeated_two_arg_concats() concat_s_s_sc_foo_one_onto_null() test_concat_s_s_sc() concat_s_s_sc_s_sc() concat_ensure_copy_is_made() same_constant_twice_bug() exception_two_param_ord_empty_string() exception_two_param_ord_empty_string_register() exception_three_param_ord_empty_string() exception_three_param_ord_empty_string_register() two_param_ord_one_character_string() two_param_ord_multi_character_string() two_param_ord_one_character_string_register() three_param_ord_one_character_string() three_param_ord_one_character_string_register() three_param_ord_multi_character_string() three_param_ord_multi_character_string_register() exception_three_param_ord_multi_character_string() exception_three_param_ord_multi_character_string() three_param_ord_one_character_string_from_end() three_param_ord_one_character_string_register_from_end() three_param_ord_multi_character_string_from_end() three_param_ord_multi_character_string_register_from_end() exception_three_param_ord_multi_character_string_register_from_end_oob() chr_of_thirty_two_is_space_in_ascii() chr_of_sixty_five_is_a_in_ascii() chr_of_one_hundred_and_twenty_two_is_z_in_ascii() test_if_s_ic() repeat_s_s_sc_i_ic() exception_repeat_oob() exception_repeat_oob_repeat_p_p_p() exception_repeat_oob_repeate_p_p_i() encodingname_oob() index_three_arg_form() index_four_arg_form() index_four_arg_form_bug_twenty_two_thousand_seven_hundred_and_eighteen() index_trac_1482() index_null_strings() index_embedded_nulls() index_big_strings() index_big_hard_to_match_strings() index_with_different_charsets() negative_index_bug_35959() index_multibyte_matching() index_multibyte_matching_two() num_to_string() string_to_int() string_to_num() concat_or_substr_cow() constant_to_cstring() cow_with_chopn_leaving_original_untouched() check_that_bug_bug_16874_was_fixed() stress_concat() ord_and_substring_see_bug_17035() test_sprintf() other_form_of_sprintf_op() sprintf_left_justify() correct_precision_for_sprintf_x() test_find_encoding() test_assign() assign_and_globber() split_on_null_string() split_on_empty_string() split_on_non_empty_string() test_join() test_join_many() eq_addr_or_ne_addr() test_if_null_s_ic() test_upcase() test_downcase() test_titlecase() three_param_ord_one_character_string_register_i() three_param_ord_multi_character_string_i() three_param_ord_multi_character_string_register_i() exception_three_param_ord_multi_character_string_i() exception_three_param_ord_multi_character_string_i() three_param_ord_one_character_string_from_end_i() three_param_ord_one_character_string_register_from_end_i() three_param_ord_multi_character_string_from_end_i() three_param_ord_multi_character_string_register_from_end_i() exception_three_param_ord_multi_character_string_register_from_end_oob_i() more_string_to_int() constant_string_and_modify_in_situ_op_rt_bug_60030() corner_cases_of_numification() non_canonical_nan_and_inf() split_hll_mapped() # END_OF_TESTS join_get_string_returns_a_null_string() done_testing() .end .macro exception_is ( M ) .local pmc exception .local string message .get_results (exception) message = exception['message'] is( message, .M, .M ) .endm .sub set_s_s_sc set $S4, "JAPH" set $S5, $S4 is( $S4, "JAPH", '' ) is( $S5, "JAPH", '' ) .end .sub test_clone set $S0, "Foo1" clone $S1, $S0 is( $S0, "Foo1", '' ) is( $S1, "Foo1", '' ) clone $S1, "Bar1" is( $S1, "Bar1", '' ) .end .sub clone_null null $S0 clone $S1, $S0 is( $S1, $S0, '' ) .end .sub test_length_i_s set $I4, 0 set $S4, "JAPH" length $I4, $S4 is( $I4, "4", '' ) .end .sub zero_length_substr set $I4, 0 set $S4, "JAPH" substr $S3, $S4, 1, 0 length $I4, $S3 is( $I4, "0", '' ) .end .sub chopn_with_clone set $S4, "JAPHxyzw" set $S5, "japhXYZW" clone $S3, $S4 set $I1, 4 $S4 = chopn $S4, 3 $S4 = chopn $S4, 1 $S5 = chopn $S5, $I1 is( $S4, "JAPH", '' ) is( $S5, "japh", '' ) is( $S3, "JAPHxyzw", '' ) .end .sub chopn_oob_values set $S1, "A string of length 21" $S1 = chopn $S1, 0 is( $S1, "A string of length 21", '' ) $S1 = chopn $S1, 4 is( $S1, "A string of lengt", '' ) # -length cuts now $S1 = chopn $S1, -4 is( $S1, "A st", '' ) $S1 = chopn $S1, 1000 is( $S1, "", '' ) .end .sub three_argument_chopn set $S1, "Parrot" chopn $S2, $S1, 0 is( $S1, "Parrot", '' ) is( $S2, "Parrot", '' ) chopn $S2, $S1, 1 is( $S1, "Parrot", '' ) is( $S2, "Parro", '' ) set $I0, 2 chopn $S2, $S1, $I0 is( $S1, "Parrot", '' ) is( $S2, "Parr", '' ) chopn $S2, "Parrot", 3 is( $S2, "Par", '' ) chopn $S1, $S1, 5 is( $S1, "P", '' ) set $S1, "Parrot" set $S3, $S1 chopn $S2, $S1, 3 is( $S3, "Parrot", '' ) .end # .sub three_argument_chopn__oob_values set $S1, "Parrot" chopn $S2, $S1, 7 is( $S1, "Parrot", '' ) is( $S2, "", '' ) chopn $S2, $S1, -1 is( $S1, "Parrot", '' ) is( $S2, "P", '' ) .end .sub substr_tests set $S4, "12345JAPH01" set $I4, 5 set $I5, 4 substr $S5, $S4, $I4, $I5 is( $S5, "JAPH", '' ) substr $S5, $S4, $I4, 4 is( $S5, "JAPH", '' ) substr $S5, $S4, 5, $I5 is( $S5, "JAPH", '' ) substr $S5, $S4, 5, 4 is( $S5, "JAPH", '' ) substr $S5, "12345JAPH01", $I4, $I5 is( $S5, "JAPH", '' ) substr $S5, "12345JAPH01", $I4, 4 is( $S5, "JAPH", '' ) substr $S5, "12345JAPH01", 5, $I5 is( $S5, "JAPH", '' ) substr $S5, "12345JAPH01", 5, 4 is( $S5, "JAPH", '' ) .end # negative offsets .sub neg_substr_offset set $S0, "A string of length 21" set $I0, -9 set $I1, 6 substr $S1, $S0, $I0, $I1 is( $S0, "A string of length 21", '' ) is( $S1, "length", '' ) .end .sub exception_substr_null_string .local string s .local pmc eh .local int r null s eh = new ['ExceptionHandler'] eh.'handle_types'(.EXCEPTION_UNEXPECTED_NULL) set_label eh, handler push_eh eh r = 1 substr s, s, 0, 0 r = 0 handler: pop_eh is(r, 1, "substr with null string throws" ) .end # This asks for substring that shouldn't be allowed... .sub exception_substr_oob .local pmc eh .local int r set $S0, "A string of length 21" set $I0, 99 set $I1, 6 eh = new ['ExceptionHandler'] eh.'handle_types'(.EXCEPTION_SUBSTR_OUT_OF_STRING) set_label eh, handler push_eh eh r = 1 substr $S1, $S0, $I0, $I1 r = 0 handler: pop_eh is(r, 1, "substr outside string throws" ) .end # This asks for substring that shouldn't be allowed... .sub exception_substr_oob_neg .local pmc eh .local int r set $S0, "A string of length 21" set $I0, -99 set $I1, 6 eh = new ['ExceptionHandler'] eh.'handle_types'(.EXCEPTION_SUBSTR_OUT_OF_STRING) set_label eh, handler push_eh eh r = 1 substr $S1, $S0, $I0, $I1 r = 0 handler: pop_eh is(r, 1, "substr outside string throws - negative" ) .end # This asks for substring much greater than length of original string .sub len_greater_than_strlen set $S0, "A string of length 21" set $I0, 12 set $I1, 1000 substr $S1, $S0, $I0, $I1 is( $S0, "A string of length 21", '' ) is( $S1, "length 21", '' ) .end # The same, with a negative offset .sub len_greater_than_strlen_neg_offset set $S0, "A string of length 21" set $I0, -9 set $I1, 1000 substr $S1, $S0, $I0, $I1 is( $S0, "A string of length 21", '' ) is( $S1, "length 21", '' ) .end .sub replace_w_rep_eq_length set $S0, "abcdefghijk" set $S1, "xyz" replace $S2, $S0, 4, 3, $S1 is( $S2, "abcdxyzhijk", '' ) .end .sub replace_w_replacement_gt_length set $S0, "abcdefghijk" set $S1, "xyz0123" $S2 = replace $S0, 4, 3, $S1 is( $S2, "abcdxyz0123hijk", '' ) .end .sub replace_w_replacement_lt_length set $S0, "abcdefghijk" set $S1, "x" $S2 = replace $S0, 4, 3, $S1 is( $S2, "abcdxhijk", '' ) .end .sub replace__offset_at_end_of_string set $S0, "abcdefghijk" set $S1, "xyz" $S2 = replace $S0, 11, 3, $S1 is( $S2, "abcdefghijkxyz", '' ) .end .sub replace_vs_hash # Check that string hashval properly updated. .local pmc hash hash = new ['Hash'] $S0 = "fooo" hash[$S0] = 1 hash["foo"] = 42 $S0 = replace $S0, 1, 1, '' $S1 = hash[$S0] is( $S1, '42', 'replace behave it self') .end .sub exception_replace__offset_past_end_of_string set $S0, "abcdefghijk" set $S1, "xyz" push_eh handler $S2 = replace $S0, 12, 3, $S1 ok(0,"no exception") handler: .exception_is( "Can only replace inside string or index after end of string" ) .end .sub replace_neg_offset_repl_eq_length set $S0, "abcdefghijk" set $S1, "xyz" $S2 = replace $S0, -3, 3, $S1 is( $S2, "abcdefghxyz", '' ) .end .sub replace_neg_offset_repl_gt_length set $S0, "abcdefghijk" set $S1, "xyz" $S2 = replace $S0, -6, 2, $S1 is( $S2, "abcdexyzhijk", '' ) .end .sub replace_neg_offset_repl_lt_length set $S0, "abcdefghijk" set $S1, "xyz" $S2 = replace $S0, -6, 4, $S1 is( $S2, "abcdexyzjk", '' ) .end .sub exception_replace_neg_offset_out_of_string set $S0, "abcdefghijk" set $S1, "xyz" push_eh handler $S2 = replace $S0, -12, 4, $S1 ok(0,"no exception") handler: .exception_is( "Can only replace inside string or index after end of string" ) .end .sub replace_length_gt_strlen set $S0, "abcdefghijk" set $S1, "xyz" $S2 = replace $S0, 3, 11, $S1 is( $S2, "abcxyz", '' ) .end .sub replace_length_gt_strlen_neg_offset set $S0, "abcdefghijk" set $S1, "xyz" $S2 = replace $S0, -3, 11, $S1 is( $S2, "abcdefghxyz", '' ) .end .sub replace_only_substr set $S0, "abcdefghijk" set $S1, "xyz" $S2 = replace $S0, 3, 3, $S1 is( $S2, "abcxyzghijk", '' ) .end .sub three_arg_substr set $S0, "JAPH" substr $S1, $S0, 2 is( $S1, "PH", '' ) .end .sub exception_substr__pos_offset_zero_length_string set $S0, "" push_eh handler substr $S1, $S0, 10, 3 ok(0,"no exception") handler: .exception_is( "Cannot take substr outside string" ) .end .sub substr_offset_zero_zero_length_string set $S0, "" substr $S1, $S0, 0, 1 is( $S1, "", '' ) .end .sub exception_substr_offset_one_zero_length_string set $S0, "" push_eh handler substr $S1, $S0, -1, 1 ok(0,"no exception") handler: .exception_is( "Cannot take substr outside string" ) .end .sub exception_substr_neg_offset_zero_length_string set $S0, "" push_eh handler substr $S1, $S0, -10, 5 handler: .exception_is( "Cannot take substr outside string" ) .end .sub exception_substr_oob_utf8 set $S0, utf8:"abc\uBEEFdef" push_eh handler substr $S1, $S0, 8, 5 handler: .exception_is( "Cannot take substr outside string" ) .end .sub zero_length_substr_zero_length_string set $S0, "" substr $S1, $S0, 10, 0 is( $S1, "", '' ) .end .sub zero_length_substr_zero_length_string set $S0, "" substr $S1, $S0, -10, 0 is( $S1, "", '' ) .end .sub three_arg_substr_zero_length_string set $S0, "" substr $S1, $S0, 2 is( $S1, "", '' ) .end .sub replace_zero_length_string set $S0, "" set $S1, "xyz" $S2 = replace $S0, 0, 3, $S1 is( $S2, "xyz", '' ) set $S3, "" set $S4, "abcde" $S5 = replace $S3, 0, 0, $S4 is( $S5, "abcde", '' ) .end .sub four_arg_substr_replace_zero_length_string set $S0, "" set $S1, "xyz" $S0 = replace $S0, 0, 3, $S1 is( $S0, "xyz", '' ) set $S2, "" set $S3, "abcde" $S2 = replace $S2, 0, 0, $S3 is( $S2, "abcde", '' ) .end .sub concat_s_s_sc_null_onto_null $S0 = concat $S0, $S0 is( $S0, "", '' ) $S1 = concat $S1, "" is( $S1, "", '' ) .end .sub concat_s_sc_repeated_two_arg_concats set $S12, "" set $I0, 0 WHILE: $S12 = concat $S12, "hi" add $I0, 1 lt $I0, 10, WHILE is( $S12, "hihihihihihihihihihi", '' ) .end .sub concat_s_s_sc_foo_one_onto_null $S0 = concat $S0, "foo1" set $S1, "foo2" $S2 = concat $S2, $S1 is( $S0, "foo1", '' ) is( $S2, "foo2", '' ) .end .sub test_concat_s_s_sc set $S1, "fish" set $S2, "bone" $S1 = concat $S1, $S2 is( $S1, "fishbone", '' ) .end .sub concat_s_s_sc_s_sc set $S1, "japh" set $S2, "JAPH" concat $S0, "japh", "JAPH" is( $S0, "japhJAPH", '' ) concat $S0, $S1, "JAPH" is( $S0, "japhJAPH", '' ) concat $S0, "japh", $S2 is( $S0, "japhJAPH", '' ) concat $S0, $S1, $S2 is( $S0, "japhJAPH", '' ) .end .sub concat_ensure_copy_is_made set $S2, "JAPH" concat $S0, $S2, "" concat $S1, "", $S2 $S0 = chopn $S0, 1 $S1 = chopn $S1, 1 is( $S2, "JAPH", '' ) .end .sub same_constant_twice_bug set $S0, "" set $S1, "" set $S2, "foo" concat $S1, $S1, $S2 is( $S1, "foo", 'same constant twice bug' ) is( $S0, "", 'same constant twice bug' ) .end .sub exception_two_param_ord_empty_string push_eh handler ord $I0,"" ok(0, 'no exception: 2-param ord, empty string' ) handler: .exception_is( 'Cannot get character of empty string' ) .end .sub exception_two_param_ord_empty_string_register push_eh handler ord $I0,$S0 ok( 0, 'no exception: 2-param ord, empty string register' ) handler: .exception_is( 'Invalid operation on null string' ) .end .sub exception_three_param_ord_empty_string push_eh handler ord $I0,"",0 ok(0, 'no exception: 3-param ord, empty string' ) handler: .exception_is( 'Cannot get character of empty string' ) .end .sub exception_three_param_ord_empty_string_register push_eh handler ord $I0,$S0,0 ok( 0, 'no exception: 3-param ord, empty string register' ) handler: .exception_is( 'Invalid operation on null string' ) .end .sub two_param_ord_one_character_string ord $I0,"a" is( $I0, "97", '2-param ord, one-character string' ) .end .sub two_param_ord_multi_character_string ord $I0,"abc" is( $I0, "97", '2-param ord, multi-character string' ) .end .sub two_param_ord_one_character_string_register set $S0,"a" ord $I0,$S0 is( $I0, "97", '2-param ord, one-character string register' ) .end .sub three_param_ord_one_character_string ord $I0,"a",0 is( $I0, "97", '3-param ord, one-character string' ) .end .sub three_param_ord_one_character_string_register set $S0,"a" ord $I0,$S0,0 is( $I0, "97", '3-param ord, one-character string register' ) .end .sub three_param_ord_multi_character_string ord $I0,"ab",1 is( $I0, "98", '3-param ord, multi-character string' ) .end .sub three_param_ord_multi_character_string_register set $S0,"ab" ord $I0,$S0,1 is( $I0, "98", '3-param ord, multi-character string register' ) .end .sub exception_three_param_ord_multi_character_string push_eh handler ord $I0,"ab",2 ok( 0, 'no exception: 3-param ord, multi-character string' ) handler: .exception_is( 'Cannot get character past end of string' ) .end .sub exception_three_param_ord_multi_character_string push_eh handler set $S0,"ab" ord $I0,$S0,2 ok( 0, 'no exception: 3-param ord, multi-character string' ) handler: .exception_is( 'Cannot get character past end of string' ) .end .sub three_param_ord_one_character_string_from_end ord $I0,"a",-1 is( $I0, "97", '3-param ord, one-character string, from end' ) .end .sub three_param_ord_one_character_string_register_from_end set $S0,"a" ord $I0,$S0,-1 is( $I0, "97", '3-param ord, one-character string register, from end' ) .end .sub three_param_ord_multi_character_string_from_end ord $I0,"ab",-1 is( $I0, "98", '3-param ord, multi-character string, from end' ) .end .sub three_param_ord_multi_character_string_register_from_end set $S0,"ab" ord $I0,$S0,-1 is( $I0, "98", '3-param ord, multi-character string register, from end' ) .end .sub exception_three_param_ord_multi_character_string_register_from_end_oob push_eh handler set $S0,"ab" ord $I0,$S0,-3 ok( 0, 'no exception: 3-param ord, multi-character string register, from end, OOB' ) handler: .exception_is( 'Cannot get character before beginning of string' ) .end .sub chr_of_thirty_two_is_space_in_ascii chr $S0, 32 is( $S0, " ", 'chr of 32 is space in ASCII' ) .end .sub chr_of_sixty_five_is_a_in_ascii chr $S0, 65 is( $S0, "A", 'chr of 65 is A in ASCII' ) .end .sub chr_of_one_hundred_and_twenty_two_is_z_in_ascii chr $S0, 122 is( $S0, "z", 'chr of 122 is z in ASCII' ) .end .sub test_if_s_ic set $S0, "I've told you once, I've told you twice..." ok( $S0, 'normal strings are true' ) set $S0, "0.0" ok( $S0, '0.0 is true' ) set $S0, "" nok( $S0, 'empty string is false' ) set $S0, "0" nok( $S0, '"0" string is false' ) set $S0, "0e0" ok( $S0, 'string "0e0" is true' ) set $S0, "x" ok( $S0, 'string "x" is true' ) set $S0, "\\x0" ok( $S0, 'string "\\x0" is true' ) set $S0, "\n" ok( $S0, 'string "\n" is true' ) set $S0, " " ok( $S0, 'string " " is true' ) # An empty register should be false... nok( $S1, 'empty register is false' ) .end .sub repeat_s_s_sc_i_ic set $S0, "x" repeat $S1, $S0, 12 is( $S0, "x", 'repeat_s_s|sc_i|ic' ) is( $S1, "xxxxxxxxxxxx", 'repeat_s_s|sc_i|ic' ) set $I0, 12 set $S2, "X" repeat $S3, $S2, $I0 is( $S2, "X", 'repeat_s_s|sc_i|ic' ) is( $S3, "XXXXXXXXXXXX", 'repeat_s_s|sc_i|ic' ) repeat $S4, "~", 12 is( $S4, "~~~~~~~~~~~~", 'repeat_s_s|sc_i|ic' ) repeat $S5, "~", $I0 is( $S5, "~~~~~~~~~~~~", 'repeat_s_s|sc_i|ic' ) repeat $S6, "***", 0 is( $S6, "", 'repeat_s_s|sc_i|ic' ) .end .sub exception_repeat_oob push_eh handler repeat $S0, "japh", -1 handler: .exception_is( 'Cannot repeat with negative arg' ) .end .sub exception_repeat_oob_repeat_p_p_p push_eh handler $P0 = new ['String'] $P1 = new ['String'] $P2 = new ['Integer'] $P2 = -1 repeat $P1, $P0, $P2 handler: .exception_is( 'Cannot repeat with negative arg' ) .end .sub exception_repeat_oob_repeate_p_p_i push_eh handler $P0 = new ['String'] $P1 = new ['String'] repeat $P1, $P0, -1 handler: .exception_is( 'Cannot repeat with negative arg' ) .end .sub encodingname_oob $I0 = -1 $S0 = encodingname -1 $S0 = encodingname $I0 ok( 1, "no exceptions in encodingname_oob" ) .end .sub index_three_arg_form set $S0, "Parrot" set $S1, "Par" index $I1, $S0, $S1 is( $I1, "0", 'index, 3-arg form' ) set $S1, "rot" index $I1, $S0, $S1 is( $I1, "3", 'index, 3-arg form' ) set $S1, "bar" index $I1, $S0, $S1 is( $I1, "-1", 'index, 3-arg form' ) # Ascii - Non-ascii, same content set $S0, "hello" set $S1, utf8:"hello" index $I1, $S0, $S1 is( $I1, "0", 'index, 3-arg form' ) index $I1, $S1, $S0 is( $I1, "0", 'index, 3-arg form' ) # Non-ascii, source shorter than searched set $S0, utf8:"-o" set $S1, utf8:"@INC" index $I1, $S0, $S1 is( $I1, "-1", 'index, 3-arg form' ) .end .sub index_four_arg_form set $S0, "Barbarian" set $S1, "ar" index $I1, $S0, $S1, 0 is( $I1, "1", 'index, 4-arg form' ) index $I1, $S0, $S1, 2 is( $I1, "4", 'index, 4-arg form' ) set $S1, "qwx" index $I1, $S0, $S1, 0 is( $I1, "-1", 'index, 4-arg form' ) # Ascii - Non-ascii, same content set $S0, "hello" set $S1, utf8:"hello" index $I1, $S0, $S1, 0 is( $I1, "0", 'index, 4-arg form' ) index $I1, $S1, $S0, 0 is( $I1, "0", 'index, 4-arg form' ) .end .sub index_four_arg_form_bug_twenty_two_thousand_seven_hundred_and_eighteen set $S1, "This is not quite right" set $S0, " is " index $I0, $S1, $S0, 0 is( $I0, "4", 'index, 4-arg form, bug 22718' ) set $S0, "is" index $I0, $S1, $S0, 0 is( $I0, "2", 'index, 4-arg form, bug 22718' ) .end .sub index_trac_1482 $S0 = utf8:"bubuc" $S1 = utf8:"buc" $I0 = index $S0, $S1, 0 is ($I0, 2, 'index, 4-arg, partial-match causes failure: TT #1482') .end .sub index_null_strings set $S0, "Parrot" set $S1, "" index $I1, $S0, $S1 is( $I1, "-1", 'index, null strings' ) index $I1, $S0, $S1, 0 is( $I1, "-1", 'index, null strings' ) index $I1, $S0, $S1, 5 is( $I1, "-1", 'index, null strings' ) index $I1, $S0, $S1, 6 is( $I1, "-1", 'index, null strings' ) set $S0, "" set $S1, "a" index $I1, $S0, $S1 is( $I1, "-1", 'index, null strings' ) index $I1, $S0, $S1, 0 is( $I1, "-1", 'index, null strings' ) set $S0, "Parrot" null $S1 index $I1, $S0, $S1 is( $I1, "-1", 'index, null strings' ) .local pmc eh eh = new ['ExceptionHandler'] eh.'handle_types'(.EXCEPTION_UNEXPECTED_NULL) set_label eh, handler push_eh eh $I1 = 1 null $S0 null $S1 index $I0, $S0, $S1 $I1 = 0 handler: pop_eh is( $I1, "1", "index with null string throws" ) .end .sub index_embedded_nulls set $S0, "Par\0\0rot" set $S1, "\0" index $I1, $S0, $S1 is( $I1, "3", 'index, embedded nulls' ) index $I1, $S0, $S1, 4 is( $I1, "4", 'index, embedded nulls' ) .end .sub index_big_strings set $S0, "a" repeat $S0, $S0, 10000 set $S1, "a" repeat $S1, $S1, 500 index $I1, $S0, $S1 is( $I1, "0", 'index, big strings' ) index $I1, $S0, $S1, 1234 is( $I1, "1234", 'index, big strings' ) index $I1, $S0, $S1, 9501 is( $I1, "-1", 'index, big strings' ) .end # Builds a 24th iteration fibonacci string (approx. 100K) .sub index_big_hard_to_match_strings set $S1, "a" set $S2, "b" set $I0, 0 LOOP: set $S3, $S1 concat $S1, $S2, $S3 set $S2, $S3 inc $I0 lt $I0, 24, LOOP index $I1, $S1, $S2 is( $I1, "46368", 'index, big, hard to match strings' ) index $I1, $S1, $S2, 50000 is( $I1, "-1", 'index, big, hard to match strings' ) .end .sub index_with_different_charsets set $S0, "Parrot" set $S1, "rot" index $I1, $S0, $S1 is( $I1, "3", 'default - default' ) set $S0, ascii:"Parrot" set $S1, ascii:"rot" index $I1, $S0, $S1 is( $I1, "3", 'ascii - ascii') set $S0, "Parrot" set $S1, ascii:"rot" index $I1, $S0, $S1 is( $I1, "3", 'default - ascii' ) set $S0, ascii:"Parrot" set $S1, "rot" index $I1, $S0, $S1 is( $I1, "3", 'ascii - default' ) set $S0, binary:"Parrot" set $S1, binary:"rot" index $I1, $S0, $S1 is( $I1, 3, 'binary - binary' ) .end .sub negative_index_bug_35959 index $I1, "u", "t", -123456 is( $I1, "-1", 'negative index #35959' ) index $I1, "u", "t", -123456789 is( $I1, "-1", 'negative index #35959' ) .end .sub index_multibyte_matching set $S0, iso-8859-1:"\xAB" find_encoding $I0, "utf8" trans_encoding $S1, $S0, $I0 is( $S0, $S1, 'equal' ) index $I0, $S0, $S1 is( $I0, "0", 'index, multibyte matching' ) index $I0, $S1, $S0 is( $I0, "0", 'index, multibyte matching' ) .end .sub index_multibyte_matching_two set $S0, iso-8859-1:"\xAB\xBA" set $S1, utf8:"foo\xAB\xAB\xBAbar" index $I0, $S0, $S1 is( $I0, "-1", 'index, multibyte matching 2' ) index $I0, $S1, $S0 is( $I0, "4", 'index, multibyte matching 2' ) set $S0, iso-8859-1:"abc\x{fc}def" set $S1, utf8:"\x{fc}" index $I1, $S0, $S1 is( $I1, "3", 'index, iso-8859-1 - utf8' ) .end .sub num_to_string set $N0, 80.43 set $S0, $N0 is( $S0, "80.43", 'num to string' ) set $N0, -1.111111 set $S0, $N0 is( $S0, "-1.111111", 'num to string' ) .end .sub string_to_int set $S0, "123" set $I0, $S0 is( $I0, "123", 'string to int' ) set $S0, " 1" set $I0, $S0 is( $I0, "1", 'string to int' ) set $S0, "-1" set $I0, $S0 is( $I0, "-1", 'string to int' ) set $S0, "Not a number" set $I0, $S0 is( $I0, "0", 'string to int' ) set $S0, "" set $I0, $S0 is( $I0, "0", 'string to int' ) .end .sub string_to_num set $S0, "6foo" set $N0, $S0 is( $N0, "6", '6foo to num' ) set $S0, "16foo" set $N0, $S0 is( $N0, "16", '16foo to num' ) .end .sub concat_or_substr_cow set $S0, "" set $S2, "" concat $S2, $S2, $S0 concat $S2, $S2, $S1 is( $S2, "", 'concat/substr (COW)' ) substr $S0, $S2, 1, 4 is( $S0, "JAPH", 'concat/substr (COW)' ) .end .sub constant_to_cstring stringinfo $I0, "\n", 2 stringinfo $I1, "\n", 2 is( $I1, $I0, 'constant to cstring' ) stringinfo $I2, "\n", 2 is( $I2, $I0, 'constant to cstring' ) .end .sub cow_with_chopn_leaving_original_untouched set $S0, "ABCD" clone $S1, $S0 $S0 = chopn $S0, 1 is( $S0, "ABC", 'COW with chopn leaving original untouched' ) is( $S1, "ABCD", 'COW with chopn leaving original untouched' ) .end .sub check_that_bug_bug_16874_was_fixed set $S0, "foo " set $S1, "bar " set $S2, "quux " set $S15, "" $S15 = concat $S15, $S0 $S15 = concat $S15, $S1 $S15 = concat $S15, $S2 is( $S15, "foo bar quux ", 'Check that bug #16874 was fixed' ) .end .sub stress_concat set $I0, 1000 set $S0, "michael" LOOP: set $S2, $I0 concat $S1, $S0, $S2 concat $S3, "mic", "hael" concat $S3, $S3, $S2 eq $S1, $S3, BOTTOM ok(0, 'failed stress concat test') end BOTTOM: sub $I0, $I0, 1 ne $I0, 0, LOOP ok(1, 'stress concat test') .end .sub ord_and_substring_see_bug_17035 set $S0, "abcdef" substr $S1, $S0, 2, 3 ord $I0, $S0, 2 ord $I1, $S1, 0 ne $I0, $I1, fail ord $I0, $S0, 3 ord $I1, $S1, 1 ne $I0, $I1, fail ord $I0, $S0, 4 ord $I1, $S1, 2 ne $I0, $I1, fail ok(1, 'ord and substring #17035') goto end fail: ok(0, 'failed: ord and substring #17035') end: .end .sub test_sprintf branch MAIN NEWARYP: new $P1, 'ResizablePMCArray' set $P1[0], $P0 local_return $P4 NEWARYS: new $P1, 'ResizablePMCArray' set $P1[0], $S0 local_return $P4 NEWARYI: new $P1, 'ResizablePMCArray' set $P1[0], $I0 local_return $P4 NEWARYN: new $P1, 'ResizablePMCArray' set $P1[0], $N0 local_return $P4 PRINTF: sprintf $S2, $S1, $P1 is( $S2, $S99, $S1 ) local_return $P4 MAIN: new $P4, 'ResizableIntegerArray' set $S1, "Hello, %s" set $S0, "Parrot!" set $S99, "Hello, Parrot!" local_branch $P4, NEWARYS local_branch $P4, PRINTF set $S1, "Hash[0x%x]" set $I0, 256 set $S99, "Hash[0x100]" local_branch $P4, NEWARYI local_branch $P4, PRINTF set $S1, "Hash[0x%lx]" set $I0, 256 set $S99, "Hash[0x100]" local_branch $P4, NEWARYI local_branch $P4, PRINTF set $S1, "Hello, %.2s!" set $S0, "Parrot" set $S99, "Hello, Pa!" local_branch $P4, NEWARYS local_branch $P4, PRINTF set $S1, "Hello, %Ss" set $S0, $S2 set $S99, "Hello, Hello, Pa!" local_branch $P4, NEWARYS local_branch $P4, PRINTF set $S1, "1 == %Pd" new $P0, 'Integer' set $P0, 1 set $S99, "1 == 1" local_branch $P4, NEWARYP local_branch $P4, PRINTF set $S1, "-255 == %vd" set $I0, -255 set $S99, "-255 == -255" local_branch $P4, NEWARYI local_branch $P4, PRINTF set $S1, "+123 == %+vd" set $I0, 123 set $S99, "+123 == +123" local_branch $P4, NEWARYI local_branch $P4, PRINTF set $S1, "256 == %vu" set $I0, 256 set $S99, "256 == 256" local_branch $P4, NEWARYI local_branch $P4, PRINTF load_bytecode 'config.pbc' .local pmc config .local string osname, gccversion config = _config() osname = config['osname'] gccversion = config['gccversion'] ne osname, 'MSWin32', nomingw eq gccversion, '', nomingw goto mingw nomingw: set $S1, "1 == %+vu" set $I0, 1 set $S99, "1 == 1" local_branch $P4, NEWARYI local_branch $P4, PRINTF set $S1, "001 == %+0.3u" set $I0, 1 set $S99, "001 == 001" local_branch $P4, NEWARYI local_branch $P4, PRINTF goto nomingw2 mingw: say "196 # skip [GH #823] %+vu on mingw" say "197 # skip [GH #823] %+0.3u on mingw" nomingw2: set $S1, "001 == %0.3u" set $I0, 1 set $S99, "001 == 001" local_branch $P4, NEWARYI local_branch $P4, PRINTF set $S1, "0.500000 == %f" set $N0, 0.5 set $S99, "0.500000 == 0.500000" local_branch $P4, NEWARYN local_branch $P4, PRINTF set $S1, "0.500 == %5.3f" set $N0, 0.5 set $S99, "0.500 == 0.500" local_branch $P4, NEWARYN local_branch $P4, PRINTF set $S1, "0.001 == %g" set $N0, 0.001 set $S99, "0.001 == 0.001" local_branch $P4, NEWARYN local_branch $P4, PRINTF set $S1, "1e+06 == %g" set $N0, 1.0e6 set $S99, "1e+06 == 1e+06" local_branch $P4, NEWARYN local_branch $P4, PRINTF set $S1, "0.5 == %3.3g" set $N0, 0.5 set $S99, "0.5 == 0.5" local_branch $P4, NEWARYN local_branch $P4, PRINTF set $S1, "%% == %%" set $I0, 0 set $S99, "% == %" local_branch $P4, NEWARYI local_branch $P4, PRINTF set $S1, "That's all, %s" set $S0, "folks!" set $S99, "That's all, folks!" local_branch $P4, NEWARYS local_branch $P4, PRINTF .end .sub other_form_of_sprintf_op new $P4, 'ResizableIntegerArray' new $P3, 'String' new $P2, 'String' set $P2, "15 is %b" new $P1, 'ResizablePMCArray' set $P1[0], 15 sprintf $P3, $P2, $P1 is( $P3, "15 is 1111", 'other form of sprintf op' ) new $P2, 'String' set $P2, "128 is %o" new $P1, 'ResizablePMCArray' set $P1[0], 128 sprintf $P3, $P2, $P1 is( $P3, "128 is 200", 'other form of sprintf op' ) .end .sub sprintf_left_justify $P0 = new 'ResizablePMCArray' $P1 = new 'Integer' $P1 = 10 $P0[0] = $P1 $P1 = new 'String' $P1 = "foo" $P0[1] = $P1 $P1 = new 'String' $P1 = "bar" $P0[2] = $P1 $S0 = sprintf "%-*s - %s", $P0 is( $S0, "foo - bar", 'sprintf - left justify' ) .end .sub correct_precision_for_sprintf_x .include "iglobals.pasm" # Create the string via concat .local pmc interp # a handle to our interpreter object. interp = getinterp .local pmc config config = interp[.IGLOBALS_CONFIG_HASH] .local int intvalsize intvalsize = config['intvalsize'] $S0 = '' $I0 = 1 $I1 = intvalsize * 2 loop: $S0 = concat $S0, 'f' inc $I0 le $I0, $I1, loop padding_loop: $S0 = concat $S0, ' ' inc $I0 le $I0, 20, padding_loop # Now see what sprintf comes up with $P0 = new 'ResizablePMCArray' $P0[0] = -1 $S1 = sprintf "%-20x", $P0 is( $S1, $S0, 'Correct precision for %x' ) .end .sub test_find_encoding find_encoding $I0, "ascii" is( $I0, "0", 'find_encoding' ) find_encoding $I0, "iso-8859-1" is( $I0, "1", 'find_encoding' ) find_encoding $I0, "binary" is( $I0, "2", 'find_encoding' ) find_encoding $I0, "utf8" is( $I0, "3", 'find_encoding' ) find_encoding $I0, "unicode" is( $I0, "3", 'find_encoding' ) find_encoding $I0, "utf16" is( $I0, "4", 'find_encoding' ) find_encoding $I0, "ucs2" is( $I0, "5", 'find_encoding' ) find_encoding $I0, "ucs4" is( $I0, "6", 'find_encoding' ) .end .sub test_assign set $S4, "JAPH" assign $S5, $S4 is( $S4, "JAPH", 'assign' ) is( $S5, "JAPH", 'assign' ) .end .sub assign_and_globber set $S4, "JAPH" assign $S5, $S4 assign $S4, "Parrot" is( $S4, "Parrot", 'assign & globber' ) is( $S5, "JAPH", 'assign & globber' ) .end .sub split_on_null_string .local string s, delim .local pmc p .local int i null s null delim split p, s, delim i = isnull p is(i, 1, 'split on null string and delim') s = 'foo' split p, s, delim i = isnull p is(i, 1, 'split on null delim') null s delim = 'bar' split p, s, delim i = isnull p is(i, 1, 'split on null string') .end .sub split_on_empty_string split $P1, "", "" set $I1, $P1 is( $I1, "0", 'split on empty string' ) split $P0, "", "ab" set $I0, $P0 is( $I0, "2", 'split on empty string' ) set $S0, $P0[0] is( $S0, "a", 'split on empty string' ) set $S0, $P0[1] is( $S0, "b", 'split on empty string' ) .end .sub split_on_non_empty_string split $P0, "a", "afooabara" set $I0, $P0 is( $I0, "5", 'split on non-empty string' ) set $S0, $P0[0] is( $S0, "", 'split on non-empty string' ) set $S0, $P0[1] is( $S0, "foo", 'split on non-empty string' ) set $S0, $P0[2] is( $S0, "b", 'split on non-empty string' ) set $S0, $P0[3] is( $S0, "r", 'split on non-empty string' ) set $S0, $P0[4] is( $S0, "", 'split on non-empty string' ) .end .sub test_join new $P0, 'ResizablePMCArray' join $S0, "--", $P0 is( $S0, "", 'join' ) push $P0, "a" join $S0, "--", $P0 is( $S0, "a", 'join' ) new $P0, 'ResizablePMCArray' push $P0, "a" push $P0, "b" join $S0, "--", $P0 is( $S0, "a--b", 'join' ) .end .sub 'test_join_many' $P1 = new ['ResizablePMCArray'] $I0 = 0 loop: unless $I0 < 20000 goto done $P2 = new ['Integer'] assign $P2, $I0 push $P1, $P2 inc $I0 goto loop done: $S0 = join ' ', $P1 ok("Join of many temporary strings doesn't crash") .end # join: get_string returns a null string -------- .namespace ["Foo5"] .sub get_string :vtable :method .local string ret null ret .begin_return .set_return ret .end_return .end .namespace [] # revert to root for next test .sub join_get_string_returns_a_null_string newclass $P0, "Foo5" new $P0, 'ResizablePMCArray' $P1 = new "Foo5" push $P0, $P1 join $S0, "", $P0 is( $S0, "", 'join: get_string returns a null string' ) .end .sub eq_addr_or_ne_addr set $S0, "Test" set $S1, $S0 set $I99, 1 eq_addr $S1, $S0, OK1 set $I99, 0 OK1: ok($I99, 'eq_addr/ne_addr') set $S0, $S1 set $I99, 0 ne_addr $S1, $S0, BAD4 set $I99, 1 BAD4: ok($I99, 'eq_addr/ne_addr') .end .sub test_if_null_s_ic set $S0, "foo" $I99 = 0 if_null $S0, ERROR $I99 = 1 ERROR: ok($I99, 'if_null s_ic' ) null $S0 $I99 = 1 if_null $S0, OK $I99 = 0 OK: ok($I99, 'if_null s_ic' ) .end .sub test_upcase set $S0, "abCD012yz" upcase $S1, $S0 is( $S1, "ABCD012YZ", 'upcase' ) push_eh catch1 null $S9 null $S0 upcase $S1, $S0 pop_eh goto null1 catch1: .get_results($P9) $S9 = $P9['message'] pop_eh null1: is ($S9, "Can't upcase NULL string", 'upcase null') push_eh catch2 null $S9 null $S0 $S0 = upcase $S0 pop_eh goto null2 catch2: .get_results($P9) $S9 = $P9['message'] pop_eh null2: is ($S9, "Can't upcase NULL string", 'upcase inplace null') push_eh catch3 null $S9 set $S0, binary:"abCD012yz" upcase $S1, $S0 pop_eh goto null3 catch3: .get_results($P9) $S9 = $P9['message'] pop_eh null3: is ($S9, "Invalid operation on binary string", 'upcase binary') .end .sub test_downcase set $S0, "ABcd012YZ" downcase $S1, $S0 is( $S1, "abcd012yz", 'downcase' ) push_eh catch1 null $S9 null $S0 downcase $S1, $S0 pop_eh goto null1 catch1: .get_results($P9) $S9 = $P9['message'] pop_eh null1: is ($S9, "Can't downcase NULL string", 'downcase null') push_eh catch2 null $S9 null $S0 $S0 = downcase $S0 pop_eh goto null2 catch2: .get_results($P9) $S9 = $P9['message'] pop_eh null2: is ($S9, "Can't downcase NULL string", 'downcase inplace null') .end .sub test_titlecase set $S0, "aBcd012YZ" titlecase $S1, $S0 is( $S1, "Abcd012yz", 'titlecase' ) push_eh catch1 null $S9 null $S0 titlecase $S1, $S0 pop_eh goto null1 catch1: .get_results($P9) $S9 = $P9['message'] pop_eh null1: is ($S9, "Can't titlecase NULL string", 'titlecase null') push_eh catch2 null $S9 null $S0 $S0 = titlecase $S0 pop_eh goto null2 catch2: .get_results($P9) $S9 = $P9['message'] pop_eh null2: is ($S9, "Can't titlecase NULL string", 'titlecase inplace null') .end .sub three_param_ord_one_character_string_register_i set $S0,"a" set $I1, 0 ord $I0,$S0,$I1 is( $I0, "97", '3-param ord, one-character string register, I' ) .end .sub three_param_ord_multi_character_string_i set $I1, 1 ord $I0,"ab",$I1 is( $I0, "98", '3-param ord, multi-character string, I' ) .end .sub three_param_ord_multi_character_string_register_i set $I1, 1 set $S0,"ab" ord $I0,$S0,$I1 is( $I0, "98", '3-param ord, multi-character string register, I' ) .end .sub exception_three_param_ord_multi_character_string_i push_eh handler set $I1, 2 ord $I0,"ab",$I1 ok( 0, 'no exception: 3-param ord, multi-character string, I' ) handler: .exception_is( 'Cannot get character past end of string' ) .end .sub exception_three_param_ord_multi_character_string_i push_eh handler set $I1, 2 set $S0,"ab" ord $I0,$S0,$I1 ok( 0, 'no exception: 3-param ord, multi-character string, I' ) handler: .exception_is( 'Cannot get character past end of string' ) .end .sub three_param_ord_one_character_string_from_end_i set $I1, -1 ord $I0,"a",$I1 is( $I0, "97", '3-param ord, one-character string, from end, I' ) .end .sub three_param_ord_one_character_string_register_from_end_i set $I1, -1 set $S0,"a" ord $I0,$S0,$I1 is( $I0, "97", '3-param ord, one-character string register, from end, I' ) .end .sub three_param_ord_multi_character_string_from_end_i set $I1, -1 ord $I0,"ab",$I1 is( $I0, "98", '3-param ord, multi-character string, from end, I' ) .end .sub three_param_ord_multi_character_string_register_from_end_i set $I1, -1 set $S0,"ab" ord $I0,$S0,$I1 is( $I0, "98", '3-param ord, multi-character string register, from end, I' ) .end .sub exception_three_param_ord_multi_character_string_register_from_end_oob_i push_eh handler set $I1, -3 set $S0,"ab" ord $I0,$S0,$I1 ok( 0, 'no exception: 3-param ord, multi-character string register, from end, OOB, I' ) handler: .exception_is( 'Cannot get character before beginning of string' ) .end # Utility method for more_string_to_int .sub 'print_as_integer' .param string s .param string answer $I0 = s concat $S99, 'string to int: ', s is( $I0, answer, $S99 ) .end .sub more_string_to_int print_as_integer('-4', "-4") print_as_integer('X-4',"0") print_as_integer('--4',"0") print_as_integer('+',"0") print_as_integer('++',"0") print_as_integer('+2',"2") print_as_integer(' +3',"3") print_as_integer('++4',"0") print_as_integer('+ 5',"0") print_as_integer('-',"0") print_as_integer('--56',"0") print_as_integer(' -+67',"0") print_as_integer('+-78',"0") print_as_integer(' -089xyz',"-89") print_as_integer('- 89',"0") .end # Utility sub for constant_string_and_modify_in_situ_op_rt_bug_60030 .sub doit_sub_for_but_60030 .param string s $I0 = index s, '::' is( s, "Foo::Bar", 'bug 60030' ) s = replace s, $I0, 2, "/" is( s, "Foo/Bar", 'bug 60030' ) collect is( s, "Foo/Bar", 'bug 60030' ) .end .sub constant_string_and_modify_in_situ_op_rt_bug_60030 doit_sub_for_but_60030('Foo::Bar') # repeat to prove that the constant 'Foo4::Bar4' remains unchanged doit_sub_for_but_60030('Foo::Bar') .end .sub corner_cases_of_numification is( 2147483647.0, "2147483647", 'corner cases of numification' ) is( -2147483648.0, "-2147483648", 'corner cases of numification' ) .end .sub non_canonical_nan_and_inf $N0 = 'nan' is( $N0, "NaN", 'Non canonical nan and inf' ) $N0 = 'iNf' is( $N0, "Inf", 'Non canonical nan and inf' ) $N0 = 'INFINITY' is( $N0, "Inf", 'Non canonical nan and inf' ) $N0 = '-INF' is( $N0, "-Inf", 'Non canonical nan and inf' ) $N0 = '-Infinity' is( $N0, "-Inf", 'Non canonical nan and inf' ) .end .HLL 'foohll' .sub split_hll_mapped .include 'test_more.pir' .local pmc RSA, fooRSA RSA = get_class ['ResizableStringArray'] fooRSA = subclass ['ResizableStringArray'], 'fooRSA' .local pmc interp interp = getinterp interp.'hll_map'(RSA, fooRSA) .local pmc a split a, "a", "afooabara" .local string t t = typeof a is( t, 'fooRSA', 'split - hll mapped' ) .local int n, i n = a is( n, '5', 'split - hll mapped' ) .local string s s = a[0] is( s, '', 'split - hll mapped' ) s = a[1] is( s, 'foo', 'split - hll mapped' ) s = a[2] is( s, 'b', 'split - hll mapped' ) s = a[3] is( s, 'r', 'split - hll mapped' ) s = a[4] is( s, '', 'split - hll mapped' ) .end # Local Variables: # mode: pir # fill-column: 100 # End: # vim: expandtab shiftwidth=4 ft=pir: