File Coverage

blib/lib/Couchbase/Test/ClientSync.pm
Criterion Covered Total %
statement 69 362 19.0
branch 0 20 0.0
condition 0 18 0.0
subroutine 23 48 47.9
pod 0 24 0.0
total 92 472 19.4


line stmt bran cond sub pod time code
1             package Couchbase::Test::ClientSync;
2 2     2   988 use strict;
  2         2  
  2         60  
3 2     2   8 use warnings;
  2         2  
  2         44  
4 2     2   8 use base qw(Couchbase::Test::Common);
  2         4  
  2         274  
5 2     2   8 use Test::More;
  2         4  
  2         14  
6 2     2   1266 use Couchbase::Client;
  2         6  
  2         64  
7 2     2   14 use Couchbase::Client::Errors;
  2         2  
  2         192  
8 2     2   8 use Data::Dumper;
  2         4  
  2         232  
9              
10             sub setup_client :Test(startup)
11             {
12 0     0 0 0 my $self = shift;
13 0         0 $self->mock_init();
14              
15 0         0 my %options = (
16 0         0 %{$self->common_options},
17             compress_threshold => 100
18             );
19              
20 0         0 my $o = Couchbase::Client->new(\%options);
21              
22 0         0 $self->cbo( $o );
23 0         0 $self->{basic_keys} = [qw(
24             Foo Bar Baz Blargh Bleh Meh Grr Gah)];
25 2     2   10 }
  2         4  
  2         16  
26              
27             sub cbo {
28 0 0   0 0   if(@_ == 1) {
    0          
29 0           return $_[0]->{object};
30             } elsif (@_ == 2) {
31 0           $_[0]->{object} = $_[1];
32 0           return $_[1];
33             }
34             }
35              
36             sub err_ok {
37 0     0 0   my $self = shift;
38 0           my $errors = $self->cbo->get_errors;
39 0           my $nerr = 0;
40 0           foreach my $errinfo (@$errors) {
41 0           $nerr++;
42             }
43 0           ok($nerr == 0, "Got no errors");
44             }
45              
46             sub k2v {
47 0     0 0   my ($self,$k) = @_;
48 0           reverse($k);
49             }
50              
51             sub v2k {
52 0     0 0   my ($self,$v) = @_;
53 0           reverse($v);
54             }
55              
56             sub set_ok {
57 0     0 0   my ($self,$msg,@args) = @_;
58 0           my $ret = $self->cbo->set(@args);
59 0           ok($ret->is_ok, $msg);
60 0           $self->err_ok();
61 0 0         if(!$ret->is_ok) {
62 0           diag($ret->errstr);
63             }
64             }
65              
66             sub get_ok {
67 0     0 0   my ($self,$key,$expected) = @_;
68 0           my $ret = $self->cbo->get($key);
69 0           ok($ret->is_ok, "Status OK for GET($key)");
70 0           ok($ret->value eq $expected, "Got expected value for $key");
71             }
72              
73             sub T00_set_values_simple :Test(no_plan) {
74 0     0 0 0 my $self = shift;
75 0         0 $self->err_ok();
76 0         0 foreach my $k (@{$self->{basic_keys}}) {
  0         0  
77 0         0 $self->set_ok("Key '$k'", $k, $self->k2v($k));
78 0         0 $self->get_ok($k, $self->k2v($k))
79             }
80 2     2   1180 }
  2         4  
  2         8  
81              
82             sub T01_get_nonexistent :Test(no_plan) {
83 0     0 0 0 my $self = shift;
84 0         0 my $v = $self->cbo->get('NonExistent');
85 0         0 is($v->errnum, COUCHBASE_KEY_ENOENT, "Got ENOENT for nonexistent key");
86 0         0 $self->err_ok();
87 2     2   414 }
  2         2  
  2         8  
88              
89             sub T02_mutators :Test(no_plan) {
90 0     0 0 0 my $self = shift;
91 0         0 my $o = $self->cbo;
92              
93 0         0 my $key = "mutate_key";
94 0         0 $o->remove($key); #if it already exists
95 0         0 is($o->add($key, "BASE")->errnum, 0, "No error for add on new key");
96 0         0 is($o->prepend($key, "PREFIX_")->errnum, 0, "No error for prepend");
97 0         0 is($o->append($key, "_SUFFIX")->errnum, 0, "No error for append");
98 0         0 is($o->get($key)->value, "PREFIX_BASE_SUFFIX", "Got expected mutated value");
99 2     2   460 }
  2         4  
  2         6  
100              
101             sub T03_arithmetic :Test(no_plan) {
102 0     0 0 0 my $self = shift;
103 0         0 my $o = $self->cbo;
104 0         0 my $key = "ArithmeticKey";
105 0         0 $o->remove($key);
106 0         0 my $wv;
107              
108 0         0 $wv = $o->arithmetic($key, -12, 42);
109 0         0 ok($wv->is_ok, "Set arithmetic with initial value");
110              
111 0         0 $o->remove($key);
112              
113 0         0 $wv = $o->arithmetic($key, -12, undef);
114 0         0 is($wv->errnum, COUCHBASE_KEY_ENOENT, "Error without initial value (undef)");
115              
116 0         0 $wv = $o->arithmetic($key, -12, 0, 120);
117 0         0 ok($wv->is_ok, "No error with initial value=0");
118 0         0 is($wv->value, 0, "Initial value is 0");
119              
120 0         0 $wv = $o->incr($key);
121 0         0 is($wv->value, 1, "incr() == 1");
122              
123 0         0 $wv = $o->decr($key);
124 0         0 is($wv->value, 0, "decr() == 0");
125 2     2   670 }
  2         10  
  2         8  
126              
127             sub T04_atomic :Test(no_plan) {
128 0     0 0 0 my $self = shift;
129 0         0 my $o = $self->cbo;
130 0         0 my $key = "AtomicKey";
131 0         0 $o->delete($key);
132              
133 0         0 is($o->replace($key, "blargh")->errnum, COUCHBASE_KEY_ENOENT,
134             "Can't replace non-existent value");
135              
136 0         0 my $wv = $o->set($key, "initial");
137 0         0 ok($wv->errnum == 0, "No error");
138 0         0 ok(length($wv->cas), "Have cas");
139 0         0 $o->set($key, "next");
140 0         0 my $newv = $o->cas($key, "my_next", $wv->cas);
141              
142 0         0 is($newv->errnum,
143             COUCHBASE_KEY_EEXISTS, "Got EEXISTS for outdated CAS");
144              
145 0         0 $newv = $o->get($key);
146 0         0 ok($newv->cas, "Have CAS for new value");
147 0         0 $wv = $o->cas($key, "synchronized", $newv->cas);
148 0         0 ok($wv->errnum == 0, "Got no error for CAS with updated CAS");
149 0         0 is($o->get($key)->value, "synchronized", "Got expected value");
150              
151 0         0 $o->delete($key);
152 0         0 ok($o->add($key, "value")->is_ok, "No error for ADD with nonexistent key");
153 0         0 is($o->add($key, "value")->errnum,
154             COUCHBASE_KEY_EEXISTS, "Got eexists for ADD on existing key");
155              
156 0         0 ok($o->delete($key, $newv->cas)->errnum, "Got error for DELETE with bad CAS");
157 0         0 $newv = $o->get($key);
158 0         0 ok($o->delete($key, $newv->cas)->errnum == 0,
159             "No error for delete with updated CAS");
160 2     2   732 }
  2         4  
  2         8  
161              
162             sub T05_conversion :Test(no_plan) {
163 0     0 0 0 my $self = shift;
164 0         0 my $o = $self->cbo;
165 0         0 my $structure = [ qw(foo bar baz) ];
166 0         0 my $key = "Serialization";
167 0         0 my $rv;
168              
169 0         0 ok($o->set($key, $structure)->is_ok, "Serialized OK");
170              
171 0         0 $rv = $o->get($key);
172 0         0 ok($rv->is_ok, "Got serialized structure OK");
173 0         0 is_deeply($rv->value, $structure, "Got back our array reference");
174 0         0 eval {
175 0         0 $o->append($key, $structure);
176             };
177 0         0 ok($@, "Got error for append/prepending a serialized structure ($@)");
178 2     2   504 }
  2         2  
  2         8  
179              
180             sub _multi_check_ret {
181 0     0     my ($rv,$keys) = @_;
182 0           my $nkeys = scalar @$keys;
183 0           my $defined = scalar grep defined $_, values %$rv;
184 0           my $n_ok = scalar grep $_->is_ok, values %$rv;
185              
186 0           is(scalar keys %$rv, $nkeys, "Expected number of keys");
187 0           is($defined, $nkeys, "All values defined");
188 0           is($n_ok,$nkeys, "All returned ok (no errors)");
189              
190             }
191              
192             sub multi_ok {
193 0     0 0   my ($rv, $msg, $expect) = @_;
194 0           my @errs;
195              
196 0 0         if ($expect) {
197 0           @errs = grep {$_->errnum != $expect} values %$rv;
  0            
198             } else {
199 0           @errs = grep { !$_->is_ok } values %$rv;
  0            
200             }
201              
202 0           ok(!@errs, $msg);
203             }
204              
205             sub T06_multi :Test(no_plan) {
206 0     0 0 0 my $self = shift;
207 0         0 my $o = $self->cbo;
208 0         0 my @keys = @{$self->{basic_keys}};
  0         0  
209              
210 0         0 my $rv = $o->set_multi(
211 0         0 map { [$_, $_] } @keys);
212              
213 0   0     0 ok($rv && ref $rv eq 'HASH', "Got hash result for multi operation");
214 0         0 ok(scalar keys %$rv == scalar @keys,
215             "got expected number of results");
216              
217 0         0 is(grep(defined $_, values %$rv), scalar @keys, "All values defined");
218 0         0 is(scalar grep(!$rv->{$_}->is_ok, @keys), 0, "No errors");
219              
220 0         0 $rv = $o->get_multi(@keys);
221 0         0 _multi_check_ret($rv, \@keys);
222              
223 0         0 is(scalar grep($rv->{$_}->value eq $_, @keys), scalar @keys,
224             "get_multi: Got expected values");
225              
226 0         0 $rv = $o->cas_multi(
227 0         0 map { [$_, scalar(reverse $_), $rv->{$_}->cas ] } @keys );
228 0         0 _multi_check_ret($rv, \@keys);
229              
230             #Remove them all:
231              
232 0         0 note "Remove (no CAS)";
233 0         0 $rv = $o->remove_multi(@keys);
234 0         0 _multi_check_ret($rv, \@keys);
235              
236 0         0 $rv = $o->set_multi(map { [$_, $_] } @keys);
  0         0  
237 0         0 _multi_check_ret($rv, \@keys);
238              
239 0         0 note "Remove (with CAS)";
240 0         0 $rv = $o->remove_multi(map { [ $_, $rv->{$_}->cas] } @keys);
  0         0  
241 0         0 _multi_check_ret($rv, \@keys);
242              
243 0         0 note "Trying arithmetic..";
244              
245 0         0 $rv = $o->arithmetic_multi(
246 0         0 map { [$_, 666, undef, 120] } @keys
247             );
248 0         0 ok(scalar(
249 0         0 grep {$_->errnum == COUCHBASE_KEY_ENOENT} values %$rv
250             ) == scalar @keys,
251             "ENOENT for non-existent deleted arithmetic keys");
252              
253              
254             #try arithmetic again:
255 0         0 $rv = $o->arithmetic_multi(
256 0         0 map { [$_, 666, 42, 120] } @keys);
257 0         0 _multi_check_ret($rv, \@keys);
258              
259 0         0 is(scalar grep($_->value == 42, values %$rv), scalar @keys,
260             "all keys have expected value");
261              
262 0         0 $rv = $o->incr_multi(@keys);
263 0         0 _multi_check_ret($rv, \@keys);
264              
265 0         0 is(scalar grep($_->value == 43, values %$rv), scalar @keys,
266             "all keys have been incremented");
267              
268 0         0 $rv = $o->decr_multi(
269 0         0 map {[ $_, 41 ]} @keys);
270 0         0 _multi_check_ret($rv, \@keys);
271 0         0 is(scalar grep($_->value == 2, values %$rv), scalar @keys,
272             "all keys have been decremented");
273 2     2   1270 }
  2         6  
  2         6  
