File Coverage

blib/lib/CHI/Memoize/t/Memoize.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package CHI::Memoize::t::Memoize;
2             $CHI::Memoize::t::Memoize::VERSION = '0.07';
3 1     1   1542 use Test::Class::Most parent => 'Test::Class';
  1         43769  
  1         7  
4 1     1   99131 use File::Temp qw(tempdir);
  1         32665  
  1         88  
5 1     1   793 use CHI::Memoize qw(memoize memoized unmemoize NO_MEMOIZE);
  0            
  0            
6              
7             my $unique_id = 0;
8             sub unique_id { ++$unique_id }
9              
10             sub func { join( ",", unique_id(), @_ ) }
11              
12             # memoize('func');
13             #
14             sub test_basic : Tests {
15             isnt( func(), func(), "different values" );
16             my $orig = \&func;
17             memoize('func');
18             is( func(), func(), "same values" );
19             my $info = memoized('func');
20             my $cache = $info->cache;
21             isa_ok( $info, 'CHI::Memoize::Info' );
22             isa_ok( $cache, 'CHI::Driver::Memory' );
23             is( scalar( $cache->get_keys ), 1, "1 key" );
24             is( $info->orig, $orig );
25             is( $info->wrapper, \&func );
26              
27             cmp_deeply( func(), re(qr/\d+/), 'no args' );
28             cmp_deeply( func( 'a', 'b' ), re(qr/\d+,a,b/), 'two args' );
29              
30             unmemoize('func');
31             isnt( func(), func(), "different values" );
32             ok( !memoized('func'), 'not memoized' );
33             is( scalar( $cache->get_keys ), 0, "0 keys" );
34             }
35              
36             # memoize('Some::Package::func');
37             #
38              
39             sub test_full_name : Tests {
40             my $full_name = join( "::", __PACKAGE__, 'func' );
41             my $orig = \&func;
42             memoize($full_name);
43             is( func(), func(), "same values" );
44             my $info = memoized('func');
45             is( $info->orig, $orig );
46             is( $info->wrapper, \&func );
47             unmemoize($full_name);
48             ok( !memoized($full_name) );
49             }
50              
51             # $anon = memoize($anon);
52             #
53             sub test_anon : Tests {
54             my $func = sub { unique_id() };
55             isnt( $func->(), $func->(), "different values" );
56             my $memo_func = memoize($func);
57             is( $memo_func->(), $memo_func->(), "same values" );
58             my $info = memoized($func);
59             isa_ok( $info, 'CHI::Memoize::Info' );
60             isa_ok( $info->cache, 'CHI::Driver::Memory' );
61             is( scalar( $info->cache->get_keys ), 1, "1 key" );
62             is( $info->orig, $func );
63             is( $info->wrapper, $memo_func );
64             }
65              
66             # memoize('func', key => sub { $_[0] });
67             # memoize('func', key => sub { $_[1], $_[2] });
68             #
69             sub test_dynamic_key : Tests {
70             memoize( 'func', key => sub { $_[0] } );
71             is( func(), func(), "empty=empty" );
72             is( func( 1, 2, 3 ), func( 1, 5 ), "123=15" );
73             isnt( func( 1, 2, 3 ), func( 2, 2, 3 ), "123=223" );
74             unmemoize('func');
75              
76             memoize( 'func', key => sub { $_[1], $_[2] } );
77             is( func( 1, 2, 3 ), func( 1, 2, 3 ), "123=123" );
78             is( func( 1, 2, 3 ), func( 5, 2, 3 ), "123=523" );
79             is( func(1), func(5), "1=5" );
80             isnt( func( 1, 2, 3 ), func( 1, 2, 4 ), "123!=124" );
81             my $info = memoized('func');
82             my @keys = $info->cache->get_keys;
83             my $prefix = join( ",", map { qq{"$_"} } ( $info->key_prefix, 'S' ) );
84             cmp_deeply( \@keys, bag( "[$prefix,null,null]", "[$prefix,2,4]", "[$prefix,2,3]" ) );
85             unmemoize('func');
86             }
87              
88             # memoized_function({a => 5, b => 6, c => { d => 7, e => 8 }});
89             # memoized_function({b => 6, c => { e => 8, d => 7 }, a => 5});
90             # memoize('func', key => sub { %@_ });
91             #
92             sub test_normalization : Tests {
93             memoize('func');
94             is(
95             func( { a => 5, b => 6, c => { d => 7, e => 8 } } ),
96             func( { b => 6, c => { e => 8, d => 7 }, a => 5 } )
97             );
98             isnt(
99             func( a => 5, b => 6, c => { d => 7, e => 8 } ),
100             func( b => 6, c => { e => 8, d => 7 }, a => 5 )
101             );
102             unmemoize('func');
103              
104             memoize( 'func', key => sub { return {@_} } );
105             is(
106             func( a => 5, b => 6, c => { d => 7, e => 8 } ),
107             func( b => 6, c => { e => 8, d => 7 }, a => 5 )
108             );
109             unmemoize('func');
110             }
111              
112             # memoize('func', key => sub { NOCACHE });
113             #
114             sub test_undef_or_empty_key : Tests {
115             memoize( 'func', key => sub { defined( $_[0] ) && $_[0] eq 'nocache' ? NO_MEMOIZE : @_ } );
116             is( func(), func(), "no args" );
117             is( func('foo'), func('foo'), "regular arg" );
118             isnt( func( 'nocache', 'a', 'b' ), func( 'nocache', 'a', 'b' ), "nocache" );
119             cmp_deeply( func( 'nocache', 'a', 'b' ), re(qr/\d+,nocache,a,b/), 'two args' );
120             unmemoize('func');
121             }
122              
123             # memoize('func', expires_in => '2 sec');
124             #
125             sub test_expires_in : Tests {
126             memoize( 'func', expires_in => '2 sec' );
127              
128             my @vals;
129             push( @vals, func(), func() );
130             push( @vals, func(), func() );
131             sleep(2);
132             push( @vals, func(), func() );
133             push( @vals, func(), func() );
134             foreach my $pair ( [ 0, 1 ], [ 2, 3 ], [ 4, 5 ], [ 6, 7 ], [ 0, 2 ], [ 4, 6 ] ) {
135             my ( $x, $y ) = @$pair;
136             is( $vals[$x], $vals[$y], "$x=$y" );
137             }
138             isnt( $vals[0], $vals[4], "0!=4" );
139              
140             unmemoize('func');
141             }
142              
143             # memoize('func', expire_if => $cond);
144             #
145             sub test_expire_if : Tests {
146             my $cond = 0;
147             memoize( 'func', expire_if => sub { $cond } );
148              
149             my @vals;
150             push( @vals, func(), func() );
151             $cond = 1;
152             push( @vals, func(), func() );
153             $cond = 0;
154             push( @vals, func(), func() );
155             foreach my $pair ( [ 0, 1 ], [ 3, 4 ], [ 4, 5 ] ) {
156             my ( $x, $y ) = @$pair;
157             is( $vals[$x], $vals[$y], "$x=$y" );
158             }
159             foreach my $pair ( [ 2, 3 ], [ 1, 2 ] ) {
160             my ( $x, $y ) = @$pair;
161             isnt( $vals[$x], $vals[$y], "$x!=$y" );
162             }
163              
164             unmemoize('func');
165             }
166              
167             # memoize('func', driver => 'File');
168             # memoize('func', cache => $cache );
169             #
170             sub test_file_driver : Tests {
171             foreach my $iter ( 0, 1 ) {
172             my $root_dir = tempdir( 'memoize-XXXX', TMPDIR => 1, CLEANUP => 1 );
173             my @options = (
174             $iter == 0
175             ? ( driver => 'File', root_dir => $root_dir )
176             : ( cache => CHI->new( driver => 'File', root_dir => $root_dir ) )
177             );
178             memoize( 'func', @options );
179             is( func(), func(), "same values" );
180             my $cache = memoized('func')->cache;
181             isa_ok( $cache, 'CHI::Driver::File' );
182             is( $cache->root_dir, $root_dir );
183             is( scalar( $cache->get_keys ), 1, "1 key" );
184             my $val = func();
185             $cache->clear();
186             isnt( func(), $val, "after clear" );
187             unmemoize('func');
188             isnt( func(), func(), "different values" );
189             is( scalar( $cache->get_keys ), 0, "0 keys" );
190             }
191             }
192              
193             # memoize('func') vs memoize('func', driver => 'RawMemory');
194             #
195             sub test_cloned_versus_raw : Tests {
196             my $base = sub { [ unique_id(), unique_id() ] };
197              
198             {
199             my $func = memoize($base);
200             my $ref1 = $func->();
201             my $ref2 = $func->();
202             cmp_deeply( $ref1, $ref2, "same contents" );
203             isnt( $ref1, $ref2, "different refs" );
204             push( @$ref1, 'foo' );
205             my $ref3 = $func->();
206             cmp_deeply( $ref3, $ref2, "memoized value unaffected by changes to result" );
207             unmemoize($base);
208             }
209              
210             {
211             my $func = memoize( $base, driver => 'RawMemory' );
212             my $ref1 = $func->();
213             my $ref2 = $func->();
214             cmp_deeply( $ref1, $ref2, "same contents" );
215             is( $ref1, $ref2, "same refs" );
216             push( @$ref1, 'foo' );
217             my $ref3 = $func->();
218             cmp_deeply( $ref3, $ref1, "memoized value affected by changes to result" );
219             unmemoize($base);
220             }
221             }
222              
223             1;