redis 4.0.1 → 4.0.2

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
  SHA1:
3
- metadata.gz: 7e0d0ba2328aca583c0f487729779c2b10b12c7b
4
- data.tar.gz: 4a411cfa3512bafe7c2c12ac8a02c02bc87065aa
3
+ metadata.gz: e8fe8cb80ceaefd35f21b3ae06bdfa7594a1878a
4
+ data.tar.gz: ec9c330b13ac9639b6033c96b9e92da659eede4e
5
5
  SHA512:
6
- metadata.gz: 3af7dc63dc7bdc243da306817583db9b6989c21a0714c6652b4a443bfd9c46b2afba0707b028d708a74148bbeedd09d4ec207a0459b3559cb19b95f2f030bb07
7
- data.tar.gz: 98d5aed456ebcd3ccdc50980879a3c14be4c8a1874c6febae95579d2fb3828bda2e82b05e62dc6a4966e178993d4a2a20dc3dedd9f8583cd731851eab2f8e164
6
+ metadata.gz: 215cf01a2c7987aafb818959f1dd70688099b48f51fbc55d0bacc2ebddc27d45f7a60aca57e412a80f94dc6d9316312fa29be1e1077092a92657bd75103cae2a
7
+ data.tar.gz: f26724045477ec4d5d5351611266489c13f778fe2eed7ace4824f37dcadfc378a69271abe22166fc2da16da0ac0b5236448828d36a0c44146a22dfe0d886045e
@@ -1,4 +1,10 @@
1
1
  language: ruby
2
+ cache:
3
+ directories:
4
+ - tmp/cache
5
+ before_install:
6
+ - gem update --system 2.6.14
7
+ - gem --version
2
8
 
3
9
  script: make test
4
10
 
@@ -6,8 +12,8 @@ rvm:
6
12
  - 2.2.2
7
13
  - 2.3.3
8
14
  - 2.4.1
9
- - jruby-9
10
- - rbx-3
15
+ - 2.5.0
16
+ - jruby-9.1.17.0
11
17
 
12
18
  gemfile: ".travis/Gemfile"
13
19
 
@@ -27,7 +33,7 @@ env:
27
33
  - DRIVER=hiredis REDIS_BRANCH=3.2
28
34
  - DRIVER=synchrony REDIS_BRANCH=3.0
29
35
  - DRIVER=synchrony REDIS_BRANCH=3.2
30
- - DRIVER=ruby REDIS_BRANCH=unstable
36
+ - DRIVER=ruby REDIS_BRANCH=4.0
31
37
 
32
38
  branches:
33
39
  only:
@@ -38,34 +44,16 @@ branches:
38
44
  matrix:
39
45
  exclude:
40
46
  # hiredis
41
- - rvm: jruby-9
42
- gemfile: .travis/Gemfile
43
- env: DRIVER=hiredis REDIS_BRANCH=3.0
44
- - rvm: jruby-9
45
- gemfile: .travis/Gemfile
46
- env: DRIVER=hiredis REDIS_BRANCH=3.2
47
- - rvm: jruby-9
48
- gemfile: .travis/Gemfile
49
- env: DRIVER=hiredis REDIS_BRANCH=3.0
50
- - rvm: jruby-9
51
- gemfile: .travis/Gemfile
52
- env: DRIVER=hiredis REDIS_BRANCH=3.2
47
+ - rvm: jruby-9.1.17.0
48
+ env: DRIVER=hiredis REDIS_BRANCH=3.0
49
+ - rvm: jruby-9.1.17.0
50
+ env: DRIVER=hiredis REDIS_BRANCH=3.2
53
51
 
54
52
  # synchrony
55
- - rvm: jruby-9
56
- gemfile: .travis/Gemfile
53
+ - rvm: jruby-9.1.17.0
57
54
  env: DRIVER=synchrony REDIS_BRANCH=3.0
58
- - rvm: jruby-9
59
- gemfile: .travis/Gemfile
55
+ - rvm: jruby-9.1.17.0
60
56
  env: DRIVER=synchrony REDIS_BRANCH=3.2
61
- - rvm: jruby-9
62
- gemfile: .travis/Gemfile
63
- env: DRIVER=synchrony REDIS_BRANCH=3.0
64
- - rvm: jruby-9
65
- gemfile: .travis/Gemfile
66
- env: DRIVER=synchrony REDIS_BRANCH=3.2
67
- allow_failures:
68
- - rvm: rbx-3
69
57
 
70
58
  notifications:
71
59
  irc:
@@ -2,6 +2,11 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec :path => "../"
4
4
 
5
+ # Using jruby-openssl 0.10.0, we get NPEs in jruby tests: https://github.com/redis/redis-rb/issues/756
6
+ platform :jruby do
7
+ gem 'jruby-openssl', '<0.10.0'
8
+ end
9
+
5
10
  case ENV["DRIVER"]
6
11
  when "hiredis"
7
12
  gem "hiredis"
@@ -1,3 +1,17 @@
1
+ # 4.0.2
2
+
3
+ * Added `Redis#unlink`. See #766.
4
+
5
+ * `Redis.new` now accept a custom connector via `:connector`. See #591.
6
+
7
+ * `Redis#multi` no longer perform empty transactions. See #747.
8
+
9
+ * `Redis#hdel` now accepts hash keys as multiple arguments like `#del`. See #755.
10
+
11
+ * Allow to skip SSL verification. See #745.
12
+
13
+ * Add Geo commands: `geoadd`, `geohash`, `georadius`, `georadiusbymember`, `geopos`, `geodist`. See #730.
14
+
1
15
  # 4.0.1
2
16
 
3
17
  * `Redis::Distributed` now supports `mget` and `mapped_mget`. See #687.
@@ -21,6 +35,15 @@
21
35
 
22
36
  * Dropped official support for Ruby < 2.2.2.
23
37
 
38
+ # 3.3.5
39
+
40
+ * Fixed Ruby 1.8 compatibility after backporting `Redis#connection`. See #719.
41
+
42
+ # 3.3.4 (yanked)
43
+
44
+ * `Redis#connection` returns a hash with connection information.
45
+ You shouldn't need to call `Redis#_client`, ever.
46
+
24
47
  # 3.3.3
25
48
 
26
49
  * Improved timeout handling after dropping Timeout module.
data/Gemfile CHANGED
@@ -1,3 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ # Using jruby-openssl 0.10.0, we get NPEs in jruby tests: https://github.com/redis/redis-rb/issues/756
6
+ platform :jruby do
7
+ gem 'jruby-openssl', '<0.10.0'
8
+ end
data/README.md CHANGED
@@ -176,7 +176,7 @@ it can't connect to the server a `Redis::CannotConnectError` error will be raise
176
176
  ```ruby
177
177
  begin
178
178
  redis.ping
179
- rescue Exception => e
179
+ rescue StandardError => e
180
180
  e.inspect
181
181
  # => #<Redis::CannotConnectError: Timed out connecting to Redis on 10.0.1.1:6380>
182
182
 
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ TARBALL = ARGV[0]
4
+
5
+ require 'digest/sha1'
6
+ require 'fileutils'
7
+
8
+ class Builder
9
+ def initialize(redis_branch, tmp_dir)
10
+ @redis_branch = redis_branch
11
+ @tmp_dir = tmp_dir
12
+ @build_dir = File.join(@tmp_dir, "cache", "redis-#{redis_branch}")
13
+ end
14
+
15
+ def run
16
+ download_tarball
17
+ if old_checkum != checksum
18
+ build
19
+ update_checksum
20
+ end
21
+ 0
22
+ end
23
+
24
+ def download_tarball
25
+ command!('wget', tarball_url, '-O', tarball_path)
26
+ end
27
+
28
+ def tarball_path
29
+ File.join(@tmp_dir, "redis-#{@redis_branch}.tar.gz")
30
+ end
31
+
32
+ def tarball_url
33
+ "https://github.com/antirez/redis/archive/#{@redis_branch}.tar.gz"
34
+ end
35
+
36
+ def build
37
+ FileUtils.rm_rf(@build_dir)
38
+ FileUtils.mkdir_p(@build_dir)
39
+ command!('tar', 'xf', tarball_path, '-C', File.expand_path('../', @build_dir))
40
+ Dir.chdir(@build_dir) do
41
+ command!('make')
42
+ end
43
+ end
44
+
45
+ def update_checksum
46
+ File.write(checksum_path, checksum)
47
+ end
48
+
49
+ def old_checkum
50
+ File.read(checksum_path)
51
+ rescue Errno::ENOENT
52
+ nil
53
+ end
54
+
55
+ def checksum_path
56
+ File.join(@build_dir, 'build.checksum')
57
+ end
58
+
59
+ def checksum
60
+ @checksum ||= Digest::SHA1.file(tarball_path).hexdigest
61
+ end
62
+
63
+ def command!(*args)
64
+ puts "$ #{args.join(' ')}"
65
+ unless system(*args)
66
+ raise "Command failed with status #{$?.exitstatus}"
67
+ end
68
+ end
69
+ end
70
+
71
+ exit Builder.new(ARGV[0], ARGV[1]).run
@@ -524,6 +524,16 @@ class Redis
524
524
  end
525
525
  end
526
526
 
527
+ # Unlink one or more keys.
528
+ #
529
+ # @param [String, Array<String>] keys
530
+ # @return [Fixnum] number of keys that were unlinked
531
+ def unlink(*keys)
532
+ synchronize do |client|
533
+ client.call([:unlink] + keys)
534
+ end
535
+ end
536
+
527
537
  # Determine if a key exists.
528
538
  #
529
539
  # @param [String] key
@@ -2102,9 +2112,9 @@ class Redis
2102
2112
  # @param [String] key
2103
2113
  # @param [String, Array<String>] field
2104
2114
  # @return [Fixnum] the number of fields that were removed from the hash
2105
- def hdel(key, field)
2115
+ def hdel(key, *fields)
2106
2116
  synchronize do |client|
2107
- client.call([:hdel, key, field])
2117
+ client.call([:hdel, key, *fields])
2108
2118
  end
2109
2119
  end
2110
2120
 
@@ -2710,6 +2720,86 @@ class Redis
2710
2720
  end
2711
2721
  end
2712
2722
 
2723
+ # Adds the specified geospatial items (latitude, longitude, name) to the specified key
2724
+ #
2725
+ # @param [String] key
2726
+ # @param [Array] member arguemnts for member or members: longitude, latitude, name
2727
+ # @return [Intger] number of elements added to the sorted set
2728
+ def geoadd(key, *member)
2729
+ synchronize do |client|
2730
+ client.call([:geoadd, key, member])
2731
+ end
2732
+ end
2733
+
2734
+ # Returns geohash string representing position for specified members of the specified key.
2735
+ #
2736
+ # @param [String] key
2737
+ # @param [String, Array<String>] member one member or array of members
2738
+ # @return [Array<String, nil>] returns array containg geohash string if member is present, nil otherwise
2739
+ def geohash(key, member)
2740
+ synchronize do |client|
2741
+ client.call([:geohash, key, member])
2742
+ end
2743
+ end
2744
+
2745
+
2746
+ # Query a sorted set representing a geospatial index to fetch members matching a
2747
+ # given maximum distance from a point
2748
+ #
2749
+ # @param [Array] args key, longitude, latitude, radius, unit(m|km|ft|mi)
2750
+ # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest to the nearest relative to the center
2751
+ # @param [Integer] count limit the results to the first N matching items
2752
+ # @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
2753
+ # @return [Array<String>] may be changed with `options`
2754
+
2755
+ def georadius(*args, **geoptions)
2756
+ geoarguments = _geoarguments(*args, **geoptions)
2757
+
2758
+ synchronize do |client|
2759
+ client.call([:georadius, *geoarguments])
2760
+ end
2761
+ end
2762
+
2763
+ # Query a sorted set representing a geospatial index to fetch members matching a
2764
+ # given maximum distance from an already existing member
2765
+ #
2766
+ # @param [Array] args key, member, radius, unit(m|km|ft|mi)
2767
+ # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest to the nearest relative to the center
2768
+ # @param [Integer] count limit the results to the first N matching items
2769
+ # @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
2770
+ # @return [Array<String>] may be changed with `options`
2771
+
2772
+ def georadiusbymember(*args, **geoptions)
2773
+ geoarguments = _geoarguments(*args, **geoptions)
2774
+
2775
+ synchronize do |client|
2776
+ client.call([:georadiusbymember, *geoarguments])
2777
+ end
2778
+ end
2779
+
2780
+ # Returns longitude and latitude of members of a geospatial index
2781
+ #
2782
+ # @param [String] key
2783
+ # @param [String, Array<String>] member one member or array of members
2784
+ # @return [Array<Array<String>, nil>] returns array of elements, where each element is either array of longitude and latitude or nil
2785
+ def geopos(key, member)
2786
+ synchronize do |client|
2787
+ client.call([:geopos, key, member])
2788
+ end
2789
+ end
2790
+
2791
+ # Returns the distance between two members of a geospatial index
2792
+ #
2793
+ # @param [String ]key
2794
+ # @param [Array<String>] members
2795
+ # @param ['m', 'km', 'mi', 'ft'] unit
2796
+ # @return [String, nil] returns distance in spefied unit if both members present, nil otherwise.
2797
+ def geodist(key, member1, member2, unit = 'm')
2798
+ synchronize do |client|
2799
+ client.call([:geodist, key, member1, member2, unit])
2800
+ end
2801
+ end
2802
+
2713
2803
  # Interact with the sentinel command (masters, master, slaves, failover)
2714
2804
  #
2715
2805
  # @param [String] subcommand e.g. `masters`, `master`, `slaves`
@@ -2805,14 +2895,24 @@ private
2805
2895
  }
2806
2896
 
2807
2897
  FloatifyPairs =
2808
- lambda { |array|
2809
- if array
2810
- array.each_slice(2).map do |member, score|
2898
+ lambda { |result|
2899
+ if result.respond_to?(:each_slice)
2900
+ result.each_slice(2).map do |member, score|
2811
2901
  [member, Floatify.call(score)]
2812
2902
  end
2903
+ else
2904
+ result
2813
2905
  end
2814
2906
  }
2815
2907
 
2908
+ def _geoarguments(*args, options: nil, sort: nil, count: nil)
2909
+ args.push sort if sort
2910
+ args.push 'count', count if count
2911
+ args.push options if options
2912
+
2913
+ args.uniq
2914
+ end
2915
+
2816
2916
  def _subscription(method, timeout, channels, block)
2817
2917
  return @client.call([method] + channels) if subscribed?
2818
2918
 
@@ -150,9 +150,12 @@ class Redis
150
150
  end
151
151
 
152
152
  def call_pipeline(pipeline)
153
+ commands = pipeline.commands
154
+ return [] if commands.empty?
155
+
153
156
  with_reconnect pipeline.with_reconnect? do
154
157
  begin
155
- pipeline.finish(call_pipelined(pipeline.commands)).tap do
158
+ pipeline.finish(call_pipelined(commands)).tap do
156
159
  self.db = pipeline.db if pipeline.db
157
160
  end
158
161
  rescue ConnectionError => e
@@ -334,6 +337,7 @@ class Redis
334
337
  @connection = @options[:driver].connect(@options)
335
338
  @pending_reads = 0
336
339
  rescue TimeoutError,
340
+ SocketError,
337
341
  Errno::ECONNREFUSED,
338
342
  Errno::EHOSTDOWN,
339
343
  Errno::EHOSTUNREACH,
@@ -444,6 +448,8 @@ class Redis
444
448
  options[:read_timeout] = Float(options[:read_timeout])
445
449
  options[:write_timeout] = Float(options[:write_timeout])
446
450
 
451
+ options[:reconnect_attempts] = options[:reconnect_attempts].to_i
452
+
447
453
  options[:db] = options[:db].to_i
448
454
  options[:driver] = _parse_driver(options[:driver]) || Connection.drivers.last
449
455
 
@@ -267,7 +267,10 @@ class Redis
267
267
  ssl_sock = new(tcp_sock, ctx)
268
268
  ssl_sock.hostname = host
269
269
  ssl_sock.connect
270
- ssl_sock.post_connection_check(host)
270
+
271
+ unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE
272
+ ssl_sock.post_connection_check(host)
273
+ end
271
274
 
272
275
  ssl_sock
273
276
  end
@@ -294,7 +297,7 @@ class Redis
294
297
  end
295
298
 
296
299
  instance = new(sock)
297
- instance.timeout = config[:timeout]
300
+ instance.timeout = config[:read_timeout]
298
301
  instance.write_timeout = config[:write_timeout]
299
302
  instance.set_tcp_keepalive config[:tcp_keepalive]
300
303
  instance
@@ -161,6 +161,14 @@ class Redis
161
161
  end
162
162
  end
163
163
 
164
+ # Unlink keys.
165
+ def unlink(*args)
166
+ keys_per_node = args.group_by { |key| node_for(key) }
167
+ keys_per_node.inject(0) do |sum, (node, keys)|
168
+ sum + node.unlink(*keys)
169
+ end
170
+ end
171
+
164
172
  # Determine if a key exists.
165
173
  def exists(key)
166
174
  node_for(key).exists(key)
@@ -692,8 +700,8 @@ class Redis
692
700
  end
693
701
 
694
702
  # Delete one or more hash fields.
695
- def hdel(key, field)
696
- node_for(key).hdel(key, field)
703
+ def hdel(key, *fields)
704
+ node_for(key).hdel(key, *fields)
697
705
  end
698
706
 
699
707
  # Determine if a hash field exists.
@@ -22,6 +22,10 @@ class Redis
22
22
  @shutdown
23
23
  end
24
24
 
25
+ def empty?
26
+ @futures.empty?
27
+ end
28
+
25
29
  def call(command, &block)
26
30
  # A pipeline that contains a shutdown should not raise ECONNRESET when
27
31
  # the connection is gone.
@@ -86,7 +90,11 @@ class Redis
86
90
  end
87
91
 
88
92
  def commands
89
- [[:multi]] + super + [[:exec]]
93
+ if empty?
94
+ []
95
+ else
96
+ [[:multi]] + super + [[:exec]]
97
+ end
90
98
  end
91
99
  end
92
100
  end
@@ -1,3 +1,3 @@
1
1
  class Redis
2
- VERSION = "4.0.1"
2
+ VERSION = "4.0.2"
3
3
  end
data/makefile CHANGED
@@ -1,7 +1,7 @@
1
- TEST_FILES := $(shell find test -name *_test.rb -type f)
2
- REDIS_BRANCH := unstable
1
+ TEST_FILES := $(shell find ./test -name *_test.rb -type f)
2
+ REDIS_BRANCH ?= unstable
3
3
  TMP := tmp
4
- BUILD_DIR := ${TMP}/redis-${REDIS_BRANCH}
4
+ BUILD_DIR := ${TMP}/cache/redis-${REDIS_BRANCH}
5
5
  TARBALL := ${TMP}/redis-${REDIS_BRANCH}.tar.gz
6
6
  BINARY := ${BUILD_DIR}/src/redis-server
7
7
  PID_PATH := ${BUILD_DIR}/redis.pid
@@ -11,20 +11,14 @@ PORT := 6381
11
11
  test: ${TEST_FILES}
12
12
  make start
13
13
  env SOCKET_PATH=${SOCKET_PATH} \
14
- ruby -v $$(echo $? | tr ' ' '\n' | awk '{ print "-r./" $$0 }') -e ''
14
+ bundle exec ruby -v -e 'ARGV.each { |test_file| require test_file }' ${TEST_FILES}
15
15
  make stop
16
16
 
17
17
  ${TMP}:
18
18
  mkdir $@
19
19
 
20
- ${TARBALL}: ${TMP}
21
- wget https://github.com/antirez/redis/archive/${REDIS_BRANCH}.tar.gz -O $@
22
-
23
- ${BINARY}: ${TARBALL} ${TMP}
24
- rm -rf ${BUILD_DIR}
25
- mkdir -p ${BUILD_DIR}
26
- tar xf ${TARBALL} -C ${TMP}
27
- cd ${BUILD_DIR} && make
20
+ ${BINARY}: ${TMP}
21
+ bin/build ${REDIS_BRANCH} ${TMP}
28
22
 
29
23
  stop:
30
24
  (test -f ${PID_PATH} && (kill $$(cat ${PID_PATH}) || true) && rm -f ${PID_PATH}) || true
@@ -0,0 +1,116 @@
1
+ require_relative "helper"
2
+
3
+ class TestCommandsGeo < Test::Unit::TestCase
4
+ include Helper::Client
5
+
6
+ def setup
7
+ super
8
+
9
+ target_version "3.2.0" do
10
+ added_items_count = r.geoadd("Sicily", 13.361389, 38.115556, "Palermo", 15.087269, 37.502669, "Catania")
11
+ assert_equal 2, added_items_count
12
+ end
13
+ end
14
+
15
+ def test_georadius_with_sort
16
+ target_version "3.2.0" do
17
+ nearest_cities = r.georadius("Sicily", 15, 37, 200, 'km', sort: 'asc')
18
+ assert_equal %w(Catania Palermo), nearest_cities
19
+
20
+ farthest_cities = r.georadius("Sicily", 15, 37, 200, 'km', sort: 'desc')
21
+ assert_equal %w(Palermo Catania), farthest_cities
22
+ end
23
+ end
24
+
25
+ def test_georadius_with_count
26
+ target_version "3.2.0" do
27
+ city = r.georadius("Sicily", 15, 37, 200, 'km', count: 1)
28
+ assert_equal %w(Catania), city
29
+ end
30
+ end
31
+
32
+ def test_georadius_with_options_count_sort
33
+ target_version "3.2.0" do
34
+ city = r.georadius("Sicily", 15, 37, 200, 'km', sort: :desc, options: :WITHDIST, count: 1)
35
+ assert_equal [["Palermo", "190.4424"]], city
36
+ end
37
+ end
38
+
39
+ def test_georadiusbymember_with_sort
40
+ target_version "3.2.0" do
41
+ nearest_cities = r.georadiusbymember("Sicily", "Catania", 200, 'km', sort: 'asc')
42
+ assert_equal %w(Catania Palermo), nearest_cities
43
+
44
+ farthest_cities = r.georadiusbymember("Sicily", "Catania", 200, 'km', sort: 'desc')
45
+ assert_equal %w(Palermo Catania), farthest_cities
46
+ end
47
+ end
48
+
49
+ def test_georadiusbymember_with_count
50
+ target_version "3.2.0" do
51
+ city = r.georadiusbymember("Sicily", "Catania", 200, 'km', count: 1)
52
+ assert_equal %w(Catania), city
53
+ end
54
+ end
55
+
56
+ def test_georadiusbymember_with_options_count_sort
57
+ target_version "3.2.0" do
58
+ city = r.georadiusbymember("Sicily", "Catania", 200, 'km', sort: :desc, options: :WITHDIST, count: 1)
59
+ assert_equal [["Palermo", "166.2742"]], city
60
+ end
61
+ end
62
+
63
+ def test_geopos
64
+ target_version "3.2.0" do
65
+ location = r.geopos("Sicily", "Catania")
66
+ assert_equal [["15.08726745843887329", "37.50266842333162032"]], location
67
+
68
+ locations = r.geopos("Sicily", ["Palermo", "Catania"])
69
+ assert_equal [["13.36138933897018433", "38.11555639549629859"], ["15.08726745843887329", "37.50266842333162032"]], locations
70
+ end
71
+ end
72
+
73
+ def test_geopos_nonexistant_location
74
+ target_version "3.2.0" do
75
+ location = r.geopos("Sicily", "Rome")
76
+ assert_equal [nil], location
77
+
78
+ locations = r.geopos("Sicily", ["Rome", "Catania"])
79
+ assert_equal [nil, ["15.08726745843887329", "37.50266842333162032"]], locations
80
+ end
81
+ end
82
+
83
+ def test_geodist
84
+ target_version "3.2.0" do
85
+ distination_in_meters = r.geodist("Sicily", "Palermo", "Catania")
86
+ assert_equal "166274.1516", distination_in_meters
87
+
88
+ distination_in_feet = r.geodist("Sicily", "Palermo", "Catania", 'ft')
89
+ assert_equal "545518.8700", distination_in_feet
90
+ end
91
+ end
92
+
93
+ def test_geodist_with_nonexistant_location
94
+ target_version "3.2.0" do
95
+ distination = r.geodist("Sicily", "Palermo", "Rome")
96
+ assert_equal nil, distination
97
+ end
98
+ end
99
+
100
+ def test_geohash
101
+ target_version "3.2.0" do
102
+ geohash = r.geohash("Sicily", "Palermo")
103
+ assert_equal ["sqc8b49rny0"], geohash
104
+
105
+ geohashes = r.geohash("Sicily", ["Palermo", "Catania"])
106
+ assert_equal %w(sqc8b49rny0 sqdtr74hyu0), geohashes
107
+ end
108
+ end
109
+
110
+ def test_geohash_with_nonexistant_location
111
+ target_version "3.2.0" do
112
+ geohashes = r.geohash("Sicily", ["Palermo", "Rome"])
113
+ assert_equal ["sqc8b49rny0", nil], geohashes
114
+ end
115
+ end
116
+ end
@@ -38,6 +38,42 @@ class TestCommandsOnValueTypes < Test::Unit::TestCase
38
38
  assert_equal [], r.keys("*").sort
39
39
  end
40
40
 
41
+ def test_unlink
42
+ target_version "4.0.0" do
43
+ r.set "foo", "s1"
44
+ r.set "bar", "s2"
45
+ r.set "baz", "s3"
46
+
47
+ assert_equal ["bar", "baz", "foo"], r.keys("*").sort
48
+
49
+ assert_equal 1, r.unlink("foo")
50
+
51
+ assert_equal ["bar", "baz"], r.keys("*").sort
52
+
53
+ assert_equal 2, r.unlink("bar", "baz")
54
+
55
+ assert_equal [], r.keys("*").sort
56
+ end
57
+ end
58
+
59
+ def test_unlink_with_array_argument
60
+ target_version "4.0.0" do
61
+ r.set "foo", "s1"
62
+ r.set "bar", "s2"
63
+ r.set "baz", "s3"
64
+
65
+ assert_equal ["bar", "baz", "foo"], r.keys("*").sort
66
+
67
+ assert_equal 1, r.unlink(["foo"])
68
+
69
+ assert_equal ["bar", "baz"], r.keys("*").sort
70
+
71
+ assert_equal 2, r.unlink(["bar", "baz"])
72
+
73
+ assert_equal [], r.keys("*").sort
74
+ end
75
+ end
76
+
41
77
  def test_randomkey
42
78
  assert r.randomkey.to_s.empty?
43
79
 
@@ -38,6 +38,42 @@ class TestDistributedCommandsOnValueTypes < Test::Unit::TestCase
38
38
  assert_equal [], r.keys("*").sort
39
39
  end
40
40
 
41
+ def test_unlink
42
+ target_version "4.0.0" do
43
+ r.set "foo", "s1"
44
+ r.set "bar", "s2"
45
+ r.set "baz", "s3"
46
+
47
+ assert_equal ["bar", "baz", "foo"], r.keys("*").sort
48
+
49
+ assert_equal 1, r.unlink("foo")
50
+
51
+ assert_equal ["bar", "baz"], r.keys("*").sort
52
+
53
+ assert_equal 2, r.unlink("bar", "baz")
54
+
55
+ assert_equal [], r.keys("*").sort
56
+ end
57
+ end
58
+
59
+ def test_unlink_with_array_argument
60
+ target_version "4.0.0" do
61
+ r.set "foo", "s1"
62
+ r.set "bar", "s2"
63
+ r.set "baz", "s3"
64
+
65
+ assert_equal ["bar", "baz", "foo"], r.keys("*").sort
66
+
67
+ assert_equal 1, r.unlink(["foo"])
68
+
69
+ assert_equal ["bar", "baz"], r.keys("*").sort
70
+
71
+ assert_equal 2, r.unlink(["bar", "baz"])
72
+
73
+ assert_equal [], r.keys("*").sort
74
+ end
75
+ end
76
+
41
77
  def test_randomkey
42
78
  assert_raise Redis::Distributed::CannotDistribute do
43
79
  r.randomkey
@@ -334,7 +334,13 @@ class TestInternals < Test::Unit::TestCase
334
334
  begin
335
335
  sa = Socket.pack_sockaddr_in(1024 + Random.rand(63076), hosts[af])
336
336
  s.bind(sa)
337
- rescue Errno::EADDRINUSE
337
+ rescue Errno::EADDRINUSE => e
338
+ # On JRuby (9.1.15.0), if IPv6 is globally disabled on the system,
339
+ # we get an EADDRINUSE with belows message.
340
+ if e.message =~ /Protocol family unavailable/
341
+ return
342
+ end
343
+
338
344
  tries -= 1
339
345
  retry if tries > 0
340
346
 
@@ -30,6 +30,21 @@ module Lint
30
30
  assert_equal nil, r.hget("foo", "f1")
31
31
  end
32
32
 
33
+ def test_splat_hdel
34
+ target_version "2.3.9" do
35
+ r.hset("foo", "f1", "s1")
36
+ r.hset("foo", "f2", "s2")
37
+
38
+ assert_equal "s1", r.hget("foo", "f1")
39
+ assert_equal "s2", r.hget("foo", "f2")
40
+
41
+ assert_equal 2, r.hdel("foo", "f1", "f2")
42
+
43
+ assert_equal nil, r.hget("foo", "f1")
44
+ assert_equal nil, r.hget("foo", "f2")
45
+ end
46
+ end
47
+
33
48
  def test_variadic_hdel
34
49
  target_version "2.3.9" do
35
50
  r.hset("foo", "f1", "s1")
@@ -128,6 +128,14 @@ class TestPipeliningCommands < Test::Unit::TestCase
128
128
  end
129
129
  end
130
130
 
131
+ def test_futures_raise_when_command_errors_and_needs_transformation
132
+ assert_raise(Redis::CommandError) do
133
+ r.pipelined do
134
+ @result = r.zrange("a", "b", 5, :with_scores => true)
135
+ end
136
+ end
137
+ end
138
+
131
139
  def test_futures_can_be_identified
132
140
  r.pipelined do
133
141
  @result = r.sadd("foo", 1)
@@ -42,7 +42,7 @@ module RedisMock
42
42
  end
43
43
  end
44
44
  rescue => ex
45
- $stderr.puts "Error running mock server: #{ex.message}"
45
+ $stderr.puts "Error running mock server: #{ex.class}: #{ex.message}"
46
46
  $stderr.puts ex.backtrace
47
47
  retry
48
48
  ensure
@@ -114,6 +114,16 @@ class TestTransactions < Test::Unit::TestCase
114
114
  assert_equal "s1", r.get("foo")
115
115
  end
116
116
 
117
+ def test_empty_multi_exec
118
+ result = nil
119
+
120
+ redis_mock(:exec => lambda { |*_| "-ERROR" }) do |redis|
121
+ result = redis.multi {}
122
+ end
123
+
124
+ assert_equal [], result
125
+ end
126
+
117
127
  def test_raise_command_errors_when_accessing_futures_after_multi_exec
118
128
  begin
119
129
  r.multi do |m|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ezra Zygmuntowicz
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2017-09-28 00:00:00.000000000 Z
19
+ date: 2018-08-13 00:00:00.000000000 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: test-unit
@@ -65,7 +65,8 @@ description: |2
65
65
  providing an idiomatic interface.
66
66
  email:
67
67
  - redis-db@googlegroups.com
68
- executables: []
68
+ executables:
69
+ - build
69
70
  extensions: []
70
71
  extra_rdoc_files: []
71
72
  files:
@@ -82,6 +83,7 @@ files:
82
83
  - benchmarking/speed.rb
83
84
  - benchmarking/suite.rb
84
85
  - benchmarking/worker.rb
86
+ - bin/build
85
87
  - bors.toml
86
88
  - examples/basic.rb
87
89
  - examples/consistency.rb
@@ -115,6 +117,7 @@ files:
115
117
  - test/blocking_commands_test.rb
116
118
  - test/client_test.rb
117
119
  - test/command_map_test.rb
120
+ - test/commands_on_geo_test.rb
118
121
  - test/commands_on_hashes_test.rb
119
122
  - test/commands_on_hyper_log_log_test.rb
120
123
  - test/commands_on_lists_test.rb
@@ -218,6 +221,7 @@ test_files:
218
221
  - test/blocking_commands_test.rb
219
222
  - test/client_test.rb
220
223
  - test/command_map_test.rb
224
+ - test/commands_on_geo_test.rb
221
225
  - test/commands_on_hashes_test.rb
222
226
  - test/commands_on_hyper_log_log_test.rb
223
227
  - test/commands_on_lists_test.rb