import Devel-Size 0.69 from CPAN
[p5sagit/Devel-Size.git] / t / recurse.t
CommitLineData
b1e5ad85 1#!/usr/bin/perl -w
2
c8db37d3 3# IMPORTANT NOTE:
4#
5# When testing total_size(), always remember that it dereferences things, so
6# total_size([]) will NOT return the size of the ref + the array, it will only
7# return the size of the array alone!
8
b1e5ad85 9use Test::More;
10use strict;
11
12my $tests;
13
14BEGIN
15 {
16 chdir 't' if -d 't';
c8db37d3 17 plan tests => 6 + 4 * 12;
b1e5ad85 18
19 use lib '../lib';
20 use lib '../blib/arch';
21 use_ok('Devel::Size');
22 }
23
24can_ok ('Devel::Size', qw/
25 size
26 total_size
27 /);
28
29Devel::Size->import( qw(size total_size) );
30
5a83b7cf 31die ("Uhoh, test uses an outdated version of Devel::Size")
32 unless is ($Devel::Size::VERSION, '0.69', 'VERSION MATCHES');
b1e5ad85 33
34#############################################################################
c8db37d3 35# verify that pointer sizes in array slots are sensible:
36# create an array with 4 slots, 2 of them used
37my $array = [ 1,2,3,4 ]; pop @$array; pop @$array;
38
39# the total size minus the array itself minus two scalars is 4 slots
40my $ptr_size = total_size($array) - total_size( [] ) - total_size(1) * 2;
41
42is ($ptr_size % 4, 0, '4 pointers are dividable by 4');
43isnt ($ptr_size, 0, '4 pointers are not zero');
44
45# size of one slot ptr
46$ptr_size /= 4;
47
48#############################################################################
49# assert hash and hash key size
b1e5ad85 50
b1e5ad85 51my $hash = {};
c8db37d3 52$hash->{a} = 1;
53is (total_size($hash), total_size( { a => undef } ) + total_size(1) - total_size(undef));
b1e5ad85 54
c8db37d3 55#############################################################################
56# #24846 (Does not correctly recurse into references in a PVNV-type scalar)
b1e5ad85 57
c8db37d3 58# run the following tests with different sizes
59
60for my $size (2, 3, 7, 100)
61 {
62 my $hash = { a => 1 };
63
64 # hash + key minus the value
65 my $hash_size = total_size($hash) - total_size(1);
66
67 $hash->{a} = 0/1;
68 $hash->{a} = [];
69
70 my $pvnv_size = total_size(\$hash->{a}) - total_size([]);
71 # size of one ref
72 my $ref_size = total_size(\\1) - total_size(1);
73
74 # $hash->{a} is now a PVNV, e.g. a scalar NV and a ref to an array:
75# SV = PVNV(0x81ff9a8) at 0x8170d48
76# REFCNT = 1
77# FLAGS = (ROK)
78# IV = 0
79# NV = 0
80# RV = 0x81717bc
81# SV = PVAV(0x8175d6c) at 0x81717bc
82# REFCNT = 1
83# FLAGS = ()
84# IV = 0
85# NV = 0
86# ARRAY = 0x0
87# FILL = -1
88# MAX = -1
89# ARYLEN = 0x0
90# FLAGS = (REAL)
91# PV = 0x81717bc ""
92# CUR = 0
93# LEN = 0
94
95 # Compare this to a plain array ref
96#SV = RV(0x81a2834) at 0x8207a2c
97# REFCNT = 1
98# FLAGS = (TEMP,ROK)
99# RV = 0x8170b44
100# SV = PVAV(0x8175d98) at 0x8170b44
101# REFCNT = 2
102# FLAGS = ()
103# IV = 0
104# NV = 0
105# ARRAY = 0x0
106# FILL = -1
107# MAX = -1
108# ARYLEN = 0x0
109
110 # Get the size of the PVNV and the contained array
111 my $element_size = total_size(\$hash->{a});
112
113 ok ($element_size < total_size($hash), "element < hash with one element");
114 ok ($element_size > total_size(\[]), "PVNV + [] > [] alone");
115
116 # Dereferencing the PVNV (the argument to total_size) leaves us with
117 # just the array, and this should be equal to a dereferenced array:
118 is (total_size($hash->{a}), total_size([]), '[] vs. []');
119
120 # the hash with one key
121 # the PVNV in the hash
122 # the RV inside the PVNV
123 # the contents of the array (array size)
124
125 my $full_hash = total_size($hash);
126 my $array_size = total_size([]);
127 is ($full_hash, $element_size + $hash_size, 'properly recurses into PVNV');
128 is ($full_hash, $array_size + $pvnv_size + $hash_size, 'properly recurses into PVNV');
129
130 $hash->{a} = [0..$size];
131
132 # the outer references stripped away, so they should be the same
133 is (total_size([0..$size]), total_size( $hash->{a} ), "hash element vs. array");
134
135 # the outer references included, one is just a normal ref, while the other
136 # is a PVNV, so they shouldn't be the same:
137 isnt (total_size(\[0..$size]), total_size( \$hash->{a} ), "[0..size] vs PVNV");
138 # and the plain ref should be smaller
139 ok (total_size(\[0..$size]) < total_size( \$hash->{a} ), "[0..size] vs. PVNV");
140
141 $full_hash = total_size($hash);
142 $element_size = total_size(\$hash->{a});
143 $array_size = total_size(\[0..$size]);
144
145 print "# full_hash = $full_hash\n";
146 print "# hash_size = $hash_size\n";
147 print "# array size: $array_size\n";
148 print "# element size: $element_size\n";
149 print "# ref_size = $ref_size\n";
150 print "# pvnv_size: $pvnv_size\n";
151
152 # the total size is:
153
154 # the hash with one key
155 # the PVNV in the hash
156 # the RV inside the PVNV
157 # the contents of the array (array size)
158
159 is ($full_hash, $element_size + $hash_size, 'properly recurses into PVNV');
160# is ($full_hash, $array_size + $pvnv_size + $hash_size, 'properly recurses into PVNV');
161
162#############################################################################
163# repeat the former test, but mix in some undef elements
b1e5ad85 164
c8db37d3 165 $array_size = total_size(\[0..$size, undef, undef]);
b1e5ad85 166
c8db37d3 167 $hash->{a} = [0..$size, undef, undef];
168 $element_size = total_size(\$hash->{a});
169 $full_hash = total_size($hash);
b1e5ad85 170
c8db37d3 171 print "# full_hash = $full_hash\n";
172 print "# hash_size = $hash_size\n";
173 print "# array size: $array_size\n";
174 print "# element size: $element_size\n";
175 print "# ref_size = $ref_size\n";
176 print "# pvnv_size: $pvnv_size\n";
177
178 is ($full_hash, $element_size + $hash_size, 'properly recurses into PVNV');
179
180#############################################################################
181# repeat the former test, but use a pre-extended array
b1e5ad85 182
c8db37d3 183 $array = [ 0..$size, undef, undef ]; pop @$array;
b1e5ad85 184
c8db37d3 185 $array_size = total_size($array);
186 my $scalar_size = total_size(1) * (1+$size) + total_size(undef) * 1 + $ptr_size
187 + $ptr_size * ($size + 2) + total_size([]);
188 is ($scalar_size, $array_size, "computed right size if full array");
b1e5ad85 189
c8db37d3 190 $hash->{a} = [0..$size, undef, undef]; pop @{$hash->{a}};
191 $full_hash = total_size($hash);
192 $element_size = total_size(\$hash->{a});
193 $array_size = total_size(\$array);
b1e5ad85 194
c8db37d3 195 print "# full_hash = $full_hash\n";
196 print "# hash_size = $hash_size\n";
197 print "# array size: $array_size\n";
198 print "# element size: $element_size\n";
199 print "# ref_size = $ref_size\n";
200 print "# pvnv_size: $pvnv_size\n";
b1e5ad85 201
c8db37d3 202 is ($full_hash, $element_size + $hash_size, 'properly handles undef/non-undef inside arrays');
b1e5ad85 203
c8db37d3 204 } # end for different sizes