moneta 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +176 -0
  3. data/.travis.yml +57 -23
  4. data/CHANGES +12 -0
  5. data/Gemfile +89 -64
  6. data/README.md +40 -14
  7. data/feature_matrix.yaml +1 -0
  8. data/lib/action_dispatch/middleware/session/moneta_store.rb +1 -0
  9. data/lib/active_support/cache/moneta_store.rb +5 -5
  10. data/lib/moneta.rb +9 -1
  11. data/lib/moneta/adapters/activerecord.rb +35 -19
  12. data/lib/moneta/adapters/activesupportcache.rb +3 -7
  13. data/lib/moneta/adapters/cassandra.rb +24 -16
  14. data/lib/moneta/adapters/client.rb +13 -9
  15. data/lib/moneta/adapters/couch.rb +220 -80
  16. data/lib/moneta/adapters/datamapper.rb +1 -0
  17. data/lib/moneta/adapters/file.rb +9 -6
  18. data/lib/moneta/adapters/hbase.rb +1 -1
  19. data/lib/moneta/adapters/kyotocabinet.rb +8 -7
  20. data/lib/moneta/adapters/leveldb.rb +1 -1
  21. data/lib/moneta/adapters/lmdb.rb +3 -4
  22. data/lib/moneta/adapters/lruhash.rb +29 -62
  23. data/lib/moneta/adapters/memcached.rb +1 -0
  24. data/lib/moneta/adapters/memcached/dalli.rb +1 -1
  25. data/lib/moneta/adapters/memcached/native.rb +10 -8
  26. data/lib/moneta/adapters/mongo.rb +1 -0
  27. data/lib/moneta/adapters/mongo/base.rb +3 -3
  28. data/lib/moneta/adapters/mongo/moped.rb +12 -13
  29. data/lib/moneta/adapters/mongo/official.rb +7 -8
  30. data/lib/moneta/adapters/null.rb +1 -2
  31. data/lib/moneta/adapters/pstore.rb +3 -2
  32. data/lib/moneta/adapters/redis.rb +3 -3
  33. data/lib/moneta/adapters/restclient.rb +12 -3
  34. data/lib/moneta/adapters/riak.rb +2 -2
  35. data/lib/moneta/adapters/sequel.rb +112 -119
  36. data/lib/moneta/adapters/sqlite.rb +3 -3
  37. data/lib/moneta/adapters/tokyotyrant.rb +1 -1
  38. data/lib/moneta/builder.rb +0 -1
  39. data/lib/moneta/enumerable.rb +38 -0
  40. data/lib/moneta/expires.rb +12 -12
  41. data/lib/moneta/fallback.rb +84 -0
  42. data/lib/moneta/lock.rb +1 -1
  43. data/lib/moneta/logger.rb +2 -2
  44. data/lib/moneta/mixins.rb +12 -10
  45. data/lib/moneta/optionmerger.rb +0 -1
  46. data/lib/moneta/pool.rb +301 -31
  47. data/lib/moneta/proxy.rb +2 -2
  48. data/lib/moneta/server.rb +9 -12
  49. data/lib/moneta/shared.rb +1 -1
  50. data/lib/moneta/stack.rb +6 -6
  51. data/lib/moneta/synchronize.rb +3 -3
  52. data/lib/moneta/transformer.rb +19 -17
  53. data/lib/moneta/transformer/config.rb +6 -5
  54. data/lib/moneta/transformer/helper.rb +3 -3
  55. data/lib/moneta/transformer/helper/bson.rb +18 -15
  56. data/lib/moneta/utils.rb +3 -9
  57. data/lib/moneta/version.rb +1 -1
  58. data/lib/moneta/weak_each_key.rb +2 -4
  59. data/lib/rack/cache/moneta.rb +16 -13
  60. data/lib/rack/moneta_rest.rb +2 -2
  61. data/lib/rack/session/moneta.rb +3 -4
  62. data/moneta.gemspec +8 -0
  63. data/script/benchmarks +55 -32
  64. data/script/reconfigure-couchdb +13 -0
  65. data/script/start-hbase +1 -0
  66. data/script/start-services +2 -10
  67. data/spec/active_support/cache_moneta_store_spec.rb +3 -1
  68. data/spec/features/concurrent_create.rb +31 -10
  69. data/spec/features/concurrent_increment.rb +27 -19
  70. data/spec/features/increment.rb +41 -41
  71. data/spec/helper.rb +2 -42
  72. data/spec/moneta/adapters/activesupportcache/adapter_activesupportcache_spec.rb +4 -1
  73. data/spec/moneta/adapters/activesupportcache/adapter_activesupportcache_with_default_expires_spec.rb +4 -1
  74. data/spec/moneta/adapters/activesupportcache/standard_activesupportcache_spec.rb +14 -0
  75. data/spec/moneta/adapters/couch/adapter_couch_spec.rb +199 -2
  76. data/spec/moneta/adapters/couch/standard_couch_spec.rb +8 -2
  77. data/spec/moneta/adapters/couch/standard_couch_with_expires_spec.rb +7 -1
  78. data/spec/moneta/adapters/faraday_helper.rb +9 -0
  79. data/spec/moneta/adapters/lruhash/adapter_lruhash_spec.rb +2 -2
  80. data/spec/moneta/adapters/memcached/adapter_memcached_spec.rb +1 -1
  81. data/spec/moneta/adapters/memcached/dalli/adapter_memcached_dalli_spec.rb +1 -1
  82. data/spec/moneta/adapters/memcached/dalli/adapter_memcached_dalli_with_default_expires_spec.rb +1 -1
  83. data/spec/moneta/adapters/memcached/dalli/standard_memcached_dalli_spec.rb +1 -1
  84. data/spec/moneta/adapters/memcached/native/adapter_memcached_native_spec.rb +1 -1
  85. data/spec/moneta/adapters/memcached/native/adapter_memcached_native_with_default_expires_spec.rb +1 -1
  86. data/spec/moneta/adapters/memcached/native/standard_memcached_native_spec.rb +1 -1
  87. data/spec/moneta/adapters/memcached/standard_memcached_spec.rb +1 -1
  88. data/spec/moneta/adapters/{memcached/helper.rb → memcached_helper.rb} +0 -0
  89. data/spec/moneta/adapters/null/null_adapter_spec.rb +1 -1
  90. data/spec/moneta/adapters/restclient/adapter_restclient_spec.rb +7 -5
  91. data/spec/moneta/adapters/restclient/helper.rb +12 -0
  92. data/spec/moneta/adapters/restclient/standard_restclient_spec.rb +9 -6
  93. data/spec/moneta/adapters/riak/standard_riak_with_expires_spec.rb +4 -0
  94. data/spec/moneta/adapters/tokyotyrant/adapter_tokyotyrant_spec.rb +6 -2
  95. data/spec/moneta/adapters/tokyotyrant/helper.rb +12 -0
  96. data/spec/moneta/adapters/tokyotyrant/standard_tokyotyrant_spec.rb +5 -2
  97. data/spec/moneta/adapters/tokyotyrant/standard_tokyotyrant_with_expires_spec.rb +5 -1
  98. data/spec/moneta/proxies/enumerable/enumerable_spec.rb +26 -0
  99. data/spec/moneta/proxies/fallback/fallback_spec.rb +42 -0
  100. data/spec/moneta/proxies/pool/pool_spec.rb +319 -6
  101. data/spec/restserver.rb +40 -0
  102. metadata +122 -7
  103. data/script/install-kyotocabinet +0 -17
@@ -69,11 +69,11 @@ module Rack
69
69
  private
70
70
 
71
71
  def empty(status)
72
- [status, {'Content-Type'=>'application/octet-stream', 'Content-Length' => '0'}, []]
72
+ [status, { 'Content-Type' => 'application/octet-stream', 'Content-Length' => '0' }, []]
73
73
  end
74
74
 
75
75
  def respond(status, value)
76
- [status, {'Content-Type'=>'application/octet-stream', 'Content-Length' => value.bytesize.to_s}, [value]]
76
+ [status, { 'Content-Type' => 'application/octet-stream', 'Content-Length' => value.bytesize.to_s }, [value]]
77
77
  end
78
78
  end
79
79
  end
@@ -1,6 +1,5 @@
1
1
  require 'moneta'
2
2
  require 'rack/session/abstract/id'
3
- require 'thread'
4
3
 
5
4
  module Rack
6
5
  module Session
@@ -44,9 +43,10 @@ module Rack
44
43
  with_lock(env) do
45
44
  unless sid && session = @pool[sid]
46
45
  session = {}
47
- begin
46
+ loop do
48
47
  sid = generate_sid
49
- end until @pool.create(sid, session)
48
+ break if @pool.create(sid, session)
49
+ end
50
50
  end
51
51
  [sid, session]
