fakeredis 0.8.0 → 0.9.1

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 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