1#!./perl -w
2#
3#  Copyright 2002, Larry Wall.
4#
5#  You may redistribute only under the same terms as Perl 5, as specified
6#  in the README file that comes with the distribution.
7#
8
9# I ought to keep this test easily backwards compatible to 5.004, so no
10# qr//;
11
12# This test checks downgrade behaviour on pre-5.8 perls when new 5.8 features
13# are encountered.
14
15sub BEGIN {
16    unshift @INC, 't';
17    unshift @INC, 't/compat' if $] < 5.006002;
18    require Config; import Config;
19    if ($ENV{PERL_CORE} and $Config{'extensions'} !~ /\bStorable\b/) {
20        print "1..0 # Skip: Storable was not built\n";
21        exit 0;
22    }
23}
24
25use Test::More;
26use Storable 'thaw';
27
28use strict;
29our (%U_HASH, $UTF8_CROAK, $RESTRICTED_CROAK);
30
31our @RESTRICT_TESTS = ('Locked hash', 'Locked hash placeholder',
32                   'Locked keys', 'Locked keys placeholder',
33                  );
34our %R_HASH = (perl => 'rules');
35
36if ($] > 5.007002) {
37  # This is cheating. "\xdf" in Latin 1 is beta S, so will match \w if it
38  # is stored in utf8, not bytes.
39  # "\xdf" is y diaresis in EBCDIC (except for cp875, but so far no-one seems
40  # to use that) which has exactly the same properties for \w
41  # So the tests happen to pass.
42  my $utf8 = "Schlo\xdf" . chr 256;
43  chop $utf8;
44
45  # \xe5 is V in EBCDIC. That doesn't have the same properties w.r.t. \w as
46  # an a circumflex, so we need to be explicit.
47
48  # and its these very properties we're trying to test - an edge case
49  # involving whether scalars are being stored in bytes or in utf8.
50  my $a_circumflex = (ord ('A') == 193 ? "\x47" : "\xe5");
51  %U_HASH = (map {$_, $_} 'castle', "ch${a_circumflex}teau", $utf8, chr 0x57CE);
52  plan tests => 169;
53} else {
54  plan tests => 59;
55}
56
57$UTF8_CROAK = "/^Cannot retrieve UTF8 data in non-UTF8 perl/";
58$RESTRICTED_CROAK = "/^Cannot retrieve restricted hash/";
59
60my %tests;
61{
62  local $/ = "\n\nend\n";
63  while (<DATA>) {
64    next unless /\S/s;
65    unless (/begin ([0-7]{3}) ([^\n]*)\n(.*)$/s) {
66      s/\n.*//s;
67      warn "Dodgy data in section starting '$_'";
68      next;
69    }
70    next unless oct $1 == ord 'A'; # Skip ASCII on EBCDIC, and vice versa
71    my $data = unpack 'u', $3;
72    $tests{$2} = $data;
73  }
74}
75
76# use Data::Dumper; $Data::Dumper::Useqq = 1; print Dumper \%tests;
77sub thaw_hash {
78  my ($name, $expected) = @_;
79  my $hash = eval {thaw $tests{$name}};
80  is ($@, '', "Thawed $name without error?");
81  isa_ok ($hash, 'HASH');
82  ok (defined $hash && eq_hash($hash, $expected),
83      "And it is the hash we expected?");
84  $hash;
85}
86
87sub thaw_scalar {
88  my ($name, $expected, $bug) = @_;
89  my $scalar = eval {thaw $tests{$name}};
90  is ($@, '', "Thawed $name without error?");
91  isa_ok ($scalar, 'SCALAR', "Thawed $name?");
92  is ($$scalar, $expected, "And it is the data we expected?");
93  $scalar;
94}
95
96sub thaw_fail {
97  my ($name, $expected) = @_;
98  my $thing = eval {thaw $tests{$name}};
99  is ($thing, undef, "Thawed $name failed as expected?");
100  like ($@, $expected, "Error as predicted?");
101}
102
103sub test_locked_hash {
104  my $hash = shift;
105  my @keys = keys %$hash;
106  my ($key, $value) = each %$hash;
107  eval {$hash->{$key} = reverse $value};
108  like( $@, "/^Modification of a read-only value attempted/",
109        'trying to change a locked key' );
110  is ($hash->{$key}, $value, "hash should not change?");
111  eval {$hash->{use} = 'perl'};
112  like( $@, "/^Attempt to access disallowed key 'use' in a restricted hash/",
113        'trying to add another key' );
114  ok (eq_array([keys %$hash], \@keys), "Still the same keys?");
115}
116
117sub test_restricted_hash {
118  my $hash = shift;
119  my @keys = keys %$hash;
120  my ($key, $value) = each %$hash;
121  eval {$hash->{$key} = reverse $value};
122  is( $@, '',
123        'trying to change a restricted key' );
124  is ($hash->{$key}, reverse ($value), "hash should change");
125  eval {$hash->{use} = 'perl'};
126  like( $@, "/^Attempt to access disallowed key 'use' in a restricted hash/",
127        'trying to add another key' );
128  ok (eq_array([keys %$hash], \@keys), "Still the same keys?");
129}
130
131sub test_placeholder {
132  my $hash = shift;
133  eval {$hash->{rules} = 42};
134  is ($@, '', 'No errors');
135  is ($hash->{rules}, 42, "New value added");
136}
137
138sub test_newkey {
139  my $hash = shift;
140  eval {$hash->{nms} = "http://nms-cgi.sourceforge.net/"};
141  is ($@, '', 'No errors');
142  is ($hash->{nms}, "http://nms-cgi.sourceforge.net/", "New value added");
143}
144
145# $Storable::DEBUGME = 1;
146thaw_hash ('Hash with utf8 flag but no utf8 keys', \%R_HASH);
147
148if (eval "use Hash::Util; 1") {
149  print "# We have Hash::Util, so test that the restricted hashes in <DATA> are valid\n";
150  for $Storable::downgrade_restricted (0, 1, undef, "cheese") {
151    my $hash = thaw_hash ('Locked hash', \%R_HASH);
152    test_locked_hash ($hash);
153    $hash = thaw_hash ('Locked hash placeholder', \%R_HASH);
154    test_locked_hash ($hash);
155    test_placeholder ($hash);
156
157    $hash = thaw_hash ('Locked keys', \%R_HASH);
158    test_restricted_hash ($hash);
159    $hash = thaw_hash ('Locked keys placeholder', \%R_HASH);
160    test_restricted_hash ($hash);
161    test_placeholder ($hash);
162  }
163} else {
164  print "# We don't have Hash::Util, so test that the restricted hashes downgrade\n";
165  my $hash = thaw_hash ('Locked hash', \%R_HASH);
166  test_newkey ($hash);
167  $hash = thaw_hash ('Locked hash placeholder', \%R_HASH);
168  test_newkey ($hash);
169  $hash = thaw_hash ('Locked keys', \%R_HASH);
170  test_newkey ($hash);
171  $hash = thaw_hash ('Locked keys placeholder', \%R_HASH);
172  test_newkey ($hash);
173  local $Storable::downgrade_restricted = 0;
174  thaw_fail ('Locked hash', $RESTRICTED_CROAK);
175  thaw_fail ('Locked hash placeholder', $RESTRICTED_CROAK);
176  thaw_fail ('Locked keys', $RESTRICTED_CROAK);
177  thaw_fail ('Locked keys placeholder', $RESTRICTED_CROAK);
178}
179
180print "# We have utf8 scalars, so test that the utf8 scalars in <DATA> are valid\n";
181thaw_scalar ('Short 8 bit utf8 data', "\xDF", 1);
182thaw_scalar ('Long 8 bit utf8 data', "\xDF" x 256, 1);
183thaw_scalar ('Short 24 bit utf8 data', chr 0xC0FFEE);
184thaw_scalar ('Long 24 bit utf8 data', chr (0xC0FFEE) x 256);
185
186if ($] > 5.007002) {
187  print "# We have utf8 hashes, so test that the utf8 hashes in <DATA> are valid\n";
188  my $hash = thaw_hash ('Hash with utf8 keys', \%U_HASH);
189  my $a_circumflex = (ord ('A') == 193 ? "\x47" : "\xe5");
190  for (keys %$hash) {
191    my $l = 0 + /^\w+$/;
192    my $r = 0 + $hash->{$_} =~ /^\w+$/;
193    cmp_ok ($l, '==', $r, sprintf "key length %d", length $_);
194    cmp_ok ($l, '==', $_ eq "ch${a_circumflex}teau" ? 0 : 1);
195  }
196  if (eval "use Hash::Util; 1") {
197    print "# We have Hash::Util, so test that the restricted utf8 hash is valid\n";
198  my $hash = thaw_hash ('Locked hash with utf8 keys', \%U_HASH);
199    for (keys %$hash) {
200      my $l = 0 + /^\w+$/;
201      my $r = 0 + $hash->{$_} =~ /^\w+$/;
202      cmp_ok ($l, '==', $r, sprintf "key length %d", length $_);
203      cmp_ok ($l, '==', $_ eq "ch${a_circumflex}teau" ? 0 : 1);
204    }
205    test_locked_hash ($hash);
206  } else {
207    print "# We don't have Hash::Util, so test that the utf8 hash downgrades\n";
208    fail ("You can't get here [perl version $]]. This is a bug in the test.
209# Please send the output of perl -V to perlbug\@perl.org");
210  }
211} else {
212  print "# We don't have utf8 hashes, so test that the utf8 hashes downgrade\n";
213  thaw_fail ('Hash with utf8 keys', $UTF8_CROAK);
214  thaw_fail ('Locked hash with utf8 keys', $UTF8_CROAK);
215  local $Storable::drop_utf8 = 1;
216  my $expect = thaw $tests{"Hash with utf8 keys for 5.6"};
217  thaw_hash ('Hash with utf8 keys', $expect);
218  #foreach (keys %$expect) { print "'$_':\t'$expect->{$_}'\n"; }
219  #foreach (keys %$got) { print "'$_':\t'$got->{$_}'\n"; }
220  if (eval "use Hash::Util; 1") {
221    print "# We have Hash::Util, so test that the restricted hashes in <DATA> are valid\n";
222    fail ("You can't get here [perl version $]]. This is a bug in the test.
223# Please send the output of perl -V to perlbug\@perl.org");
224  } else {
225    print "# We don't have Hash::Util, so test that the restricted hashes downgrade\n";
226    my $hash = thaw_hash ('Locked hash with utf8 keys', $expect);
227    test_newkey ($hash);
228    local $Storable::downgrade_restricted = 0;
229    thaw_fail ('Locked hash with utf8 keys', $RESTRICTED_CROAK);
230    # Which croak comes first is a bit of an implementation issue :-)
231    local $Storable::drop_utf8 = 0;
232    thaw_fail ('Locked hash with utf8 keys', $RESTRICTED_CROAK);
233  }
234}
235__END__
236# A whole run of 2.x nfreeze data, uuencoded. The "mode bits" are the octal
237# value of 'A', the "file name" is the test name. Use make_downgrade.pl to
238# generate these.
239begin 101 Locked hash
2408!049`0````$*!7)U;&5S!`````1P97)L
241
242end
243
244begin 101 Locked hash placeholder
245C!049`0````(*!7)U;&5S!`````1P97)L#A0````%<G5L97,`
246
247end
248
249begin 101 Locked keys
2508!049`0````$*!7)U;&5S``````1P97)L
251
252end
253
254begin 101 Locked keys placeholder
255C!049`0````(*!7)U;&5S``````1P97)L#A0````%<G5L97,`
256
257end
258
259begin 101 Short 8 bit utf8 data
260&!047`L.?
261
262end
263
264begin 101 Short 8 bit utf8 data as bytes
265&!04*`L.?
266
267end
268
269begin 101 Long 8 bit utf8 data
270M!048```"`,.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?
271MPY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#
272MG\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?
273MPY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#
274MG\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?
275MPY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#
276MG\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?
277MPY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#
278MG\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?
279MPY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#
280MG\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?
2818PY_#G\.?PY_#G\.?PY_#G\.?PY_#G\.?
282
283end
284
285begin 101 Short 24 bit utf8 data
286)!047!?BPC[^N
287
288end
289
290begin 101 Short 24 bit utf8 data as bytes
291)!04*!?BPC[^N
292
293end
294
295begin 101 Long 24 bit utf8 data
296M!048```%`/BPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
297MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
298MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
299MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
300MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
301MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
302MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
303MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
304MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
305MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
306MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
307MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
308MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
309MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
310MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
311MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
312MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
313MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
314MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
315MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
316MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
317MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
318MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
319MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
320MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
321MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
322MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
323MOZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N^+"/
324;OZ[XL(^_KOBPC[^N^+"/OZ[XL(^_KOBPC[^N
325
326end
327
328begin 101 Hash with utf8 flag but no utf8 keys
3298!049``````$*!7)U;&5S``````1P97)L
330
331end
332
333begin 101 Hash with utf8 keys
334M!049``````0*!F-A<W1L90`````&8V%S=&QE"@=C:.5T96%U``````=C:.5T
335D96%U%P/EGXX!`````^6?CA<'4V-H;&_#GP(````&4V-H;&_?
336
337end
338
339begin 101 Locked hash with utf8 keys
340M!049`0````0*!F-A<W1L900````&8V%S=&QE"@=C:.5T96%U!`````=C:.5T
341D96%U%P/EGXX%`````^6?CA<'4V-H;&_#GP8````&4V-H;&_?
342
343end
344
345begin 101 Hash with utf8 keys for 5.6
346M!049``````0*!F-A<W1L90`````&8V%S=&QE"@=C:.5T96%U``````=C:.5T
347D96%U%P/EGXX``````^6?CA<'4V-H;&_#GP(````&4V-H;&_?
348
349end
350
351begin 301 Locked hash
3528!049`0````$*!9FDDX6B!`````27A9F3
353
354end
355
356begin 301 Locked hash placeholder
357C!049`0````(.%`````69I).%H@H%F:23A:($````!)>%F9,`
358
359end
360
361begin 301 Locked keys
3628!049`0````$*!9FDDX6B``````27A9F3
363
364end
365
366begin 301 Locked keys placeholder
367C!049`0````(.%`````69I).%H@H%F:23A:(`````!)>%F9,`
368
369end
370
371begin 301 Short 8 bit utf8 data
372&!047`HMS
373
374end
375
376begin 301 Short 8 bit utf8 data as bytes
377&!04*`HMS
378
379end
380
381begin 301 Long 8 bit utf8 data
382M!048```"`(MSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMS
383MBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+
384M<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMS
385MBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+
386M<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMS
387MBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+
388M<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMS
389MBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+
390M<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMS
391MBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+
392M<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMS
3938BW.+<XMSBW.+<XMSBW.+<XMSBW.+<XMS
394
395end
396
397begin 301 Short 24 bit utf8 data
398*!047!OM30G-S50``
399
400end
401
402begin 301 Short 24 bit utf8 data as bytes
403*!04*!OM30G-S50``
404
405end
406
407begin 301 Long 24 bit utf8 data
408M!048```&`/M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
409M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
410M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
411M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
412M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
413M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
414M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
415M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
416M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
417M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
418M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
419M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
420M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
421M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
422M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
423M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
424M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
425M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
426M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
427M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
428M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
429M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
430M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
431M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
432M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
433M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
434M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
435M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
436M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
437M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
438M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
439M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
440M5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M3
441M0G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S5?M30G-S
442-5?M30G-S5?M30G-S50``
443
444end
445
446begin 301 Hash with utf8 flag but no utf8 keys
4478!049``````$*!9FDDX6B``````27A9F3
448
449end
450
451begin 301 Hash with utf8 keys
452M!049``````0*!X.(1Z.%@:0`````!X.(1Z.%@:0*!H.!HJ.3A0`````&@X&B
453FHY.%%P3<9')5`0````3<9')5%P?B@XB3EHMS`@````;B@XB3EM\`
454
455end
456
457begin 301 Locked hash with utf8 keys
458M!049`0````0*!X.(1Z.%@:0$````!X.(1Z.%@:0*!H.!HJ.3A00````&@X&B
459FHY.%%P3<9')5!0````3<9')5%P?B@XB3EHMS!@````;B@XB3EM\`
460
461end
462
463begin 301 Hash with utf8 keys for 5.6
464M!049``````0*!H.!HJ.3A0`````&@X&BHY.%"@>#B$>CA8&D``````>#B$>C
465FA8&D%P?B@XB3EHMS`@````;B@XB3EM\7!-QD<E4`````!-QD<E4`
466
467end
468