52
52
  end
@@ -76,4 +76,3 @@ module Rack
76
76
  end
77
77
  end
78
78
  end
79
-
@@ -18,4 +18,12 @@ Gem::Specification.new do |s|
18
18
  s.require_paths = %w(lib)
19
19
  s.summary = %{A unified interface to key/value stores, including Redis, Memcached, TokyoCabinet, ActiveRecord and many more}
20
20
  s.required_ruby_version = '>= 2.2.2'
21
+
22
+ s.add_development_dependency 'rspec', '~> 3.0'
23
+ s.add_development_dependency 'rspec-retry', '~> 0.6.1'
24
+ s.add_development_dependency 'rantly', '~> 1.2.0'
25
+ s.add_development_dependency 'parallel_tests', '~> 2.29.2'
26
+ s.add_development_dependency 'timecop', '~> 0.9.1'
27
+ s.add_development_dependency 'rubocop', '~> 0.67.2'
28
+ s.add_development_dependency 'irb', '~> 1.0.0'
21
29
  end
@@ -7,6 +7,8 @@ require 'fileutils'
7
7
  require 'active_support'
8
8
  require 'active_support/cache/moneta_store'
9
9
 
10
+ require_relative '../spec/restserver.rb'
11
+
10
12
  class String
11
13
  def random(n)
12
14
  (1..n).map { self[rand(size),1] }.join
@@ -104,7 +106,16 @@ class MonetaBenchmarks
104
106
  },
105
107
  {name: "Cassandra"},
106
108
  {name: "Client (Memory)", adapter: :Client},
107
- {name: "Couch"},
109
+ {
110
+ name: "Couch",
111
+ options: {
112
+ backend: if defined?(JRUBY_VERSION)
113
+ require 'faraday/adapter/manticore'
114
+ ::Faraday.new("http://127.0.0.1:5984/moneta") { |f| f.adapter :manticore }
115
+ end
116
+ },
117
+ clear_options: { compact: true, await_compact: true },
118
+ },
108
119
  {
109
120
  name: "DBM",
110
121
  options: {file: "#{DIR}/dbm"}
@@ -152,7 +163,17 @@ class MonetaBenchmarks
152
163
  {name: "MongoOfficial"},
153
164
  {name: "PStore", options: { file: "#{DIR}/pstore" }},
154
165
  {name: "Redis"},
155
- {name: "RestClient", options: { url: 'http://localhost:8808/' }},
166
+ {
167
+ name: "RestClient (Memory)",
168
+ adapter: :RestClient,
169
+ options: {
170
+ url: 'http://127.0.0.1:8808/moneta',
171
+ backend: if defined?(JRUBY_VERSION)
172
+ require 'faraday/adapter/manticore'
173
+ ::Faraday.new("http://127.0.0.1:8808/moneta") { |f| f.adapter :manticore }
174
+ end
175
+ }
176
+ },
156
177
  {name: "Riak"},
157
178
  {
158
179
  name: "Sequel (MySQL)",
@@ -214,7 +235,7 @@ class MonetaBenchmarks
214
235
  },
215
236
  {name: "TDB", options: { file: "#{DIR}/tdb" }},
216
237
  {name: "TokyoCabinet", options: { file: "#{DIR}/tokyocabinet" }},
217
- {name: "TokyoTyrant"},
238
+ {name: "TokyoTyrant", options: {port: 10431}},
218
239
  ].compact
219
240
 
220
241
  CONFIGS = {
@@ -349,43 +370,44 @@ class MonetaBenchmarks
349
370
  end
350
371
 
351
372
  def start_servers
352
- parallel do
353
- begin
354
- Moneta::Server.new(Moneta.new(:Memory)).run
355
- rescue Exception => ex
356
- puts "\e[31mFailed to start Moneta server - #{ex.message}\e[0m"
373
+ @moneta_server_handle =
374
+ parallel do
375
+ begin
376
+ Moneta::Server.new(Moneta.new(:Memory)).run
377
+ rescue => ex
378
+ puts "\e[31mFailed to start Moneta server - #{ex.message}\e[0m"
379
+ end
357
380
  end
358
- end
359
381
 
360
- parallel do
361
- begin
362
- require 'rack'
363
- require 'webrick'
364
- require 'rack/moneta_rest'
382
+ @restserver_handle = start_restserver(8808)
365
383
 
366
- # Keep webrick quiet
367
- ::WEBrick::HTTPServer.class_eval do
368
- def access_log(config, req, res); end
369
- end
370
- ::WEBrick::BasicLog.class_eval do
371
- def log(level, data); end
372
- end
384
+ @tokyotyrant_handle = spawn("ttserver -port 10431 -le -log #{DIR}/tokyotyrant.log #{DIR}/tokyotyrant.tch")
373
385
 
374
- Rack::Server.start(app: Rack::Builder.app do
375
- use Rack::Lint
376
- run Rack::MonetaRest.new(store: :Memory)
377
- end,
378
- environment: :none,
379
- server: :webrick,
380
- Port: 8808)
381
- rescue Exception => ex
382
- puts "\e[31mFailed to start Rack server - #{ex.message}\e[0m"
383
- end
386
+ Signal.trap "INT" do
387
+ stop_servers
388
+ exit
384
389
  end
385
390
 
386
391
  sleep 1 # Wait for servers
387
392
  end
388
393
 
394
+ def stop_servers
395
+ if @restserver_handle
396
+ stop_restserver(@restserver_handle)
397
+ @restserver_handle = nil
398
+ end
399
+
400
+ case @moneta_server_handle
401
+ when Thread
402
+ Thread.kill @moneta_server_handle
403
+ when Integer
404
+ Process.kill "TERM", @moneta_server_handle
405
+ Process.wait @moneta_server_handle
406
+ end
407
+
408
+ Process.kill "TERM", @tokyotyrant_handle
409
+ end
410
+
389
411
  def test_stores
390
412
  @stores.select! do |spec|
391
413
  adapter = spec[:adapter] || spec[:name].to_sym
@@ -480,7 +502,7 @@ class MonetaBenchmarks
480
502
  print "%s [%#{2 * @config[:runs]}s] " % [type, state]
481
503
 
482
504
  @config[:runs].times do |run|
483
- store.clear
505
+ store.clear(spec[:clear_options] || {})
484
506
 
485
507
  @data.shuffle!
486
508
  m1 = Benchmark.measure do
@@ -571,6 +593,7 @@ class MonetaBenchmarks
571
593
  generate_data
572
594
  run_benchmarks
573
595
  print_summary
596
+ stop_servers
574
597
  FileUtils.rm_rf(DIR)
575
598
  end
576
599
  end
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Reconfigure CouchDB to use delayed commits for speed: http://guide.couchdb.org/draft/performance.html
5
+ sudo sed -i '/\[couchdb\]/a delayed_commits = true' /etc/couchdb/local.ini
6
+ sudo systemctl restart couchdb
7
+
8
+ # Display some info about CouchDB
9
+ sudo systemctl status couchdb
10
+ until curl http://localhost:5984/; do
11
+ sleep 1
12
+ done
13
+
@@ -1,4 +1,5 @@
1
1
  #!/bin/sh
2
+ set -e
2
3
 
3
4
  cd $(dirname $(dirname $0))
4
5
 
@@ -1,18 +1,10 @@
1
1
  #!/bin/bash
2
2
 
3
- echo Starting TokyoTyrant ...
4
- /usr/sbin/ttserver -dmn -pid /tmp/ttserver.pid -log /tmp/ttserver.log -port 1978
5
-
6
- # Reconfigure CouchDB to use delayed commits for speed: http://guide.couchdb.org/draft/performance.html
7
- sudo sed -i '/\[couchdb\]/a delayed_commits = true' /etc/couchdb/local.ini
8
- sudo service couchdb restart
3
+ # Restart CouchDB
4
+ $(dirname $0)/reconfigure-couchdb
9
5
 
10
6
  # Start HBase
11
7
  $(dirname $0)/start-hbase
12
8
 
13
9
  # Waiting for servers to start
14
10
  sleep 3
15
-
16
- echo TokyoTyrant status:
17
- ps aux | grep ttserver
18
- cat /tmp/ttserver.log
@@ -2,6 +2,7 @@ require 'moneta'
2
2
  require 'active_support'
3
3
  require 'active_support/cache/moneta_store'
4
4
  require 'ostruct'
5
+ require_relative '../moneta/adapters/memcached_helper.rb'
5
6
 
6
7
  describe "cache_moneta_store" do
7
8
  before(:all) do
@@ -261,7 +262,8 @@ describe "cache_moneta_store" do
261
262
 
262
263
  describe ActiveSupport::Cache::MemCacheStore do
263
264
  let(:store){ described_class.new('127.0.0.1:11213') }
264
- start_memcached 11213
265
+
266
+ include_context :start_memcached, 11213
265
267
 
266
268
  include_examples :basic_store
267
269
  include_examples :expiry
@@ -1,21 +1,42 @@
1
1
  shared_examples :concurrent_create do
2
+ # Each thread attempts to create
2
3
  def create_thread(name)
3
4
  Thread.new do
4
5
  s = new_store
5
- 1000.times do |i|
6
- s[i.to_s].should == name if s.create(i.to_s, name, expires: false)
7
- Thread.pass if rand(100) >= 99
6
+ begin
7
+ (0...1000).map do |i|
8
+ s.create(i.to_s, name, expires: false).tap do
9
+ Thread.pass if rand(100) >= 99
10
+ end
11
+ end
12
+ ensure
13
+ s.close
8
14
  end
9
- s.close
10
15
  end
11
16
  end
12
17
 
13
18
  it 'have atomic create across multiple threads', isolate: true do
14
- a = create_thread('a')
15
- b = create_thread('b')
16
- c = create_thread('c')
17
- a.join
18
- b.join
19
- c.join
19
+ names = %w{a b c}
20
+
21
+ # Spawn threads and then group results (lists of true/false values) by
22
+ # store index (0...1000)
23
+ results = names
24
+ .map { |name| create_thread(name) }
25
+ .map(&:value)
26
+ .transpose.each_with_index
27
+ .map { |created_values, i| [i.to_s, created_values] }
28
+ .to_h
29
+
30
+ # Just a quick sanity check
31
+ expect(results.length).to eq 1000
32
+
33
+ # Ensure that for each index, one and only one created value is true
34
+ expect(results.map { |_, created_values| created_values.inject(:^) }).to all(be true)
35
+
36
+ # Check that the when a call to create returned true, that the store
37
+ # contains the correct value as a result
38
+ expect(store.slice(*results.keys).to_h).to eq(results.map do |i, values|
39
+ [i, names[values.index(true)]]
40
+ end.to_h)
20
41
  end
21
42
  end
@@ -2,31 +2,39 @@ shared_examples :concurrent_increment do
2
2
  def increment_thread(name)
3
3
  Thread.new do
4
4
  s = new_store
5
- 100.times do |i|
6
- 100.times do |j|
7
- s.increment("counter#{j}", 1, expires: false)
8
- Thread.pass if rand(1000) >= 995
5
+ begin
6
+ # Create an array where each entry is a list of all the return values
7
+ # from calling increment for a particular key.
8
+ increments = (0...100).map { [] }
9
+ 100.times do
10
+ 100.times do |j|
11
+ increments[j] << s.increment(j.to_s, 1, expires: false).tap do
12
+ Thread.pass if rand(1000) >= 995
13
+ end
14
+ end
9
15
  end
10
- s.store("#{name}#{i}", i.to_s, expires: false)
16
+ increments
17
+ ensure
18
+ s.close
11
19
  end
12
- s.close
13
20
  end
14
21
  end
15
22
 
16
23
  it 'have atomic increment across multiple threads', isolate: true do
17
- a = increment_thread('a')
18
- b = increment_thread('b')
19
- c = increment_thread('c')
20
- a.join
21
- b.join
22
- c.join
23
- 100.times do |i|
24
- store["a#{i}"].should == i.to_s
25
- store["b#{i}"].should == i.to_s
26
- store["c#{i}"].should == i.to_s
27
- end
28
- 100.times do |j|
29
- store.raw["counter#{j}"].should == 300.to_s
24
+ results = %w{a b c}
25
+ .map { |name| increment_thread(name) }
26
+ .map(&:value)
27
+ .transpose # Now the array is indexed by store key instead of thread
28
+
29
+ # Sanity check
30
+ expect(results.length).to eq 100
31
+
32
+ results.each do |ith_values|
33
+ # ensure that for each pair in the triple there are no overlapping values
34
+ expect(ith_values.combination(2).map { |a, b| a & b }).to all be_empty
35
+
36
+ # ensure that when joined together they cover the full 1..300 range
37
+ expect(ith_values.inject(:+)).to contain_exactly(*1..300)
30
38
  end
31
39
  end
32
40
  end
@@ -1,72 +1,72 @@
1
1
  shared_examples :increment do
2
2
  it 'initializes in #increment with 1' do
3
- store.key?('inckey').should be false
4
- store.increment('inckey').should == 1
5
- store.key?('inckey').should be true
6
- store.raw['inckey'].should == '1'
7
- store.raw.load('inckey').should == '1'
8
- store.load('inckey', raw: true).should == '1'
3
+ expect(store.key?('inckey')).to be false
4
+ expect(store.increment('inckey')).to eq 1
5
+ expect(store.key?('inckey')).to be true
6
+ expect(store.raw['inckey'].to_s).to match(/^1\b/)
7
+ expect(store.raw.load('inckey').to_s).to match(/^1\b/)
8
+ expect(store.load('inckey', raw: true).to_s).to match(/^1\b/)
9
9
 
10
- store.delete('inckey', raw: true).should == '1'
11
- store.key?('inckey').should be false
10
+ expect(store.delete('inckey', raw: true).to_s).to match(/^1\b/)
11
+ expect(store.key?('inckey')).to be false
12
12
  end
13
13
 
14
14
  it 'initializes in #increment with higher value' do
15
- store.increment('inckey', 42).should == 42
16
- store.key?('inckey').should be true
17
- store.raw['inckey'].should == '42'
18
- store.delete('inckey', raw: true).should == '42'
15
+ expect(store.increment('inckey', 42)).to eq 42
16
+ expect(store.key?('inckey')).to be true
17
+ expect(store.raw['inckey'].to_s).to match(/^42\b/)
18
+ expect(store.delete('inckey', raw: true).to_s).to match(/^42\b/)
19
19
  end
20
20
 
21
21
  it 'initializes in #increment with 0' do
22
- store.increment('inckey', 0).should == 0
23
- store.key?('inckey').should be true
24
- store.raw['inckey'].should == '0'
25
- store.delete('inckey', raw: true).should == '0'
22
+ expect(store.increment('inckey', 0)).to eq 0
23
+ expect(store.key?('inckey')).to be true
24
+ expect(store.raw['inckey'].to_s).to match(/^0\b/)
25
+ expect(store.delete('inckey', raw: true).to_s).to match(/^0\b/)
26
26
  end
27
27
 
28
28
  it 'initializes in #decrement with 0' do
29
- store.decrement('inckey', 0).should == 0
30
- store.raw['inckey'].should == '0'
29
+ expect(store.decrement('inckey', 0)).to eq 0
30
+ expect(store.raw['inckey'].to_s).to match(/^0\b/)
31
31
  end
32
32
 
33
33
  it 'initializes in #decrement with negative value' do
34
- store.decrement('inckey', -42).should == 42
35
- store.raw['inckey'].should == '42'
34
+ expect(store.decrement('inckey', -42)).to eq 42
35
+ expect(store.raw['inckey'].to_s).to match(/^42\b/)
36
36
  end
37
37
 
38
38
  it 'supports incrementing existing value by value' do
39
- store.increment('inckey').should == 1
40
- store.increment('inckey', 42).should == 43
41
- store.raw['inckey'].should == '43'
39
+ expect(store.increment('inckey')).to eq 1
40
+ expect(store.increment('inckey', 42)).to eq 43
41
+ expect(store.raw['inckey'].to_s).to match(/^43\b/)
42
42
  end
43
43
 
44
44
  it 'supports decrementing existing value by value' do
45
- store.increment('inckey').should == 1
46
- store.decrement('inckey').should == 0
47
- store.increment('inckey', 42).should == 42
48
- store.decrement('inckey', 2).should == 40
49
- store.raw['inckey'].should == '40'
45
+ expect(store.increment('inckey')).to eq 1
46
+ expect(store.decrement('inckey')).to eq 0
47
+ expect(store.increment('inckey', 42)).to eq 42
48
+ expect(store.decrement('inckey', 2)).to eq 40
49
+ expect(store.raw['inckey'].to_s).to match(/^40\b/)
50
50
  end
51
51
 
52
52
  it 'supports incrementing existing value by 0' do
53
- store.increment('inckey').should == 1
54
- store.increment('inckey', 0).should == 1
55
- store.raw['inckey'].should == '1'
53
+ expect(store.increment('inckey')).to eq 1
54
+ expect(store.increment('inckey', 0)).to eq 1
55
+ expect(store.raw['inckey'].to_s).to match(/^1\b/)
56
56
  end
57
57
 
58
58
  it 'supports decrementing existing value' do
59
- store.increment('inckey', 10).should == 10
60
- store.increment('inckey', -5).should == 5
61
- store.raw['inckey'].should == '5'
62
- store.increment('inckey', -5).should == 0
63
- store.raw['inckey'].should == '0'
59
+ expect(store.increment('inckey', 10)).to eq 10
60
+ expect(store.increment('inckey', -5)).to eq 5
61
+ expect(store.raw['inckey'].to_s).to match(/^5\b/)
62
+ expect(store.increment('inckey', -5)).to eq 0
63
+ expect(store.raw['inckey'].to_s).to match(/^0\b/)
64
64
  end
65
65
 
66
66
  it 'interprets raw value as integer' do
67
67
  store.store('inckey', '42', raw: true)
68
- store.increment('inckey').should == 43
69
- store.raw['inckey'].should == '43'
68
+ expect(store.increment('inckey')).to eq 43
69
+ expect(store.raw['inckey'].to_s).to match(/^43\b/)
70
70
  end
71
71
 
72
72
  it 'raises error in #increment on non integer value' do
@@ -88,10 +88,10 @@ shared_examples :increment do
88
88
  b = Moneta::Semaphore.new(store, 'semaphore', 2)
89
89
  c = Moneta::Semaphore.new(store, 'semaphore', 2)
90
90
  a.synchronize do
91
- a.locked?.should be true
91
+ expect(a.locked?).to be true
92
92
  b.synchronize do
93
- b.locked?.should be true
94
- c.try_lock.should be false
93
+ expect(b.locked?).to be true
94
+ expect(c.try_lock).to be false
95
95
  end
96
96
  end
97
97
  end