2 # Copyright (C) 2001-2008, The Perl Foundation.
7 t/pmc/hash.t - Test the Hash PMC
15 Tests the C<Hash> PMC. Checks key access with various types of
16 normal and potentially hazardous keys. Does a bit of stress testing as
22 .include 'include/test_more.pir'
28 hash_keys_with_nulls_in_them()
29 nearly_the_same_hash_keys()
31 key_that_hashes_to_zero()
33 stress_test_loop_set_check()
34 stress_test_lots_of_keys()
35 stress_test_loop_set_loop_check()
36 testing_two_hash_indices_with_integers_at_a_time()
37 testing_two_hash_indices_with_numbers_at_a_time()
38 testing_two_hash_indices_with_strings_at_a_time()
39 setting_and_getting_scalar_pmcs()
40 setting_scalar_pmcs_and_getting_scalar_values()
41 getting_values_from_undefined_keys()
42 setting_and_getting_non_scalar_pmcs()
45 getting_pmcs_from_compound_keys()
46 getting_pmcs_from_string_int_compound_keys()
54 entry_types_type_keyed()
55 delete_and_free_list()
56 exists_with_constant_string_key()
58 setting_with_compound_keys()
59 mutating_the_lookup_string()
60 check_whether_interface_is_done()
63 unicode_keys_register_rt_39249()
64 unicode_keys_literal_rt_39249()
68 .sub initial_hash_tests
73 set $P0["baz"], "value"
79 is( $I0, -7, 'lookup Int in hash' )
80 is( $N0, 3.500000, 'lookup Num in hash' )
81 is( $S0, "value", 'lookup Str in hash' )
95 is( $I0, 7, 'lookup Int in hash via Str' )
96 is( $N0, -3.500000, 'lookup Num in hash via Str' )
97 is( $S0, "VALUE", 'lookup Str in hash via Str' )
101 .sub more_than_one_hash
107 set $S1, "another_key"
113 is( $I0, 1, 'two hashes: lookup Int from hash via Str' )
114 is( $I1, 2, 'two hashes: lookup Int from hash via Str in second' )
117 .sub hash_keys_with_nulls_in_them
122 set $P0[$S0], 1 # $P0{parp\0me} = 1
123 set $P0[$S1], 2 # $P0{parp\0you} = 2
128 is( $I0, 1, 'hash key with null 1' )
129 is( $I1, 2, 'hash key will null 2' )
132 .sub nearly_the_same_hash_keys
143 is( $I0, 1, 'hash key with null' )
144 is( $I1, 2, 'almost identical hash key with null' )
147 .sub the_same_hash_keys
154 is( $I0, 1, 'lookup by $S0' )
159 is( $I1, 2, 'set and lookup by $S1 (identical to $S0)' )
162 # NB Next test depends on "key2" hashing to zero, which it does with
163 # the current algorithm; if the algorithm changes, change the test!
166 .sub key_that_hashes_to_zero
172 is( $I0, 1, 'key that hashes to zero XXX' )
175 .sub size_of_the_hash
180 is( $I0, 1, 'hash size of 1' )
184 is( $I0, 2, 'hash size of 2' )
188 is( $I0, 2, 'hash size of 2' )
191 .sub stress_test_loop_set_check
198 set $P0[$S1], "bases"
201 set $P0[$S1], "start"
202 set $S3, $P0["mikey"]
203 is( $S3, 'base', 'setup: lookup mikey' )
204 set $S3, $P0["mikeys"]
205 is( $S3, 'bases', 'setup: lookup mikeys' )
206 set $S3, $P0["mikey200"]
207 is( $S3, 'start', 'setup: lookup mikey200' )
215 ## this should be fail(), but it is not implemented yet
216 ok( 0, 'concat mismatch' )
221 ## this should be fail(), but it is not implemented yet
222 ok( 0, 'lookup mismatch' )
226 set $I0, $P0["mikey199"]
227 is( $I0, 199, 'lookup: mikey199' )
228 set $I0, $P0["mikey117"]
229 is( $I0, 117, 'lookup: mikey117' )
230 set $I0, $P0["mikey1"]
231 is( $I0, 1, 'lookup: mikey1' )
232 set $I0, $P0["mikey23"]
233 is( $I0, 23, 'lookup: miky23' )
234 set $I0, $P0["mikey832"]
235 is( $I0, 0, 'lookup: mikey832 (never set)' )
238 ## stuff them in, and check periodically that we can pull selected ones out.
239 ## *_multiple_keys are used by stress_test_lots_of_keys
241 .sub set_multiple_keys
248 if count <= 0 goto ret
250 $S1 = concat "key", $S0
251 $S2 = concat "value", $S0
253 key_index = key_index + step
259 .sub delete_multiple_keys
266 if count <= 0 goto ret
268 $S1 = concat "key", $S0
270 key_index = key_index + step
281 $S0 = concat "key", $S10
282 $S1 = concat "value", $S10
285 $S3 = concat "correct value for key ", $S10
289 .sub stress_test_lots_of_keys
296 set_multiple_keys($P30, $I29, $I30, $I31)
298 check_key( $P30, 1001 )
299 check_key( $P30, 2001 )
303 set_multiple_keys($P30, $I21, $I30, $I31)
305 check_key( $P30, 1001 )
306 check_key( $P30, 2001 )
307 check_key( $P30, 100000 )
308 check_key( $P30, 101000 )
309 check_key( $P30, 102000 )
313 set_multiple_keys($P30, $I22, $I29, $I22)
315 check_key( $P30, 1001 )
316 check_key( $P30, 2001 )
317 check_key( $P30, 500000 )
318 check_key( $P30, 510000 )
319 check_key( $P30, 520000 )
322 delete_multiple_keys($P30, $I22, $I29, $I22)
323 check_key( $P30, 1001 )
324 check_key( $P30, 2001 )
325 $I50 = exists $P30['key50000']
326 $I51 = exists $P30['key51000']
327 $I52 = exists $P30['key52000']
328 is( $I50, 0, 'key50000 does not exist after delete' )
329 is( $I51, 0, 'key51000 does not exist after delete' )
330 is( $I52, 0, 'key52000 does not exist after delete' )
333 # Check all values after setting all of them
334 .sub stress_test_loop_set_loop_check
355 is( $I0, $I1, 'lookup mismatch in stress test loop' )
360 ok( 1, 'stress test: loop set with loop check' )
363 .sub testing_two_hash_indices_with_integers_at_a_time
370 is( $I0, 37, 'lookup int in foo' )
373 is( $I0, -15, 'lookup int in bar' )
377 is( $I0,37, 'lookup int in foo via var' )
381 is( $I0,-15, 'lookup int in bar via var' )
384 .sub testing_two_hash_indices_with_numbers_at_a_time
387 set $P0["foo"],37.100000
388 set $P0["bar"],-15.100000
391 is( $N0,37.100000, 'lookup num in foo' )
394 is( $N0,-15.100000, 'lookup num in bar' )
398 is( $N0,37.100000, 'lookup num in foo via var' )
402 is( $N0,-15.100000, 'lookup num in bar via var' )
406 .sub testing_two_hash_indices_with_strings_at_a_time
413 is( $S0,"baz", 'lookup str in foo' )
416 is( $S0,"qux", 'lookup str in bar' )
420 is( $S0,"baz", 'lookup str in foo via var' )
424 is( $S0,"qux", 'lookup str in bar via var' )
428 # So far, we have only used INTVALs, FLOATVALs and STRINGs as values
429 # and/or keys. Now we try PMCs.
431 .sub setting_and_getting_scalar_pmcs
436 set $S0, "non-PMC key"
441 is( $P2, $P1, 'lookup PMC Integer' )
443 set $P1, -1234.000000
446 is( $P2, $P1, 'lookup num after PMC Integer in slot' )
448 set $P1, "abcdefghijklmnopq"
451 is( $P2, $P1, 'lookup string' )
457 is( $S1, "Undef", 'lookup Undef PMC' )
461 .sub setting_scalar_pmcs_and_getting_scalar_values
465 set $S0, "A rather large key"
471 is( $I1, $I0, 'lookup PMC and get scalar Int' )
473 set $N0, -1234.000000
477 is( $N1, $N0, 'lookup PMC and get scalar Num' )
479 set $S1, "abcdefghijklmnopq"
483 is( $S2, $S1, 'lookup PMC and get scalar Str' )
487 .sub getting_values_from_undefined_keys
490 set $I0, $P2["qwerty"]
491 set $N0, $P2["asdfgh"]
492 set $S0, $P2["zxcvbn"]
493 set $P0, $P2["123456"]
495 is( $I0, 0, 'undefined key returns Int 0' )
496 is( $N0, 0.0, 'undefined key returns Num 0.0' )
497 is( $S0, "", 'undefined key returns Str ""' )
500 if_null $P0, P0_is_null
503 ok( $I1, 'undefined key returns null PMC' )
506 .sub setting_and_getting_non_scalar_pmcs
508 new $P1,'ResizablePMCArray'
509 new $P2,'ResizablePMCArray'
514 is( $S0, 'string', 'set and get non-scalar PMCs' )
521 new $P2, 'ResizablePMCArray'
525 # $P0 = { a => "a", b => [undef, undef] }
534 # $P0 = { a => "a", b => [undef, undef, undef], c => 4 }
535 # $P1 = { a => "A", b => [undef, undef] }
538 is( $S0, "a", 'original hash lookup pre-clone value' )
542 is( $I0, 3, 'original hash lookup post-clone value' )
545 is( $I0, 4, 'original hash lookup post-clone value in new slot' )
548 is( $S0, "A", 'cloned hash lookup post-clone value' )
552 is( $I0, 2, 'cloned hash lookup pre-clone complex value' )
554 # XXX: this should return undef or something, but it dies instead.
565 new $P2, 'ResizablePMCArray'
568 set $S0, $P0["a";"b"]
569 is( $S0, "ab", 'Str from compound key' )
573 set $I0, $P0["a";"n";20]
574 is( $I0, 77, 'Int from compound key^2' )
579 set $I0, $P0[$S0;$S1;$I0]
580 is( $I0, 77, 'Int from indirect compound key^2' )
584 set $S0, $P0["c";33;"b"]
585 is( $S0, "ab", 'Str from indirect/direct compound key^2' )
590 set $S0, $P0[$S0;$I1;$S2]
591 is( $S0, "ab", 'Str from indirect compound key^2' )
594 set $N0, $P0["c";$I1;$S2]
595 is( $N0, 47.11, 'Num from indirect compound key^2' )
598 .sub getting_pmcs_from_compound_keys
605 set $P3, $P0["a";"b"]
607 is( $S0, "12", "lookup PMC from compound key" )
611 .sub getting_pmcs_from_string_int_compound_keys
618 is( $I0, 4, 'lookup Int PMC from hash' )
622 is( $I0, 4, 'lookup Inc PMC from compound hash' )
625 # A hash is only false if it has size 0
630 ## Could just use Test::More tests directly, but then we are really
631 ## checking casting to Int then testing value (I think)
632 ## ie. ok( $P0, '...' )
638 ok( $I1, 'Empty hash is false' )
640 set $P0["key"], "value"
645 ok( $I1, 'Hash with one slot is true' )
652 ok( $I1, 'Hash with one value ("") is true' )
660 ok( $P0, 'Hash with one value (Undef PMC) is true' )
671 ok( $I0, 'Empty hash is false in unless' )
674 set $P0["key"], "value"
678 ok( $I0, 'Hash with one value is true' )
685 ok( $I0, 'Hash with one value ("\0") is true' )
693 ok( $I0, 'Hash with one value (Undef PMC) is true' )
701 ok( $I0, 'Empty has is defined' )
703 ## nok() had not been (correctly) implemented when this test was written
707 ok( $I1, 'Unassigned var is undefined' )
710 defined $I0, $P0["a"]
711 ok( $I0, 'Int in hash value is defined' )
713 defined $I0, $P0["b"]
715 ok( $I0, 'Unassigned hash slot is undefined' )
719 defined $I0, $P0["c"]
721 ok( $I0, 'Undef PMC in hash slot is undefined' )
729 ok( $I0, 'assigned hash key exists' )
733 ok( $I0, 'unassigned hash key does not exist' )
738 ok( $I0, 'hash key assigned Undef PMC exists' )
746 ok( $I0, 'assigned hash key exists' )
751 ok( $I0, 'delete hash key does not exist' )
759 set $P10[$P1], "Food"
762 is( $S0, "Food", 'cloned key looks up same value' )
765 set $P10[$S1], "Sheep"
768 is( $S0, "Sheep", 'cloned key again look up same value' )
771 .sub cloning_pmc_vals
784 is( $P0, 42, 'cloned hash contained pre-clone set int' )
786 is( $P0, 'value', 'cloned hash contains pre-clone set str' )
789 .sub entry_types_type_keyed
790 ## XXX is there any concern that including this will impact other tests?
791 .include "pmctypes.pasm"
795 set $P1["Integer"], $P2
796 typeof $I0, $P1["Integer"]
797 is( $I0, .Integer, 'entry type is Integer' )
800 set $P1["Integer"], $P3
801 typeof $I0, $P1["Integer"]
802 is( $I0, .Integer, 'entry type is Integer' )
804 set $P1["native int"], -123456
805 typeof $I0, $P1["native int"]
806 is( $I0, .Integer, 'entry type is Integer' )
808 set $P1["native float"], -123.456
809 typeof $I0, $P1["native float"]
810 is( $I0, .Float, 'entry type is Float' )
812 set $P1["native string"], "hello world\n"
813 typeof $I0, $P1["native string"]
814 is( $I0, .String, 'entry type is String' )
818 .sub delete_and_free_list
826 sprintf $S0, "ok %vd\n", $P0
829 ## set $P1[key]=1 then delete it 100 times
843 is( $I0, 10, 'hash has size 10' )
846 ## XXX already tested?
847 .sub exists_with_constant_string_key
850 set $P16["key1"], "value for key1"
851 set $S16, $P16["key1"]
852 is( $S16, "value for key1" , 'set and lookup value for const str key' )
854 exists $I17, $P16["key1"]
855 ok( $I17, 'exists with constant string key' )
857 exists $I17, $P16["no such"]
859 ok( $I17, 'does not exist with unassigned const string key' )
868 is( val1, "U", 'hash in PIR' )
871 .sub setting_with_compound_keys
872 .local pmc outer_hash
873 outer_hash = new 'Hash'
874 .local pmc inner_hash
875 inner_hash = new 'Hash'
876 .local pmc inner_array
877 inner_array = new 'ResizablePMCArray'
878 .local string elem_string
883 # setting and retrieving strings in an inner ResizablePMCArray
884 inner_array[128] = 'inner_array:128'
885 outer_hash['inner_array'] = inner_array
886 elem_string = outer_hash['inner_array';128]
887 is( elem_string, 'inner_array:128', 'string in inner ResizeablePMCArray' )
888 outer_hash['inner_array';128] = 'changed inner_array:128'
889 elem_string = outer_hash['inner_array';128]
890 is( elem_string, 'changed inner_array:128', 'string in inner ResizeablePMCArray' )
892 # setting and retrieving strings in an inner Hash
893 inner_hash['129'] = 'inner_hash:129'
894 outer_hash['inner_hash'] = inner_hash
895 elem_string = outer_hash['inner_hash';'129']
896 is( elem_string, 'inner_hash:129', 'string in inner Hash' )
897 outer_hash['inner_hash';'129'] = 'changed inner_hash:129'
898 elem_string = outer_hash['inner_hash';'129']
899 is( elem_string, 'changed inner_hash:129', 'string in inner Hash' )
901 # setting and retrieving integer in an inner ResizablePMCArray
902 inner_array[130] = 130
903 outer_hash['inner_array'] = inner_array
904 elem_int = outer_hash['inner_array';130]
905 is( elem_int, 130, 'int in inner ResizablePMCArray' )
906 outer_hash['inner_array';130] = -130
907 elem_int = outer_hash['inner_array';130]
908 is( elem_int, -130, 'int in inner ResizablePMCArray' )
910 # setting and retrieving integer in an inner Hash
911 inner_hash['131'] = 131
912 outer_hash['inner_hash'] = inner_hash
913 elem_int = outer_hash['inner_hash';'131']
914 is( elem_int, 131, 'int in inner Hash' )
915 outer_hash['inner_hash';'131'] = -131
916 elem_int = outer_hash['inner_hash';'131']
917 is( elem_int, -131, 'int in inner Hash' )
919 # setting and retrieving a PMC in an inner ResizablePMCArray
921 in_pmc = new 'String'
922 in_pmc = 'inner_array:132'
923 inner_array[132] = in_pmc
924 outer_hash['inner_array'] = inner_array
925 elem_pmc = outer_hash['inner_array';132]
926 is( elem_pmc, 'inner_array:132', 'PMC in inner ResizablePMCArray' )
927 in_pmc = 'changed inner_array:132'
928 outer_hash['inner_array';132] = in_pmc
929 elem_pmc = outer_hash['inner_array';132]
930 is( elem_pmc, 'changed inner_array:132', 'PMC in inner ResizablePMCArray' )
932 # setting and retrieving a PMC in an inner Hash
933 in_pmc = 'inner_array:133'
934 inner_hash['133'] = in_pmc
935 outer_hash['inner_hash'] = inner_hash
936 elem_string = outer_hash['inner_hash';'133']
937 is( elem_string, 'inner_array:133', 'PMC in inner Hash' )
938 in_pmc = 'changed inner_hash:133'
939 outer_hash['inner_hash';'133'] = in_pmc
940 elem_string = outer_hash['inner_hash';'133']
941 is( elem_string, 'changed inner_hash:133', 'PMC in inner Hash' )
943 # setting and retrieving a float in an inner ResizablePMCArray
944 inner_array[134] = 134.134
945 outer_hash['inner_array'] = inner_array
946 elem_num = outer_hash['inner_array';134]
947 is( elem_num, 134.134000, 'float in inner ResizablePMCArray' )
948 outer_hash['inner_array';134] = -134.134
949 elem_num = outer_hash['inner_array';134]
950 is( elem_num, -134.134000, 'float in inner ResizablePMCArray' )
952 # setting and retrieving a float in an inner Hash
953 inner_hash['135'] = 135.135
954 outer_hash['inner_hash'] = inner_hash
955 elem_num = outer_hash['inner_hash';'135']
956 is( elem_num, 135.135000, 'float in inner Hash' )
957 outer_hash['inner_hash';'135'] = -135.135
958 elem_num = outer_hash['inner_hash';'135']
959 is( elem_num, -135.135000, 'float in inner Hash' )
963 .sub mutating_the_lookup_string
967 set $P0["abc"], "three"
971 is( $S1, "one", 'lookup via str in reg' )
975 is( $S1, "two", 'lookup via concated str in reg' )
979 is( $S1, "three", 'lookup via concated^2 str in reg' )
982 .sub check_whether_interface_is_done
987 does bool1, pmc1, "scalar"
989 ok( bool1, 'Hash PMC does not do scalar' )
991 does bool1, pmc1, "hash"
992 ok( bool1, 'Hash PMC does hash' )
994 does bool1, pmc1, "no_interface"
996 ok( bool1, 'Hash PMC does not do no_interface' )
1008 ok( $I0, 'iterator is true' )
1011 is( $P2, 'a', 'shifting iterator give the key' )
1017 ok( $I0, 'iterator is now false' )
1020 ## thx to azuroth on irc
1022 .include "iterator.pasm"
1023 .local string result
1028 # just put in some dummy data...
1035 iter = new 'Iterator', thash
1036 iter = .ITERATE_FROM_START
1040 # go through the hash, print out all the keys: should be a c and e
1042 unless iter goto preit_end
1050 is( result, 'ace', 'iterated through keys successfully' )
1052 # get rid of the c element?
1055 # what do we have after deletion?
1058 iter = new 'Iterator', thash
1059 iter = .ITERATE_FROM_START
1061 # go through the hash, print out all the keys... I believe it should be a and e?
1062 # it actually outputs a, c and e.
1064 unless iter goto postit_end
1072 is( result, 'ae', 'the c key was no longer iterated over' )
1075 .sub unicode_keys_register_rt_39249
1078 $S99 = unicode:"\u7777"
1081 is( $S1, 'ok', 'unicode key' )
1084 .sub unicode_keys_literal_rt_39249
1087 $P1[unicode:"\u7777"] = "ok"
1088 $S1 = $P1[unicode:"\u7777"]
1089 is( $S1, 'ok', 'literal unicode key' )
1091 $S2 = unicode:"\u7777"
1093 is( $S1, 'ok', 'literal unicode key lookup via var' )
1100 # vim: expandtab shiftwidth=4 ft=pir: