fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / t / pmc / string.t
blob892a83b258d601185d87f407133fb42e9c89ba36
1 #!./parrot
2 # Copyright (C) 2001-2010, Parrot Foundation.
3 # $Id$
5 =head1 NAME
7 t/pmc/string.t - Strings
9 =head1 SYNOPSIS
11     % prove t/pmc/string.t
13 =head1 DESCRIPTION
15 Tests the C<String> PMC.
17 =cut
19 .sub main :main
20     .include 'test_more.pir'
22     plan(121)
24     set_or_get_strings()
25     setting_integers()
26     setting_numbers()
27     ensure_that_concat_ppp_copies_strings()
28     ensure_that_concat_pps_copies_strings()
29     test_repeat()
30     test_repeat_without_creating_dest_pmc()
31     test_repeat_int()
32     test_repeat_int_without_declaring_dest()
33     test_if_string()
34     test_concat()
35     test_concat_without_defining_dest()
36     test_cmp()
37     cmp_with_integer()
38     test_substr()
39     test_eq_str()
40     test_ne_str()
41     check_whether_interface_is_done()
42     test_clone()
43     test_set_px_i()
44     test_set_px_s()
45     test_string_replace()
46     set_i0__p0__string_to_int()
47     test_string_trans()
48     is_integer__check_integer()
49     instantiate_str()
50     get_string_returns_cow_string()
51     to_int_1()
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()
56     exception_to_int_2()
57     exception_to_int_3()
58     assign_null_string()
59     access_keyed()
60     # END_OF_TESTS
61 .end
63 .sub set_or_get_strings
64         new $P0, ['String']
66         set $P0, "foo"
67         set $S0, $P0
68         is( $S0, "foo", 'String obj set with literal string' )
70         set $P0, "\0"
71         set $S0, $P0
72         is( $S0, "\0", 'String obj set with \0 string' )
74         set $P0, ""
75         set $S0, $P0
76         is( $S0, "", 'String obj set with "" string' )
78         set $P0, 123
79         set $S0, $P0
80         is( $S0, "123", 'String obj set with literal int' )
82         set $P0, 1.23456789
83         set $S0, $P0
84         is( $S0, "1.23456789", 'String obj set with literal floating point' )
86         set $P0, "0xFFFFFF"
87         set $S0, $P0
88         is( $S0, "0xFFFFFF", 'String obj set with literal hex string' )
90         null $S0
91         set $P0, $S0
92         set $S1, $P0
93         isnull $I0, $S1
94         ok( $I0, 'String obj is null-in null-out' )
95 .end
97 .sub setting_integers
98         new $P0, ['String']
99         set $P0, "1"
100         set $I0, $P0
101         is( $I0, 1, 'string "1" -> int' )
103         new $P0, ['String']
104         set $P0, "2.0"
105         set $I0, $P0
106         is( $I0, 2, 'string "2.0" -> int' )
108         new $P0, ['String']
109         set $P0, ""
110         set $I0, $P0
111         is( $I0, 0, 'string "" -> int' )
113         new $P0, ['String']
114         set $P0, "\0"
115         set $I0, $P0
116         is( $I0, 0, 'string "\0" -> int' )
118         new $P0, ['String']
119         set $P0, "foo"
120         set $I0, $P0
121         is( $I0, 0, 'string "foo" -> int' )
122 .end
124 .sub setting_numbers
125         .include 'fp_equality.pasm'
126         new $P0, ['String']
127         set $P0, "1"
128         set $N0, $P0
129         .fp_eq_ok($N0, 1.0, 'String 1 -> $N0 == 1.0')
131         new $P0, ['String']
132         set $P0, "2.0"
133         set $N0, $P0
134         .fp_eq_ok($N0, 2.0, 'String "2.0" -> $N0 == 2.0')
136         new $P0, ['String']
137         set $P0, ""
138         set $N0, $P0
139         .fp_eq_ok($N0, 0.0, 'String "" -> $N0 == 0.0')
141         new $P0, ['String']
142         set $P0, "\0"
143         set $N0, $P0
144         .fp_eq_ok($N0, 0.0, 'String "\0" -> $N0 == 0.0')
146         new $P0, ['String']
147         set $P0, "foo"
148         set $N0, $P0
149         .fp_eq_ok($N0, 0.0, 'String "foo" -> $N0 == 0.0')
151         new $P0, ['String']
152         set $P0, "1.3e5"
153         set $N0, $P0
154         .fp_eq_ok($N0, 130000.0, 'String "1.3e5" -> $N0 == 130000.0')
155 .end
157 .sub ensure_that_concat_ppp_copies_strings
158     new $P0, ['String']
159     new $P1, ['String']
160     new $P2, ['String']
162     set $P0, "foo"
163     concat  $P1, $P0, $P0
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"
170     concat $P0, $P1, $P2
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' )
175 .end
177 .sub ensure_that_concat_pps_copies_strings
178     new $P0, ['String']
179     new $P1, ['String']
181     set $S0, "Grunties"
182     set $P1, "fnargh"
183     concat $P0, $P1, $S0
185     is( $S0, 'Grunties', 'original untouched' )
186     is( $P1, 'fnargh', 'original untouched' )
187     is( $P0, 'fnarghGrunties', 'concat success' )
188 .end
190 .sub test_repeat
191     new $P0, ['String']
192     set $P0, "x"
193     new $P1, ['Integer']
194     set $P1, 12
195     new $P2, ['String']
196     repeat $P2, $P0, $P1
197     is( $P2, 'xxxxxxxxxxxx', 'Integer arg to repeat' )
199     set $P0, "y"
200     new $P1, ['Float']
201     set $P1, 6.5
202     repeat $P2, $P0, $P1
203     is( $P2, 'yyyyyy', 'Float arg to repeat' )
205     set $P0, "z"
206     new $P1, ['String']
207     set $P1, "3"
208     repeat $P2, $P0, $P1
209     is( $P2, 'zzz', 'String "3" arg to repeat' )
211     set $P0, "a"
212     new $P1, ['Undef']
213     repeat $P2, $P0, $P1
214     is( $P2, '', 'undef PMC arg to repeat' )
215 .end
217 .sub test_repeat_without_creating_dest_pmc
218     new $P0, ['String']
219     set $P0, "x"
220     new $P1, ['Integer']
221     set $P1, 12
222     repeat $P2, $P0, $P1
223     is( $P2, 'xxxxxxxxxxxx', 'Integer argument to repeat' )
225     set $P0, "y"
226     new $P1, ['Float']
227     set $P1, 6.5
228     repeat $P3, $P0, $P1
229     is( $P3, 'yyyyyy', 'Float arg to repeat' )
231     set $P0, "z"
232     new $P1, ['String']
233     set $P1, "3"
234     repeat $P4, $P0, $P1
235     is( $P4, 'zzz', 'String "3" arg to repeat' )
237     set $P0, "a"
238     new $P1, ['Undef']
239     repeat $P5, $P0, $P1
240     is( $P5, '', 'Undef PMC arg to repeat' )
241 .end
243 .sub test_repeat_int
244     new $P0, ['String']
245     set $P0, "x"
246     set $I1, 12
247     new $P2, ['String']
248     repeat $P2, $P0, $I1
249     is( $P2, 'xxxxxxxxxxxx', 'repeat with int arg' )
251     set $P0, "za"
252     set $I1, 3
253     repeat $P2, $P0, $I1
254     is( $P2, 'zazaza', 'repeat with int arg' )
255 .end
257 .sub test_repeat_int_without_declaring_dest
258     new $P0, ['String']
259     set $P0, "x"
260     set $I1, 12
261     repeat $P2, $P0, $I1
262     is( $P2, "xxxxxxxxxxxx", 'repeat with int arg' )    # print $P2
264     set $P0, "za"
265     repeat $P3, $P0, 3
266     is( $P3, "zazaza", 'repeat with literal int arg' )    # print $P3
267 .end
270 .sub test_if_string
271     new $P0, ['String']
272     set $S0, "True"
273     set $P0, $S0
275         set $I0, 1
276         if $P0, TRUE
277         set $I0, 0
278 TRUE:   ok( $I0, 'String "String" is true' )
280         new $P1, ['String']
281         set $S1, ""
282         set $P1, $S1
283         set $I0, 1
284         if $P1, TRUE2
285         set $I0, 0
286 TRUE2:  nok( $I0, 'String "" is false' )
288         new $P2, ['String']
289         set $S2, "0"
290         set $P2, $S2
291         set $I0, 1
292         if $P2, TRUE3
293         set $I0, 0
294 TRUE3:  nok( $I0, 'String "0" is false' )
296         new $P3, ['String']
297         set $S3, "0123"
298         set $P3, $S3
299         set $I0, 1
300         if $P3, TRUE4
301         set $I0, 0
302 TRUE4:  ok( $I0, 'String "0123" is true' )
304         new $P4, ['String']
305         set $I0, 1
306         if $P4, TRUE5
307         set $I0, 0
308 TRUE5:  nok( $I0, 'uninitialized String is false' )
309 .end
311 .sub test_concat
312     new $P0, ['String']
313     new $P1, ['Undef']
314     set $P0, "foo"
315     concat  $P1, $P0, $P0
316     is( $P0, "foo", 'original String is untouched' )
317     is( $P1, "foofoo", '...and concat worked' )
319     new $P0, ['String']
320     new $P1, ['Undef']
321     set $P0, "bar"
322     concat  $P0, $P0, $P1
323     is( $P0, "bar", '"bar" + Undef = "bar"' )
324     is( $P1, "", '... Undef is ""' )
326     new $P0, ['String']
327     new $P1, ['Undef']
328     set $P1, "str"
329     concat  $P1, $P0, $P1
330     is( $P0, "", 'original Undef is ""' )
331     is( $P1, "str", '"str" + Undef = "str"' )
332 .end
334 .sub test_concat_without_defining_dest
335     new $P0, ['String']
336     set $P0, "foo"
337     concat    $P1, $P0, $P0
338     is( $P0, "foo", 'original String is unchanged' )
339     is( $P1, "foofoo", '... concat String x2' )
341     new $P0, ['String']
342     set $P0, "foo"
343     concat $P2, $P0, "bar"
344     is( $P0, "foo", 'original String is unchanged' )
345     is( $P2, "foobar", '... concat String and "bar"' )
346 .end
348 .sub test_cmp
349     new $P1, ['String']
350     new $P2, ['String']
352     set $P1, "abc"
353     set $P2, "abc"
354     cmp $I0, $P1, $P2
355     is( $I0, "0", 'cmp "abc", "abc" = 0' )
357     set $P1, "abcde"
358     set $P2, "abc"
359     cmp $I0, $P1, $P2
360     is( $I0, "1", 'cmp "abcde", "abc" = 1' )
362     set $P1, "abc"
363     set $P2, "abcde"
364     cmp $I0, $P1, $P2
365     is( $I0, "-1", 'cmp "abcde", "abc" = -1' )
366 .end
368 .sub cmp_with_integer
369     new $P1, ['Integer']
370     new $P2, ['String']
371     set $P2, "10"
373     # Int. vs Str.
374     set $P1, 10
375     cmp $I0, $P1, $P2
376     is( $I0, 0, 'cmp 10(Integer PMC), "10"(String PMC) = 0' )
378     set $P1, 20
379     cmp $I0, $P1, $P2
380     is( $I0, 1, 'cmp 20, "10" = 1' )
382     set $P1, 0
383     cmp $I0, $P1, $P2
384     is( $I0, -1, 'cmp 0, "10" = -1' )
386     # Str. vs Int.
387     set $P1, 0
388     cmp $I0, $P2, $P1
389     is( $I0, 1, 'cmp "10", 0 = 1' )
391     set $P1, 20
392     cmp $I0, $P2, $P1
393     is( $I0, -1, 'cmp "10", 20 = -1' )
395     set $P1, 10
396     cmp $I0, $P2, $P1
397     is( $I0, 0, 'cmp "10", 10 = 0' )
398 .end
400 .sub test_substr
401     new $P0, ['String']
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' )
413 .end
415 .sub test_eq_str
416         new $P1, ['String']
417         new $P2, ['String']
418         set $P1, "ABC"
419         set $P2, "ABC"
421         set $I0, 1
422         eq_str $P2, $P1, OK1
423         set $I0, 0
424 OK1:    ok( $I0, 'eq_str "ABC"(String), "ABC"(String) -> true' )
426         set $P2, "abc"
427         set $I0, 1
428         eq_str $P2, $P1, OK2
429         set $I0, 0
430 OK2:    nok( $I0, 'eq_str "abc"(String), 1(Int) -> false' )
432         new $P3, ['Integer']
433         set $P3, 0
434         set $I0, 1
435         eq_str $P2, $P3, OK3
436         set $I0, 0
437 OK3:    nok( $I0, 'eq_str "abc"(String), 0(Integer) -> false' )
439         set $I0, 1
440         eq_str $P3, $P2, OK4
441         set $I0, 0
442 OK4:    nok( $I0, 'eq_str 0(Integer), "abc"(String) -> false' )
443 .end
445 .sub test_ne_str
446         new $P1, ['String']
447         new $P2, ['String']
448         set $P1, "ABC"
449         set $P2, "abc"
450         set $I0, 1
451         ne_str $P2, $P1, OK1
452         set $I0, 0
453 OK1:    ok( $I0, 'ne_str "abc", "ABC" -> true' )
455         set $P2, "ABC"
456         set $I0, 1
457         ne_str $P2, $P1, OK2
458         set $I0, 0
459 OK2:    nok( $I0, 'ne_str "ABC", "ABC" -> false' )
461         new $P3, ['Integer']
462         set $P3, 0
463         set $I0, 1
464         ne_str $P2, $P3, OK3
465         set $I0, 0
466 OK3:    ok( $I0, 'ne_str "ABC", 0(Integer) -> true' )
468         set $I0, 1
469         ne_str $P3, $P2, OK4
470         set $I0, 0
471 OK4:    ok( $I0, 'ne_str "0(Integer), "ABC" -> true' )
472 .end
474 .sub check_whether_interface_is_done
475     .local pmc pmc1
476     pmc1 = new ['String']
477     .local int bool1
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' )
487 .end
489 .sub test_clone
490     new $P0, ['String']
491     set $P0, "Tacitus\n"
492     clone $P1, $P0
493     set $P0, ""
494     is( $P1, "Tacitus\n", 'clone creates a copy' )
495 .end
497 .sub test_set_px_i
498   new $P0, ['String']
499   set $P0, "abcdef\n"
500   set $P0[2], 65
501   is( $P0, "abAdef\n", 'set p[x] = int' )
502 .end
504 .sub test_set_px_s
505   new $P0, ['String']
506   set $P0, "abcdef\n"
507   set $P0[2], "AB"
508   is( $P0, "abABef\n", 'set p[x] = string' )
509 .end
511 .sub test_string_replace
512     $P0 = new ['String']
513     $P0 = "hello world"
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 ""' )
522 .end
524 .sub set_i0__p0__string_to_int
525     new $P0, ['String']
526     set $P0, "12.3E5\n"
527     set $I0, $P0
528     is( $I0, 12, '"12.3E4\n" -> $I0 = 12' )
529 .end
531 .sub test_string_trans
532 # tr{wsatugcyrkmbdhvnATUGCYRKMBDHVN}
533 #            {WSTAACGRYMKVHDBNTAACGRYMKVHDBN};
534     .local string s, t
535     .local int el
537     s = "atugcsATUGCS"
538     .const 'Sub' tr_00 = 'tr_00_init'
539     el = elements tr_00
540     is( el, 256, 'elements' )
542     $P0 = new ['String']
543     t = $P0.'trans'(s, tr_00)
545     is( t, 'TAACGSTAACGS', 'trans' )
546     is( s, 'atugcsATUGCS', "trans doesn't touch source string")
547 .end
549 # create tr table at compile-time
550 .sub tr_00_init :immediate
551     .local pmc tr_array
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
558     len = length from
559     null i
560 loop:
561     ch = ord from, i
562     r  = ord to,   i
563     tr_array[ch] = r
564     inc i
565     if i < len goto loop
566     .return(tr_array)
567 .end
569 .sub is_integer__check_integer
570   $P0 = new ['String']
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')
582   ok( $I0, '... -1' )
584   $I0 = $P0.'is_integer'('+-1')
585   nok( $I0, '... +-1' )
587   $I0 = $P0.'is_integer'('+1')
588   ok( $I0, '... +1' )
590   $S0 = 'abc123abc'
591   $S1 = substr $S0, 3, 3
592   $I0 = $P0.'is_integer'($S1)
593   ok( $I0, '... substr' )
594 .end
596 .sub instantiate_str
597     .const 'String' ok = "ok"
598     is( ok, "ok", ".const 'String'" )
599 .end
601 .sub get_string_returns_cow_string
602   $P0 = new ['String']
603   $P0 = "Foo44"
605   $S0 = $P0
606   $S0 = replace $S0, 0, 1, "B"
607   is( $S0, "Boo44", 'substr replace' )
608   is( $P0, "Foo44", '... no change to original' )
609 .end
611 .sub to_int_1
612     .local pmc s
613     s = new ['String']
614     s = "123"
615     $I0 = s.'to_int'(10)
616     is( $I0, "123", 'String.to_int(10)' )
617     s = "2a"
618     $I0 = s.'to_int'(16)
619     is( $I0, "42", '... 16' )
620     s = "1001"
621     $I0 = s.'to_int'(2)
622     is( $I0, "9", '... 2' )
623 .end
625 .sub elements_gives_length_of_string
626     .local pmc s
627     s = new ['String']
628     s = "123456789"
629     $I0 = elements s
630     is( $I0, "9", 'elements gives length of string' )
631 .end
633 .sub test_string_reverse_index
634   $P0 = new ['String']
635   $I0 = $P0.'reverse_index'('hello', 0)
636   is( $I0, -1, "main empty -1" )
638   $P0 = "Hello world"
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" )
653 .end
655 .macro exception_is ( M )
656     .local pmc exception
657     .local string message
658     .get_results (exception)
660     message = exception['message']
661     is( message, .M, .M )
662 .endm
664 .sub out_of_bounds_substr_positive_offset
665     new $P0, ['String']
666     set $P0, "Woburn"
668     set $I0, 0
669     push_eh handler
670         substr $S0, $P0, 123, 22
671 handler:
672     .exception_is( 'Cannot take substr outside string' )
673 .end
675 .sub out_of_bounds_substr_negative_offset
676     new $P0, ['String']
677     set $P0, "Woburn"
678     push_eh handler
679         substr $S0, $P0, -123, 22
680 handler:
681     .exception_is( 'Cannot take substr outside string' )
682 .end
684 .sub exception_to_int_2
685     .local pmc s
686     s = new ['String']
687     s = "123"
688     push_eh handler
689         $I0 = s.'to_int'(3)
690 handler:
691     .exception_is( 'invalid conversion to int - bad char 3' )
692 .end
694 .sub exception_to_int_3
695     .local pmc s
696     s = new ['String']
697     s = "123"
698     push_eh handler
699         $I0 = s.'to_int'(37)
700 handler:
701     .exception_is( 'invalid conversion to int - bad base 37' )
702 .end
704 .sub assign_null_string
705     .local pmc s
706     .local string m
707     s = new ['String']
708     null m
709     assign s, m
710     m = 'Any other thing'
711     m = s
712     $I0 = 0
713     if null m goto check
714     inc $I0
715 check:
716     is( $I0, 0, 'assign null string, TT #729' )
717 .end
719 .sub access_keyed
720     .local pmc s
721     s = new ['String']
722     s = "BAR" # Second character is zero, not 'o'
724     # Get
725     $S0 = s[0]
726     is($S0, 'B', 'Get string by index')
728     $I0 = s[1]
729     $I1 = ord 'A'
730     is($I0, $I1, 'Get integer by index')
732     $P0 = s[2]
733     is($P0, 'R', 'Get PMC by index')
735     # Set
736     s = new ['String']
737     s = ''
739     $S0 = 'f'
740     s[0] = $S0
741     is(s, 'f', 'Set string keyed')
743     $I0 = ord 'o'
744     s[1] = $I0
745     is(s, 'fo', 'Set integer keyed')
747     $P0 = new ['String']
748     $P0 = 'o'
749     s[2] = $P0
750     is(s, 'foo', 'Set PMC keyed')
752     push_eh null_replace
753     s = new ['String']
754     s[0] = 'f'
755     nok('Replace on null string throws')
756     goto done_null_replace
758   null_replace:
759     ok(1, 'Replace on null string throws')
760   done_null_replace:
761 .end
763 # Local Variables:
764 #   mode: pir
765 #   fill-column: 100
766 # End:
767 # vim: expandtab shiftwidth=4 ft=pir: