fakeredis 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/codeql.yml +74 -0
- data/.github/workflows/ruby.yml +33 -0
- data/Gemfile +0 -6
- data/LICENSE +1 -1
- data/README.md +4 -3
- data/fakeredis.gemspec +2 -2
- data/lib/fakeredis/version.rb +1 -1
- data/lib/fakeredis/zset.rb +1 -1
- data/lib/redis/connection/memory.rb +60 -26
- data/spec/hashes_spec.rb +35 -5
- data/spec/keys_spec.rb +56 -23
- data/spec/lists_spec.rb +2 -2
- data/spec/memory_spec.rb +1 -1
- data/spec/server_spec.rb +4 -4
- data/spec/sets_spec.rb +21 -1
- data/spec/sorted_sets_spec.rb +17 -17
- data/spec/strings_spec.rb +11 -0
- data/spec/support/shared_examples/bitwise_operation.rb +1 -1
- data/spec/transactions_spec.rb +1 -1
- metadata +12 -11
- data/.travis.yml +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 472bc70d16d42ddd98a542825b81fdd5d8f7af18a8b704f5022046895ca5a867
|
4
|
+
data.tar.gz: 7f0b48ebe4cfa88e99b9d949be3e0bd6816dbc3c0629062d42e0e1fce92a03fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcef2e419257364269044dbd0d8b21d0aacdaeb613d91e83abaef77a18a6c5551e72ded9e90ac334d17760aaf80e4c0fec9fd72f15e3a80efe63c7be5b3f2903
|
7
|
+
data.tar.gz: 6076a543910d3eec4a6fb8912ce1be5b44bea9fa71cbd76fd62f8b0a130eb97d85a4a2390d05ef5bd2a1eae699c487b01de537f9781c8aa39553c198f53c9618
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
2
|
+
# to commit it to your repository.
|
3
|
+
#
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
5
|
+
# or to provide custom queries or build logic.
|
6
|
+
#
|
7
|
+
# ******** NOTE ********
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
10
|
+
# supported CodeQL languages.
|
11
|
+
#
|
12
|
+
name: "CodeQL"
|
13
|
+
|
14
|
+
on:
|
15
|
+
push:
|
16
|
+
branches: [ "master" ]
|
17
|
+
pull_request:
|
18
|
+
# The branches below must be a subset of the branches above
|
19
|
+
branches: [ "master" ]
|
20
|
+
schedule:
|
21
|
+
- cron: '34 3 * * 3'
|
22
|
+
|
23
|
+
jobs:
|
24
|
+
analyze:
|
25
|
+
name: Analyze
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
permissions:
|
28
|
+
actions: read
|
29
|
+
contents: read
|
30
|
+
security-events: write
|
31
|
+
|
32
|
+
strategy:
|
33
|
+
fail-fast: false
|
34
|
+
matrix:
|
35
|
+
language: [ 'ruby' ]
|
36
|
+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
37
|
+
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
38
|
+
|
39
|
+
steps:
|
40
|
+
- name: Checkout repository
|
41
|
+
uses: actions/checkout@v3
|
42
|
+
|
43
|
+
# Initializes the CodeQL tools for scanning.
|
44
|
+
- name: Initialize CodeQL
|
45
|
+
uses: github/codeql-action/init@v2
|
46
|
+
with:
|
47
|
+
languages: ${{ matrix.language }}
|
48
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
49
|
+
# By default, queries listed here will override any specified in a config file.
|
50
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
51
|
+
|
52
|
+
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
53
|
+
# queries: security-extended,security-and-quality
|
54
|
+
|
55
|
+
|
56
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
57
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
58
|
+
- name: Autobuild
|
59
|
+
uses: github/codeql-action/autobuild@v2
|
60
|
+
|
61
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
62
|
+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
63
|
+
|
64
|
+
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
65
|
+
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
66
|
+
|
67
|
+
# - run: |
|
68
|
+
# echo "Run, Build Application using script"
|
69
|
+
# ./location_of_script_within_repo/buildscript.sh
|
70
|
+
|
71
|
+
- name: Perform CodeQL Analysis
|
72
|
+
uses: github/codeql-action/analyze@v2
|
73
|
+
with:
|
74
|
+
category: "/language:${{matrix.language}}"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
|
6
|
+
# GitHub recommends pinning actions to a commit SHA.
|
7
|
+
# To get a newer version, you will need to update the SHA.
|
8
|
+
# You can also reference a tag or branch, but the action may change without warning.
|
9
|
+
|
10
|
+
name: Ruby CI
|
11
|
+
|
12
|
+
on:
|
13
|
+
push:
|
14
|
+
branches: [ master ]
|
15
|
+
pull_request:
|
16
|
+
branches: [ master ]
|
17
|
+
|
18
|
+
jobs:
|
19
|
+
test:
|
20
|
+
runs-on: ${{ matrix.os }}-latest
|
21
|
+
strategy:
|
22
|
+
fail-fast: false
|
23
|
+
matrix:
|
24
|
+
os: [ubuntu, macos]
|
25
|
+
ruby: [3.0, 3.1, 3.2, head, debug, jruby, jruby-head, truffleruby, truffleruby-head]
|
26
|
+
continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
|
27
|
+
steps:
|
28
|
+
- uses: actions/checkout@v3
|
29
|
+
- uses: ruby/setup-ruby@v1
|
30
|
+
with:
|
31
|
+
ruby-version: ${{ matrix.ruby }}
|
32
|
+
- run: bundle install
|
33
|
+
- run: bundle exec rake
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
# FakeRedis
|
1
|
+
# FakeRedis
|
2
|
+
![Build Status](https://github.com/guilleiguaran/fakeredis/actions/workflows/ruby.yml/badge.svg)
|
3
|
+
|
2
4
|
This a fake implementation of redis-rb for machines without Redis or test environments
|
3
5
|
|
4
6
|
|
@@ -100,5 +102,4 @@ Thanks to [all contributors](https://github.com/guilleiguaran/fakeredis/graphs/c
|
|
100
102
|
|
101
103
|
## Copyright
|
102
104
|
|
103
|
-
Copyright (c) 2011-
|
104
|
-
further details.
|
105
|
+
Copyright (c) 2011-2023 Guillermo Iguaran. See LICENSE for further details.
|
data/fakeredis.gemspec
CHANGED
@@ -18,6 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_runtime_dependency(%q<redis>, ["~> 4.
|
22
|
-
s.add_development_dependency(%q<rspec>, ["~> 3
|
21
|
+
s.add_runtime_dependency(%q<redis>, ["~> 4.8"])
|
22
|
+
s.add_development_dependency(%q<rspec>, ["~> 3"])
|
23
23
|
end
|
data/lib/fakeredis/version.rb
CHANGED
data/lib/fakeredis/zset.rb
CHANGED
@@ -26,7 +26,7 @@ module FakeRedis
|
|
26
26
|
def _floatify(str, increment = true)
|
27
27
|
if (( inf = str.to_s.match(/^([+-])?inf/i) ))
|
28
28
|
(inf[1] == "-" ? -1.0 : 1.0) / 0.0
|
29
|
-
elsif (( number = str.to_s.match(/^\((
|
29
|
+
elsif (( number = str.to_s.match(/^\((-?\d+)/i) ))
|
30
30
|
number[1].to_i + (increment ? 1 : -1)
|
31
31
|
else
|
32
32
|
Float str.to_s
|
@@ -86,13 +86,14 @@ class Redis
|
|
86
86
|
attr_writer :replies
|
87
87
|
|
88
88
|
def connected?
|
89
|
-
true
|
89
|
+
defined?(@disconnected) ? false : true
|
90
90
|
end
|
91
91
|
|
92
92
|
def connect_unix(path, timeout)
|
93
93
|
end
|
94
94
|
|
95
95
|
def disconnect
|
96
|
+
@disconnected = true
|
96
97
|
end
|
97
98
|
|
98
99
|
def client(command, _options = {})
|
@@ -168,7 +169,7 @@ class Redis
|
|
168
169
|
end
|
169
170
|
|
170
171
|
def dump(key)
|
171
|
-
return nil
|
172
|
+
return nil if exists(key).zero?
|
172
173
|
|
173
174
|
value = data[key]
|
174
175
|
|
@@ -179,7 +180,7 @@ class Redis
|
|
179
180
|
end
|
180
181
|
|
181
182
|
def restore(key, ttl, serialized_value)
|
182
|
-
raise Redis::CommandError, "ERR Target key name is busy." if exists(key)
|
183
|
+
raise Redis::CommandError, "ERR Target key name is busy." if exists(key) > 0
|
183
184
|
|
184
185
|
raise Redis::CommandError, "ERR DUMP payload version or checksum are wrong" if serialized_value.nil?
|
185
186
|
|
@@ -240,9 +241,9 @@ class Redis
|
|
240
241
|
end
|
241
242
|
|
242
243
|
def mget(*keys)
|
244
|
+
keys = keys[0] if flatten?(keys)
|
243
245
|
raise_argument_error('mget') if keys.empty?
|
244
|
-
|
245
|
-
keys = keys.first if keys.size == 1
|
246
|
+
keys.each { |key| data_type_check(key, String) }
|
246
247
|
data.values_at(*keys)
|
247
248
|
end
|
248
249
|
|
@@ -358,7 +359,11 @@ class Redis
|
|
358
359
|
data.keys.count
|
359
360
|
end
|
360
361
|
|
361
|
-
def exists(
|
362
|
+
def exists(*keys)
|
363
|
+
keys.count { |key| data.key?(key) }
|
364
|
+
end
|
365
|
+
|
366
|
+
def exists?(key)
|
362
367
|
data.key?(key)
|
363
368
|
end
|
364
369
|
|
@@ -542,6 +547,8 @@ class Redis
|
|
542
547
|
|
543
548
|
def sadd(key, value)
|
544
549
|
data_type_check(key, ::Set)
|
550
|
+
should_return_int = value.is_a? Array
|
551
|
+
|
545
552
|
value = Array(value)
|
546
553
|
raise_argument_error('sadd') if value.empty?
|
547
554
|
|
@@ -554,15 +561,15 @@ class Redis
|
|
554
561
|
data[key].size
|
555
562
|
end
|
556
563
|
|
557
|
-
# 0 = false, 1 = true
|
558
|
-
return result == 1
|
564
|
+
# 0 = false, 1 = true unless an array was passed in
|
565
|
+
return result == 1 unless should_return_int
|
566
|
+
|
559
567
|
result
|
560
568
|
end
|
561
569
|
|
562
570
|
def srem(key, value)
|
563
571
|
data_type_check(key, ::Set)
|
564
|
-
|
565
|
-
raise_argument_error('srem') if value.empty?
|
572
|
+
raise_argument_error('srem') if Array(value).empty?
|
566
573
|
return false unless data[key]
|
567
574
|
|
568
575
|
if value.is_a?(Array)
|
@@ -649,6 +656,8 @@ class Redis
|
|
649
656
|
data_type_check(destination, ::Set)
|
650
657
|
result = sdiff(key1, *keys)
|
651
658
|
data[destination] = ::Set.new(result)
|
659
|
+
|
660
|
+
result.size
|
652
661
|
end
|
653
662
|
|
654
663
|
def srandmember(key, number=nil)
|
@@ -702,7 +711,7 @@ class Redis
|
|
702
711
|
end
|
703
712
|
|
704
713
|
def setnx(key, value)
|
705
|
-
if exists(key)
|
714
|
+
if exists(key) > 0
|
706
715
|
0
|
707
716
|
else
|
708
717
|
set(key, value)
|
@@ -718,7 +727,7 @@ class Redis
|
|
718
727
|
end
|
719
728
|
|
720
729
|
def renamenx(key, new_key)
|
721
|
-
if exists(new_key)
|
730
|
+
if exists(new_key) > 0
|
722
731
|
false
|
723
732
|
else
|
724
733
|
rename(key, new_key)
|
@@ -742,7 +751,7 @@ class Redis
|
|
742
751
|
if data.expires.include?(key) && (ttl = data.expires[key].to_i - Time.now.to_i) > 0
|
743
752
|
ttl
|
744
753
|
else
|
745
|
-
exists(key) ? -1 : -2
|
754
|
+
exists(key) > 0 ? -1 : -2
|
746
755
|
end
|
747
756
|
end
|
748
757
|
|
@@ -750,7 +759,7 @@ class Redis
|
|
750
759
|
if data.expires.include?(key) && (ttl = data.expires[key].to_f - Time.now.to_f) > 0
|
751
760
|
ttl * 1000
|
752
761
|
else
|
753
|
-
exists(key) ? -1 : -2
|
762
|
+
exists(key) > 0 ? -1 : -2
|
754
763
|
end
|
755
764
|
end
|
756
765
|
|
@@ -763,17 +772,32 @@ class Redis
|
|
763
772
|
!!data.expires.delete(key)
|
764
773
|
end
|
765
774
|
|
766
|
-
def hset(key,
|
775
|
+
def hset(key, *fields)
|
776
|
+
fields = fields.first if fields.size == 1 && fields.first.is_a?(Hash)
|
777
|
+
raise_argument_error('hset') if fields.empty?
|
778
|
+
|
779
|
+
is_list_of_arrays = fields.all?{|field| field.instance_of?(Array)}
|
780
|
+
|
781
|
+
raise_argument_error('hmset') if fields.size.odd? and !is_list_of_arrays
|
782
|
+
raise_argument_error('hmset') if is_list_of_arrays and !fields.all?{|field| field.length == 2}
|
783
|
+
|
767
784
|
data_type_check(key, Hash)
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
785
|
+
insert_count = 0
|
786
|
+
data[key] ||= {}
|
787
|
+
|
788
|
+
if fields.is_a?(Hash)
|
789
|
+
insert_count = fields.keys.size - (data[key].keys & fields.keys).size
|
790
|
+
|
791
|
+
data[key].merge!(fields)
|
773
792
|
else
|
774
|
-
|
775
|
-
|
793
|
+
fields.each_slice(2) do |field|
|
794
|
+
insert_count += 1 if data[key][field[0].to_s].nil?
|
795
|
+
|
796
|
+
data[key][field[0].to_s] = field[1].to_s
|
797
|
+
end
|
776
798
|
end
|
799
|
+
|
800
|
+
insert_count
|
777
801
|
end
|
778
802
|
|
779
803
|
def hsetnx(key, field, value)
|
@@ -876,12 +900,13 @@ class Redis
|
|
876
900
|
|
877
901
|
return nil if option_nx && option_xx
|
878
902
|
|
879
|
-
return nil if option_nx && exists(key)
|
880
|
-
return nil if option_xx &&
|
903
|
+
return nil if option_nx && exists(key) > 0
|
904
|
+
return nil if option_xx && exists(key).zero?
|
881
905
|
|
882
906
|
data[key] = value.to_s
|
883
907
|
|
884
908
|
options = Hash[array_options.each_slice(2).to_a]
|
909
|
+
raise_command_error('ERR value is not an integer or out of range') if non_integer_expirations?(options)
|
885
910
|
ttl_in_seconds = options["EX"] if options["EX"]
|
886
911
|
ttl_in_seconds = options["PX"] / 1000.0 if options["PX"]
|
887
912
|
|
@@ -890,6 +915,11 @@ class Redis
|
|
890
915
|
"OK"
|
891
916
|
end
|
892
917
|
|
918
|
+
def non_integer_expirations?(options)
|
919
|
+
(options["EX"] && !options["EX"].is_a?(Integer)) ||
|
920
|
+
(options["PX"] && !options["PX"].is_a?(Integer))
|
921
|
+
end
|
922
|
+
|
893
923
|
def setbit(key, offset, bit)
|
894
924
|
old_val = data[key] ? data[key].unpack('B*')[0].split("") : []
|
895
925
|
size_increment = [((offset/8)+1)*8-old_val.length, 0].max
|
@@ -903,13 +933,17 @@ class Redis
|
|
903
933
|
end
|
904
934
|
|
905
935
|
def setex(key, seconds, value)
|
936
|
+
raise_command_error('ERR value is not an integer or out of range') unless seconds.is_a?(Integer)
|
906
937
|
data[key] = value.to_s
|
907
938
|
expire(key, seconds)
|
908
939
|
"OK"
|
909
940
|
end
|
910
941
|
|
911
942
|
def psetex(key, milliseconds, value)
|
912
|
-
|
943
|
+
raise_command_error('ERR value is not an integer or out of range') unless milliseconds.is_a?(Integer)
|
944
|
+
data[key] = value.to_s
|
945
|
+
expire(key, milliseconds / 1000.0)
|
946
|
+
"OK"
|
913
947
|
end
|
914
948
|
|
915
949
|
def setrange(key, offset, value)
|
@@ -1153,7 +1187,7 @@ class Redis
|
|
1153
1187
|
data[key][value.to_s] ||= 0
|
1154
1188
|
data[key].increment(value.to_s, num)
|
1155
1189
|
|
1156
|
-
if num =~ /^\+?inf/
|
1190
|
+
if num.is_a?(String) && num =~ /^\+?inf/
|
1157
1191
|
"inf"
|
1158
1192
|
elsif num == "-inf"
|
1159
1193
|
"-inf"
|
data/spec/hashes_spec.rb
CHANGED
@@ -32,7 +32,7 @@ module FakeRedis
|
|
32
32
|
expect(@client.hdel("key1", "k1")).to be(1)
|
33
33
|
expect(@client.hdel("key1", "k2")).to be(1)
|
34
34
|
|
35
|
-
expect(@client.exists("key1")).to eq(
|
35
|
+
expect(@client.exists("key1")).to eq(0)
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should convert key to a string for hset" do
|
@@ -135,13 +135,13 @@ module FakeRedis
|
|
135
135
|
|
136
136
|
it "should reject an empty list of values" do
|
137
137
|
expect { @client.hmset("key") }.to raise_error(Redis::CommandError)
|
138
|
-
expect(@client.exists("key")).to be false
|
138
|
+
expect(@client.exists?("key")).to be false
|
139
139
|
end
|
140
140
|
|
141
141
|
it "rejects an insert with a key but no value" do
|
142
142
|
expect { @client.hmset("key", 'foo') }.to raise_error(Redis::CommandError)
|
143
143
|
expect { @client.hmset("key", 'foo', 3, 'bar') }.to raise_error(Redis::CommandError)
|
144
|
-
expect(@client.exists("key")).to be false
|
144
|
+
expect(@client.exists?("key")).to be false
|
145
145
|
end
|
146
146
|
|
147
147
|
it "should reject the wrong number of arguments" do
|
@@ -167,12 +167,42 @@ module FakeRedis
|
|
167
167
|
end
|
168
168
|
|
169
169
|
it "should set the string value of a hash field" do
|
170
|
-
expect(@client.hset("key1", "k1", "val1")).to eq(
|
171
|
-
expect(@client.hset("key1", "k1", "val1")).to eq(
|
170
|
+
expect(@client.hset("key1", "k1", "val1")).to eq(1)
|
171
|
+
expect(@client.hset("key1", "k1", "val1")).to eq(0)
|
172
172
|
|
173
173
|
expect(@client.hget("key1", "k1")).to eq("val1")
|
174
174
|
end
|
175
175
|
|
176
|
+
it "should accept a list of key-value pair" do
|
177
|
+
@client.hset("key1", "k1", "val1", "k2", "val2")
|
178
|
+
|
179
|
+
expect(@client.hget("key1", "k1")).to eq("val1")
|
180
|
+
expect(@client.hget("key1", "k2")).to eq("val2")
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should accept a hash of attributes to insert" do
|
184
|
+
@client.hset("key1", {"k1" => "val1", "k2" => "val2"})
|
185
|
+
|
186
|
+
expect(@client.hget("key1", "k1")).to eq("val1")
|
187
|
+
expect(@client.hget("key1", "k2")).to eq("val2")
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should return correct value when inserting a list of key-value pair" do
|
191
|
+
@client.hset("key1", "k1", "val1", "k2", "val2")
|
192
|
+
|
193
|
+
expect(@client.hset("key1", "k1", "val1", "k2", "val2")).to eq(0)
|
194
|
+
expect(@client.hset("key1", "k2", "val2", "k3", "val3")).to eq(1)
|
195
|
+
expect(@client.hset("key1", "k4", "val4", "k5", "val5")).to eq(2)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should return correct value when inserting a hash of attributes" do
|
199
|
+
@client.hset("key1", { "k1" => "val1", "k2" => "val2" })
|
200
|
+
|
201
|
+
expect(@client.hset("key1", { "k1" => "val1", "k2" => "val2" })).to eq(0)
|
202
|
+
expect(@client.hset("key1", { "k2" => "val2", "k3" => "val3" })).to eq(1)
|
203
|
+
expect(@client.hset("key1", { "k4" => "val4", "k5" => "val5" })).to eq(2)
|
204
|
+
end
|
205
|
+
|
176
206
|
it "should set the value of a hash field, only if the field does not exist" do
|
177
207
|
@client.hset("key1", "k1", "val1")
|
178
208
|
expect(@client.hsetnx("key1", "k1", "value")).to eq(false)
|
data/spec/keys_spec.rb
CHANGED
@@ -29,11 +29,16 @@ module FakeRedis
|
|
29
29
|
@client.set("key1", "1")
|
30
30
|
expect(@client.public_send(command, ["key1", "key2"])).to eq(1)
|
31
31
|
end
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
it "should return 0 when deleting no keys" do
|
35
|
+
expect(@client.del).to eq(0)
|
36
|
+
expect(@client.del([])).to eq(0)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should error when unlinking no keys" do
|
40
|
+
expect { @client.unlink }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'unlink' command")
|
41
|
+
expect { @client.unlink([]) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for 'unlink' command")
|
37
42
|
end
|
38
43
|
|
39
44
|
it "should return true when setnx keys that don't exist" do
|
@@ -63,13 +68,6 @@ module FakeRedis
|
|
63
68
|
expect(@client.pexpire("key1", 1)).to eq(false)
|
64
69
|
end
|
65
70
|
|
66
|
-
it "should determine if a key exists" do
|
67
|
-
@client.set("key1", "1")
|
68
|
-
|
69
|
-
expect(@client.exists("key1")).to eq(true)
|
70
|
-
expect(@client.exists("key2")).to eq(false)
|
71
|
-
end
|
72
|
-
|
73
71
|
it "should set a key's time to live in seconds" do
|
74
72
|
@client.set("key1", "1")
|
75
73
|
@client.expire("key1", 1)
|
@@ -134,7 +132,7 @@ module FakeRedis
|
|
134
132
|
@client.set("key1", "1")
|
135
133
|
@client.expireat("key1", Time.now.to_i)
|
136
134
|
|
137
|
-
expect(@client.exists("key1")).to be false
|
135
|
+
expect(@client.exists?("key1")).to be false
|
138
136
|
end
|
139
137
|
|
140
138
|
it "should get integer and string keys" do
|
@@ -362,14 +360,14 @@ module FakeRedis
|
|
362
360
|
it "uses ex option to set the expire time, in seconds" do
|
363
361
|
ttl = 7
|
364
362
|
|
365
|
-
expect(@client.set("key1", "1",
|
363
|
+
expect(@client.set("key1", "1", ex: ttl)).to eq("OK")
|
366
364
|
expect(@client.ttl("key1")).to eq(ttl)
|
367
365
|
end
|
368
366
|
|
369
367
|
it "uses px option to set the expire time, in miliseconds" do
|
370
368
|
ttl = 7000
|
371
369
|
|
372
|
-
expect(@client.set("key1", "1",
|
370
|
+
expect(@client.set("key1", "1", px: ttl)).to eq("OK")
|
373
371
|
expect(@client.ttl("key1")).to eq(ttl / 1000)
|
374
372
|
end
|
375
373
|
|
@@ -379,37 +377,37 @@ module FakeRedis
|
|
379
377
|
ttl_px = 6000
|
380
378
|
ttl_ex = 10
|
381
379
|
|
382
|
-
@client.set("key1", "1",
|
380
|
+
@client.set("key1", "1", px: ttl_px, ex: ttl_ex)
|
383
381
|
expect(@client.ttl("key1")).to eq(ttl_px / 1000)
|
384
382
|
|
385
|
-
@client.set("key1", "1",
|
383
|
+
@client.set("key1", "1", ex: ttl_ex, px: ttl_px)
|
386
384
|
expect(@client.ttl("key1")).to eq(ttl_px / 1000)
|
387
385
|
end
|
388
386
|
|
389
387
|
it "uses nx option to only set the key if it does not already exist" do
|
390
|
-
expect(@client.set("key1", "1",
|
391
|
-
expect(@client.set("key1", "2",
|
388
|
+
expect(@client.set("key1", "1", nx: true)).to eq(true)
|
389
|
+
expect(@client.set("key1", "2", nx: true)).to eq(false)
|
392
390
|
|
393
391
|
expect(@client.get("key1")).to eq("1")
|
394
392
|
end
|
395
393
|
|
396
394
|
it "uses xx option to only set the key if it already exists" do
|
397
|
-
expect(@client.set("key2", "1",
|
395
|
+
expect(@client.set("key2", "1", xx: true)).to eq(false)
|
398
396
|
@client.set("key2", "2")
|
399
|
-
expect(@client.set("key2", "1",
|
397
|
+
expect(@client.set("key2", "1", xx: true)).to eq(true)
|
400
398
|
|
401
399
|
expect(@client.get("key2")).to eq("1")
|
402
400
|
end
|
403
401
|
|
404
402
|
it "does not set the key if both xx and nx option are specified" do
|
405
|
-
expect(@client.set("key2", "1",
|
403
|
+
expect(@client.set("key2", "1", nx: true, xx: true)).to eq(false)
|
406
404
|
expect(@client.get("key2")).to be_nil
|
407
405
|
end
|
408
406
|
end
|
409
407
|
|
410
408
|
describe "#dump" do
|
411
409
|
it "returns nil for unknown key" do
|
412
|
-
expect(@client.exists("key1")).to be false
|
410
|
+
expect(@client.exists?("key1")).to be false
|
413
411
|
expect(@client.dump("key1")).to be nil
|
414
412
|
end
|
415
413
|
|
@@ -445,7 +443,7 @@ module FakeRedis
|
|
445
443
|
@dumped_value = @client.dump("key1")
|
446
444
|
|
447
445
|
@client.del("key1")
|
448
|
-
expect(@client.exists("key1")).to be false
|
446
|
+
expect(@client.exists?("key1")).to be false
|
449
447
|
end
|
450
448
|
|
451
449
|
it "restores to a new key successfully" do
|
@@ -504,10 +502,45 @@ module FakeRedis
|
|
504
502
|
expect(@client.pttl("key")).to be_within(0.1).of(2200)
|
505
503
|
end
|
506
504
|
|
505
|
+
it "should raise an error if a non-integer is provided as the expiration" do
|
506
|
+
expect { @client.psetex("key", 100.5, "value") }.to raise_error(Redis::CommandError)
|
507
|
+
end
|
508
|
+
|
507
509
|
it "should return 'OK'" do
|
508
510
|
expect(@client.psetex("key", 1000, "value")).to eq("OK")
|
509
511
|
end
|
510
512
|
end
|
513
|
+
|
514
|
+
describe "#exists" do
|
515
|
+
it "returns 0 if none of the keys exist" do
|
516
|
+
expect(@client.exists("key1", "key2")).to eq 0
|
517
|
+
end
|
518
|
+
|
519
|
+
it "returns number of the keys that exist" do
|
520
|
+
@client.set("key2", "val2")
|
521
|
+
@client.set("key3", "val3")
|
522
|
+
expect(@client.exists("key1", "key2", "key3")).to eq 2
|
523
|
+
end
|
524
|
+
|
525
|
+
it "keys mentioned and existing multiple times counted multiple times" do
|
526
|
+
@client.set("key2", "val")
|
527
|
+
expect(@client.exists("key2", "key2")).to eq 2
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
describe "#exists?" do
|
532
|
+
it "should return true if any of the key exists" do
|
533
|
+
@client.set("key1", "1")
|
534
|
+
|
535
|
+
expect(@client.exists?("key1")).to eq(true)
|
536
|
+
expect(@client.exists?("key1", "key2")).to eq(true)
|
537
|
+
end
|
538
|
+
|
539
|
+
it "should return false if none of the key exists" do
|
540
|
+
expect(@client.exists?("key2")).to eq(false)
|
541
|
+
expect(@client.exists?("key2", "key3")).to eq(false)
|
542
|
+
end
|
543
|
+
end
|
511
544
|
end
|
512
545
|
end
|
513
546
|
|
data/spec/lists_spec.rb
CHANGED
@@ -119,7 +119,7 @@ module FakeRedis
|
|
119
119
|
end
|
120
120
|
|
121
121
|
it "should return 0 if key does not map to a list" do
|
122
|
-
expect(@client.exists("nonexistant")).to eq(false)
|
122
|
+
expect(@client.exists?("nonexistant")).to eq(false)
|
123
123
|
expect(@client.lrem("nonexistant", 0, "value")).to eq(0)
|
124
124
|
end
|
125
125
|
|
@@ -129,7 +129,7 @@ module FakeRedis
|
|
129
129
|
@client.lrem("key1", 1, "v1")
|
130
130
|
@client.lrem("key1", 1, "v2")
|
131
131
|
|
132
|
-
expect(@client.exists("key1")).to eq(false)
|
132
|
+
expect(@client.exists?("key1")).to eq(false)
|
133
133
|
end
|
134
134
|
|
135
135
|
it "should set the value of an element in a list by its index" do
|
data/spec/memory_spec.rb
CHANGED
data/spec/server_spec.rb
CHANGED
@@ -45,13 +45,13 @@ module FakeRedis
|
|
45
45
|
|
46
46
|
@client.select(0)
|
47
47
|
expect(@client.dbsize).to eq(2)
|
48
|
-
expect(@client.exists("key1")).to be true
|
49
|
-
expect(@client.exists("key3")).to be false
|
48
|
+
expect(@client.exists?("key1")).to be true
|
49
|
+
expect(@client.exists?("key3")).to be false
|
50
50
|
|
51
51
|
@client.select(1)
|
52
52
|
expect(@client.dbsize).to eq(3)
|
53
|
-
expect(@client.exists("key4")).to be true
|
54
|
-
expect(@client.exists("key2")).to be false
|
53
|
+
expect(@client.exists?("key4")).to be true
|
54
|
+
expect(@client.exists?("key2")).to be false
|
55
55
|
|
56
56
|
@client.flushall
|
57
57
|
expect(@client.dbsize).to eq(0)
|
data/spec/sets_spec.rb
CHANGED
@@ -30,6 +30,13 @@ module FakeRedis
|
|
30
30
|
expect(@client.smembers("key")).to match_array(["value", "other", "something", "more", "and", "additional", "values"])
|
31
31
|
end
|
32
32
|
|
33
|
+
it "should return the number added to a set when an array is passed in" do
|
34
|
+
expect(@client.sadd("key", %w(value other something more))).to eq(4)
|
35
|
+
expect(@client.sadd("key", %w(more value additional))).to eq(1)
|
36
|
+
expect(@client.sadd("key", %w(additional))).to eq(0)
|
37
|
+
expect(@client.smembers("key")).to match_array(["value", "other", "something", "more", "additional"])
|
38
|
+
end
|
39
|
+
|
33
40
|
it "should get the number of members in a set" do
|
34
41
|
@client.sadd("key", "val1")
|
35
42
|
@client.sadd("key", "val2")
|
@@ -75,6 +82,19 @@ module FakeRedis
|
|
75
82
|
expect(@client.smembers("new_key")).to match_array(["b", "d"])
|
76
83
|
end
|
77
84
|
|
85
|
+
it "should return integer on sdiffstore" do
|
86
|
+
@client.sadd("key1", "a")
|
87
|
+
@client.sadd("key1", "b")
|
88
|
+
@client.sadd("key1", "c")
|
89
|
+
@client.sadd("key1", "d")
|
90
|
+
@client.sadd("key2", "c")
|
91
|
+
@client.sadd("key3", "a")
|
92
|
+
@client.sadd("key3", "c")
|
93
|
+
@client.sadd("key3", "e")
|
94
|
+
|
95
|
+
expect(@client.sdiffstore("key", "key1", "key2", "key3")).to eq(2)
|
96
|
+
end
|
97
|
+
|
78
98
|
it "should intersect multiple sets" do
|
79
99
|
@client.sadd("key1", "a")
|
80
100
|
@client.sadd("key1", "b")
|
@@ -188,7 +208,7 @@ module FakeRedis
|
|
188
208
|
@client.srem("key1", "b")
|
189
209
|
@client.srem("key1", "a")
|
190
210
|
|
191
|
-
expect(@client.exists("key1")).to eq(false)
|
211
|
+
expect(@client.exists?("key1")).to eq(false)
|
192
212
|
end
|
193
213
|
|
194
214
|
it "should add multiple sets" do
|
data/spec/sorted_sets_spec.rb
CHANGED
@@ -100,7 +100,7 @@ module FakeRedis
|
|
100
100
|
it "should remove sorted set's key when it is empty" do
|
101
101
|
@client.zadd("key", 1, "val")
|
102
102
|
@client.zrem("key", "val")
|
103
|
-
expect(@client.exists("key")).to eq(false)
|
103
|
+
expect(@client.exists?("key")).to eq(false)
|
104
104
|
end
|
105
105
|
|
106
106
|
it "should pop members with the highest scores from sorted set" do
|
@@ -685,13 +685,13 @@ module FakeRedis
|
|
685
685
|
context "with {nx: true, incr: true}" do
|
686
686
|
let(:options) { {nx: true, incr: true} }
|
687
687
|
it "should increment to the provided score only if the element is new and return the element's score" do
|
688
|
-
expect(@client.zadd("key", 1, "first", options)).to eq(1.0)
|
688
|
+
expect(@client.zadd("key", 1, "first", **options)).to eq(1.0)
|
689
689
|
expect(@client.zscore("key", "first")).to eq(1.0)
|
690
690
|
|
691
|
-
expect(@client.zadd("key", 2, "second", options)).to eq(2.0)
|
691
|
+
expect(@client.zadd("key", 2, "second", **options)).to eq(2.0)
|
692
692
|
expect(@client.zscore("key", "second")).to eq(2.0)
|
693
693
|
|
694
|
-
expect(@client.zadd("key", 99, "first", options)).to be_nil
|
694
|
+
expect(@client.zadd("key", 99, "first", **options)).to be_nil
|
695
695
|
expect(@client.zscore("key", "first")).to eq(1.0)
|
696
696
|
end
|
697
697
|
end
|
@@ -699,11 +699,11 @@ module FakeRedis
|
|
699
699
|
context "with {nx: true, ch: true}" do
|
700
700
|
let(:options) { {nx: true, ch: true} }
|
701
701
|
it "should add only new elements, not update existing elements, and return the number of added elements" do
|
702
|
-
expect(@client.zadd("key", 1, "first", options)).to eq(true)
|
703
|
-
expect(@client.zadd("key", 1, "first", options)).to eq(false)
|
702
|
+
expect(@client.zadd("key", 1, "first", **options)).to eq(true)
|
703
|
+
expect(@client.zadd("key", 1, "first", **options)).to eq(false)
|
704
704
|
|
705
705
|
# add two new elements
|
706
|
-
expect(@client.zadd("key", [99, "first", 2, "second", 3, "third"], options)).to eq(2)
|
706
|
+
expect(@client.zadd("key", [99, "first", 2, "second", 3, "third"], **options)).to eq(2)
|
707
707
|
expect(@client.zscore("key", "first")).to eq(1.0)
|
708
708
|
end
|
709
709
|
end
|
@@ -712,19 +712,19 @@ module FakeRedis
|
|
712
712
|
let(:options) { {nx: true, incr: true, ch: true} }
|
713
713
|
|
714
714
|
it "should add only new elements" do
|
715
|
-
expect(@client.zadd("key", 1, "first", options)).to eq(1.0)
|
716
|
-
expect(@client.zadd("key", 99, "first", options)).to be_nil
|
715
|
+
expect(@client.zadd("key", 1, "first", **options)).to eq(1.0)
|
716
|
+
expect(@client.zadd("key", 99, "first", **options)).to be_nil
|
717
717
|
expect(@client.zscore("key", "first")).to eq(1.0)
|
718
718
|
end
|
719
719
|
|
720
720
|
# when INCR is present, return value is always the new score of member
|
721
721
|
it "should return the score of the new member" do
|
722
|
-
expect(@client.zadd("key", 2, "second", options)).to eq(2.0)
|
722
|
+
expect(@client.zadd("key", 2, "second", **options)).to eq(2.0)
|
723
723
|
end
|
724
724
|
|
725
725
|
it "should return nil when the member already exists" do
|
726
726
|
@client.zadd("key", 1, "first")
|
727
|
-
expect(@client.zadd("key", 99, "first", options)).to be_nil
|
727
|
+
expect(@client.zadd("key", 99, "first", **options)).to be_nil
|
728
728
|
end
|
729
729
|
end
|
730
730
|
|
@@ -733,12 +733,12 @@ module FakeRedis
|
|
733
733
|
before { @client.zadd("key", 1, "existing") }
|
734
734
|
|
735
735
|
it "should return nil if the member does not already exist" do
|
736
|
-
expect(@client.zadd("key", 1, "new1", options)).to be_nil
|
736
|
+
expect(@client.zadd("key", 1, "new1", **options)).to be_nil
|
737
737
|
expect(@client.zscore("key", "new1")).to be_nil
|
738
738
|
end
|
739
739
|
|
740
740
|
it "should increment only existing elements" do
|
741
|
-
expect(@client.zadd("key", [11, "existing"], options)).to eq(12.0)
|
741
|
+
expect(@client.zadd("key", [11, "existing"], **options)).to eq(12.0)
|
742
742
|
expect(@client.zscore("key", "existing")).to eq(12.0)
|
743
743
|
end
|
744
744
|
end
|
@@ -748,8 +748,8 @@ module FakeRedis
|
|
748
748
|
it "should return the number of updated elements and not add new members" do
|
749
749
|
@client.zadd("key", 1, "first")
|
750
750
|
|
751
|
-
expect(@client.zadd("key", 99, "first", options)).to eq(true)
|
752
|
-
expect(@client.zadd("key", [100, "first", 2, "second"], options)).to eq(1.0)
|
751
|
+
expect(@client.zadd("key", 99, "first", **options)).to eq(true)
|
752
|
+
expect(@client.zadd("key", [100, "first", 2, "second"], **options)).to eq(1.0)
|
753
753
|
expect(@client.zscore("key", "second")).to be_nil
|
754
754
|
end
|
755
755
|
end
|
@@ -760,11 +760,11 @@ module FakeRedis
|
|
760
760
|
|
761
761
|
# when INCR is present, return value is always the new score of member
|
762
762
|
it "should return the new score of the inserted member" do
|
763
|
-
expect(@client.zadd("key", 2, "existing", options)).to eq(3.0)
|
763
|
+
expect(@client.zadd("key", 2, "existing", **options)).to eq(3.0)
|
764
764
|
end
|
765
765
|
|
766
766
|
it "should increment only existing elements" do
|
767
|
-
expect(@client.zadd("key", 1, "new", options)).to be_nil
|
767
|
+
expect(@client.zadd("key", 1, "new", **options)).to be_nil
|
768
768
|
end
|
769
769
|
end
|
770
770
|
end
|
data/spec/strings_spec.rb
CHANGED
@@ -183,6 +183,12 @@ module FakeRedis
|
|
183
183
|
expect { @client.mget }.to raise_error(Redis::CommandError)
|
184
184
|
end
|
185
185
|
|
186
|
+
it 'raises an argument error when the data is a hash' do
|
187
|
+
@client.hincrby("key1", "cont1", 5)
|
188
|
+
|
189
|
+
expect { @client.mget("key1") }.to raise_error(Redis::CommandError)
|
190
|
+
end
|
191
|
+
|
186
192
|
it "should set multiple keys to multiple values" do
|
187
193
|
@client.mset(:key1, "value1", :key2, "value2")
|
188
194
|
|
@@ -242,6 +248,11 @@ module FakeRedis
|
|
242
248
|
expect(@client.ttl("key1")).to eq(30)
|
243
249
|
end
|
244
250
|
|
251
|
+
it "should raise an error if a non-integer is provided as the expiration" do
|
252
|
+
expect { @client.setex("key1", 1.5, "value1") }.to raise_error(Redis::CommandError)
|
253
|
+
expect { @client.set("key1", "value1", ex: 1.5) }.to raise_error(Redis::CommandError)
|
254
|
+
end
|
255
|
+
|
245
256
|
it "should set the value of a key, only if the key does not exist" do
|
246
257
|
expect(@client.setnx("key1", "test value")).to eq(true)
|
247
258
|
expect(@client.setnx("key1", "new value")).to eq(false)
|
@@ -5,7 +5,7 @@ shared_examples_for "a bitwise operation" do |operator|
|
|
5
5
|
|
6
6
|
it "should not create destination key if nothing found" do
|
7
7
|
expect(@client.bitop(operator, "dest1", "nothing_here1")).to eq(0)
|
8
|
-
expect(@client.exists("dest1")).to eq(false)
|
8
|
+
expect(@client.exists?("dest1")).to eq(false)
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should accept operator as a case-insensitive symbol" do
|
data/spec/transactions_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fakeredis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillermo Iguaran
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '4.
|
19
|
+
version: '4.8'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '4.
|
26
|
+
version: '4.8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '3
|
33
|
+
version: '3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '3
|
40
|
+
version: '3'
|
41
41
|
description: Fake (In-memory) driver for redis-rb. Useful for testing environment
|
42
42
|
and machines without Redis.
|
43
43
|
email:
|
@@ -46,8 +46,9 @@ executables: []
|
|
46
46
|
extensions: []
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
|
+
- ".github/workflows/codeql.yml"
|
50
|
+
- ".github/workflows/ruby.yml"
|
49
51
|
- ".gitignore"
|
50
|
-
- ".travis.yml"
|
51
52
|
- Gemfile
|
52
53
|
- LICENSE
|
53
54
|
- README.md
|
@@ -96,7 +97,7 @@ homepage: https://guilleiguaran.github.com/fakeredis
|
|
96
97
|
licenses:
|
97
98
|
- MIT
|
98
99
|
metadata: {}
|
99
|
-
post_install_message:
|
100
|
+
post_install_message:
|
100
101
|
rdoc_options: []
|
101
102
|
require_paths:
|
102
103
|
- lib
|
@@ -111,8 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
112
|
- !ruby/object:Gem::Version
|
112
113
|
version: '0'
|
113
114
|
requirements: []
|
114
|
-
rubygems_version: 3.
|
115
|
-
signing_key:
|
115
|
+
rubygems_version: 3.4.1
|
116
|
+
signing_key:
|
116
117
|
specification_version: 4
|
117
118
|
summary: Fake (In-memory) driver for redis-rb.
|
118
119
|
test_files:
|
data/.travis.yml
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
cache: bundler
|
3
|
-
# Use the faster container based infrastructure
|
4
|
-
# http://blog.travis-ci.com/2014-12-17-faster-builds-with-container-based-infrastructure/
|
5
|
-
sudo: false
|
6
|
-
|
7
|
-
rvm:
|
8
|
-
- 2.4
|
9
|
-
- 2.5
|
10
|
-
- 2.6
|
11
|
-
- ruby-head
|
12
|
-
- jruby
|
13
|
-
- rbx-2
|
14
|
-
|
15
|
-
matrix:
|
16
|
-
allow_failures:
|
17
|
-
- rvm: rbx-2
|