File Coverage

blib/lib/Cache/Memcached/Mock.pm
Criterion Covered Total %
statement 80 88 90.9
branch 21 24 87.5
condition 9 15 60.0
subroutine 20 23 86.9
pod 0 13 0.0
total 130 163 79.7


line stmt bran cond sub pod time code
1             # ABSTRACT: A mock class for Cache::Memcached
2             package Cache::Memcached::Mock;
3              
4 8     8   172053 use strict;
  8         20  
  8         303  
5 8     8   43 use warnings;
  8         141  
  8         232  
6 8     8   7545 use bytes;
  8         77  
  8         40  
7 8     8   8998 use Storable ();
  8         38504  
  8         10429  
8              
9             our $VERSION = '0.07';
10              
11             sub VALUE () {0}
12             sub TIMESTAMP () {1}
13             sub REFERENCE () {2}
14              
15             # All instances share the memory space
16             our %MEMCACHE_STORAGE = ();
17              
18             sub add {
19 2     2 0 3 my ($self, $key, $value, $expiry_time) = @_;
20 2 100       6 if (exists $MEMCACHE_STORAGE{$key}) {
21 1         3 return;
22             }
23 1         3 return $self->set($key, $value, $expiry_time);
24             }
25              
26             sub new {
27              
28 7     7 0 82 my ($class, $options) = @_;
29              
30 7   33     48 $class = ref $class || $class;
31              
32 7   50     38 $options ||= {};
33              
34             # Default memcached size limit
35 7   50     52 $options->{size_limit} ||= 1024 * 1024;
36              
37             # Default unsigned integer bit width when incrementing/decrementing.
38 7   50     35 $options->{bit_width} ||= 32;
39              
40 7         16 my $self = { %{$options} };
  7         31  
41              
42 7         20 bless $self, $class;
43 7         26 $self->flush_all();
44              
45 7         27 return $self;
46             }
47              
48             sub delete {
49 3     3 0 10 my ($self, $key) = @_;
50 3 50       12 if (!exists $MEMCACHE_STORAGE{$key}) {
51 0         0 return;
52             }
53 3         9 delete $MEMCACHE_STORAGE{$key};
54 3         38 return 1;
55             }
56              
57             sub disconnect_all {
58             return # noop
59 0     0 0 0 }
60              
61             sub flush_all {
62 7     7 0 24 %MEMCACHE_STORAGE = ();
63 7         13 return;
64             }
65              
66             sub get {
67 20     20 0 2766 my ($self, $key) = @_;
68 20         55 return $self->get_multi($key)->{$key};
69             }
70              
71             sub get_multi {
72 22     22 0 3015016 my ($self, @keys) = @_;
73 22         33 my %pairs;
74              
75 22         51 for my $key (@keys) {
76 28 100       110 if (exists $MEMCACHE_STORAGE{$key}) {
77              
78             # Check if value had an expire time
79 19         44 my $struct = $MEMCACHE_STORAGE{$key};
80 19         37 my $expiry_time = $struct->[TIMESTAMP];
81              
82 19 100 100     96 if (defined $expiry_time && (time > $expiry_time)) {
83 2         20 delete $MEMCACHE_STORAGE{$key};
84             }
85             else {
86 17 50       101 $pairs{$key}
87             = $struct->[REFERENCE]
88             ? Storable::thaw($struct->[VALUE])
89             : $struct->[VALUE];
90             }
91             }
92             }
93              
94 22         188 return \%pairs;
95             }
96              
97             sub replace {
98 2     2 0 6 my ($self, $key, $value, $expiry_time) = @_;
99 2 100       7 if (!exists $MEMCACHE_STORAGE{$key}) {
100 1         4 return;
101             }
102 1         4 return $self->set($key, $value, $expiry_time);
103             }
104              
105             sub set {
106 18     18 0 1344 my ($self, $key, $value, $expiry_time) = @_;
107 18         592 my $size_limit = $self->_size_limit();
108 18         30 my $is_ref = 0;
109              
110 18 50       95 if (ref $value) {
111 0         0 $is_ref = 1;
112 0         0 $value = Storable::nfreeze($value);
113             }
114              
115             # Can't store values longer than (default) 1Mb limit
116 18 100 66     127 if (defined $value and bytes::length($value) > $size_limit) {
117 1         8 return;
118             }
119              
120 17 100       8301 if ($expiry_time) {
121 2         25 $expiry_time += time();
122             }
123             else {
124 15         28 $expiry_time = undef;
125             }
126              
127 17         67 $MEMCACHE_STORAGE{$key} = [ $value, $expiry_time, $is_ref ];
128              
129 17         79 return 1;
130             }
131              
132             sub set_servers {
133 0     0 0 0 my ($self, $servers) = @_;
134 0         0 return ($self->{servers} = $servers);
135             }
136              
137             sub set_compress_threshold {
138 0     0 0 0 my ($self, $comp_thr) = @_;
139 0         0 return ($self->{compress_threshold} = $comp_thr - 0);
140             }
141              
142             # XXX NIY
143             #sub set_readonly {
144             # my ($self, $readonly) = @_;
145             # return ($self->{readonly} = $readonly);
146             #}
147              
148             sub incr {
149 12     12 0 20 my ($self, $key, $offset) = @_;
150 12         29 return $self->_incr_or_decr($key, $offset, '_add');
151             }
152              
153             sub decr {
154 6     6 0 14 my ($self, $key, $offset) = @_;
155 6         14 return $self->_incr_or_decr($key, $offset, '_subtract');
156             }
157              
158             sub _add {
159 11     11   360 my ($self, $x, $y) = @_;
160 11         25 my $result = $self->_to_uint($x) + $self->_to_uint($y);
161            
162 11         22 return $result % (2 ** $self->_bit_width());
163             }
164              
165             sub _bit_width {
166 47     47   53 my ($self) = @_;
167 47         148 return $self->{bit_width};
168             }
169              
170             sub _incr_or_decr {
171 18     18   30 my ($self, $key, $offset, $operation) = @_;
172 18 100       84 return unless exists $MEMCACHE_STORAGE{$key};
173            
174 16 100       36 $offset = 1 unless defined $offset;
175 16         75 my $new_val = $self->$operation($MEMCACHE_STORAGE{$key}->[VALUE], $offset);
176            
177 16         87 return ($MEMCACHE_STORAGE{$key}->[VALUE] = $new_val);
178             }
179              
180             sub _size_limit {
181 18     18   28 my ($self) = @_;
182 18         63 return $self->{size_limit};
183             }
184              
185             sub _subtract {
186 5     5   10 my ($self, $x, $y) = @_;
187 5         14 my $result = $self->_to_uint($x) - $self->_to_uint($y);
188            
189 5 100       20 return $result <= 0 ? 0 : $result % (2 ** $self->_bit_width());
190             }
191              
192             sub _to_uint {
193 32     32   42 my ($self, $n) = @_;
194 32         51 return $n & (2 ** $self->_bit_width() - 1);
195             }
196              
197             1;
198              
199             __END__