274              
275             sub T06_multi_GH4 :Test(no_plan) {
276 0     0 0 0 my $self = shift;
277 0         0 my $o = $self->cbo;
278 0         0 my $rv = $o->set_multi(['single_key', 'single_value']);
279 0         0 ok($rv->{"single_key"}->is_ok, "Single arrayref on setmulti does not fail");
280 2     2   418 }
  2         2  
  2         8  
281              
282             sub T06_multi_PLCBC_1 :Test(no_plan) {
283 0     0 0 0 my $self = shift;
284 0         0 my $o = $self->cbo;
285 0         0 $o->set_multi(["key", "value"]);
286 0         0 my $rv = $o->get_multi("single_key");
287 0         0 ok($rv->{"single_key"}->is_ok, "Does not crash");
288 2     2   402 }
  2         2  
  2         8  
289              
290             sub T06_multi_argtypes :Test(no_plan)
291             {
292 0     0 0 0 my $self = shift;
293 0         0 my $o = $self->cbo;
294 0         0 my @keys = qw(foo bar baz);
295 0         0 my @set_args = map { [$_, $_ ] } @keys;
  0         0  
296 0         0 my $k1 = $keys[0];
297              
298 0         0 multi_ok($o->set_multi(@set_args), "set_multi - multiple argrefs");
299 0         0 multi_ok($o->set_multi([$k1, $k1]), "set_multi - single argref");
300 0         0 multi_ok($o->set_multi_A([[$k1, $k1]]), "set_multi_A");
301              
302 0         0 multi_ok($o->get_multi([$k1]), "get_multi. single arg ref");
303 0         0 multi_ok($o->get_multi($k1), "get_multi. single key");
304 0         0 multi_ok($o->get_multi(@keys), "get_multi, key list");
305 0         0 multi_ok($o->get_multi(map { [$_] } @keys), "get_multi, key arrayrefs");
  0         0  
306              
307 0         0 multi_ok($o->get_multi_A([$k1]), "get_multi_A, single arrayref");
308 0         0 multi_ok($o->get_multi_A([[$k1]]), "get_mutli_A - nested arrayref");
309 0         0 multi_ok($o->get_multi_A(\@keys), "get_multi, arrayrefs of keys");
310              
311 0 0 0     0 if ( !($self->mock && $self->mock->nodes) ) {
312 0         0 my $lock_rvs = $o->lock_multi(map {[$_, 10]} @keys);
  0         0  
313 0         0 multi_ok($lock_rvs, "lock_multi");
314              
315 0         0 my $unlock_rvs = $o->unlock_multi(
316 0         0 map { [ $_, $lock_rvs->{$_}->cas ] } keys %$lock_rvs
317             );
318              
319 0         0 multi_ok($unlock_rvs, "unlock_multi");
320              
321             } else {
322 0         0 diag "Skipping lock tests on mock";
323             }
324              
325 0         0 $o->remove_multi(@keys);
326              
327 0         0 @set_args = map { [$_, { initial => 1 }] } @keys;
  0         0  
328 0         0 multi_ok($o->incr_multi(@set_args), "incr_multi, key list with options");
329 0         0 multi_ok($o->incr_multi(@keys), "incr_multi, key list");
330 0         0 multi_ok($o->incr_multi($k1), "incr_multi. single key");
331 0         0 multi_ok($o->incr_multi([$k1]), "incr_multi. single arrayref");
332 0         0 multi_ok($o->incr_multi([$k1, { delta => 10 }]),
333             "incr_multi. single arrayref with options");
334              
335 0         0 multi_ok($o->incr_multi_A(\@keys), "incr_multi_A - arrayref of keys");
336 0         0 multi_ok($o->incr_multi_A([$k1]), "incr_multi_A, - single arrayref");
337 0         0 multi_ok($o->incr_multi_A([[$k1]]), "incr_multi_A - single nested arrayref");
338              
339 0         0 multi_ok($o->remove_multi(@keys), "remove_multi - list of keys");
340 0         0 multi_ok($o->remove_multi(@keys), "remove_multi - ENOENT", COUCHBASE_KEY_ENOENT);
341 0         0 multi_ok($o->remove_multi_A(\@keys), "remove_multi_A", COUCHBASE_KEY_ENOENT);
342 2     2   1100 }
  2         4  
  2         12  
343              
344             sub T07_stats :Test(no_plan) {
345 0     0 0 0 my $self = shift;
346 0         0 my $o = $self->cbo;
347 0         0 my $stats = $o->stats();
348              
349 0   0     0 ok($stats && ref $stats eq 'HASH', "Got a hashref");
350 0         0 ok(scalar keys %$stats, "stats not empty");
351              
352 0 0 0     0 if($self->mock && $self->mock->nodes) {
353 0         0 ok(scalar keys %$stats == $self->mock->nodes, "Got expected stat count");
354             } else {
355 0         0 diag "Cannot determine expected stat count for real cluster";
356             }
357 2     2   482 }
  2         2  
  2         8  
358              
359             sub T08_iterator :Test(no_plan) {
360 0     0 0 0 my $self = shift;
361 0         0 my $o = $self->cbo;
362 0         0 my @keys = map { "T08_NonExistent_$_" } (1..200);
  0         0  
363 0         0 my $iterator = $o->get_iterator_A(\@keys);
364 0         0 ok(!$iterator->error, "Got no errors for creating iterator");
365              
366 0         0 my $rescount = 0;
367 0         0 my $key_count = 0;
368 0         0 my $not_found_count = 0;
369              
370 0         0 while (my ($k,$v) = $iterator->next) {
371 0 0       0 if ($k) {
372 0         0 $key_count++;
373             }
374              
375 0 0       0 if ($v->KEY_ENOENT) {
376 0         0 $not_found_count++;
377             }
378 0         0 $rescount++;
379             }
380              
381 0         0 is($rescount, 200, "Got expected number of results");
382 0         0 is($key_count, 200, "all keys received in good health");
383 0         0 is($not_found_count, 200, "Got expected number of ENOENT");
384 2     2   606 }
  2         4  
  2         8  
385              
386             sub T09_kwargs :Test(no_plan) {
387             # Tests the keyword args functionality
388 0     0 0 0 my $self = shift;
389 0         0 my $o = $self->cbo;
390 0         0 my $rv;
391              
392 0         0 $rv = $o->set("foo", "bar", { exp => 1 });
393 0         0 ok($rv->is_ok);
394              
395 0         0 $rv = $o->set("foo", "bar", { cas => 0x4, exp => 43 });
396 0         0 is($rv->errnum, COUCHBASE_KEY_EEXISTS);
397              
398 0         0 my $grv = $o->get("foo", {exp => 10 });
399 0         0 $rv = $o->set("foo", "bar", { cas => $grv->cas});
400 0         0 ok($rv->is_ok);
401              
402             # Try arithmetic
403 0         0 $rv = $o->remove("arith_key");
404 0   0     0 ok($rv->is_ok || $rv->errnum == COUCHBASE_KEY_ENOENT);
405              
406 0         0 $rv = $o->incr("arith_key", { initial => 40 });
407 0         0 ok($rv->is_ok);
408 0         0 is($rv->value, 40);
409 2     2   618 }
  2         4  
  2         6  
410              
411             sub T10_locks :Test(no_plan) {
412 0     0 0 0 my $self = shift;
413 0 0 0     0 if ($self->mock && $self->mock->nodes) {
414 0         0 diag "Skipping lock tests on mock";
415 0         0 return;
416             }
417              
418 0         0 my $lrv;
419 0         0 my $o = $self->cbo;
420              
421 0         0 $lrv = $o->lock("foo", 10);
422 0         0 ok($lrv->is_ok, "Lock OK");
423              
424 0         0 my $rv = $o->unlock("foo", $lrv->cas);
425 0         0 ok($rv->is_ok, "Unlock OK");
426              
427 0         0 $rv = $o->unlock("foo", $lrv->cas);
428 0         0 is($rv->errnum, COUCHBASE_ETMPFAIL, "Unlock with bad CAS: TMPFAIL");
429              
430 0         0 $lrv = $o->lock("foo", 10);
431 0         0 my $fail_rv = $o->lock("foo", 10);
432 0         0 is($fail_rv->errnum, COUCHBASE_ETMPFAIL, "Lock while locked. TMPFAIL");
433 0         0 $fail_rv = $o->set("foo", "something");
434 0         0 is($fail_rv->errnum, COUCHBASE_KEY_EEXISTS, "Storage fails with EEXISTS");
435              
436 0         0 $rv = $o->unlock("foo", $lrv->cas);
437 0         0 ok($rv->is_ok, "Can unlock with valid CAS");
438 0         0 $rv = $o->lock("foo", 10);
439 0         0 ok($rv->is_ok, "Can lock again with valid CAS");
440 0         0 $o->unlock("foo", $rv->cas);
441              
442 0         0 $rv = $o->unlock("foo", $rv->cas);
443 0         0 is($rv->errnum, COUCHBASE_ETMPFAIL,
444             "Unlock on unlocked key fails with ETMPFAIL");
445 2     2   1034 }
  2         4  
  2         8  
446              
447             sub wait_for_exp {
448 0     0 0   my ($o,$k,$limit) = @_;
449 0           my $begin_time = time();
450              
451 0           while (time() - $begin_time < $limit) {
452 0           sleep(1);
453 0           my $rv = $o->get($k);
454 0 0         if ($rv->errnum == COUCHBASE_KEY_ENOENT) {
455 0           return 1;
456             }
457 0           diag("Sleeping again..");
458             }
459 0           return 0;
460             }
461              
462             sub T11_expiry :Test(no_plan) {
463 0     0 0   my $self = shift;
464 0           my $o = $self->cbo;
465 0           $self->set_ok(
466             "Setting with numeric expiry",
467             "key", "value", 1);
468              
469 0           $self->set_ok(
470             "Setting with stringified expiry",
471             "key", "value", "1");
472              
473              
474 0           eval {
475 0           $o->set("key", "Value", "bad-expiry");
476             };
477 0           ok($@, "Got error for invalid expiry");
478              
479             # Hrm, this is apparently slower than i'd like. Let's use
480             # a loop
481 0           ok(wait_for_exp($o, "key", 3), "Key expired");
482              
483             # Try with multi
484 0           eval {
485 0           $o->set_multi(["key", "value", "blah"],
486             ["foo", "bar"])
487             };
488 0           ok($@, "Got error for invalid expiry (multi-set)");
489              
490 0           my $rvs = $o->set_multi(["key", "value", "1"],
491             ["foo", "bar"]);
492 0           ok($rvs->{key}->is_ok, "Multi set with stringified expiry");
493 0           ok(wait_for_exp($o, "key", 3), "Multi: Key expired");
494              
495 2     2   744 }
  2         4  
  2         8  
496              
497              
498             1;