Codebase list libtest-mock-redis-perl / 79276ac
New upstream version 0.22 gregor herrmann 4 years ago
23 changed file(s) with 262 addition(s) and 151 deletion(s). Raw diff Collapse all Expand all
00 Revision history for Perl module Test::Mock::Redis
1
2 0.22 2019-06-26
3 - Major update via pull request 28 on github (Valery Kalesnik)
14
25 0.21 2018-12-19
36 - fix lrem issue with array length changing (Thomas Bloor)
33 "Jeff Lavallee <jeff@zeroclue.com>"
44 ],
55 "dynamic_config" : 1,
6 "generated_by" : "Module::Build version 0.422",
6 "generated_by" : "Module::Build version 0.4229",
77 "license" : [
88 "perl_5"
99 ],
1010 "meta-spec" : {
1111 "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
12 "version" : "2"
12 "version" : 2
1313 },
1414 "name" : "Test-Mock-Redis",
1515 "no_index" : {
4848 "provides" : {
4949 "Test::Mock::Redis" : {
5050 "file" : "lib/Test/Mock/Redis.pm",
51 "version" : "0.21"
51 "version" : "0.22"
5252 },
5353 "Test::Mock::Redis::Hash" : {
5454 "file" : "lib/Test/Mock/Redis.pm"
7878 "url" : "http://github.com/jlavallee/Test-Mock-Redis/"
7979 }
8080 },
81 "version" : "0.21",
82 "x_serialization_backend" : "JSON::PP version 2.27300"
81 "version" : "0.22",
82 "x_serialization_backend" : "JSON::PP version 2.97001"
8383 }
99 configure_requires:
1010 Module::Build: '0.4'
1111 dynamic_config: 1
12 generated_by: 'Module::Build version 0.422, CPAN::Meta::Converter version 2.150010'
12 generated_by: 'Module::Build version 0.4229, CPAN::Meta::Converter version 2.150010'
1313 license: perl
1414 meta-spec:
1515 url: http://module-build.sourceforge.net/META-spec-v1.4.html
2525 provides:
2626 Test::Mock::Redis:
2727 file: lib/Test/Mock/Redis.pm
28 version: '0.21'
28 version: '0.22'
2929 Test::Mock::Redis::Hash:
3030 file: lib/Test/Mock/Redis.pm
3131 Test::Mock::Redis::List:
4646 bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-Mock-Redis
4747 license: http://dev.perl.org/licenses/
4848 repository: http://github.com/jlavallee/Test-Mock-Redis/
49 version: '0.21'
49 version: '0.22'
5050 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
0 # Note: this file was auto-generated by Module::Build::Compat version 0.4220
0 # Note: this file was auto-generated by Module::Build::Compat version 0.4229
11 use ExtUtils::MakeMaker;
22 WriteMakefile
33 (
4 'EXE_FILES' => [],
5 'PL_FILES' => {},
64 'PREREQ_PM' => {
7 'namespace::clean' => 0,
8 'Test::Deep::UnorderedPairs' => 0,
9 'Test::More' => '0.88',
10 'Scalar::Util' => 0,
5 'Package::Stash' => '0.34',
116 'Test::Fatal' => 0,
127 'Try::Tiny' => 0,
8 'Test::Deep::UnorderedPairs' => 0,
9 'Test::Deep' => 0,
10 'Test::More' => '0.88',
11 'namespace::clean' => 0,
1312 'Class::Method::Modifiers' => 0,
14 'Test::Deep' => 0,
15 'Package::Stash' => '0.34'
13 'Scalar::Util' => 0
1614 },
17 'INSTALLDIRS' => 'site',
15 'PL_FILES' => {},
16 'EXE_FILES' => [],
1817 'VERSION_FROM' => 'lib/Test/Mock/Redis.pm',
19 'NAME' => 'Test::Mock::Redis'
18 'NAME' => 'Test::Mock::Redis',
19 'INSTALLDIRS' => 'site'
2020 )
2121 ;
22 use warnings;
33 use strict;
44
5 use Carp;
5 use Carp 'confess';
66 use Config;
77 use Scalar::Util qw/blessed/;
88 use Class::Method::Modifiers;
9 use Package::Stash;
9 use Package::Stash ();
1010 use Try::Tiny;
1111 use namespace::clean; # important: clean all subs imported above this line
1212
1616
1717 =head1 VERSION
1818
19 Version 0.21
19 Version 0.22
2020
2121 =cut
2222
23 our $VERSION = '0.21';
23 our $VERSION = '0.22';
2424
2525 =head1 SYNOPSIS
2626
164164
165165 sub set {
166166 my ( $self, $key, $value, @args ) = @_;
167 my $expires = 0;
167
168 my ( $expires, $expire_cmd, $cond_cmd );
168169 while (my $option = shift @args) {
169 $option = lc $option;
170 # Only set if key exists
171 if ($option eq 'xx') {
172 return unless $self->exists($key);
173
174 # Only set if key doesn't exist
175 } elsif ($option eq 'nx') {
176 return if $self->exists($key);
177
178 # Set expire time (in seconds)
179 } elsif ($option eq 'ex') {
180 my $new_expires = shift @args;
181 if ($new_expires > $expires) {
182 $expires = $new_expires;
183 }
184
185 # Set expire time (in milliseconds)
186 } elsif ($option eq 'px') {
187 my $new_expires = shift @args;
188 $new_expires /= 1000; # To seconds
189 if ($new_expires > $expires) {
190 $expires = $new_expires;
191 }
192 } else {
193 confess '[error] ERR syntax error';
194 }
195 }
170 $option = lc $option;
171
172 if ($option eq 'nx' || $option eq 'xx') { # the same condition can be repeated but mix isn't allowed
173 confess '[set] ERR syntax error'
174 if defined $cond_cmd && $cond_cmd ne $option;
175
176 $cond_cmd = $option;
177 } elsif ($option eq 'ex' || $option eq 'px') { # same units can be repeated but mix isn't allowed
178 confess '[set] ERR syntax error'
179 if defined $expire_cmd && $expire_cmd ne $option;
180
181 $expire_cmd = $option;
182
183 $expires = shift @args; # do we need a validation here?
184
185 $expires /= 1000 # milliseconds to seconds
186 if $expire_cmd eq 'px';
187 } else {
188 confess '[set] ERR syntax error';
189 }
190 }
191
192 if ( defined $cond_cmd ) {
193 # Only set if key exists
194 return
195 if $cond_cmd eq 'xx'
196 && ! $self->exists($key);
197
198 # Only set if key doesn't exist
199 return
200 if $cond_cmd eq 'nx'
201 && $self->exists($key);
202 }
203
196204 $self->_stash->{$key} = "$value";
197 if ($expires) {
198 $self->expire($key, $expires);
199 }
205 $self->expire($key, $expires)
206 if defined $expires;
200207
201208 return 'OK';
202209 }
253260 sub ttl {
254261 my ( $self, $key, $ttl ) = @_;
255262
256 return -1 unless exists $self->_stash->{$key};
263 return -2 unless exists $self->_stash->{$key};
257264
258265 my $slot = $self->_stash;
259266 my $tied = tied(%$slot);
435442 }
436443
437444 sub rpush {
445 my ( $self, $key, @values ) = @_;
446
447 confess "[rpush] ERR wrong number of arguments for 'rpush' command"
448 unless @values;
449
450 confess "[rpush] WRONGTYPE Operation against a key holding the wrong kind of value"
451 unless !$self->exists($key) or $self->_is_list($key);
452
453 $self->_make_list($key);
454
455 push @{ $self->_stash->{$key} }, map "$_", @values;
456 return scalar @{ $self->_stash->{$key} };
457 }
458
459 sub lpush {
460 my ( $self, $key, @values ) = @_;
461
462 confess "[lpush] ERR wrong number of arguments for 'lpush' command"
463 unless @values;
464
465 confess "[lpush] WRONGTYPE Operation against a key holding the wrong kind of value"
466 unless !$self->exists($key) or $self->_is_list($key);
467
468 $self->_make_list($key);
469
470 unshift @{ $self->_stash->{$key} }, map "$_", reverse @values;
471 return scalar @{ $self->_stash->{$key} };
472 }
473
474 sub rpushx {
438475 my ( $self, $key, $value ) = @_;
439476
440 $self->_make_list($key);
477 return unless $self->_is_list($key);
441478
442479 push @{ $self->_stash->{$key} }, "$value";
443480 return scalar @{ $self->_stash->{$key} };
444481 }
445482
446 sub lpush {
483 sub lpushx {
447484 my ( $self, $key, $value ) = @_;
448485
449 confess "[lpush] ERR Operation against a key holding the wrong kind of value"
450 unless !$self->exists($key) or $self->_is_list($key);
451
452 $self->_make_list($key);
486 return unless $self->_is_list($key);
453487
454488 unshift @{ $self->_stash->{$key} }, "$value";
455489 return scalar @{ $self->_stash->{$key} };
456490 }
457491
458 sub rpushx {
459 my ( $self, $key, $value ) = @_;
460
461 return unless $self->_is_list($key);
462
463 push @{ $self->_stash->{$key} }, "$value";
464 return scalar @{ $self->_stash->{$key} };
465 }
466
467 sub lpushx {
468 my ( $self, $key, $value ) = @_;
469
470 return unless $self->_is_list($key);
471
472 unshift @{ $self->_stash->{$key} }, "$value";
473 return scalar @{ $self->_stash->{$key} };
474 }
475
476492 sub rpoplpush {
477493 my ( $self, $source_key, $destination_key ) = @_;
478494
494510 sub lrange {
495511 my ( $self, $key, $start, $end ) = @_;
496512
497 my $array = $self->_stash->{$key};
498 ($start,$end) = _normalize_range(scalar(@$array),$start,$end);
499 return @{ $array }[$start..$end];
513 my @result;
514
515 if ( my $array = $self->_stash->{$key} ) {
516 ($start,$end) = _normalize_range(scalar(@$array),$start,$end);
517 @result = @{ $array }[$start..$end];
518 }
519
520 return wantarray ? @result : \ @result;
500521 }
501522
502523 sub ltrim {
634655 sub smove {
635656 my ( $self, $source, $dest, $value ) = @_;
636657
637 confess "[smove] ERR Operation against a key holding the wrong kind of value"
658 confess "[smove] WRONGTYPE Operation against a key holding the wrong kind of value"
638659 if ( $self->exists($source) and not $self->_is_set($source) )
639660 or ( $self->exists($dest) and not $self->_is_set($dest) );
640661
723744 sub hset {
724745 my ( $self, $key, $hkey, $value ) = @_;
725746
726 confess '[hset] ERR Operation against a key holding the wrong kind of value'
747 confess '[hset] WRONGTYPE Operation against a key holding the wrong kind of value'
727748 if $self->exists($key) and !$self->_is_hash($key);
728749
729750
778799 sub hexists {
779800 my ( $self, $key, $hkey ) = @_;
780801
781 confess '[hexists] ERR Operation against a key holding the wrong kind of value'
802 confess '[hexists] WRONGTYPE Operation against a key holding the wrong kind of value'
782803 if $self->exists($key) and !$self->_is_hash($key);
783804
784 return exists $self->_stash->{$key}->{$hkey} ? 1 : 0;
805 return $self->exists($key) && exists $self->_stash->{$key}->{$hkey} ? 1 : 0;
785806 }
786807
787808 sub hdel {
804825 if $self->exists($key) and !$self->_is_hash($key);
805826
806827 confess "[hincrby] ERR hash value is not an integer"
807 if $self->hexists($key, $hkey) # it exists
808 and $self->hget($key, $hkey) !~ /^-?\d+$|^$/ # and it doesn't look like an integer (and it isn't empty)
828 if $self->hexists($key, $hkey) # it exists
829 and $self->hget($key, $hkey) !~ /^-?\d+$/ # and it doesn't look like an integer (and it isn't empty)
809830 ;
810831
811832 $self->_make_hash($key) unless $self->_is_hash($key);
826847 sub hkeys {
827848 my ( $self, $key ) = @_;
828849
829 confess '[hkeys] ERR Operation against a key holding the wrong kind of value'
850 confess '[hkeys] WRONGTYPE Operation against a key holding the wrong kind of value'
830851 if $self->exists($key) and !$self->_is_hash($key);
831852
832853 return () unless $self->exists($key);
837858 sub hvals {
838859 my ( $self, $key ) = @_;
839860
840 confess '[hvals] ERR Operation against a key holding the wrong kind of value'
861 confess '[hvals] WRONGTYPE Operation against a key holding the wrong kind of value'
841862 if $self->exists($key) and !$self->_is_hash($key);
842863
843864 return values %{ $self->_stash->{$key} };
846867 sub hgetall {
847868 my ( $self, $key ) = @_;
848869
849 confess "[hgetall] ERR Operation against a key holding the wrong kind of value"
870 confess "[hgetall] WRONGTYPE Operation against a key holding the wrong kind of value"
850871 if $self->exists($key) and !$self->_is_hash($key);
851872
852873 return $self->exists( $key )
972993 used_memory_peak => '1055728',
973994 used_memory_peak_human => '1.01M',
974995 used_memory_rss => '1699840',
975 map { 'db'.$_ => sprintf('keys=%d,expires=%d',
996 map { 'db'.$_ => sprintf('keys=%d,expires=%d,avg_ttl=%d',
976997 scalar keys %{ $self->_stash($_) },
977 $self->_expires_count_for_db($_),
998 $self->_expires_count_and_avg_ttl_for_db($_),
978999 )
9791000 } grep { scalar keys %{ $self->_stash($_) } > 0 }
9801001 (0..15)
9811002 };
9821003 }
9831004
984 sub _expires_count_for_db {
1005 sub _expires_count_and_avg_ttl_for_db {
9851006 my ( $self, $db_index ) = @_;
9861007
9871008 my $slot = $self->_stash($db_index);
9881009 my $tied = tied(%$slot);
9891010
990 $tied->expire_count;
1011 $tied->expire_count_and_avg_ttl;
9911012 }
9921013
9931014 sub zadd {
12281249
12291250 =item * Thomas Bloor
12301251
1252 =item * Valery Kalesnik
1253
12311254 =item * Yaakov Shaul
12321255
12331256 =back
13411364 my %want_list = map { $_ => 1 } @want_list;
13421365
13431366 sub exec {
1344 my ( $self ) = @_;
1367 my ( $self, $cb ) = @_;
13451368
13461369 # we are going to commit all the changes we saved up;
13471370 # replay them now and return all their output
13521375 delete $self->{_multi_commands};
13531376
13541377 # replay all the queries that were queued up
1378 # exec has special behaviour when run in a pipeline:
1379 # the $reply argument to the pipeline callback is an array ref whose elements are themselves [$reply, $error] pairs.
1380 if ( $cb && 'CODE' eq ref $cb ) {
1381 my @reply = map {
1382 my ( $method, @args ) = @$_;
1383 try {
1384 my @result = $self->$method( @args );
1385 [ $want_list{ $method } ? \ @result : $result[ 0 ],
1386 undef,
1387 ];
1388 } catch {
1389 s/^\[\w+\] //;
1390 [ undef, $_ ];
1391 };
1392 } @commands;
1393
1394 $cb->( \ @reply, undef );
1395
1396 return 1;
1397 }
1398
13551399 # the returned result is a nested array of the results of all the commands
13561400 my @exceptions;
13571401 my @results = map {
14461490 psubscribe => 1,
14471491 punsubscribe => 1,
14481492 wait_all_responses => 1,
1493 exec => 1, # doc: 'exec has special behaviour when run in a pipeline'. covered in the method
14491494 );
14501495
14511496 my @pipeline_wrapped_methods =
14751520 # and "Pipeline management" in the Redis docs
14761521 # To make this work, we just need to special-case exec, to collect all the
14771522 # results and errors in tuples and send that to the $cb
1478 die 'cannot combine pipelining with MULTI' if $self->{_multi_commands};
1523 # die 'cannot combine pipelining with MULTI' if $self->{_multi_commands};
14791524
14801525 # We could also implement this with a queue, not bothering to process
14811526 # the commands until wait_all_responses is called - but then we need to
15691614 $expires->{$self}->{$key} = $time;
15701615 }
15711616
1572 sub expire_count {
1617 sub expire_count_and_avg_ttl {
15731618 my ( $self ) = @_;
15741619
1575 # really, we should probably only count keys that haven't expired
1576 scalar keys %{ $expires->{$self} };
1620 my $now = time();
1621 my $count = 0;
1622 my $ttl = 0; # looks like actual redis uses more complicated calculations here. let's do something simple to start with
1623 for my $key ( keys %{ $expires->{$self} } ) {
1624 if ( $now >= $expires->{$self}->{$key} ) {
1625 delete $self->{$key};
1626 delete $expires->{$self}->{$key};
1627 } else {
1628 ++ $count;
1629 $ttl += $expires->{$self}->{$key} - $now;
1630 }
1631 }
1632
1633 $ttl = int( $ttl / $count * 1_000 )
1634 if $count;
1635
1636 ( $count, $ttl );
15771637 }
15781638
15791639 sub persist {
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
0 #!perl
0 #!/usr/bin/env perl
11 #
22 # borrowed from Redis.pm's test suite with permission
33 #
88 use Test::More;
99 use Test::Fatal;
1010 use Test::Mock::Redis;
11 use Encode ();
1112
1213 ok(my $r = Test::Mock::Redis->new, 'pretended to connect to our test redis-server');
1314 my @redi = ($r);
4546 cmp_ok($o->get('foo'), 'eq', 'baz', 'get foo = baz');
4647
4748 my $euro = "\x{20ac}";
48 ok($o->set(utf8 => $euro), 'set utf8');
49 cmp_ok($o->get('utf8'), 'eq', $euro, 'get utf8');
49 ok($o->set(utf8 => Encode::encode( 'UTF-8', $euro ) ), 'set utf8');
50 cmp_ok( Encode::decode( 'UTF-8', $o->get('utf8') ), 'eq', $euro, 'get utf8');
5051
5152 ok($o->set('test-undef' => 42), 'set test-undef');
5253 ok($o->exists('test-undef'), 'exists undef');
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
44 use Test::More;
5 use Test::Mock::Redis;
5 use Test::Mock::Redis ();
66
77
88 my $r = Test::Mock::Redis->new;
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
110110 like($info->{run_id},qr/^[0-9a-f]{40}/, 'run_id is 40 random hex chars');
111111
112112 for(0..14){
113 is($info->{"db$_"}, 'keys=1,expires=0', "db$_ info is correct");
113 is($info->{"db$_"}, 'keys=1,expires=0,avg_ttl=0', "db$_ info is correct");
114114 }
115115 # db15 was left with nothing in it, since it was the last one flushed
116116 is($info->{"db15"}, undef, 'info returns no data about databases with no keys');
118118 $r->setex("volitile-key-$_", 15, 'some value') for (1..5);
119119
120120
121 is($r->info->{'db0'}, 'keys=6,expires=5', 'db0 info now has six keys and five expire');
121 like $r->info->{'db0'}, qr/^keys=6,expires=5,avg_ttl=\d+$/,
122 'db0 info now has six keys and five expires';
122123
123124 ok($r->quit, 'quit returns true');
124125 ok(!$r->quit, 'quit returns false the second time');
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
6666
6767 ok(grep { $_ eq $rand } qw/foo bar baz/, 'random returned one of our keys');
6868
69 like exception { $r->rename('foo', 'foo') }, qr/^\Q[rename] ERR source and destination objects are the same\E/,
70 'rename with identical source and dest returns false';
69 # commenting this out as 'Before Redis 3.2.0, an error is returned if source and destination names are the same'
70 # modern versions don't return an error
71 # like exception { $r->rename('foo', 'foo') }, qr/^\Q[rename] ERR source and destination objects are the same\E/,
72 # 'rename with identical source and dest returns false';
7173
7274 like exception { $r->rename('quizlebub', 'foo') }, qr/^\Q[rename] ERR no such key\E/,
7375 "rename with source that doesn't exist returns false";
9092 is( $r->get('newfoo2'), 'foobar', 'renamenx worked');
9193
9294 is($r->ttl('newfoo2'), -1, 'ttl for key with no timeout is -1');
93 is($r->ttl('quizlebub'), -1, "ttl for key that doesn't exist is -1");
95 is($r->ttl('quizlebub'), -2, "ttl for key that doesn't exist is -2");
9496
9597 $r->expire('newfoo2', 3);
9698 ok($r->ttl('newfoo2') >= 2, 'ttl for newfoo2 is at least 2');
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
44 use lib 't/tlib';
55 use Test::More;
6 use Test::Mock::Redis;
6 use Test::Mock::Redis ();
77
88 =pod
99 x SETEX
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use utf8;
33 use strict;
44 use warnings;
55 use lib 't/tlib';
66 use Test::More;
7 use Test::Fatal 'exception';
78 use Test::Mock::Redis;
9 use Encode ();
810
911 =pod
1012 x APPEND
7779 ok($r->set('raboof', 'bar', 'XX', EX => 20), 'Called set with XX and EX');
7880 is($r->get('raboof'), 'bar', ' - updated key');
7981 ok($r->ttl('raboof') > 19 && $r->ttl('raboof') <= 20, ' - reset TTL');
80 ok(! defined $r->set('finaltest', 'baz', 'NX', 'XX'), 'Returns nil with NX and XX');
8182
82 ok($r->set('raboof', 'val', 'EX', 100, 'PX', 10), 'Called set with EX and PX, EX greater');
83 ok($r->ttl('raboof') > 99 && $r->ttl('raboof') <= 100, 'Used EX value');
84 ok($r->set('raboof', 'val', 'PX', 5000, 'EX', 2), 'Called set with EX and PX, PX greater');
85 ok($r->ttl('raboof') > 4 && $r->ttl('raboof') <= 5, 'Used PX value');
83 like exception { $r->set('finaltest', 'baz', 'NX', 'XX') },
84 qr/\[set\] ERR syntax error/,
85 'Combining NX and XX is a syntax error';
86
87 like exception { $r->set('raboof', 'val', 'EX', 100, 'PX', 10) },
88 qr/^\[set\] ERR syntax error/,
89 'Combining EX and PX is a syntax error';
90
91 like exception { $r->set('raboof', 'val', 'EXX') },
92 qr/^\[set\] ERR syntax error/,
93 'Using unknown option is a syntax error';
8694 };
8795
8896 ok(! $r->setnx('foo', 'foobar'), 'setnx returns false for existing key');
115123
116124 is($r->strlen('append-test'), 9, 'length of append-test key is now 9');
117125
118 is($r->append('append-test', '€'), 12, 'euro character (multi-byte) only counted by bytes');
126 is($r->append('append-test', Encode::encode( 'UTF-8', '€') ), 12, 'euro character (multi-byte) only counted by bytes');
119127
120128 is($r->getset('foo', 'whee!'), 'foobar', 'getset returned old value of foo');
121129 is($r->getset('foo', 'foobar'), 'whee!', 'getset returned old value of foo again (so it must have been set)');
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
44 use lib 't/tlib';
55 use Test::More;
6 use Test::Mock::Redis;
6 use Test::Mock::Redis ();
77
88 =pod
99 BLPOP
5353 is $r->llen('list'), 0, "llen returns 0 for a list that doesn't exist";
5454
5555 for my $op (qw/lpush rpush/){
56 eval { $r->lpush('foo', 'barfoo') };
57 like $@, qr/^\Q[lpush] ERR Operation against a key holding the wrong kind of value\E/, "lpush against a key that doesn't hold a list died";
56 eval { $r->$op('foo', 'barfoo') };
57 like $@, qr/^\Q[$op] WRONGTYPE Operation against a key holding the wrong kind of value\E/, "$op against a key that doesn't hold a list died";
58
59 eval { $r->$op('foo') };
60 like $@, qr/^\[$op\] ERR wrong number of arguments for '$op' command/,
61 "$op without values against a key of wrong kind errors out complaining about values, not wrong kind of the key";
5862
5963 ok ! $r->exists("list-$op"), "key 'list-$op' does not exist yet";
6064 is $r->$op("list-$op", 'foobar'), 1, "$op returns length of list";
6569 is $r->llen("list-$op"), 3, "llen agrees";
6670 is $r->$op("list-$op", 'quxqux'), 4, "$op returns length of list";
6771 is $r->llen("list-$op"), 4, "llen agrees";
72
73 eval { $r->$op("list-$op") };
74 like $@, qr/^\[$op\] ERR wrong number of arguments for '$op' command/,
75 "$op without values errors out";
76
77 is $r->$op( "list-$op", qw/ a b c / ), 7,
78 "$op can push multiple values at once";
79
80 if ( $op eq 'lpush' ) {
81 is_deeply scalar $r->lrange( "list-$op", 0, 2 ), [ reverse qw/ a b c / ],
82 "$op has multiple values stored in correct order";
83 } else {
84 is_deeply scalar $r->lrange( "list-$op", -3, -1 ), [ qw/ a b c / ],
85 "$op has multiple values stored in correct order";
86 }
6887 }
6988
7089 $r->rpush('list', $_) for 0..9;
105124 is_deeply([$r->lrange(destination => 2, -2)], [qw/x/]);
106125 is_deeply([$r->lrange(destination => -3, 5)], [qw/c x y/]);
107126 is_deeply([$r->lrange(destination => 3, 1)], []);
127 is_deeply([$r->lrange(nonexisting => 0, -1)], []);
128
129 # arrayref versions of the above block
130 is_deeply scalar $r->lrange(destination => 0, 2), [qw/z c x/];
131 is_deeply scalar $r->lrange(destination => 1, 2), [qw/c x/];
132 is_deeply scalar $r->lrange(destination => 1, -1), [qw/c x y/];
133 is_deeply scalar $r->lrange(destination => 2, -2), [qw/x/];
134 is_deeply scalar $r->lrange(destination => -3, 5), [qw/c x y/];
135 is_deeply scalar $r->lrange(destination => 3, 1), [];
136 is_deeply scalar $r->lrange(nonexisting => 0, -1), [];
108137
109138 $r->lset(destination => 0, 'a');
110139 $r->lset(destination => -1, 'f');
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
3737 foreach my $r (@redi){
3838 diag("testing $r") if $ENV{RELEASE_TESTING};
3939
40 ok ! $r->hexists('hash', 'foo'), "hexists on an empty hash returns false";
41
42 ok ! $r->hexists('hash', 'foo'), "hexists on the same empty hash returns false proving there was no autovivification";
43
4044 is $r->hget('hash', 'foo'), undef, "hget for a hash that doesn't exist is undef";
4145
4246 is_deeply([sort $r->hkeys('hash')], [], "hkeys returned no keys for a hash that doesn't exist");
6468 is $r->get('hash'), 'blarg', "even though it squashed it";
6569
6670 like exception { $r->hset('hash', 'foo', 'foobar') },
67 qr/^\Q[hset] ERR Operation against a key holding the wrong kind of value\E/,
71 qr/^\Q[hset] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
6872 "hset throws error when we overwrite a string with a hash";
6973
7074 ok ! $r->hexists('blarg', 'blorf'), "hexists on a hash that doesn't exist returns false";
7175
7276 like exception { $r->hexists('hash', 'blarg') },
73 qr/^\Q[hexists] ERR Operation against a key holding the wrong kind of value\E/,
77 qr/^\Q[hexists] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
7478 "hexists on a field that's not a hash throws error";
7579
7680 $r->del('hash');
9498 $r->set('not a hash', 'foo bar');
9599
96100 like exception { $r->hkeys('not a hash') },
97 qr/^\Q[hkeys] ERR Operation against a key holding the wrong kind of value\E/,
101 qr/^\Q[hkeys] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
98102 "hkeys on key that isn't a hash throws error";
99103
100104 # OK seems inconsistient
106110 is_deeply { $r->hgetall("I don't exist") }, { }, "hgetall on non-existent key is empty";
107111
108112 like exception { $r->hgetall('not a hash') },
109 qr/^\Q[hgetall] ERR Operation against a key holding the wrong kind of value\E/,
113 qr/^\Q[hgetall] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
110114 "hgetall on key that isn't a hash throws error";
111115
112116
118122 $r->set('not a hash', 'foo bar');
119123
120124 like exception { $r->hvals('not a hash') },
121 qr/^\Q[hvals] ERR Operation against a key holding the wrong kind of value\E/,
125 qr/^\Q[hvals] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
122126 "hvals on key that isn't a hash throws error";
123127
124128
146150
147151 is $r->hset('hash', 'emptystr', ''), 1, "can set hash value to empty string";
148152
149 is $r->hincrby('hash', 'emptystr', 1), 1, "incrby 1 on the empty string returns 1";
153 like exception { $r->hincrby('hash', 'emptystr', 1) },
154 qr/^\Q[hincrby] ERR hash value is not an integer\E/,
155 "hincrby dies when an empty string is incremented";
150156 }
151157
152158
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
147147 $r->set('justakey', 'foobar');
148148
149149 like exception { $r->smove('justakey', 'set', 'foo') },
150 qr/^\Q[smove] ERR Operation against a key holding the wrong kind of value\E/,
150 qr/^\Q[smove] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
151151 "smove dies when source isn't a set";
152152
153153 like exception { $r->smove('set', 'justakey', 'foo') },
154 qr/^\Q[smove] ERR Operation against a key holding the wrong kind of value\E/,
154 qr/^\Q[smove] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
155155 "smove dies when dest isn't a set";
156156
157157 is $r->smove('otherset', 'newset', 'foo'), 1, "smove returns true when destination doesn't exist";
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
44 use Test::More;
5 use Test::Mock::Redis;
5 use Test::Mock::Redis ();
66
77 =pod
88 ZADD
0 #!/usr/bin/env perl
01 use strict;
12 use warnings FATAL => 'all';
23
126127
127128 like(
128129 exception { $redis->exec },
129 qr/^\[exec\] ERR Operation against a key holding the wrong kind of value/,
130 qr/^\Q[exec] WRONGTYPE Operation against a key holding the wrong kind of value\E/,
130131 'a bad transaction results in an exception',
131132 );
132133
0 #!/usr/bin/env perl
01 use strict;
12 use warnings FATAL => 'all';
23
34 use Test::More 0.88;
45 use Test::Deep;
5 use Test::Fatal;
6 use Test::Fatal 'exception';
67 use Test::Deep::UnorderedPairs;
7 use Test::Mock::Redis;
8 use Test::Mock::Redis ();
89
910 use lib 't/tlib';
1011
7071 $redis->hset(
7172 'pipeline_key_2', 'bar', '9',
7273 # weird, when pipelining, the real redis doesn't always include the command name?
73 sub { cmp_deeply(\@_, [ undef, re(qr/^(\[hset\] )?ERR Operation against a key holding the wrong kind of value/) ], 'hset callback') },
74 sub { cmp_deeply(\@_, [ undef, re(qr/^(\[hset\] )?WRONGTYPE Operation against a key holding the wrong kind of value/) ], 'hset callback') },
7475 ),
7576 '1',
7677 'hset operation sent',
0 #!perl
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
44 use Test::More;
5 use Test::Fatal;
5 use Test::Fatal 'exception';
66 use Test::Deep;
7 use Test::Mock::Redis;
7 use Test::Mock::Redis ();
88
99 #
1010 # first demonstrate failure
0 #!perl
0 #!/usr/bin/env perl
11
22 use warnings;
33 use strict;
44 use lib 't/tlib';
55 use Test::More;
6 use Test::Fatal;
7 use Test::Mock::Redis;
6 use Test::Mock::Redis ();
87
98 ok(my $r = Test::Mock::Redis->new, 'pretended to connect to our test redis-server');
109 my @redi = ($r);
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;
0 #!perl -T
0 #!/usr/bin/env perl
11
22 use strict;
33 use warnings;