mock_redis 0.5.4 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/lint.yml +31 -0
- data/.github/workflows/tests.yml +63 -0
- data/.gitignore +1 -1
- data/.overcommit.yml +21 -0
- data/.rspec +1 -1
- data/.rubocop.yml +148 -0
- data/.rubocop_todo.yml +35 -0
- data/.simplecov +4 -0
- data/CHANGELOG.md +278 -0
- data/Gemfile +9 -5
- data/LICENSE.md +21 -0
- data/README.md +52 -16
- data/Rakefile +0 -8
- data/lib/mock_redis/assertions.rb +0 -1
- data/lib/mock_redis/connection_method.rb +13 -0
- data/lib/mock_redis/database.rb +193 -257
- data/lib/mock_redis/expire_wrapper.rb +2 -2
- data/lib/mock_redis/future.rb +23 -0
- data/lib/mock_redis/geospatial_methods.rb +240 -0
- data/lib/mock_redis/hash_methods.rb +83 -24
- data/lib/mock_redis/indifferent_hash.rb +11 -0
- data/lib/mock_redis/info_method.rb +160 -0
- data/lib/mock_redis/list_methods.rb +34 -19
- data/lib/mock_redis/multi_db_wrapper.rb +8 -7
- data/lib/mock_redis/pipelined_wrapper.rb +42 -16
- data/lib/mock_redis/set_methods.rb +62 -19
- data/lib/mock_redis/sort_method.rb +81 -0
- data/lib/mock_redis/stream/id.rb +58 -0
- data/lib/mock_redis/stream.rb +88 -0
- data/lib/mock_redis/stream_methods.rb +102 -0
- data/lib/mock_redis/string_methods.rb +235 -42
- data/lib/mock_redis/transaction_wrapper.rb +62 -28
- data/lib/mock_redis/utility_methods.rb +62 -11
- data/lib/mock_redis/version.rb +4 -1
- data/lib/mock_redis/zset.rb +24 -29
- data/lib/mock_redis/zset_methods.rb +187 -59
- data/lib/mock_redis.rb +77 -27
- data/mock_redis.gemspec +23 -15
- data/spec/client_spec.rb +29 -0
- data/spec/cloning_spec.rb +17 -18
- data/spec/commands/append_spec.rb +4 -4
- data/spec/commands/auth_spec.rb +1 -1
- data/spec/commands/bgrewriteaof_spec.rb +2 -2
- data/spec/commands/bgsave_spec.rb +2 -2
- data/spec/commands/bitcount_spec.rb +25 -0
- data/spec/commands/bitfield_spec.rb +169 -0
- data/spec/commands/blpop_spec.rb +19 -21
- data/spec/commands/brpop_spec.rb +25 -20
- data/spec/commands/brpoplpush_spec.rb +16 -17
- data/spec/commands/connected_spec.rb +7 -0
- data/spec/commands/connection_spec.rb +15 -0
- data/spec/commands/dbsize_spec.rb +3 -3
- data/spec/commands/decr_spec.rb +8 -8
- data/spec/commands/decrby_spec.rb +8 -8
- data/spec/commands/del_spec.rb +35 -3
- data/spec/commands/disconnect_spec.rb +7 -0
- data/spec/commands/dump_spec.rb +19 -0
- data/spec/commands/echo_spec.rb +4 -4
- data/spec/commands/eval_spec.rb +7 -0
- data/spec/commands/evalsha_spec.rb +10 -0
- data/spec/commands/exists_spec.rb +36 -7
- data/spec/commands/expire_spec.rb +48 -20
- data/spec/commands/expireat_spec.rb +12 -13
- data/spec/commands/flushall_spec.rb +5 -5
- data/spec/commands/flushdb_spec.rb +5 -5
- data/spec/commands/future_spec.rb +30 -0
- data/spec/commands/geoadd_spec.rb +58 -0
- data/spec/commands/geodist_spec.rb +118 -0
- data/spec/commands/geohash_spec.rb +52 -0
- data/spec/commands/geopos_spec.rb +55 -0
- data/spec/commands/get_spec.rb +14 -6
- data/spec/commands/getbit_spec.rb +7 -7
- data/spec/commands/getrange_spec.rb +9 -9
- data/spec/commands/getset_spec.rb +7 -7
- data/spec/commands/hdel_spec.rb +41 -11
- data/spec/commands/hexists_spec.rb +11 -11
- data/spec/commands/hget_spec.rb +7 -7
- data/spec/commands/hgetall_spec.rb +15 -5
- data/spec/commands/hincrby_spec.rb +16 -16
- data/spec/commands/hincrbyfloat_spec.rb +58 -0
- data/spec/commands/hkeys_spec.rb +5 -5
- data/spec/commands/hlen_spec.rb +5 -5
- data/spec/commands/hmget_spec.rb +19 -9
- data/spec/commands/hmset_spec.rb +38 -12
- data/spec/commands/hscan_each_spec.rb +48 -0
- data/spec/commands/hscan_spec.rb +27 -0
- data/spec/commands/hset_spec.rb +26 -12
- data/spec/commands/hsetnx_spec.rb +16 -16
- data/spec/commands/hvals_spec.rb +5 -5
- data/spec/commands/incr_spec.rb +8 -8
- data/spec/commands/incrby_spec.rb +13 -13
- data/spec/commands/incrbyfloat_spec.rb +13 -13
- data/spec/commands/info_spec.rb +54 -5
- data/spec/commands/keys_spec.rb +83 -31
- data/spec/commands/lastsave_spec.rb +2 -2
- data/spec/commands/lindex_spec.rb +20 -10
- data/spec/commands/linsert_spec.rb +14 -14
- data/spec/commands/llen_spec.rb +4 -4
- data/spec/commands/lpop_spec.rb +6 -6
- data/spec/commands/lpush_spec.rb +21 -15
- data/spec/commands/lpushx_spec.rb +24 -11
- data/spec/commands/lrange_spec.rb +24 -8
- data/spec/commands/lrem_spec.rb +16 -16
- data/spec/commands/lset_spec.rb +17 -12
- data/spec/commands/ltrim_spec.rb +17 -7
- data/spec/commands/mapped_hmget_spec.rb +13 -9
- data/spec/commands/mapped_hmset_spec.rb +12 -12
- data/spec/commands/mapped_mget_spec.rb +22 -0
- data/spec/commands/mapped_mset_spec.rb +19 -0
- data/spec/commands/mapped_msetnx_spec.rb +26 -0
- data/spec/commands/mget_spec.rb +48 -17
- data/spec/commands/move_spec.rb +37 -37
- data/spec/commands/mset_spec.rb +20 -6
- data/spec/commands/msetnx_spec.rb +14 -14
- data/spec/commands/persist_spec.rb +15 -16
- data/spec/commands/pexpire_spec.rb +86 -0
- data/spec/commands/pexpireat_spec.rb +48 -0
- data/spec/commands/ping_spec.rb +6 -2
- data/spec/commands/pipelined_spec.rb +98 -7
- data/spec/commands/pttl_spec.rb +41 -0
- data/spec/commands/randomkey_spec.rb +3 -3
- data/spec/commands/rename_spec.rb +16 -12
- data/spec/commands/renamenx_spec.rb +13 -15
- data/spec/commands/restore_spec.rb +47 -0
- data/spec/commands/rpop_spec.rb +6 -6
- data/spec/commands/rpoplpush_spec.rb +13 -8
- data/spec/commands/rpush_spec.rb +21 -15
- data/spec/commands/rpushx_spec.rb +24 -11
- data/spec/commands/sadd_spec.rb +14 -10
- data/spec/commands/scan_each_spec.rb +39 -0
- data/spec/commands/scan_spec.rb +64 -0
- data/spec/commands/scard_spec.rb +3 -3
- data/spec/commands/script_spec.rb +9 -0
- data/spec/commands/sdiff_spec.rb +13 -13
- data/spec/commands/sdiffstore_spec.rb +13 -13
- data/spec/commands/select_spec.rb +13 -5
- data/spec/commands/set_spec.rb +112 -0
- data/spec/commands/setbit_spec.rb +25 -16
- data/spec/commands/setex_spec.rb +20 -4
- data/spec/commands/setnx_spec.rb +6 -6
- data/spec/commands/setrange_spec.rb +12 -12
- data/spec/commands/sinter_spec.rb +11 -13
- data/spec/commands/sinterstore_spec.rb +12 -12
- data/spec/commands/sismember_spec.rb +10 -10
- data/spec/commands/smembers_spec.rb +15 -5
- data/spec/commands/smove_spec.rb +13 -13
- data/spec/commands/sort_list_spec.rb +21 -0
- data/spec/commands/sort_set_spec.rb +21 -0
- data/spec/commands/sort_zset_spec.rb +21 -0
- data/spec/commands/spop_spec.rb +19 -4
- data/spec/commands/srandmember_spec.rb +28 -4
- data/spec/commands/srem_spec.rb +17 -12
- data/spec/commands/sscan_each_spec.rb +48 -0
- data/spec/commands/sscan_spec.rb +39 -0
- data/spec/commands/strlen_spec.rb +4 -5
- data/spec/commands/sunion_spec.rb +13 -11
- data/spec/commands/sunionstore_spec.rb +12 -12
- data/spec/commands/ttl_spec.rb +11 -6
- data/spec/commands/type_spec.rb +1 -1
- data/spec/commands/watch_spec.rb +9 -4
- data/spec/commands/xadd_spec.rb +122 -0
- data/spec/commands/xlen_spec.rb +22 -0
- data/spec/commands/xrange_spec.rb +164 -0
- data/spec/commands/xread_spec.rb +66 -0
- data/spec/commands/xrevrange_spec.rb +130 -0
- data/spec/commands/xtrim_spec.rb +36 -0
- data/spec/commands/zadd_spec.rb +100 -11
- data/spec/commands/zcard_spec.rb +4 -4
- data/spec/commands/zcount_spec.rb +18 -10
- data/spec/commands/zincrby_spec.rb +6 -6
- data/spec/commands/zinterstore_spec.rb +54 -20
- data/spec/commands/zpopmax_spec.rb +60 -0
- data/spec/commands/zpopmin_spec.rb +60 -0
- data/spec/commands/zrange_spec.rb +54 -13
- data/spec/commands/zrangebyscore_spec.rb +42 -27
- data/spec/commands/zrank_spec.rb +4 -4
- data/spec/commands/zrem_spec.rb +18 -12
- data/spec/commands/zremrangebyrank_spec.rb +5 -5
- data/spec/commands/zremrangebyscore_spec.rb +12 -5
- data/spec/commands/zrevrange_spec.rb +35 -10
- data/spec/commands/zrevrangebyscore_spec.rb +26 -15
- data/spec/commands/zrevrank_spec.rb +4 -4
- data/spec/commands/zscan_each_spec.rb +48 -0
- data/spec/commands/zscan_spec.rb +26 -0
- data/spec/commands/zscore_spec.rb +7 -7
- data/spec/commands/zunionstore_spec.rb +54 -21
- data/spec/mock_redis_spec.rb +61 -0
- data/spec/spec_helper.rb +35 -8
- data/spec/support/redis_multiplexer.rb +62 -37
- data/spec/support/shared_examples/does_not_cleanup_empty_strings.rb +14 -0
- data/spec/support/shared_examples/only_operates_on_hashes.rb +5 -3
- data/spec/support/shared_examples/only_operates_on_lists.rb +5 -3
- data/spec/support/shared_examples/only_operates_on_sets.rb +5 -3
- data/spec/support/shared_examples/only_operates_on_strings.rb +4 -4
- data/spec/support/shared_examples/only_operates_on_zsets.rb +18 -16
- data/spec/support/shared_examples/sorts_enumerables.rb +56 -0
- data/spec/transactions_spec.rb +79 -29
- metadata +162 -42
- data/LICENSE +0 -19
- data/spec/commands/hash_operator_spec.rb +0 -21
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#sort(key, options)' do
|
4
|
+
before do
|
5
|
+
@key = 'mock-redis-test:set_sort'
|
6
|
+
|
7
|
+
@redises.sadd(@key, '1')
|
8
|
+
@redises.sadd(@key, '2')
|
9
|
+
|
10
|
+
@redises.set('mock-redis-test:values_1', 'a')
|
11
|
+
@redises.set('mock-redis-test:values_2', 'b')
|
12
|
+
|
13
|
+
@redises.set('mock-redis-test:weight_1', '2')
|
14
|
+
@redises.set('mock-redis-test:weight_2', '1')
|
15
|
+
|
16
|
+
@redises.hset('mock-redis-test:hash_1', 'key', 'x')
|
17
|
+
@redises.hset('mock-redis-test:hash_2', 'key', 'y')
|
18
|
+
end
|
19
|
+
|
20
|
+
it_should_behave_like 'a sortable'
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#sort(key, options)' do
|
4
|
+
before do
|
5
|
+
@key = 'mock-redis-test:zset_sort'
|
6
|
+
|
7
|
+
@redises.zadd(@key, 100, '1')
|
8
|
+
@redises.zadd(@key, 99, '2')
|
9
|
+
|
10
|
+
@redises.set('mock-redis-test:values_1', 'a')
|
11
|
+
@redises.set('mock-redis-test:values_2', 'b')
|
12
|
+
|
13
|
+
@redises.set('mock-redis-test:weight_1', '2')
|
14
|
+
@redises.set('mock-redis-test:weight_2', '1')
|
15
|
+
|
16
|
+
@redises.hset('mock-redis-test:hash_1', 'key', 'x')
|
17
|
+
@redises.hset('mock-redis-test:hash_2', 'key', 'y')
|
18
|
+
end
|
19
|
+
|
20
|
+
it_should_behave_like 'a sortable'
|
21
|
+
end
|
data/spec/commands/spop_spec.rb
CHANGED
@@ -7,19 +7,34 @@ describe '#spop(key)' do
|
|
7
7
|
@redises.sadd(@key, 'value')
|
8
8
|
end
|
9
9
|
|
10
|
-
it
|
10
|
+
it 'returns a member of the set' do
|
11
11
|
@redises.spop(@key).should == 'value'
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
14
|
+
it 'removes a member of the set' do
|
15
15
|
@redises.spop(@key)
|
16
16
|
@redises.smembers(@key).should == []
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
19
|
+
it 'returns nil if the set is empty' do
|
20
20
|
@redises.spop(@key)
|
21
21
|
@redises.spop(@key).should be_nil
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
it 'returns an array if count is not nil' do
|
25
|
+
@redises.sadd(@key, 'value2')
|
26
|
+
@redises.spop(@key, 2).should == %w[value value2]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns only whats in the set' do
|
30
|
+
@redises.spop(@key, 2).should == ['value']
|
31
|
+
@redises.smembers(@key).should == []
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns an empty array if count is not nil and the set it empty' do
|
35
|
+
@redises.spop(@key)
|
36
|
+
@redises.spop(@key, 100).should == []
|
37
|
+
end
|
38
|
+
|
39
|
+
it_should_behave_like 'a set-only command'
|
25
40
|
end
|
@@ -7,19 +7,43 @@ describe '#srandmember(key)' do
|
|
7
7
|
@redises.sadd(@key, 'value')
|
8
8
|
end
|
9
9
|
|
10
|
-
it
|
10
|
+
it 'returns a member of the set' do
|
11
11
|
@redises.srandmember(@key).should == 'value'
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
14
|
+
it 'does not modify the set' do
|
15
15
|
@redises.srandmember(@key)
|
16
16
|
@redises.smembers(@key).should == ['value']
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
19
|
+
it 'returns nil if the set is empty' do
|
20
20
|
@redises.spop(@key)
|
21
21
|
@redises.srandmember(@key).should be_nil
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
context 'when count argument is specified' do
|
25
|
+
before do
|
26
|
+
@redises.sadd(@key, 'value2')
|
27
|
+
@redises.sadd(@key, 'value3')
|
28
|
+
end
|
29
|
+
|
30
|
+
# NOTE: We disable result checking since MockRedis and Redis will likely
|
31
|
+
# return a different random set (since the selection is, well, random)
|
32
|
+
it 'returns the whole set if count is greater than the set size' do
|
33
|
+
@redises.send_without_checking(:srandmember, @key, 5).should =~ %w[value value2 value3]
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns random members up to count from the set when count is smaller than the set size' do
|
37
|
+
@redises.send_without_checking(:srandmember, @key, 2).size.should == 2
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns random members up to count from the set when count is negative even if count.abs is greater than the set size' do # rubocop:disable Layout/LineLength
|
41
|
+
@redises.send_without_checking(:srandmember, @key, -5).size.should == 5
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns nil if the set is empty' do
|
45
|
+
@redises.srem(@key, %w[value value2 value3])
|
46
|
+
@redises.srandmember(@key, 2).should be_empty
|
47
|
+
end
|
48
|
+
end
|
25
49
|
end
|
data/spec/commands/srem_spec.rb
CHANGED
@@ -8,33 +8,38 @@ describe '#srem(key, member)' do
|
|
8
8
|
@redises.sadd(@key, 'ernie')
|
9
9
|
end
|
10
10
|
|
11
|
-
it
|
12
|
-
@redises.srem(@key, 'bert').should
|
11
|
+
it 'returns true if member is in the set' do
|
12
|
+
@redises.srem(@key, 'bert').should == true
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
16
|
-
@redises.srem(@key, 'cookiemonster').should
|
15
|
+
it 'returns false if member is not in the set' do
|
16
|
+
@redises.srem(@key, 'cookiemonster').should == false
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
19
|
+
it 'removes member from the set' do
|
20
20
|
@redises.srem(@key, 'ernie')
|
21
21
|
@redises.smembers(@key).should == ['bert']
|
22
22
|
end
|
23
23
|
|
24
|
-
it
|
24
|
+
it 'stringifies member' do
|
25
25
|
@redises.sadd(@key, '1')
|
26
|
-
@redises.srem(@key, 1).should
|
26
|
+
@redises.srem(@key, 1).should == true
|
27
27
|
end
|
28
28
|
|
29
|
-
it
|
30
|
-
@redises.smembers(@key).each {|m| @redises.srem(@key, m)}
|
29
|
+
it 'cleans up empty sets' do
|
30
|
+
@redises.smembers(@key).each { |m| @redises.srem(@key, m) }
|
31
31
|
@redises.get(@key).should be_nil
|
32
32
|
end
|
33
33
|
|
34
|
-
it
|
35
|
-
@redises.srem(@key, [
|
34
|
+
it 'supports a variable number of arguments' do
|
35
|
+
@redises.srem(@key, %w[bert ernie]).should == 2
|
36
36
|
@redises.get(@key).should be_nil
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
it 'allow passing an array of integers as argument' do
|
40
|
+
@redises.sadd(@key, %w[1 2])
|
41
|
+
@redises.srem(@key, [1, 2]).should == 2
|
42
|
+
end
|
43
|
+
|
44
|
+
it_should_behave_like 'a set-only command'
|
40
45
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#sscan_each' do
|
4
|
+
subject { MockRedis::Database.new(self) }
|
5
|
+
|
6
|
+
let(:key) { 'mock-redis-test:sscan_each' }
|
7
|
+
|
8
|
+
before do
|
9
|
+
allow(subject).to receive(:smembers).and_return(collection)
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when no keys are found' do
|
13
|
+
let(:collection) { [] }
|
14
|
+
|
15
|
+
it 'does not iterate over any elements' do
|
16
|
+
results = subject.sscan_each(key).map do |k|
|
17
|
+
k
|
18
|
+
end
|
19
|
+
expect(results).to match_array(collection)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when keys are found' do
|
24
|
+
context 'when no match filter is supplied' do
|
25
|
+
let(:collection) { Array.new(20) { |i| "k#{i}" } }
|
26
|
+
|
27
|
+
it 'iterates over each item in the collection' do
|
28
|
+
results = subject.sscan_each(key).map do |k|
|
29
|
+
k
|
30
|
+
end
|
31
|
+
expect(results).to match_array(collection)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when giving a custom match filter' do
|
36
|
+
let(:match) { 'k1*' }
|
37
|
+
let(:collection) { Array.new(12) { |i| "k#{i}" } }
|
38
|
+
let(:expected) { %w[k1 k10 k11] }
|
39
|
+
|
40
|
+
it 'iterates over each item in the filtered collection' do
|
41
|
+
results = subject.sscan_each(key, match: match).map do |k|
|
42
|
+
k
|
43
|
+
end
|
44
|
+
expect(results).to match_array(expected)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#sscan' do
|
4
|
+
let(:count) { 10 }
|
5
|
+
let(:match) { '*' }
|
6
|
+
let(:key) { 'mock-redis-test:sscan' }
|
7
|
+
|
8
|
+
before do
|
9
|
+
# The return order of the members is non-deterministic, so we sort them to compare
|
10
|
+
expect_any_instance_of(Redis).to receive(:sscan).and_wrap_original do |m, *args|
|
11
|
+
result = m.call(*args)
|
12
|
+
[result[0], result[1].sort]
|
13
|
+
end
|
14
|
+
expect_any_instance_of(MockRedis).to receive(:sscan).and_wrap_original do |m, *args|
|
15
|
+
result = m.call(*args)
|
16
|
+
[result[0], result[1].sort]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when the set does not exist' do
|
21
|
+
it 'returns a 0 cursor and an empty collection' do
|
22
|
+
expect(@redises.sscan(key, 0, count: count, match: match)).to eq(['0', []])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when the set exists' do
|
27
|
+
before do
|
28
|
+
@redises.sadd(key, 'Hello')
|
29
|
+
@redises.sadd(key, 'World')
|
30
|
+
@redises.sadd(key, 'Test')
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:expected) { ['0', %w[Hello Test World]] }
|
34
|
+
|
35
|
+
it 'returns a 0 cursor and the collection' do
|
36
|
+
expect(@redises.sscan(key, 0, count: count)).to eq(expected)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,19 +1,18 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
1
|
require 'spec_helper'
|
3
2
|
|
4
|
-
describe
|
3
|
+
describe '#strlen(key)' do
|
5
4
|
before do
|
6
5
|
@key = 'mock-redis-test:73288'
|
7
|
-
@redises.set(@key,
|
6
|
+
@redises.set(@key, '5 ∈ (0..10)')
|
8
7
|
end
|
9
8
|
|
10
9
|
it "returns the string's length in bytes" do
|
11
10
|
@redises.strlen(@key).should == 13
|
12
11
|
end
|
13
12
|
|
14
|
-
it
|
13
|
+
it 'returns 0 for a nonexistent value' do
|
15
14
|
@redises.strlen('mock-redis-test:does-not-exist').should == 0
|
16
15
|
end
|
17
16
|
|
18
|
-
it_should_behave_like
|
17
|
+
it_should_behave_like 'a string-only command'
|
19
18
|
end
|
@@ -5,36 +5,38 @@ describe '#sunion(key [, key, ...])' do
|
|
5
5
|
@evens = 'mock-redis-test:sunion:evens'
|
6
6
|
@primes = 'mock-redis-test:sunion:primes'
|
7
7
|
|
8
|
-
[2, 4, 6, 8, 10].each {|i| @redises.sadd(@evens, i) }
|
9
|
-
[2, 3, 5, 7].each {|i| @redises.sadd(@primes, i) }
|
8
|
+
[2, 4, 6, 8, 10].each { |i| @redises.sadd(@evens, i) }
|
9
|
+
[2, 3, 5, 7].each { |i| @redises.sadd(@primes, i) }
|
10
10
|
end
|
11
11
|
|
12
|
-
it
|
12
|
+
it 'returns the elements in the resulting set' do
|
13
13
|
@redises.sunion(@evens, @primes).should == %w[2 4 6 8 10 3 5 7]
|
14
14
|
end
|
15
15
|
|
16
|
-
it
|
16
|
+
it 'treats missing keys as empty sets' do
|
17
17
|
@redises.sunion(@primes, 'mock-redis-test:nonesuch').
|
18
18
|
should == %w[2 3 5 7]
|
19
19
|
end
|
20
20
|
|
21
|
-
it
|
21
|
+
it 'allows Array as argument' do
|
22
|
+
@redises.sunion([@evens, @primes]).should == %w[2 4 6 8 10 3 5 7]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'raises an error if given 0 sets' do
|
22
26
|
lambda do
|
23
27
|
@redises.sunion
|
24
|
-
end.should raise_error(
|
28
|
+
end.should raise_error(Redis::CommandError)
|
25
29
|
end
|
26
30
|
|
27
|
-
it
|
31
|
+
it 'raises an error if any argument is not a a set' do
|
28
32
|
@redises.set('mock-redis-test:notset', 1)
|
29
33
|
|
30
34
|
lambda do
|
31
35
|
@redises.sunion(@numbers, 'mock-redis-test:notset')
|
32
|
-
end.should raise_error(
|
36
|
+
end.should raise_error(Redis::CommandError)
|
33
37
|
|
34
38
|
lambda do
|
35
39
|
@redises.sunion('mock-redis-test:notset', @numbers)
|
36
|
-
end.should raise_error(
|
40
|
+
end.should raise_error(Redis::CommandError)
|
37
41
|
end
|
38
42
|
end
|
39
|
-
|
40
|
-
|
@@ -6,54 +6,54 @@ describe '#sunionstore(destination, key [, key, ...])' do
|
|
6
6
|
@primes = 'mock-redis-test:sunionstore:primes'
|
7
7
|
@destination = 'mock-redis-test:sunionstore:destination'
|
8
8
|
|
9
|
-
[2, 4, 6, 8, 10].each {|i| @redises.sadd(@evens, i) }
|
10
|
-
[2, 3, 5, 7].each {|i| @redises.sadd(@primes, i) }
|
9
|
+
[2, 4, 6, 8, 10].each { |i| @redises.sadd(@evens, i) }
|
10
|
+
[2, 3, 5, 7].each { |i| @redises.sadd(@primes, i) }
|
11
11
|
end
|
12
12
|
|
13
|
-
it
|
13
|
+
it 'returns the number of elements in the resulting set' do
|
14
14
|
@redises.sunionstore(@destination, @primes, @evens).should == 8
|
15
15
|
end
|
16
16
|
|
17
|
-
it
|
17
|
+
it 'stores the resulting set' do
|
18
18
|
@redises.sunionstore(@destination, @primes, @evens)
|
19
19
|
@redises.smembers(@destination).should == %w[10 8 6 4 7 5 3 2]
|
20
20
|
end
|
21
21
|
|
22
|
-
it
|
22
|
+
it 'does not store empty sets' do
|
23
23
|
@redises.sunionstore(@destination,
|
24
24
|
'mock-redis-test:nonesuch',
|
25
25
|
'mock-redis-test:nonesuch2').should == 0
|
26
26
|
@redises.get(@destination).should be_nil
|
27
27
|
end
|
28
28
|
|
29
|
-
it
|
29
|
+
it 'removes existing elements in destination' do
|
30
30
|
@redises.sadd(@destination, 42)
|
31
31
|
|
32
32
|
@redises.sunionstore(@destination, @primes)
|
33
33
|
@redises.smembers(@destination).should == %w[7 5 3 2]
|
34
34
|
end
|
35
35
|
|
36
|
-
it
|
36
|
+
it 'correctly unions and stores when the destination is empty and is one of the arguments' do
|
37
37
|
@redises.sunionstore(@destination, @destination, @primes)
|
38
38
|
|
39
39
|
@redises.smembers(@destination).should == %w[7 5 3 2]
|
40
40
|
end
|
41
41
|
|
42
|
-
it
|
42
|
+
it 'raises an error if given 0 sets' do
|
43
43
|
lambda do
|
44
44
|
@redises.sunionstore(@destination)
|
45
|
-
end.should raise_error(
|
45
|
+
end.should raise_error(Redis::CommandError)
|
46
46
|
end
|
47
47
|
|
48
|
-
it
|
48
|
+
it 'raises an error if any argument is not a a set' do
|
49
49
|
@redises.set('mock-redis-test:notset', 1)
|
50
50
|
|
51
51
|
lambda do
|
52
52
|
@redises.sunionstore(@destination, @primes, 'mock-redis-test:notset')
|
53
|
-
end.should raise_error(
|
53
|
+
end.should raise_error(Redis::CommandError)
|
54
54
|
|
55
55
|
lambda do
|
56
56
|
@redises.sunionstore(@destination, 'mock-redis-test:notset', @primes)
|
57
|
-
end.should raise_error(
|
57
|
+
end.should raise_error(Redis::CommandError)
|
58
58
|
end
|
59
59
|
end
|
data/spec/commands/ttl_spec.rb
CHANGED
@@ -1,20 +1,25 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe '#ttl(key)' do
|
4
4
|
before do
|
5
5
|
@key = 'mock-redis-test:persist'
|
6
6
|
@redises.set(@key, 'spork')
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
9
|
+
it 'returns -1 for a key with no expiration' do
|
10
10
|
@redises.ttl(@key).should == -1
|
11
11
|
end
|
12
12
|
|
13
|
-
it
|
14
|
-
@redises.ttl('mock-redis-test:nonesuch').should == -
|
13
|
+
it 'returns -2 for a key that does not exist' do
|
14
|
+
@redises.ttl('mock-redis-test:nonesuch').should == -2
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
it 'stringifies key' do
|
18
|
+
@redises.expire(@key, 9)
|
19
|
+
@redises.ttl(@key.to_sym).should > 0
|
20
|
+
end
|
21
|
+
|
22
|
+
context '[mock only]' do
|
18
23
|
# These are mock-only since we can't actually manipulate time in
|
19
24
|
# the real Redis.
|
20
25
|
|
@@ -24,7 +29,7 @@ describe "#ttl(key)" do
|
|
24
29
|
|
25
30
|
before do
|
26
31
|
@now = Time.now
|
27
|
-
Time.stub
|
32
|
+
Time.stub(:now).and_return(@now)
|
28
33
|
end
|
29
34
|
|
30
35
|
it "gives you the key's remaining lifespan in seconds" do
|
data/spec/commands/type_spec.rb
CHANGED
data/spec/commands/watch_spec.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '#watch(key)' do
|
4
|
-
|
5
|
-
@
|
3
|
+
describe '#watch(key [, key, ...)' do
|
4
|
+
before do
|
5
|
+
@key1 = 'mock-redis-test-watch1'
|
6
|
+
@key2 = 'mock-redis-test-watch2'
|
7
|
+
end
|
8
|
+
|
9
|
+
it "returns 'OK'" do
|
10
|
+
@redises.watch(@key1, @key2).should == 'OK'
|
6
11
|
end
|
7
12
|
|
8
13
|
it 'EXECs its MULTI on successes' do
|
9
|
-
@redises.watch
|
14
|
+
@redises.watch @key1, @key2 do
|
10
15
|
@redises.multi do |multi|
|
11
16
|
multi.set 'bar', 'baz'
|
12
17
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#xadd("mystream", { f1: "v1", f2: "v2" }, id: "0-0", maxlen: 1000, approximate: true)' do
|
4
|
+
before :all do
|
5
|
+
sleep 1 - (Time.now.to_f % 1)
|
6
|
+
@key = 'mock-redis-test:xadd'
|
7
|
+
end
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
# TODO: Redis appears to be returning a timestamp a few seconds in the future
|
11
|
+
# so we're ignoring the last 5 digits (time in milliseconds)
|
12
|
+
@redises._gsub(/\d{5}-\d/, '....-.')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns an id based on the timestamp' do
|
16
|
+
t = Time.now.to_i
|
17
|
+
id = @redises.xadd(@key, { key: 'value' })
|
18
|
+
expect(id).to match(/#{t}\d{3}-0/)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'adds data with symbols' do
|
22
|
+
@redises.xadd(@key, { symbol_key: :symbol_value })
|
23
|
+
expect(@redises.xrange(@key, '-', '+').last[1])
|
24
|
+
.to eq('symbol_key' => 'symbol_value')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'increments the sequence number with the same timestamp' do
|
28
|
+
Timecop.freeze do
|
29
|
+
@redises.xadd(@key, { key: 'value' })
|
30
|
+
expect(@redises.xadd(@key, { key: 'value' })).to match(/\d+-1/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'sets the id if it is given' do
|
35
|
+
expect(@redises.xadd(@key, { key: 'value' }, id: '1234567891234-2'))
|
36
|
+
.to eq '1234567891234-2'
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'accepts is as an integer' do
|
40
|
+
expect(@redises.xadd(@key, { key: 'value' }, id: 1_234_567_891_234))
|
41
|
+
.to eq '1234567891234-0'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'raises exception if id is less that stream top item' do
|
45
|
+
@redises.xadd(@key, { key: 'value' }, id: '1234567891234-0')
|
46
|
+
expect { @redises.xadd(@key, { key: 'value' }, id: '1234567891233-0') }
|
47
|
+
.to raise_error(
|
48
|
+
Redis::CommandError,
|
49
|
+
'ERR The ID specified in XADD is equal or smaller than the target ' \
|
50
|
+
'stream top item'
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'raises exception if id of 0 is added to an empty stream' do
|
55
|
+
expect { @redises.xadd('mock-redis-test:unknown-stream', { key: 'value' }, id: '0') }
|
56
|
+
.to raise_error(
|
57
|
+
Redis::CommandError,
|
58
|
+
'ERR The ID specified in XADD must be greater than 0-0'
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'does not raise exception on empty stream with id of 0 and positive sequence number' do
|
63
|
+
expect { @redises.xadd('mock-redis-test:unknown-stream', { key: 'value' }, id: '0-1') }
|
64
|
+
.to_not raise_error
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'caters for the current time being before the last time' do
|
68
|
+
t = (Time.now.to_f * 1000).to_i + 2000
|
69
|
+
@redises.xadd(@key, { key: 'value' }, id: "#{t}-0")
|
70
|
+
expect(@redises.xadd(@key, { key: 'value' })).to match(/#{t}-1/)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'appends a sequence number if it is missing' do
|
74
|
+
expect(@redises.xadd(@key, { key: 'value' }, id: '1234567891234'))
|
75
|
+
.to eq '1234567891234-0'
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'raises an invalid stream id error' do
|
79
|
+
expect { @redises.xadd(@key, { key: 'value' }, id: 'X') }
|
80
|
+
.to raise_error(
|
81
|
+
Redis::CommandError,
|
82
|
+
'ERR Invalid stream ID specified as stream command argument'
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'caps the stream to 5 elements' do
|
87
|
+
@redises.xadd(@key, { key1: 'value1' }, id: '1234567891234-0')
|
88
|
+
@redises.xadd(@key, { key2: 'value2' }, id: '1234567891245-0')
|
89
|
+
@redises.xadd(@key, { key3: 'value3' }, id: '1234567891245-1')
|
90
|
+
@redises.xadd(@key, { key4: 'value4' }, id: '1234567891278-0')
|
91
|
+
@redises.xadd(@key, { key5: 'value5' }, id: '1234567891278-1')
|
92
|
+
@redises.xadd(@key, { key6: 'value6' }, id: '1234567891299-0')
|
93
|
+
@redises.xadd(@key, { key7: 'value7' }, id: '1234567891300-0', maxlen: 5)
|
94
|
+
expect(@redises.xrange(@key, '-', '+')).to eq(
|
95
|
+
[
|
96
|
+
['1234567891245-1', { 'key3' => 'value3' }],
|
97
|
+
['1234567891278-0', { 'key4' => 'value4' }],
|
98
|
+
['1234567891278-1', { 'key5' => 'value5' }],
|
99
|
+
['1234567891299-0', { 'key6' => 'value6' }],
|
100
|
+
['1234567891300-0', { 'key7' => 'value7' }]
|
101
|
+
]
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'supports a maxlen greater than the current size' do
|
106
|
+
@redises.xadd(@key, { key1: 'value1' }, id: '1234567891234-0')
|
107
|
+
@redises.xadd(@key, { key2: 'value2' }, id: '1234567891245-0', maxlen: 1000)
|
108
|
+
expect(@redises.xrange(@key, '-', '+')).to eq(
|
109
|
+
[
|
110
|
+
['1234567891234-0', { 'key1' => 'value1' }],
|
111
|
+
['1234567891245-0', { 'key2' => 'value2' }],
|
112
|
+
]
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'creates an empty stream with maxlen of 0' do
|
117
|
+
@redises.xadd(@key, { key: 'value' }, maxlen: 0)
|
118
|
+
expect(@redises.xlen(@key)).to eq 0
|
119
|
+
expect(@redises.xrange(@key, '-', '+')).to eq([])
|
120
|
+
expect(@redises.exists?(@key)).to eq true
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#xlen(key)' do
|
4
|
+
before :all do
|
5
|
+
sleep 1 - (Time.now.to_f % 1)
|
6
|
+
@key = 'mock-redis-test:xlen'
|
7
|
+
end
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
# TODO: Redis appears to be returning a timestamp a few seconds in the future
|
11
|
+
# so we're ignoring the last 5 digits (time in milliseconds)
|
12
|
+
@redises._gsub(/\d{5}-\d/, '...-.')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns the number of items in the stream' do
|
16
|
+
expect(@redises.xlen(@key)).to eq 0
|
17
|
+
@redises.xadd(@key, { key: 'value' })
|
18
|
+
expect(@redises.xlen(@key)).to eq 1
|
19
|
+
3.times { @redises.xadd(@key, { key: 'value' }) }
|
20
|
+
expect(@redises.xlen(@key)).to eq 4
|
21
|
+
end
|
22
|
+
end
|