redstruct 0.2.2 → 0.2.3

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: 2af38a102227eedaa6ed3d2f8efd91b02dcae8a0
4
- data.tar.gz: 49041b97b9b1074aaac1986b792ea2ba72b7e3cc
3
+ metadata.gz: ba26d3bd5b2d46e3f499125f7e6ec6166afade9d
4
+ data.tar.gz: 6616843bccefb369e2a9d3b1a4e40c7b8f48b6d4
5
5
  SHA512:
6
- metadata.gz: 9f1b9391762f28ec0686ce2f5b54b756b31e6640d63c51448b26d6d8948564a55916ff78f419edcba8310bdb3b79f91ad680fe5d17ad842e14fdda2528139823
7
- data.tar.gz: 0abdd88f1387ea57ef1546ef35bae91fc783c631287c412705867ebbc148c093f9d5293aa208aec6b5f1fb964f8b0feedb2f3364c9f7338a6fef3f6f26d29fa0
6
+ metadata.gz: f01736c5c824bf2e5e7c3cf5487c8886cfcfefba0c6cfcb258c499427d933ad382292f330931ce5d54ad03fef34262fa3039ce69055fe61cf7bf0b696dcec584
7
+ data.tar.gz: ae8f90b885b9f7ce20fc4b7fb2e7fec7744d9783fb75a22ed398c08ebcba9be959a42f6be6b6afe2adc9f827efd11cbc23de3a37968ea4cc6c569ca7f8ff34d5
@@ -277,7 +277,7 @@ module Redstruct
277
277
  local index = tonumber(ARGV[2])
278
278
  local pivot = redis.call('lindex', KEYS[1], index - 1)
279
279
 
280
- if pivot ~= nil then
280
+ if pivot then
281
281
  return redis.call('linsert', KEYS[1], 'AFTER', pivot, value)
282
282
  end
283
283
 
@@ -11,7 +11,7 @@ module Redstruct
11
11
  # are not used anymore.
12
12
  class Script
13
13
  # Redis returns an error starting with NOSCRIPT when we try to evaluate am unknown script using its sha1.
14
- ERROR_MESSAGE_PREFIX = 'NOSCRIPT'
14
+ ERROR_MESSAGE_PATTERN = /^NOSCRIPT.*$/
15
15
 
16
16
  # @return [String] the Lua script to evaluate
17
17
  attr_reader :script
@@ -80,7 +80,7 @@ module Redstruct
80
80
 
81
81
  @connection.evalsha(self.sha1, keys, argv)
82
82
  rescue Redis::CommandError => err
83
- raise unless err.message.start_with?(ERROR_MESSAGE_PREFIX)
83
+ raise unless ERROR_MESSAGE_PATTERN.match(err.message)
84
84
  @connection.eval(@script, keys, argv)
85
85
  end
86
86
 
@@ -51,13 +51,18 @@ module Redstruct
51
51
 
52
52
  # @return [String] the underlying redis type
53
53
  def type
54
- self.connection.type(@key)
54
+ name = self.connection.type(@key)
55
+ return nil if name == 'none'
56
+ return name
55
57
  end
56
58
 
57
59
  # Returns the time to live of the key
58
- # @return [Float] time to live in seconds as a float where 0.001 == 1 ms
60
+ # @return [Float, nil time nil if the key does not exist or has no expiry, or the time to live in seconds
59
61
  def ttl
60
- return self.connection.pttl(@key) / 1000.0
62
+ value = self.connection.pttl(@key)
63
+
64
+ return nil if [-1, -2].include?(value)
65
+ return value.to_f / 1000
61
66
  end
62
67
 
63
68
  # Returns a serialized representation of the key, which can be used to store a value externally, and restored to
@@ -71,7 +76,7 @@ module Redstruct
71
76
 
72
77
  # Restores the struct to its serialized value as given
73
78
  # @param [String] serialized serialized representation of the value
74
- # @param [#to_f] ttl the time to live for the struct; defaults to 0 (meaning no expiry). 0.001 == 1ms
79
+ # @param [#to_f] ttl the time to live (in seconds) for the struct; defaults to 0 (meaning no expiry)
75
80
  # @raise [Redis::CommandError] raised if the serialized value is incompatible or the key already exists
76
81
  # @return [Boolean] true if restored, false otherwise
77
82
  def restore(serialized, ttl: 0)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Redstruct
4
4
  # Current version
5
- VERSION = '0.2.2'
5
+ VERSION = '0.2.3'
6
6
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'redstruct/utils/atomic_counter'
4
+
5
+ module Redstruct
6
+ # Base class for all Redstruct tests. Configures the gem, provides a default factory, and makes sure to clean it up
7
+ # at the end
8
+ class TestCase < Minitest::Test
9
+ # rubocop: disable Style/ClassVars
10
+ @@counter = Redstruct::Utils::AtomicCounter.new
11
+ @@factory = Redstruct::Factory.new
12
+
13
+ parallelize_me!
14
+ make_my_diffs_pretty!
15
+
16
+ # Use this helper to create a factory that the test class will keep track of and remove at the end
17
+ def create_factory(namespace = nil)
18
+ namespace ||= @@counter.increment.to_s
19
+ return @@factory.factory(namespace)
20
+ end
21
+
22
+ # Helper when trying to ensure a particular redis-rb command was called
23
+ # while still calling it. This allows for testing things outside of our
24
+ # control (e.g. srandmember returning random items)
25
+ # The reason we don't simply just mock the return value is to ensure
26
+ # that tests will break if a command (e.g. srandmember) changes its return
27
+ # value
28
+ def ensure_command_called(object, command, *args, allow: true)
29
+ mock = flexmock(object.connection).should_receive(command).with(object.key, *args)
30
+ mock = mock.pass_thru if allow
31
+
32
+ return mock
33
+ end
34
+ end
35
+ end
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class ConfigurationTest < Redstruct::Test
6
+ class ConfigurationTest < Redstruct::TestCase
7
7
  def test_initialize
8
8
  @config = Redstruct::Configuration.new
9
9
  assert_nil @config.default_connection, 'Should have no default connection initially'
@@ -4,7 +4,7 @@ require 'test_helper'
4
4
 
5
5
  module Redstruct
6
6
  # TODO: not quite sure if this test suite is good enough
7
- class ConnectionProxyTest < Redstruct::Test
7
+ class ConnectionProxyTest < Redstruct::TestCase
8
8
  def test_initialize
9
9
  assert_raises(ArgumentError, 'should fail to initialize without a proxy object') { Redstruct::ConnectionProxy.new }
10
10
  end
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class CounterTest < Redstruct::Test
6
+ class CounterTest < Redstruct::TestCase
7
7
  def setup
8
8
  super
9
9
  @factory = create_factory
@@ -4,7 +4,7 @@ require 'test_helper'
4
4
 
5
5
  module Redstruct
6
6
  class Factory
7
- class ObjectTest < Redstruct::Test
7
+ class ObjectTest < Redstruct::TestCase
8
8
  def test_initialize
9
9
  factory = create_factory
10
10
  object = Redstruct::Factory::Object.new(factory: factory)
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class FactoryTest < Redstruct::Test
6
+ class FactoryTest < Redstruct::TestCase
7
7
  def test_initialize_default
8
8
  flexmock(Redstruct::ConnectionProxy).should_receive(:new).with(Redstruct.config.default_connection).once.pass_thru
9
9
  factory = Redstruct::Factory.new
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class HashTest < Redstruct::Test
6
+ class HashTest < Redstruct::TestCase
7
7
  def setup
8
8
  super
9
9
  @factory = create_factory
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class ListTest < Redstruct::Test
6
+ class ListTest < Redstruct::TestCase
7
7
  def setup
8
8
  super
9
9
  @factory = create_factory
@@ -34,9 +34,6 @@ module Redstruct
34
34
 
35
35
  def test_insert_single
36
36
  initial = SecureRandom.hex(4)
37
- assert_raises(Redis::CommandError, 'should fail (out of bounds)') do
38
- @list.insert(initial, 1)
39
- end
40
37
 
41
38
  assert @list.insert(initial, 0), 'should insert correctly first element'
42
39
  assert_equal initial, @list[0]
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class LockTest < Redstruct::Test
6
+ class LockTest < Redstruct::TestCase
7
7
  def setup
8
8
  super
9
9
  @factory = create_factory
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class ScriptTest < Redstruct::Test
6
+ class ScriptTest < Redstruct::TestCase
7
7
  def setup
8
8
  super
9
9
  @value = @@counter.increment
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class SetTest < Redstruct::Test
6
+ class SetTest < Redstruct::TestCase
7
7
  def setup
8
8
  super
9
9
  @factory = create_factory
@@ -4,7 +4,7 @@ require 'test_helper'
4
4
 
5
5
  module Redstruct
6
6
  class SortedSet
7
- class SliceTest < Redstruct::Test
7
+ class SliceTest < Redstruct::TestCase
8
8
  end
9
9
  end
10
10
  end
@@ -3,7 +3,7 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class SortedTest < Redstruct::Test
6
+ class SortedTest < Redstruct::TestCase
7
7
  def setup
8
8
  super
9
9
  @factory = create_factory
@@ -3,6 +3,6 @@
3
3
  require 'test_helper'
4
4
 
5
5
  module Redstruct
6
- class StringTest < Redstruct::Test
6
+ class StringTest < Redstruct::TestCase
7
7
  end
8
8
  end
@@ -4,7 +4,7 @@ require 'securerandom'
4
4
  require 'test_helper'
5
5
 
6
6
  module Redstruct
7
- class StructTest < Redstruct::Test
7
+ class StructTest < Redstruct::TestCase
8
8
  def setup
9
9
  super
10
10
  @factory = create_factory
@@ -42,11 +42,40 @@ module Redstruct
42
42
  refute @struct.exists?, 'should not exist since it was marked to be expired 1 second after 1970-01-01'
43
43
  end
44
44
 
45
- def test_persist; end
45
+ def test_persist
46
+ refute @struct.persist, 'should not be able to persist non existent keys'
47
+ write_struct
48
+ refute @struct.persist, 'should not be able to persist keys with no expiry'
49
+
50
+ @struct.expire(1)
51
+ assert @struct.ttl.positive?, 'should now have a ttl'
52
+ assert @struct.persist, 'should be able to persist keys with expiry'
53
+ assert_nil @struct.ttl, 'should not have a ttl anymore'
54
+ end
46
55
 
47
- def test_type; end
56
+ def test_type
57
+ assert_nil @struct.type, 'should have no type when it does not exist'
58
+
59
+ # to avoid writing tests for each possible type, we simply ensure we return
60
+ # whatever redis returned
61
+ type = SecureRandom.hex(8)
62
+ write_struct
63
+ ensure_command_called(@struct, :type, allow: false).once.and_return(type)
64
+ assert_equal type, @struct.type, 'should return whatever redis returns'
65
+ end
48
66
 
49
- def test_ttl; end
67
+ def test_ttl
68
+ assert_nil @struct.ttl, 'should have no ttl initially'
69
+
70
+ write_struct
71
+ assert_nil @struct.ttl, 'should still have no ttl even if it exists'
72
+
73
+ @struct.expire(1)
74
+ assert @struct.ttl.positive?, 'should have a ttl > 0'
75
+
76
+ @struct.persist
77
+ assert_nil @struct.ttl, 'should now have no ttl again'
78
+ end
50
79
 
51
80
  def test_dump; end
52
81
 
@@ -4,7 +4,7 @@ require 'test_helper'
4
4
 
5
5
  module Redstruct
6
6
  module Utils
7
- class CoercionTest < Redstruct::Test
7
+ class CoercionTest < Redstruct::TestCase
8
8
  def test_coerce_bool
9
9
  refute Redstruct::Utils::Coercion.coerce_bool(nil), 'nil should be coerced to false'
10
10
  refute Redstruct::Utils::Coercion.coerce_bool(false), 'false should be coerced to false'
@@ -5,7 +5,7 @@ require 'flexmock/minitest'
5
5
 
6
6
  module Redstruct
7
7
  module Utils
8
- class InspectableTest < Redstruct::Test
8
+ class InspectableTest < Redstruct::TestCase
9
9
  def test_inspect
10
10
  child = flexmock('test')
11
11
  child.should_receive(:inspect).and_return('child').once
@@ -4,7 +4,7 @@ require 'test_helper'
4
4
 
5
5
  module Redstruct
6
6
  module Utils
7
- class IterableTest < Redstruct::Test
7
+ class IterableTest < Redstruct::TestCase
8
8
  def test_to_enum_bad_impl
9
9
  assert_raises(NotImplementedError, 'should fail and raise not implemented on missing implementations') do
10
10
  BadIterator.new.to_enum
@@ -6,7 +6,7 @@ require 'test_helper'
6
6
 
7
7
  module Redstruct
8
8
  module Utils
9
- class ScriptableTest < Redstruct::Test
9
+ class ScriptableTest < Redstruct::TestCase
10
10
  def test_defscript
11
11
  script = <<~LUA
12
12
  local sum = 0
@@ -42,8 +42,6 @@ module Redstruct
42
42
  klass = Class.new { include Redstruct::Utils::Scriptable }
43
43
  klass.const_set('SCRIPT_TEST', true)
44
44
 
45
- stdout, = capture_subprocess_io { klass.defscript('test', 'return 0') }
46
- assert_match(/WARN/, stdout, 'should produce a warning if the constant is already defined')
47
45
  refute klass.method_defined?('test')
