2 # Copyright (C) 2001-2010, Parrot Foundation.
7 t/pmc/string.t - Strings
11 % prove t/pmc/string.t
15 Tests the C<String> PMC.
20 .include 'test_more.pir'
27 ensure_that_concat_ppp_copies_strings()
28 ensure_that_concat_pps_copies_strings()
30 test_repeat_without_creating_dest_pmc()
32 test_repeat_int_without_declaring_dest()
35 test_concat_without_defining_dest()
41 check_whether_interface_is_done()
46 set_i0__p0__string_to_int()
48 is_integer__check_integer()
50 get_string_returns_cow_string()
52 elements_gives_length_of_string()
53 test_string_reverse_index()
54 out_of_bounds_substr_positive_offset()
55 out_of_bounds_substr_negative_offset()
63 .sub set_or_get_strings
68 is( $S0, "foo", 'String obj set with literal string' )
72 is( $S0, "\0", 'String obj set with \0 string' )
76 is( $S0, "", 'String obj set with "" string' )
80 is( $S0, "123", 'String obj set with literal int' )
84 is( $S0, "1.23456789", 'String obj set with literal floating point' )
88 is( $S0, "0xFFFFFF", 'String obj set with literal hex string' )
94 ok( $I0, 'String obj is null-in null-out' )
101 is( $I0, 1, 'string "1" -> int' )
106 is( $I0, 2, 'string "2.0" -> int' )
111 is( $I0, 0, 'string "" -> int' )
116 is( $I0, 0, 'string "\0" -> int' )
121 is( $I0, 0, 'string "foo" -> int' )
125 .include 'fp_equality.pasm'
129 .fp_eq_ok($N0, 1.0, 'String 1 -> $N0 == 1.0')
134 .fp_eq_ok($N0, 2.0, 'String "2.0" -> $N0 == 2.0')
139 .fp_eq_ok($N0, 0.0, 'String "" -> $N0 == 0.0')
144 .fp_eq_ok($N0, 0.0, 'String "\0" -> $N0 == 0.0')
149 .fp_eq_ok($N0, 0.0, 'String "foo" -> $N0 == 0.0')
154 .fp_eq_ok($N0, 130000.0, 'String "1.3e5" -> $N0 == 130000.0')
157 .sub ensure_that_concat_ppp_copies_strings
165 is( $P0, 'foo', 'original String is unchanged' )
166 is( $P1, 'foofoo', 'concat on String' )
168 set $P1, "You can't teach an old dog new..."
169 set $P2, "clear physics"
172 is( $P1, "You can't teach an old dog new...", 'original String is unchanges' )
173 is( $P2, 'clear physics', 'original String is unchanges' )
174 is( $P0, "You can't teach an old dog new...clear physics", 'concat on String' )
177 .sub ensure_that_concat_pps_copies_strings
185 is( $S0, 'Grunties', 'original untouched' )
186 is( $P1, 'fnargh', 'original untouched' )
187 is( $P0, 'fnarghGrunties', 'concat success' )
197 is( $P2, 'xxxxxxxxxxxx', 'Integer arg to repeat' )
203 is( $P2, 'yyyyyy', 'Float arg to repeat' )
209 is( $P2, 'zzz', 'String "3" arg to repeat' )
214 is( $P2, '', 'undef PMC arg to repeat' )
217 .sub test_repeat_without_creating_dest_pmc
223 is( $P2, 'xxxxxxxxxxxx', 'Integer argument to repeat' )
229 is( $P3, 'yyyyyy', 'Float arg to repeat' )
235 is( $P4, 'zzz', 'String "3" arg to repeat' )
240 is( $P5, '', 'Undef PMC arg to repeat' )
249 is( $P2, 'xxxxxxxxxxxx', 'repeat with int arg' )
254 is( $P2, 'zazaza', 'repeat with int arg' )
257 .sub test_repeat_int_without_declaring_dest
262 is( $P2, "xxxxxxxxxxxx", 'repeat with int arg' ) # print $P2
266 is( $P3, "zazaza", 'repeat with literal int arg' ) # print $P3
278 TRUE: ok( $I0, 'String "String" is true' )
286 TRUE2: nok( $I0, 'String "" is false' )
294 TRUE3: nok( $I0, 'String "0" is false' )
302 TRUE4: ok( $I0, 'String "0123" is true' )
308 TRUE5: nok( $I0, 'uninitialized String is false' )
316 is( $P0, "foo", 'original String is untouched' )
317 is( $P1, "foofoo", '...and concat worked' )
323 is( $P0, "bar", '"bar" + Undef = "bar"' )
324 is( $P1, "", '... Undef is ""' )
330 is( $P0, "", 'original Undef is ""' )
331 is( $P1, "str", '"str" + Undef = "str"' )
334 .sub test_concat_without_defining_dest
338 is( $P0, "foo", 'original String is unchanged' )
339 is( $P1, "foofoo", '... concat String x2' )
343 concat $P2, $P0, "bar"
344 is( $P0, "foo", 'original String is unchanged' )
345 is( $P2, "foobar", '... concat String and "bar"' )
355 is( $I0, "0", 'cmp "abc", "abc" = 0' )
360 is( $I0, "1", 'cmp "abcde", "abc" = 1' )
365 is( $I0, "-1", 'cmp "abcde", "abc" = -1' )
368 .sub cmp_with_integer
376 is( $I0, 0, 'cmp 10(Integer PMC), "10"(String PMC) = 0' )
380 is( $I0, 1, 'cmp 20, "10" = 1' )
384 is( $I0, -1, 'cmp 0, "10" = -1' )
389 is( $I0, 1, 'cmp "10", 0 = 1' )
393 is( $I0, -1, 'cmp "10", 20 = -1' )
397 is( $I0, 0, 'cmp "10", 10 = 0' )
403 set $P0, "This is a test\n"
404 substr $S0, $P0, 0, 5
405 substr $S1, $P0, 10, 4
406 substr $S2, $P0, -11, 3
407 substr $S3, $P0, 7, 1000 # Valid offset, but length > string length
408 is( $S0, 'This ', 'first 5 chars' )
409 is( $S1, 'test', '10-14' )
410 is( $S2, ' is', 'start from the end' )
411 is( $S3, " a test\n", 'valid offset, but length > string length' )
412 is( $P0, "This is a test\n", 'original is unmodified' )
424 OK1: ok( $I0, 'eq_str "ABC"(String), "ABC"(String) -> true' )
430 OK2: nok( $I0, 'eq_str "abc"(String), 1(Int) -> false' )
437 OK3: nok( $I0, 'eq_str "abc"(String), 0(Integer) -> false' )
442 OK4: nok( $I0, 'eq_str 0(Integer), "abc"(String) -> false' )
453 OK1: ok( $I0, 'ne_str "abc", "ABC" -> true' )
459 OK2: nok( $I0, 'ne_str "ABC", "ABC" -> false' )
466 OK3: ok( $I0, 'ne_str "ABC", 0(Integer) -> true' )
471 OK4: ok( $I0, 'ne_str "0(Integer), "ABC" -> true' )
474 .sub check_whether_interface_is_done
476 pmc1 = new ['String']
479 does bool1, pmc1, "scalar"
480 ok( bool1, 'String does scalar' )
482 does bool1, pmc1, "string"
483 ok( bool1, 'String does string' )
485 does bool1, pmc1, "no_interface"
486 nok( bool1, 'String !does no_interface' )
494 is( $P1, "Tacitus\n", 'clone creates a copy' )
501 is( $P0, "abAdef\n", 'set p[x] = int' )
508 is( $P0, "abABef\n", 'set p[x] = string' )
511 .sub test_string_replace
515 is( $P0, "hello world", 'original' )
516 $P0."replace"("l", "-")
517 is( $P0, "he--o wor-d", 'String."replace" l with -' )
518 $P0."replace"("wo", "!!!!")
519 is( $P0, "he--o !!!!r-d", 'String."replace" wo with !!!!' )
520 $P0."replace"("he-", "")
521 is( $P0, "-o !!!!r-d", 'String."replace" he- with ""' )
524 .sub set_i0__p0__string_to_int
528 is( $I0, 12, '"12.3E4\n" -> $I0 = 12' )
531 .sub test_string_trans
532 # tr{wsatugcyrkmbdhvnATUGCYRKMBDHVN}
533 # {WSTAACGRYMKVHDBNTAACGRYMKVHDBN};
538 .const 'Sub' tr_00 = 'tr_00_init'
540 is( el, 256, 'elements' )
543 t = $P0.'trans'(s, tr_00)
545 is( t, 'TAACGSTAACGS', 'trans' )
546 is( s, 'atugcsATUGCS', "trans doesn't touch source string")
549 # create tr table at compile-time
550 .sub tr_00_init :immediate
552 tr_array = new ['FixedIntegerArray'] # Todo char array
553 tr_array = 256 # Python compat ;)
554 .local string from, to
555 from = 'wsatugcyrkmbdhvnATUGCYRKMBDHVN'
556 to = 'WSTAACGRYMKVHDBNTAACGRYMKVHDBN'
557 .local int i, ch, r, len
569 .sub is_integer__check_integer
572 $I0 = $P0.'is_integer'('543')
573 ok( $I0, 'String."is_integer("543")' )
575 $I0 = $P0.'is_integer'('4.3')
576 nok( $I0, '... 4.3' )
578 $I0 = $P0.'is_integer'('foo')
579 nok( $I0, '... foo' )
581 $I0 = $P0.'is_integer'('-1')
584 $I0 = $P0.'is_integer'('+-1')
585 nok( $I0, '... +-1' )
587 $I0 = $P0.'is_integer'('+1')
591 $S1 = substr $S0, 3, 3
592 $I0 = $P0.'is_integer'($S1)
593 ok( $I0, '... substr' )
597 .const 'String' ok = "ok"
598 is( ok, "ok", ".const 'String'" )
601 .sub get_string_returns_cow_string
606 $S0 = replace $S0, 0, 1, "B"
607 is( $S0, "Boo44", 'substr replace' )
608 is( $P0, "Foo44", '... no change to original' )
616 is( $I0, "123", 'String.to_int(10)' )
619 is( $I0, "42", '... 16' )
622 is( $I0, "9", '... 2' )
625 .sub elements_gives_length_of_string
630 is( $I0, "9", 'elements gives length of string' )
633 .sub test_string_reverse_index
635 $I0 = $P0.'reverse_index'('hello', 0)
636 is( $I0, -1, "main empty -1" )
639 $I0 = $P0.'reverse_index'('', 0)
640 is( $I0, -1, "search empty -1" )
642 $I0 = $P0.'reverse_index'('o', -1)
643 is( $I0, -1, "negative start -1" )
645 $I0 = $P0.'reverse_index'('o', 999)
646 is( $I0, -1, "far far away -1" )
648 $I0 = $P0.'reverse_index'('l', 0)
649 is( $I0, 9, "search1 9" )
651 $I0 = $P0.'reverse_index'('l', 8)
652 is( $I0, 3, "search2 3" )
655 .macro exception_is ( M )
657 .local string message
658 .get_results (exception)
660 message = exception['message']
661 is( message, .M, .M )
664 .sub out_of_bounds_substr_positive_offset
670 substr $S0, $P0, 123, 22
672 .exception_is( 'Cannot take substr outside string' )
675 .sub out_of_bounds_substr_negative_offset
679 substr $S0, $P0, -123, 22
681 .exception_is( 'Cannot take substr outside string' )
684 .sub exception_to_int_2
691 .exception_is( 'invalid conversion to int - bad char 3' )
694 .sub exception_to_int_3
701 .exception_is( 'invalid conversion to int - bad base 37' )
704 .sub assign_null_string
710 m = 'Any other thing'
716 is( $I0, 0, 'assign null string, TT #729' )
722 s = "BAR" # Second character is zero, not 'o'
726 is($S0, 'B', 'Get string by index')
730 is($I0, $I1, 'Get integer by index')
733 is($P0, 'R', 'Get PMC by index')
741 is(s, 'f', 'Set string keyed')
745 is(s, 'fo', 'Set integer keyed')
750 is(s, 'foo', 'Set PMC keyed')
755 nok('Replace on null string throws')
756 goto done_null_replace
759 ok(1, 'Replace on null string throws')
767 # vim: expandtab shiftwidth=4 ft=pir: