redstruct 0.2.2 → 0.2.3

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