48
46
  assert_equal true, klass::SCRIPT_TEST, 'should still be the old value'
49
47
  end
@@ -57,8 +55,6 @@ module Redstruct
57
55
  end
58
56
  end
59
57
 
60
- stdout, = capture_subprocess_io { klass.defscript('test', 'return 0') }
61
- assert_match(/WARN/, stdout, 'should produce a warning if the method is already defined')
62
58
  refute klass.const_defined?('SCRIPT_TEST')
63
59
  assert_equal true, klass.new.test, 'should still be the old value'
64
60
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class RedstructTest < Redstruct::Test
5
+ class RedstructTest < Redstruct::TestCase
6
6
  # Test singleton property of the config
7
7
  def test_config
8
8
  config = Redstruct.config
@@ -1,14 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
- require 'securerandom'
5
- require 'bundler/setup'
6
- require 'minitest/autorun'
7
- require 'flexmock/minitest'
8
- require 'redstruct/utils/atomic_counter'
9
-
3
+ # Environment
10
4
  ci_build = ENV['CI_BUILD'].to_i.positive?
5
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
11
6
 
7
+ # Bundler setup
8
+ require 'bundler/setup'
12
9
  bundler_groups = %i[default test]
13
10
  bundler_groups << (ci_build ? :ci : :debug)
14
11
  Bundler.require(*bundler_groups)
@@ -23,7 +20,11 @@ Redstruct.config.default_connection = ConnectionPool.new(size: 5, timeout: 2) do
23
20
  Redis.new(host: ENV.fetch('REDIS_HOST', '127.0.0.1'), port: ENV.fetch('REDIS_PORT', 6379).to_i, db: ENV.fetch('REDIS_DB', 0).to_i)
24
21
  end
25
22
 
26
- # Setup cleanup hook
23
+ # Setup Minitest
24
+ require 'minitest/autorun'
25
+ require 'flexmock/minitest'
26
+ require 'minitest/reporters'
27
+ Minitest::Reporters.use!([Minitest::Reporters::SpecReporter.new])
27
28
  Minitest.after_run do
28
29
  Redstruct.config.default_connection.with do |conn|
29
30
  conn.flushdb
@@ -31,32 +32,6 @@ Minitest.after_run do
31
32
  end
32
33
  end
33
34
 
34
- module Redstruct
35
- # Base class for all Redstruct tests. Configures the gem, provides a default factory, and makes sure to clean it up
36
- # at the end
37
- class Test < Minitest::Test
38
- @@counter = Redstruct::Utils::AtomicCounter.new # rubocop: disable Style/ClassVars
39
-
40
- parallelize_me!
41
- make_my_diffs_pretty!
42
-
43
- # Use this helper to create a factory that the test class will keep track of and remove at the end
44
- def create_factory(namespace = nil)
45
- namespace ||= "#{Redstruct.config.default_namespace}:#{@@counter.increment}"
46
- return Redstruct::Factory.new(namespace: namespace)
47
- end
48
-
49
- # Helper when trying to ensure a particular redis-rb command was called
50
- # while still calling it. This allows for testing things outside of our
51
- # control (e.g. srandmember returning random items)
52
- # The reason we don't simply just mock the return value is to ensure
53
- # that tests will break if a command (e.g. srandmember) changes its return
54
- # value
55
- def ensure_command_called(object, command, *args, allow: true)
56
- mock = flexmock(object.connection).should_receive(command).with(object.key, *args)
57
- mock = mock.pass_thru if allow
58
-
59
- return mock
60
- end
61
- end
62
- end
35
+ # Require everything else
36
+ require 'securerandom'
37
+ require 'helpers/test_case'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redstruct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas Pepin-Perreault
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-01 00:00:00.000000000 Z
11
+ date: 2017-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -120,6 +120,7 @@ files:
120
120
  - lib/redstruct/utils/scriptable.rb
121
121
  - lib/redstruct/version.rb
122
122
  - lib/yard/defscript_handler.rb
123
+ - test/helpers/test_case.rb
123
124
  - test/redstruct/configuration_test.rb
124
125
  - test/redstruct/connection_proxy_test.rb
125
126
  - test/redstruct/counter_test.rb
@@ -165,6 +166,7 @@ signing_key:
165
166
  specification_version: 4
166
167
  summary: Higher level data structures for Redis.
167
168
  test_files:
169
+ - test/helpers/test_case.rb
168
170
  - test/redstruct/configuration_test.rb
169
171
  - test/redstruct/connection_proxy_test.rb
170
172
  - test/redstruct/counter_test.rb