This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop "test" filename clashing with "TEST" on Win32
[perl5.git] / ext / XS / APItest / t / hash.t
CommitLineData
0314122a
NC
1#!perl -w
2
3BEGIN {
4 chdir 't' if -d 't';
5 @INC = '../lib';
6 push @INC, "::lib:$MacPerl::Architecture:" if $^O eq 'MacOS';
7 require Config; import Config;
8 if ($Config{'extensions'} !~ /\bXS\/APItest\b/) {
9 # Look, I'm using this fully-qualified variable more than once!
10 my $arch = $MacPerl::Architecture;
11 print "1..0 # Skip: XS::APItest was not built\n";
12 exit 0;
13 }
14}
15
3128e575
NC
16use strict;
17use utf8;
0314122a 18use Tie::Hash;
3128e575
NC
19use Test::More 'no_plan';
20
21use_ok('XS::APItest');
0314122a 22
3128e575
NC
23sub preform_test;
24sub test_present;
25sub test_absent;
26sub test_delete_present;
27sub test_delete_absent;
28sub brute_force_exists;
29sub test_store;
30sub test_fetch_present;
31sub test_fetch_absent;
0314122a 32
b60cf05a
NC
33my $utf8_for_258 = chr 258;
34utf8::encode $utf8_for_258;
0314122a 35
3128e575 36my @testkeys = ('N', chr 198, chr 256);
b60cf05a 37my @keys = (@testkeys, $utf8_for_258);
0314122a 38
3128e575
NC
39foreach (@keys) {
40 utf8::downgrade $_, 1;
41}
42main_tests (\@keys, \@testkeys, '');
0314122a 43
3128e575
NC
44foreach (@keys) {
45 utf8::upgrade $_;
46}
47main_tests (\@keys, \@testkeys, ' [utf8 hash]');
0314122a 48
3128e575
NC
49{
50 my %h = (a=>'cheat');
51 tie %h, 'Tie::StdHash';
52 is (XS::APItest::Hash::store(\%h, chr 258, 1), 1);
53
54 ok (!exists $h{$utf8_for_258},
55 "hv_store doesn't insert a key with the raw utf8 on a tied hash");
56}
0314122a 57
5d2b1485
NC
58{
59 my $strtab = strtab();
60 is (ref $strtab, 'HASH', "The shared string table quacks like a hash");
61 eval {
62 $strtab->{wibble}++;
63 };
64 my $prefix = "Cannot modify shared string table in hv_";
65 my $what = $prefix . 'fetch';
66 like ($@, qr/^$what/,$what);
67 eval {
68 XS::APItest::Hash::store($strtab, 'Boom!', 1)
69 };
70 $what = $prefix . 'store';
71 like ($@, qr/^$what/, $what);
72 if (0) {
73 A::B->method();
74 }
75 # DESTROY should be in there.
76 eval {
77 delete $strtab->{DESTROY};
78 };
79 $what = $prefix . 'delete';
80 like ($@, qr/^$what/, $what);
81 # I can't work out how to get to the code that flips the wasutf8 flag on
82 # the hash key without some ikcy XS
83}
3128e575 84exit;
0314122a 85
3128e575 86################################ The End ################################
0314122a 87
3128e575
NC
88sub main_tests {
89 my ($keys, $testkeys, $description) = @_;
90 foreach my $key (@$testkeys) {
91 my $lckey = ($key eq chr 198) ? chr 230 : lc $key;
92 my $unikey = $key;
93 utf8::encode $unikey;
0314122a 94
3128e575
NC
95 utf8::downgrade $key, 1;
96 utf8::downgrade $lckey, 1;
97 utf8::downgrade $unikey, 1;
98 main_test_inner ($key, $lckey, $unikey, $keys, $description);
0314122a 99
3128e575
NC
100 utf8::upgrade $key;
101 utf8::upgrade $lckey;
102 utf8::upgrade $unikey;
103 main_test_inner ($key, $lckey, $unikey, $keys,
104 $description . ' [key utf8 on]');
105 }
0314122a 106
3128e575
NC
107 # hv_exists was buggy for tied hashes, in that the raw utf8 key was being
108 # used - the utf8 flag was being lost.
109 perform_test (\&test_absent, (chr 258), $keys, '');
0314122a 110
3128e575
NC
111 perform_test (\&test_fetch_absent, (chr 258), $keys, '');
112 perform_test (\&test_delete_absent, (chr 258), $keys, '');
0314122a
NC
113}
114
3128e575
NC
115sub main_test_inner {
116 my ($key, $lckey, $unikey, $keys, $description) = @_;
117 perform_test (\&test_present, $key, $keys, $description);
118 perform_test (\&test_fetch_present, $key, $keys, $description);
119 perform_test (\&test_delete_present, $key, $keys, $description);
b60cf05a 120
3128e575
NC
121 perform_test (\&test_store, $key, $keys, $description, [a=>'cheat']);
122 perform_test (\&test_store, $key, $keys, $description, []);
b60cf05a 123
3128e575
NC
124 perform_test (\&test_absent, $lckey, $keys, $description);
125 perform_test (\&test_fetch_absent, $lckey, $keys, $description);
126 perform_test (\&test_delete_absent, $lckey, $keys, $description);
b60cf05a 127
3128e575
NC
128 return if $unikey eq $key;
129
130 perform_test (\&test_absent, $unikey, $keys, $description);
131 perform_test (\&test_fetch_absent, $unikey, $keys, $description);
132 perform_test (\&test_delete_absent, $unikey, $keys, $description);
b60cf05a
NC
133}
134
3128e575
NC
135sub perform_test {
136 my ($test_sub, $key, $keys, $message, @other) = @_;
b60cf05a
NC
137 my $printable = join ',', map {ord} split //, $key;
138
3128e575
NC
139 my (%hash, %tiehash);
140 tie %tiehash, 'Tie::StdHash';
b60cf05a 141
3128e575
NC
142 @hash{@$keys} = @$keys;
143 @tiehash{@$keys} = @$keys;
b60cf05a 144
3128e575
NC
145 &$test_sub (\%hash, $key, $printable, $message, @other);
146 &$test_sub (\%tiehash, $key, $printable, "$message tie", @other);
b60cf05a
NC
147}
148
3128e575
NC
149sub test_present {
150 my ($hash, $key, $printable, $message) = @_;
151
152 ok (exists $hash->{$key}, "hv_exists_ent present$message $printable");
153 ok (XS::APItest::Hash::exists ($hash, $key),
154 "hv_exists present$message $printable");
b60cf05a
NC
155}
156
3128e575
NC
157sub test_absent {
158 my ($hash, $key, $printable, $message) = @_;
858117f8 159
3128e575
NC
160 ok (!exists $hash->{$key}, "hv_exists_ent absent$message $printable");
161 ok (!XS::APItest::Hash::exists ($hash, $key),
162 "hv_exists absent$message $printable");
b60cf05a
NC
163}
164
3128e575
NC
165sub test_delete_present {
166 my ($hash, $key, $printable, $message) = @_;
b60cf05a 167
3128e575
NC
168 my $copy = {};
169 my $class = tied %$hash;
170 if (defined $class) {
171 tie %$copy, ref $class;
172 }
173 $copy = {%$hash};
8829b5e2
NC
174 ok (brute_force_exists ($copy, $key),
175 "hv_delete_ent present$message $printable");
3128e575 176 is (delete $copy->{$key}, $key, "hv_delete_ent present$message $printable");
8829b5e2
NC
177 ok (!brute_force_exists ($copy, $key),
178 "hv_delete_ent present$message $printable");
3128e575 179 $copy = {%$hash};
8829b5e2
NC
180 ok (brute_force_exists ($copy, $key),
181 "hv_delete present$message $printable");
3128e575
NC
182 is (XS::APItest::Hash::delete ($copy, $key), $key,
183 "hv_delete present$message $printable");
8829b5e2
NC
184 ok (!brute_force_exists ($copy, $key),
185 "hv_delete present$message $printable");
b60cf05a
NC
186}
187
3128e575
NC
188sub test_delete_absent {
189 my ($hash, $key, $printable, $message) = @_;
b60cf05a 190
3128e575
NC
191 my $copy = {};
192 my $class = tied %$hash;
193 if (defined $class) {
194 tie %$copy, ref $class;
195 }
196 $copy = {%$hash};
197 is (delete $copy->{$key}, undef, "hv_delete_ent absent$message $printable");
198 $copy = {%$hash};
199 is (XS::APItest::Hash::delete ($copy, $key), undef,
200 "hv_delete absent$message $printable");
b60cf05a
NC
201}
202
3128e575
NC
203sub test_store {
204 my ($hash, $key, $printable, $message, $defaults) = @_;
205 my $HV_STORE_IS_CRAZY = 1;
b60cf05a 206
3128e575
NC
207 # We are cheating - hv_store returns NULL for a store into an empty
208 # tied hash. This isn't helpful here.
0314122a 209
3128e575 210 my $class = tied %$hash;
0314122a 211
3128e575
NC
212 my %h1 = @$defaults;
213 my %h2 = @$defaults;
214 if (defined $class) {
215 tie %h1, ref $class;
216 tie %h2, ref $class;
217 $HV_STORE_IS_CRAZY = undef unless @$defaults;
218 }
219 is (XS::APItest::Hash::store_ent(\%h1, $key, 1), 1,
220 "hv_store_ent$message $printable");
221 ok (brute_force_exists (\%h1, $key), "hv_store_ent$message $printable");
222 is (XS::APItest::Hash::store(\%h2, $key, 1), $HV_STORE_IS_CRAZY,
223 "hv_store$message $printable");
224 ok (brute_force_exists (\%h2, $key), "hv_store$message $printable");
225}
0314122a 226
3128e575
NC
227sub test_fetch_present {
228 my ($hash, $key, $printable, $message) = @_;
b60cf05a 229
3128e575
NC
230 is ($hash->{$key}, $key, "hv_fetch_ent present$message $printable");
231 is (XS::APItest::Hash::fetch ($hash, $key), $key,
232 "hv_fetch present$message $printable");
0314122a
NC
233}
234
3128e575
NC
235sub test_fetch_absent {
236 my ($hash, $key, $printable, $message) = @_;
b60cf05a 237
3128e575
NC
238 is ($hash->{$key}, undef, "hv_fetch_ent absent$message $printable");
239 is (XS::APItest::Hash::fetch ($hash, $key), undef,
240 "hv_fetch absent$message $printable");
241}
b60cf05a 242
3128e575
NC
243sub brute_force_exists {
244 my ($hash, $key) = @_;
245 foreach (keys %$hash) {
246 return 1 if $key eq $_;
247 }
248 return 0;
b60cf05a 249}