fakeredis 0.8.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c0b77a04c1c761edb3a6544aca213f373d57bb485d17f9e7e0f2c63bfd7e660
4
- data.tar.gz: 57975993a6664bc469ee297a6a36d75ac2e4e429972aee6e50a2f518f93ca580
3
+ metadata.gz: 8f5bfa00feb72f7ffcaa7a1b0c2f316fe6f0e83c1a1e5d68f09f6243aeadca14
4
+ data.tar.gz: 8c31af643286808f7226f138278673d4523d9ef2fdf39a67336519d762ea9385
5
5
  SHA512:
6
- metadata.gz: ba35de9b7e297eca69cb7652d7817f257c447d7533d8c259c47215b15355ec49e5c2584907f0726f97327c443de122bd240cbca6fa194222f114bc99ffd0dbb9
7
- data.tar.gz: 8c4e340be842d1fe966a3a4c6f63987bc8af346da74ced914cdc77488e08a6d15101ee6625097337287ec55c19f41118da4a79892b7fdd00bbebff1d103a813a
6
+ metadata.gz: 5164767bdeed993d36fdaf7410c8a79d933b1e3d3958437e5346b080c5ac1c3f78b0f0a4ba77f9438a84f5480cd9f1629aead81e58c1bb9999a258009a944eff
7
+ data.tar.gz: d337bec1b6a2d54dfa96686cc177ce3c15b660205f8d5c71f7e0b52bee9a40909642604dd70b975755ede946091bc55fec82d644c82df02f2305e0e2d27e630b
@@ -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: [2.7, 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
@@ -3,11 +3,5 @@ source "https://rubygems.org"
3
3
  gem 'rake'
4
4
  gem 'rdoc'
5
5
 
6
- platforms :rbx do
7
- gem 'racc'
8
- gem 'rubysl', '~> 2.0'
9
- gem 'psych'
10
- end
11
-
12
6
  # Specify your gem's dependencies in fakeredis.gemspec
13
7
  gemspec
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2018 Guillermo Iguaran
1
+ Copyright (c) 2011-2023 Guillermo Iguaran
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
- # FakeRedis [![Build Status](https://secure.travis-ci.org/guilleiguaran/fakeredis.png)](http://travis-ci.org/guilleiguaran/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
 
@@ -85,7 +87,7 @@ require 'fakeredis/minitest'
85
87
 
86
88
  ## Acknowledgements
87
89
 
88
- Thanks to [all contributors](https://github.com/guilleiguaran/fakeredis/graphs/contributors), specially to [Caius Durling](https://github.com/caius) the most active one.
90
+ Thanks to [all contributors](https://github.com/guilleiguaran/fakeredis/graphs/contributors).
89
91
 
90
92
  ## Contributing to FakeRedis
91
93
 
@@ -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-2018 Guillermo Iguaran. See LICENSE for
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.1"])
22
- s.add_development_dependency(%q<rspec>, ["~> 3.0"])
21
+ s.add_runtime_dependency(%q<redis>, ["~> 4.8"])
22
+ s.add_development_dependency(%q<rspec>, ["~> 3"])
23
23
  end
@@ -74,7 +74,7 @@ module FakeRedis
74
74
  def georadiusbymember(*args)
75
75
  args = args.dup
76
76
  raise_argument_error("georadiusbymember") if args.size < 4
77
- key, member, radius, unit, *rest = args
77
+ key, member, radius, unit, *_ = args
78
78
  raise_argument_error("georadiusbymember") unless DISTANCE_UNITS.has_key?(unit)
79
79
  radius *= DISTANCE_UNITS[unit]
80
80
 
@@ -1,3 +1,3 @@
1
1
  module FakeRedis
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.1"
3
3
  end
@@ -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(/^\((\d+)/i) ))
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 = {})
@@ -121,7 +122,7 @@ class Redis
121
122
  "OK"
122
123
  end
123
124
 
124
- def auth(password)
125
+ def auth(*args)
125
126
  "OK"
126
127
  end
127
128
 
@@ -168,7 +169,7 @@ class Redis
168
169
  end
169
170
 
170
171
  def dump(key)
171
- return nil unless exists(key)
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
- # We work with either an array, or list of arguments
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(key)
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,21 @@ class Redis
554
561
  data[key].size
555
562
  end
556
563
 
557
- # 0 = false, 1 = true, 2+ untouched
558
- return result == 1 if result < 2
564
+ # 0 = false, 1 = true unless an array was passed in
565
+ if Redis.sadd_returns_boolean && !should_return_int
566
+ return result == 1
567
+ end
568
+
559
569
  result
560
570
  end
561
571
 
572
+ def sadd?(key, value)
573
+ sadd(key, value) == 1
574
+ end
575
+
562
576
  def srem(key, value)
563
577
  data_type_check(key, ::Set)
564
- value = Array(value)
565
- raise_argument_error('srem') if value.empty?
578
+ raise_argument_error('srem') if Array(value).empty?
566
579
  return false unless data[key]
567
580
 
568
581
  if value.is_a?(Array)
@@ -649,6 +662,8 @@ class Redis
649
662
  data_type_check(destination, ::Set)
650
663
  result = sdiff(key1, *keys)
651
664
  data[destination] = ::Set.new(result)
665
+
666
+ result.size
652
667
  end
653
668
 
654
669
  def srandmember(key, number=nil)
@@ -702,7 +717,7 @@ class Redis
702
717
  end
703
718
 
704
719
  def setnx(key, value)
705
- if exists(key)
720
+ if exists(key) > 0
706
721
  0
707
722
  else
708
723
  set(key, value)
@@ -718,7 +733,7 @@ class Redis
718
733
  end
719
734
 
720
735
  def renamenx(key, new_key)
721
- if exists(new_key)
736
+ if exists(new_key) > 0
722
737
  false
723
738
  else
724
739
  rename(key, new_key)
@@ -742,7 +757,7 @@ class Redis
742
757
  if data.expires.include?(key) && (ttl = data.expires[key].to_i - Time.now.to_i) > 0
743
758
  ttl
744
759
  else
745
- exists(key) ? -1 : -2
760
+ exists(key) > 0 ? -1 : -2
746
761
  end
747
762
  end
748
763
 
@@ -750,7 +765,7 @@ class Redis
750
765
  if data.expires.include?(key) && (ttl = data.expires[key].to_f - Time.now.to_f) > 0
751
766
  ttl * 1000
752
767
  else
753
- exists(key) ? -1 : -2
768
+ exists(key) > 0 ? -1 : -2
754
769
  end
755
770
  end
756
771
 
@@ -763,17 +778,32 @@ class Redis
763
778
  !!data.expires.delete(key)
764
779
  end
765
780
 
766
- def hset(key, field, value)
781
+ def hset(key, *fields)
782
+ fields = fields.first if fields.size == 1 && fields.first.is_a?(Hash)
783
+ raise_argument_error('hset') if fields.empty?
784
+
785
+ is_list_of_arrays = fields.all?{|field| field.instance_of?(Array)}
786
+
787
+ raise_argument_error('hmset') if fields.size.odd? and !is_list_of_arrays
788
+ raise_argument_error('hmset') if is_list_of_arrays and !fields.all?{|field| field.length == 2}
789
+
767
790
  data_type_check(key, Hash)
768
- field = field.to_s
769
- if data[key]
770
- result = !data[key].include?(field)
771
- data[key][field] = value.to_s
772
- result ? 1 : 0
791
+ insert_count = 0
792
+ data[key] ||= {}
793
+
794
+ if fields.is_a?(Hash)
795
+ insert_count = fields.keys.size - (data[key].keys & fields.keys).size
796
+
797
+ data[key].merge!(fields)
773
798
  else
774
- data[key] = { field => value.to_s }
775
- 1
799
+ fields.each_slice(2) do |field|
800
+ insert_count += 1 if data[key][field[0].to_s].nil?
801
+
802
+ data[key][field[0].to_s] = field[1].to_s
803
+ end
776
804
  end
805
+
806
+ insert_count
777
807
  end
778
808
 
779
809
  def hsetnx(key, field, value)
@@ -876,12 +906,13 @@ class Redis
876
906
 
877
907
  return nil if option_nx && option_xx
878
908
 
879
- return nil if option_nx && exists(key)
880
- return nil if option_xx && !exists(key)
909
+ return nil if option_nx && exists(key) > 0
910
+ return nil if option_xx && exists(key).zero?
881
911
 
882
912
  data[key] = value.to_s
883
913
 
884
914
  options = Hash[array_options.each_slice(2).to_a]
915
+ raise_command_error('ERR value is not an integer or out of range') if non_integer_expirations?(options)
885
916
  ttl_in_seconds = options["EX"] if options["EX"]
886
917
  ttl_in_seconds = options["PX"] / 1000.0 if options["PX"]
887
918
 
@@ -890,6 +921,11 @@ class Redis
890
921
  "OK"
891
922
  end
892
923
 
924
+ def non_integer_expirations?(options)
925
+ (options["EX"] && !options["EX"].is_a?(Integer)) ||
926
+ (options["PX"] && !options["PX"].is_a?(Integer))
927
+ end
928
+
893
929
  def setbit(key, offset, bit)
894
930
  old_val = data[key] ? data[key].unpack('B*')[0].split("") : []
895
931
  size_increment = [((offset/8)+1)*8-old_val.length, 0].max
@@ -903,13 +939,17 @@ class Redis
903
939
  end
904
940
 
905
941
  def setex(key, seconds, value)
942
+ raise_command_error('ERR value is not an integer or out of range') unless seconds.is_a?(Integer)
906
943
  data[key] = value.to_s
907
944
  expire(key, seconds)
908
945
  "OK"
909
946
  end
910
947
 
911
948
  def psetex(key, milliseconds, value)
912
- setex(key, milliseconds / 1000.0, value)
949
+ raise_command_error('ERR value is not an integer or out of range') unless milliseconds.is_a?(Integer)
950
+ data[key] = value.to_s
951
+ expire(key, milliseconds / 1000.0)
952
+ "OK"
913
953
  end
914
954
 
915
955
  def setrange(key, offset, value)
@@ -1116,12 +1156,12 @@ class Redis
1116
1156
  count.nil? ? results.first : results.flatten
1117
1157
  end
1118
1158
 
1119
- def bzpopmax(*args)
1120
- bzpop(:bzpopmax, args)
1159
+ def bzpopmax(*args, timeout: 0)
1160
+ bzpop(:bzpopmax, args, timeout)
1121
1161
  end
1122
1162
 
1123
- def bzpopmin(*args)
1124
- bzpop(:bzpopmin, args)
1163
+ def bzpopmin(*args, timeout: 0)
1164
+ bzpop(:bzpopmin, args, timeout)
1125
1165
  end
1126
1166
 
1127
1167
  def zcard(key)
@@ -1153,7 +1193,7 @@ class Redis
1153
1193
  data[key][value.to_s] ||= 0
1154
1194
  data[key].increment(value.to_s, num)
1155
1195
 
1156
- if num =~ /^\+?inf/
1196
+ if num.is_a?(String) && num =~ /^\+?inf/
1157
1197
  "inf"
1158
1198
  elsif num == "-inf"
1159
1199
  "-inf"
@@ -1560,15 +1600,7 @@ class Redis
1560
1600
  end
1561
1601
  end
1562
1602
 
1563
- def bzpop(command, args)
1564
- timeout =
1565
- if args.last.is_a?(Hash)
1566
- args.pop[:timeout]
1567
- elsif args.last.respond_to?(:to_int)
1568
- args.pop.to_int
1569
- end
1570
-
1571
- timeout ||= 0
1603
+ def bzpop(command, args, timeout)
1572
1604
  single_pop_command = command.to_s[1..-1]
1573
1605
  keys = args.flatten
1574
1606
  keys.each do |key|
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(false)
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(true)
171
- expect(@client.hset("key1", "k1", "val1")).to eq(false)
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
- it "should error '#{command}'ing no keys" do
34
- expect { @client.public_send(command) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for '#{command}' command")
35
- expect { @client.public_send(command, []) }.to raise_error(Redis::CommandError, "ERR wrong number of arguments for '#{command}' command")
36
- end
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", { :ex => ttl })).to eq("OK")
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", { :px => ttl })).to eq("OK")
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", { :px => ttl_px, :ex => ttl_ex })
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", { :ex => ttl_ex, :px => ttl_px })
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", { :nx => true })).to eq(true)
391
- expect(@client.set("key1", "2", { :nx => true })).to eq(false)
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", { :xx => true })).to eq(false)
395
+ expect(@client.set("key2", "1", xx: true)).to eq(false)
398
396
  @client.set("key2", "2")
399
- expect(@client.set("key2", "1", { :xx => true })).to eq(true)
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", { :nx => true, :xx => true })).to eq(false)
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
@@ -21,7 +21,7 @@ RSpec.describe FakeRedis do
21
21
  cursor = 0
22
22
 
23
23
  loop do
24
- cursor, keys = redis.scan(cursor, match_arguments)
24
+ cursor, keys = redis.scan(cursor, **match_arguments)
25
25
  returned_keys += keys
26
26
  break if cursor == '0'
27
27
  end
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
@@ -7,8 +7,8 @@ module FakeRedis
7
7
  end
8
8
 
9
9
  it "should add a member to a set" do
10
- expect(@client.sadd("key", "value")).to eq(true)
11
- expect(@client.sadd("key", "value")).to eq(false)
10
+ expect(@client.sadd?("key", "value")).to eq(true)
11
+ expect(@client.sadd?("key", "value")).to eq(false)
12
12
 
13
13
  expect(@client.smembers("key")).to eq(["value"])
14
14
  end
@@ -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
@@ -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
@@ -120,14 +120,14 @@ module FakeRedis
120
120
  it "should pop members with the highest score from first sorted set that is non-empty" do
121
121
  @client.zadd("key1", [1, "val1", 2, "val2"])
122
122
  @client.zadd("key2", [3, "val3"])
123
- expect(@client.bzpopmax("nonexistent", "key1", "key2", 0)).to eq(["key1", "val2", 2.0])
123
+ expect(@client.bzpopmax("nonexistent", "key1", "key2", timeout: 0)).to eq(["key1", "val2", 2.0])
124
124
  expect(@client.bzpopmax("nonexistent")).to eq(nil)
125
125
  end
126
126
 
127
127
  it "should pop members with the lowest score from first sorted set that is non-empty" do
128
128
  @client.zadd("key1", [1, "val1", 2, "val2"])
129
129
  @client.zadd("key2", [3, "val3"])
130
- expect(@client.bzpopmin("nonexistent", "key1", "key2", 0)).to eq(["key1", "val1", 1.0])
130
+ expect(@client.bzpopmin("nonexistent", "key1", "key2", timeout: 0)).to eq(["key1", "val1", 1.0])
131
131
  expect(@client.bzpopmin("nonexistent")).to eq(nil)
132
132
  end
133
133
 
@@ -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/spec_helper.rb CHANGED
@@ -11,6 +11,9 @@ RSpec.configure do |config|
11
11
  # Enable memory adapter
12
12
  config.before(:each) { FakeRedis.enable }
13
13
 
14
+ # Set the default behavior for sadd in v5.0
15
+ config.before(:all) { Redis.sadd_returns_boolean = false }
16
+
14
17
  config.backtrace_exclusion_patterns = []
15
18
  end
16
19
 
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
@@ -85,7 +85,7 @@ module FakeRedis
85
85
  it "returns true if the nested hash command succeeds" do
86
86
  responses = @client.multi { |multi| multi.hset('hash', 'key', 'value') }
87
87
 
88
- expect(responses[0]).to eq(true)
88
+ expect(responses[0]).to eq(1)
89
89
  end
90
90
  end
91
91
 
@@ -94,8 +94,8 @@ module FakeRedis
94
94
  @client.sadd('set', 'member1')
95
95
 
96
96
  responses = @client.multi do |multi|
97
- multi.sadd('set', 'member1')
98
- multi.sadd('set', 'member2')
97
+ multi.sadd?('set', 'member1')
98
+ multi.sadd?('set', 'member2')
99
99
  end
100
100
 
101
101
  expect(responses).to eq([false, true])
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.8.0
4
+ version: 0.9.1
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: 2020-03-04 00:00:00.000000000 Z
11
+ date: 2023-04-17 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.1'
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.1'
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.0'
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.0'
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.0.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