moneta 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/CHANGES +21 -10
- data/README.md +1 -1
- data/SPEC.md +4 -12
- data/lib/moneta.rb +7 -5
- data/lib/moneta/adapters/activerecord.rb +9 -3
- data/lib/moneta/adapters/cassandra.rb +9 -4
- data/lib/moneta/adapters/client.rb +9 -3
- data/lib/moneta/adapters/cookie.rb +3 -0
- data/lib/moneta/adapters/couch.rb +8 -3
- data/lib/moneta/adapters/datamapper.rb +8 -3
- data/lib/moneta/adapters/dbm.rb +1 -2
- data/lib/moneta/adapters/file.rb +9 -4
- data/lib/moneta/adapters/fog.rb +8 -3
- data/lib/moneta/adapters/gdbm.rb +1 -2
- data/lib/moneta/adapters/hbase.rb +10 -3
- data/lib/moneta/adapters/leveldb.rb +3 -2
- data/lib/moneta/adapters/localmemcache.rb +4 -4
- data/lib/moneta/adapters/lruhash.rb +8 -4
- data/lib/moneta/adapters/memcached/dalli.rb +10 -4
- data/lib/moneta/adapters/memcached/native.rb +9 -4
- data/lib/moneta/adapters/memory.rb +8 -3
- data/lib/moneta/adapters/mongo.rb +7 -3
- data/lib/moneta/adapters/null.rb +8 -1
- data/lib/moneta/adapters/pstore.rb +9 -3
- data/lib/moneta/adapters/redis.rb +10 -4
- data/lib/moneta/adapters/riak.rb +12 -7
- data/lib/moneta/adapters/sdbm.rb +1 -2
- data/lib/moneta/adapters/sequel.rb +9 -3
- data/lib/moneta/adapters/sqlite.rb +10 -4
- data/lib/moneta/adapters/tokyocabinet.rb +2 -2
- data/lib/moneta/builder.rb +11 -7
- data/lib/moneta/cache.rb +16 -6
- data/lib/moneta/expires.rb +12 -6
- data/lib/moneta/lock.rb +0 -2
- data/lib/moneta/logger.rb +0 -2
- data/lib/moneta/mixins.rb +175 -47
- data/lib/moneta/optionmerger.rb +2 -0
- data/lib/moneta/proxy.rb +14 -30
- data/lib/moneta/server.rb +0 -2
- data/lib/moneta/shared.rb +1 -3
- data/lib/moneta/stack.rb +20 -10
- data/lib/moneta/transformer.rb +84 -61
- data/lib/moneta/version.rb +1 -1
- data/lib/rack/moneta_rest.rb +56 -0
- data/moneta.gemspec +1 -1
- data/spec/active_support/cache_moneta_store_spec.rb +4 -4
- data/spec/generate.rb +216 -203
- data/spec/helper.rb +0 -6
- data/spec/moneta/adapter_cassandra_spec.rb +2 -2
- data/spec/moneta/adapter_datamapper_spec.rb +1 -1
- data/spec/moneta/adapter_lruhash_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_dalli_spec.rb +2 -2
- data/spec/moneta/adapter_memcached_native_spec.rb +2 -2
- data/spec/moneta/adapter_memcached_spec.rb +2 -2
- data/spec/moneta/adapter_redis_spec.rb +2 -2
- data/spec/moneta/cache_file_memory_spec.rb +3 -3
- data/spec/moneta/expires_file_spec.rb +4 -4
- data/spec/moneta/expires_memory_spec.rb +2 -2
- data/spec/moneta/optionmerger_spec.rb +6 -6
- data/spec/moneta/shared_spec.rb +1 -1
- data/spec/moneta/simple_client_tcp_spec.rb +1 -1
- data/spec/moneta/transformer_key_marshal_spec.rb +109 -0
- data/spec/moneta/transformer_key_yaml_spec.rb +109 -0
- data/spec/moneta/transformer_marshal_spec.rb +109 -0
- data/spec/moneta/transformer_value_marshal_spec.rb +109 -0
- data/spec/moneta/transformer_value_yaml_spec.rb +109 -0
- data/spec/monetaspecs.rb +14460 -3956
- metadata +16 -6
- data/lib/moneta/base.rb +0 -98
- data/lib/moneta/net.rb +0 -22
data/lib/moneta/transformer.rb
CHANGED
@@ -10,19 +10,17 @@ module Moneta
|
|
10
10
|
#
|
11
11
|
# @example Bypass serialization
|
12
12
|
# store.store('key', 'value', :raw => true)
|
13
|
-
# store['key']
|
14
|
-
# store.load('key', :raw => true)
|
13
|
+
# store['key'] # raises an Exception
|
14
|
+
# store.load('key', :raw => true) # returns 'value'
|
15
15
|
#
|
16
16
|
# store['key'] = 'value'
|
17
|
-
# store.load('key', :raw => true)
|
17
|
+
# store.load('key', :raw => true) # returns "\x04\bI\"\nvalue\x06:\x06ET"
|
18
18
|
#
|
19
19
|
# @api public
|
20
20
|
class Transformer < Proxy
|
21
21
|
class << self
|
22
22
|
alias_method :original_new, :new
|
23
23
|
|
24
|
-
# Constructor
|
25
|
-
#
|
26
24
|
# @param [Moneta store] adapter The underlying store
|
27
25
|
# @param [Hash] options
|
28
26
|
# @return [Transformer] new Moneta transformer
|
@@ -31,28 +29,25 @@ module Moneta
|
|
31
29
|
# @option options [String] :prefix Prefix string for key namespacing (Used by the :prefix key transformer)
|
32
30
|
# @option options [String] :secret HMAC secret to verify values (Used by the :hmac value transformer)
|
33
31
|
# @option options [Integer] :maxlen Maximum key length (Used by the :truncate key transformer)
|
34
|
-
# @option options [Boolean] :quiet Disable error message
|
35
32
|
def new(adapter, options = {})
|
36
33
|
keys = [options[:key]].flatten.compact
|
37
34
|
values = [options[:value]].flatten.compact
|
38
35
|
raise ArgumentError, 'Option :key or :value is required' if keys.empty? && values.empty?
|
39
36
|
options[:prefix] ||= '' if keys.include?(:prefix)
|
40
|
-
name = class_name(
|
41
|
-
const_set(name, compile(
|
37
|
+
name = class_name(keys, values)
|
38
|
+
const_set(name, compile(keys, values)) unless const_defined?(name)
|
42
39
|
const_get(name).original_new(adapter, options)
|
43
40
|
end
|
44
41
|
|
45
42
|
private
|
46
43
|
|
47
|
-
def compile(
|
44
|
+
def compile(keys, values)
|
48
45
|
@key_validator ||= compile_validator(KEY_TRANSFORMER)
|
49
46
|
@value_validator ||= compile_validator(VALUE_TRANSFORMER)
|
50
47
|
|
51
48
|
raise ArgumentError, 'Invalid key transformer chain' if @key_validator !~ keys.map(&:inspect).join
|
52
49
|
raise ArgumentError, 'Invalid value transformer chain' if @value_validator !~ values.map(&:inspect).join
|
53
50
|
|
54
|
-
key = compile_transformer(keys, 'key')
|
55
|
-
|
56
51
|
klass = Class.new(self)
|
57
52
|
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
58
53
|
def initialize(adapter, options = {})
|
@@ -60,62 +55,90 @@ module Moneta
|
|
60
55
|
#{compile_initializer('key', keys)}
|
61
56
|
#{compile_initializer('value', values)}
|
62
57
|
end
|
58
|
+
end_eval
|
59
|
+
|
60
|
+
key = compile_transformer(keys, 'key')
|
61
|
+
dump = compile_transformer(values, 'value')
|
62
|
+
load = compile_transformer(values.reverse, 'value', 1)
|
63
|
+
|
64
|
+
if values.empty?
|
65
|
+
compile_key_transformer(klass, key)
|
66
|
+
elsif keys.empty?
|
67
|
+
compile_value_transformer(klass, load, dump)
|
68
|
+
else
|
69
|
+
compile_key_value_transformer(klass, key, load, dump)
|
70
|
+
end
|
71
|
+
|
72
|
+
klass
|
73
|
+
end
|
74
|
+
|
75
|
+
def compile_key_transformer(klass, key)
|
76
|
+
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
63
77
|
def key?(key, options = {})
|
64
78
|
@adapter.key?(#{key}, options)
|
65
79
|
end
|
66
80
|
def increment(key, amount = 1, options = {})
|
67
81
|
@adapter.increment(#{key}, amount, options)
|
68
82
|
end
|
83
|
+
def load(key, options = {})
|
84
|
+
options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
85
|
+
@adapter.load(#{key}, options)
|
86
|
+
end
|
87
|
+
def store(key, value, options = {})
|
88
|
+
options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
89
|
+
@adapter.store(#{key}, value, options)
|
90
|
+
end
|
91
|
+
def delete(key, options = {})
|
92
|
+
options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
93
|
+
@adapter.delete(#{key}, options)
|
94
|
+
end
|
69
95
|
end_eval
|
96
|
+
end
|
70
97
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
end_eval
|
117
|
-
end
|
118
|
-
klass
|
98
|
+
def compile_value_transformer(klass, load, dump)
|
99
|
+
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
100
|
+
def load(key, options = {})
|
101
|
+
raw = options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
102
|
+
value = @adapter.load(key, options)
|
103
|
+
value && !raw ? #{load} : value
|
104
|
+
end
|
105
|
+
def store(key, value, options = {})
|
106
|
+
raw = options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
107
|
+
@adapter.store(key, raw ? value : #{dump}, options)
|
108
|
+
value
|
109
|
+
end
|
110
|
+
def delete(key, options = {})
|
111
|
+
raw = options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
112
|
+
value = @adapter.delete(key, options)
|
113
|
+
value && !raw ? #{load} : value
|
114
|
+
end
|
115
|
+
end_eval
|
116
|
+
end
|
117
|
+
|
118
|
+
def compile_key_value_transformer(klass, key, load, dump)
|
119
|
+
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
120
|
+
def key?(key, options = {})
|
121
|
+
@adapter.key?(#{key}, options)
|
122
|
+
end
|
123
|
+
def increment(key, amount = 1, options = {})
|
124
|
+
@adapter.increment(#{key}, amount, options)
|
125
|
+
end
|
126
|
+
def load(key, options = {})
|
127
|
+
raw = options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
128
|
+
value = @adapter.load(#{key}, options)
|
129
|
+
value && !raw ? #{load} : value
|
130
|
+
end
|
131
|
+
def store(key, value, options = {})
|
132
|
+
raw = options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
133
|
+
@adapter.store(#{key}, raw ? value : #{dump}, options)
|
134
|
+
value
|
135
|
+
end
|
136
|
+
def delete(key, options = {})
|
137
|
+
raw = options.include?(:raw) && (options = options.dup; options.delete(:raw))
|
138
|
+
value = @adapter.delete(#{key}, options)
|
139
|
+
value && !raw ? #{load} : value
|
140
|
+
end
|
141
|
+
end_eval
|
119
142
|
end
|
120
143
|
|
121
144
|
# Compile option initializer
|
@@ -149,8 +172,8 @@ module Moneta
|
|
149
172
|
end
|
150
173
|
end
|
151
174
|
|
152
|
-
def class_name(
|
153
|
-
|
175
|
+
def class_name(keys, values)
|
176
|
+
(keys.empty? ? '' : keys.map(&:to_s).map(&:capitalize).join << 'Key') <<
|
154
177
|
(values.empty? ? '' : values.map(&:to_s).map(&:capitalize).join << 'Value')
|
155
178
|
end
|
156
179
|
end
|
data/lib/moneta/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'moneta'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class MonetaRest
|
5
|
+
def initialize(store = nil, options = {}, &block)
|
6
|
+
if block
|
7
|
+
raise ArgumentError, 'Use either block or options' unless options.emtpy?
|
8
|
+
@store = ::Moneta.build(&block)
|
9
|
+
else
|
10
|
+
raise ArgumentError, 'Option :store is required' unless @store = store
|
11
|
+
@store = ::Moneta.new(@store, options) if Symbol === @store
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
key = env['PATH_INFO'][1..-1]
|
17
|
+
case env['REQUEST_METHOD']
|
18
|
+
when 'HEAD'
|
19
|
+
if @store.key?(key)
|
20
|
+
respond(200)
|
21
|
+
else
|
22
|
+
empty(404)
|
23
|
+
end
|
24
|
+
when 'GET'
|
25
|
+
if value = @store[key]
|
26
|
+
respond(200, value)
|
27
|
+
else
|
28
|
+
empty(404)
|
29
|
+
end
|
30
|
+
when 'POST', 'PUT'
|
31
|
+
respond(200, @store[key] = env['rack.input'].read)
|
32
|
+
when 'DELETE'
|
33
|
+
if key.empty?
|
34
|
+
@store.clear
|
35
|
+
empty(200)
|
36
|
+
else
|
37
|
+
respond(200, @store.delete(key))
|
38
|
+
end
|
39
|
+
else
|
40
|
+
empty(400)
|
41
|
+
end
|
42
|
+
rescue => ex
|
43
|
+
respond(500, ex.message)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def empty(status)
|
49
|
+
[status, {'Content-Type'=>'application/octet-stream', 'Content-Length' => '0'}, []]
|
50
|
+
end
|
51
|
+
|
52
|
+
def respond(status, value)
|
53
|
+
[status, {'Content-Type'=>'application/octet-stream', 'Content-Length' => value.bytesize.to_s}, [value]]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/moneta.gemspec
CHANGED
@@ -15,5 +15,5 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
16
|
s.homepage = 'http://github.com/minad/moneta'
|
17
17
|
s.require_paths = ['lib']
|
18
|
-
s.summary = %{A unified interface to key/value stores, including
|
18
|
+
s.summary = %{A unified interface to key/value stores, including Redis, Memcached, TokyoCabinet, ActiveRecord and many more}
|
19
19
|
end
|
@@ -76,24 +76,24 @@ describe ActiveSupport::Cache::MonetaStore do
|
|
76
76
|
|
77
77
|
it 'increments a key' do
|
78
78
|
3.times { @store.increment 'counter' }
|
79
|
-
@store.read('counter').should == '3'
|
79
|
+
@store.read('counter', :raw => true).should == '3'
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'decrements a key' do
|
83
83
|
3.times { @store.increment 'counter' }
|
84
84
|
2.times { @store.decrement 'counter' }
|
85
|
-
@store.read('counter').should == '1'
|
85
|
+
@store.read('counter', :raw => true).should == '1'
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'increments a key by given value' do
|
89
89
|
@store.increment 'counter', 3
|
90
|
-
@store.read('counter').should == '3'
|
90
|
+
@store.read('counter', :raw => true).should == '3'
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'decrements a key by given value' do
|
94
94
|
3.times { @store.increment 'counter' }
|
95
95
|
@store.decrement 'counter', 2
|
96
|
-
@store.read('counter').should == '1'
|
96
|
+
@store.read('counter', :raw => true).should == '1'
|
97
97
|
end
|
98
98
|
|
99
99
|
describe 'notifications' do
|
data/spec/generate.rb
CHANGED
@@ -3,24 +3,24 @@ class Specs
|
|
3
3
|
|
4
4
|
def initialize(specs, key = nil, value = nil)
|
5
5
|
@specs = specs
|
6
|
-
@key = key || %w(
|
7
|
-
@value = value || %w(
|
6
|
+
@key = key || %w(object string hash boolean nil integer)
|
7
|
+
@value = value || %w(object string hash boolean nil integer)
|
8
8
|
end
|
9
9
|
|
10
10
|
def stringkeys_only
|
11
|
-
Specs.new(specs, %w(
|
11
|
+
Specs.new(specs, %w(string), value)
|
12
12
|
end
|
13
13
|
|
14
14
|
def stringvalues_only
|
15
|
-
Specs.new(specs, key, %w(
|
15
|
+
Specs.new(specs, key, %w(string))
|
16
16
|
end
|
17
17
|
|
18
18
|
def simplekeys_only
|
19
|
-
Specs.new(specs, %w(
|
19
|
+
Specs.new(specs, %w(string hash integer), value)
|
20
20
|
end
|
21
21
|
|
22
22
|
def simplevalues_only
|
23
|
-
Specs.new(specs, key, %w(
|
23
|
+
Specs.new(specs, key, %w(string hash integer))
|
24
24
|
end
|
25
25
|
|
26
26
|
def without_increment
|
@@ -95,7 +95,7 @@ class Specs
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
ADAPTER_SPECS = Specs.new([:null, :store, :returndifferent, :increment, :persist], %w(
|
98
|
+
ADAPTER_SPECS = Specs.new([:null, :store, :returndifferent, :increment, :persist], %w(string), %w(string))
|
99
99
|
STANDARD_SPECS = Specs.new([:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :increment, :persist])
|
100
100
|
TRANSFORMER_SPECS = Specs.new([:null, :store, :returndifferent, :transform_value, :increment])
|
101
101
|
|
@@ -107,7 +107,7 @@ TESTS = {
|
|
107
107
|
:store => :Client,
|
108
108
|
:specs => STANDARD_SPECS,
|
109
109
|
:tests => %{
|
110
|
-
it '
|
110
|
+
it 'supports multiple clients' do
|
111
111
|
client = Moneta.new(:Client)
|
112
112
|
client['shared_key'] = 'shared_val'
|
113
113
|
(1..100).each do |i|
|
@@ -449,7 +449,7 @@ end
|
|
449
449
|
end},
|
450
450
|
:specs => STANDARD_SPECS.without_transform.with_expires.without_persist,
|
451
451
|
:tests => %{
|
452
|
-
it '
|
452
|
+
it 'supports default expiration time' do
|
453
453
|
store = Moneta.new(:Memory, :expires => 2)
|
454
454
|
store.store('key1', 'val1')
|
455
455
|
store.store('key2', 'val2', :expires => 60)
|
@@ -457,7 +457,7 @@ it 'should support default expiration time' do
|
|
457
457
|
sleep 1
|
458
458
|
store.load('key1').should == 'val1'
|
459
459
|
sleep 2
|
460
|
-
store.load('key1').should
|
460
|
+
store.load('key1').should be_nil
|
461
461
|
store['key2'].should == 'val2'
|
462
462
|
end}
|
463
463
|
},
|
@@ -469,15 +469,15 @@ end}
|
|
469
469
|
end},
|
470
470
|
:specs => STANDARD_SPECS.with_expires.stringvalues_only,
|
471
471
|
:tests => %{
|
472
|
-
it '
|
472
|
+
it 'deletes expired value in underlying file storage' do
|
473
473
|
store.store('foo', 'bar', :expires => 2)
|
474
474
|
store['foo'].should == 'bar'
|
475
475
|
sleep 1
|
476
476
|
store['foo'].should == 'bar'
|
477
477
|
sleep 2
|
478
|
-
store['foo'].should
|
479
|
-
store.adapter['foo'].should
|
480
|
-
store.adapter.adapter['foo'].should
|
478
|
+
store['foo'].should be_nil
|
479
|
+
store.adapter['foo'].should be_nil
|
480
|
+
store.adapter.adapter['foo'].should be_nil
|
481
481
|
end
|
482
482
|
}
|
483
483
|
},
|
@@ -507,15 +507,15 @@ end},
|
|
507
507
|
end},
|
508
508
|
:specs => ADAPTER_SPECS,
|
509
509
|
:tests => %{
|
510
|
-
it '
|
510
|
+
it 'stores loaded values in cache' do
|
511
511
|
store.backend['foo'] = 'bar'
|
512
|
-
store.cache['foo'].should
|
512
|
+
store.cache['foo'].should be_nil
|
513
513
|
store['foo'].should == 'bar'
|
514
514
|
store.cache['foo'].should == 'bar'
|
515
515
|
store.backend.delete('foo')
|
516
516
|
store['foo'].should == 'bar'
|
517
517
|
store.delete('foo')
|
518
|
-
store['foo'].should
|
518
|
+
store['foo'].should be_nil
|
519
519
|
end
|
520
520
|
}
|
521
521
|
},
|
@@ -536,7 +536,7 @@ end},
|
|
536
536
|
end},
|
537
537
|
:specs => ADAPTER_SPECS.without_persist,
|
538
538
|
:tests => %{
|
539
|
-
it '
|
539
|
+
it 'shares values' do
|
540
540
|
store['shared_key'] = 'shared_value'
|
541
541
|
second = new_store
|
542
542
|
second.key?('shared_key').should be_true
|
@@ -678,10 +678,50 @@ end},
|
|
678
678
|
:specs => TRANSFORMER_SPECS.simplekeys_only.simplevalues_only,
|
679
679
|
:load_value => '::MessagePack.unpack(value)'
|
680
680
|
},
|
681
|
+
'transformer_marshal' => {
|
682
|
+
:build => %{Moneta.build do
|
683
|
+
use :Transformer, :key => :marshal, :value => :marshal
|
684
|
+
adapter :Memory
|
685
|
+
end},
|
686
|
+
:specs => TRANSFORMER_SPECS,
|
687
|
+
:load_value => '::Marshal.load(value)'
|
688
|
+
},
|
689
|
+
'transformer_key_marshal' => {
|
690
|
+
:build => %{Moneta.build do
|
691
|
+
use :Transformer, :key => :marshal
|
692
|
+
adapter :Memory
|
693
|
+
end},
|
694
|
+
:specs => TRANSFORMER_SPECS,
|
695
|
+
:load_value => 'value'
|
696
|
+
},
|
697
|
+
'transformer_value_marshal' => {
|
698
|
+
:build => %{Moneta.build do
|
699
|
+
use :Transformer, :value => :marshal
|
700
|
+
adapter :Memory
|
701
|
+
end},
|
702
|
+
:specs => TRANSFORMER_SPECS,
|
703
|
+
:load_value => '::Marshal.load(value)'
|
704
|
+
},
|
681
705
|
'transformer_yaml' => {
|
682
706
|
:build => %{Moneta.build do
|
683
707
|
use :Transformer, :key => :yaml, :value => :yaml
|
684
708
|
adapter :Memory
|
709
|
+
end},
|
710
|
+
:specs => TRANSFORMER_SPECS,
|
711
|
+
:load_value => '::YAML.load(value)'
|
712
|
+
},
|
713
|
+
'transformer_key_yaml' => {
|
714
|
+
:build => %{Moneta.build do
|
715
|
+
use :Transformer, :key => :yaml
|
716
|
+
adapter :Memory
|
717
|
+
end},
|
718
|
+
:specs => TRANSFORMER_SPECS,
|
719
|
+
:load_value => 'value'
|
720
|
+
},
|
721
|
+
'transformer_value_yaml' => {
|
722
|
+
:build => %{Moneta.build do
|
723
|
+
use :Transformer, :value => :yaml
|
724
|
+
adapter :Memory
|
685
725
|
end},
|
686
726
|
:specs => TRANSFORMER_SPECS,
|
687
727
|
:load_value => '::YAML.load(value)'
|
@@ -808,7 +848,7 @@ end
|
|
808
848
|
:build => "Moneta::Adapters::Cassandra.new(:keyspace => 'adapter_cassandra')",
|
809
849
|
:specs => ADAPTER_SPECS.without_increment.with_expires,
|
810
850
|
:tests => %{
|
811
|
-
it '
|
851
|
+
it 'supports default expiration time' do
|
812
852
|
store = Moneta::Adapters::Cassandra.new(:expires => 2, :keyspace => 'adapter_cassandra')
|
813
853
|
store.store('key1', 'val1')
|
814
854
|
store.store('key2', 'val2', :expires => 60)
|
@@ -816,7 +856,7 @@ it 'should support default expiration time' do
|
|
816
856
|
sleep 1
|
817
857
|
store.load('key1').should == 'val1'
|
818
858
|
sleep 2
|
819
|
-
store.load('key1').should
|
859
|
+
store.load('key1').should be_nil
|
820
860
|
store['key2'].should == 'val2'
|
821
861
|
end}
|
822
862
|
},
|
@@ -863,7 +903,7 @@ it 'does not cross contaminate when deleting' do
|
|
863
903
|
second['key'] = 'value2'
|
864
904
|
|
865
905
|
first.delete('key').should == 'value'
|
866
|
-
first.key?('key').should
|
906
|
+
first.key?('key').should be_false
|
867
907
|
second['key'].should == 'value2'
|
868
908
|
end
|
869
909
|
}
|
@@ -897,7 +937,7 @@ end
|
|
897
937
|
:build => 'Moneta::Adapters::MemcachedDalli.new(:namespace => "adapter_memcached_dalli")',
|
898
938
|
:specs => ADAPTER_SPECS.with_expires,
|
899
939
|
:tests => %{
|
900
|
-
it '
|
940
|
+
it 'supports default expiration time' do
|
901
941
|
store = Moneta::Adapters::MemcachedDalli.new(:expires => 2, :namespace => "adapter_memcached_dalli")
|
902
942
|
store.store('key1', 'val1')
|
903
943
|
store.store('key2', 'val2', :expires => 60)
|
@@ -905,7 +945,7 @@ it 'should support default expiration time' do
|
|
905
945
|
sleep 1
|
906
946
|
store.load('key1').should == 'val1'
|
907
947
|
sleep 2
|
908
|
-
store.load('key1').should
|
948
|
+
store.load('key1').should be_nil
|
909
949
|
store['key2'].should == 'val2'
|
910
950
|
end}
|
911
951
|
},
|
@@ -913,7 +953,7 @@ end}
|
|
913
953
|
:build => 'Moneta::Adapters::MemcachedNative.new(:namespace => "adapter_memcached_native")',
|
914
954
|
:specs => ADAPTER_SPECS.with_expires,
|
915
955
|
:tests => %{
|
916
|
-
it '
|
956
|
+
it 'supports default expiration time' do
|
917
957
|
store = Moneta::Adapters::MemcachedNative.new(:expires => 2, :namespace => "adapter_memcached_native")
|
918
958
|
store.store('key1', 'val1')
|
919
959
|
store.store('key2', 'val2', :expires => 60)
|
@@ -921,7 +961,7 @@ it 'should support default expiration time' do
|
|
921
961
|
sleep 1
|
922
962
|
store.load('key1').should == 'val1'
|
923
963
|
sleep 2
|
924
|
-
store.load('key1').should
|
964
|
+
store.load('key1').should be_nil
|
925
965
|
store['key2'].should == 'val2'
|
926
966
|
end
|
927
967
|
}
|
@@ -930,7 +970,7 @@ end
|
|
930
970
|
:build => 'Moneta::Adapters::Memcached.new(:namespace => "adapter_memcached")',
|
931
971
|
:specs => ADAPTER_SPECS.with_expires,
|
932
972
|
:tests => %{
|
933
|
-
it '
|
973
|
+
it 'supports default expiration time' do
|
934
974
|
store = Moneta::Adapters::Memcached.new(:expires => 2, :namespace => "adapter_memcached")
|
935
975
|
store.store('key1', 'val1')
|
936
976
|
store.store('key2', 'val2', :expires => 60)
|
@@ -938,7 +978,7 @@ it 'should support default expiration time' do
|
|
938
978
|
sleep 1
|
939
979
|
store.load('key1').should == 'val1'
|
940
980
|
sleep 2
|
941
|
-
store.load('key1').should
|
981
|
+
store.load('key1').should be_nil
|
942
982
|
store['key2'].should == 'val2'
|
943
983
|
end}
|
944
984
|
},
|
@@ -950,7 +990,7 @@ end}
|
|
950
990
|
:build => 'Moneta::Adapters::LRUHash.new',
|
951
991
|
:specs => ADAPTER_SPECS.without_persist,
|
952
992
|
:tests => %{
|
953
|
-
it '
|
993
|
+
it 'deletes oldest' do
|
954
994
|
store = Moneta::Adapters::LRUHash.new(:max_size => 10)
|
955
995
|
store[0] = 'y'
|
956
996
|
(1..1000).each do |i|
|
@@ -976,7 +1016,7 @@ end}
|
|
976
1016
|
:build => 'Moneta::Adapters::Redis.new',
|
977
1017
|
:specs => ADAPTER_SPECS.with_expires,
|
978
1018
|
:tests => %{
|
979
|
-
it '
|
1019
|
+
it 'supports default expiration time' do
|
980
1020
|
store = Moneta::Adapters::Redis.new(:expires => 2)
|
981
1021
|
store.store('key1', 'val1')
|
982
1022
|
store.store('key2', 'val2', :expires => 60)
|
@@ -984,7 +1024,7 @@ it 'should support default expiration time' do
|
|
984
1024
|
sleep 1
|
985
1025
|
store.load('key1').should == 'val1'
|
986
1026
|
sleep 2
|
987
|
-
store.load('key1').should
|
1027
|
+
store.load('key1').should be_nil
|
988
1028
|
store['key2'].should == 'val2'
|
989
1029
|
end}
|
990
1030
|
},
|
@@ -1033,7 +1073,7 @@ it '#with should return OptionMerger' do
|
|
1033
1073
|
merger.should be_instance_of(Moneta::OptionMerger)
|
1034
1074
|
end
|
1035
1075
|
|
1036
|
-
it '
|
1076
|
+
it 'saves default options' do
|
1037
1077
|
options = {:optionname => :optionvalue}
|
1038
1078
|
merger = store.with(options)
|
1039
1079
|
Moneta::OptionMerger::METHODS.each do |method|
|
@@ -1043,14 +1083,14 @@ end
|
|
1043
1083
|
|
1044
1084
|
PREFIX = [['alpha', nil], ['beta', nil], ['alpha', 'beta']]
|
1045
1085
|
|
1046
|
-
it '
|
1086
|
+
it 'merges options' do
|
1047
1087
|
merger = store.with(:opt1 => :val1, :opt2 => :val2).with(:opt2 => :overwrite, :opt3 => :val3)
|
1048
1088
|
Moneta::OptionMerger::METHODS.each do |method|
|
1049
1089
|
merger.default_options[method].should == {:opt1 => :val1, :opt2 => :overwrite, :opt3 => :val3}
|
1050
1090
|
end
|
1051
1091
|
end
|
1052
1092
|
|
1053
|
-
it '
|
1093
|
+
it 'merges options only for some methods' do
|
1054
1094
|
PREFIX.each do |(alpha,beta)|
|
1055
1095
|
options = {:opt1 => :val1, :opt2 => :val2, :prefix => alpha}
|
1056
1096
|
merger = store.with(options).with(:opt2 => :overwrite, :opt3 => :val3, :prefix => beta, :only => :clear)
|
@@ -1068,7 +1108,7 @@ it 'should merge options only for some methods' do
|
|
1068
1108
|
end
|
1069
1109
|
end
|
1070
1110
|
|
1071
|
-
it '
|
1111
|
+
it 'merges options except for some methods' do
|
1072
1112
|
PREFIX.each do |(alpha,beta)|
|
1073
1113
|
options = {:opt1 => :val1, :opt2 => :val2, :prefix => alpha}
|
1074
1114
|
merger = store.with(options).with(:opt2 => :overwrite, :opt3 => :val3, :except => :clear, :prefix => beta)
|
@@ -1086,12 +1126,12 @@ it 'should merge options except for some methods' do
|
|
1086
1126
|
end
|
1087
1127
|
end
|
1088
1128
|
|
1089
|
-
it '
|
1129
|
+
it 'has method #raw' do
|
1090
1130
|
store.raw.default_options.should == {:store=>{:raw=>true},:load=>{:raw=>true},:delete=>{:raw=>true}}
|
1091
1131
|
store.raw.should equal(store.raw.raw)
|
1092
1132
|
end
|
1093
1133
|
|
1094
|
-
it '
|
1134
|
+
it 'has method #prefix' do
|
1095
1135
|
store.prefix('a').default_options.should == {:store=>{:prefix=>'a'},:load=>{:prefix=>'a'},
|
1096
1136
|
:delete=>{:prefix=>'a'},:key? => {:prefix=>'a'},:increment=>{:prefix=>'a'}}
|
1097
1137
|
|
@@ -1110,122 +1150,100 @@ end}
|
|
1110
1150
|
SPECS = {}
|
1111
1151
|
|
1112
1152
|
KEYS = {
|
1113
|
-
'
|
1114
|
-
'
|
1115
|
-
'
|
1116
|
-
'
|
1117
|
-
'
|
1118
|
-
'
|
1153
|
+
'nil' => [0, 'nil'],
|
1154
|
+
'integer' => [-10, 42],
|
1155
|
+
'boolean' => [true, false],
|
1156
|
+
'string' => ['strkey1', 'strkey2'].map(&:inspect),
|
1157
|
+
'object' => ['Value.new(:objkey1)', 'Value.new(:objkey2)'],
|
1158
|
+
'hash' => [{'hashkey1' => 'hashkey2'}, {'hashkey3' => 'hashkey4'}].map(&:inspect)
|
1119
1159
|
}
|
1120
1160
|
|
1121
1161
|
VALUES = {
|
1122
|
-
'
|
1123
|
-
'
|
1124
|
-
'
|
1125
|
-
'
|
1126
|
-
'
|
1127
|
-
'
|
1162
|
+
'nil' => [0, 'nil'],
|
1163
|
+
'integer' => [41, -12],
|
1164
|
+
'boolean' => [true, false],
|
1165
|
+
'string' => ['strval1', 'strval2'].map(&:inspect),
|
1166
|
+
'hash' => [{'hashval1' => ['array1', 1]}, {'hashval3' => ['array2', {'hashval4' => 42}]}].map(&:inspect),
|
1167
|
+
'object' => ['Value.new(:objval1)', 'Value.new(:objval2)'],
|
1128
1168
|
}
|
1129
1169
|
|
1130
|
-
KEYS.each do |key_type,
|
1131
|
-
VALUES.each do |val_type,
|
1170
|
+
KEYS.each do |key_type, keypair|
|
1171
|
+
VALUES.each do |val_type, valpair|
|
1172
|
+
4.times do |i|
|
1173
|
+
key1, key2 = i % 2 == 0 ? keypair : keypair.reverse
|
1174
|
+
val1, val2 = i < 2 ? valpair : valpair.reverse
|
1132
1175
|
|
1133
|
-
|
1134
|
-
store[#{key1}].should
|
1135
|
-
store.load(#{key1}).should
|
1136
|
-
|
1137
|
-
store[#{key2}].should == nil
|
1138
|
-
store.load(#{key2}).should == nil
|
1176
|
+
code = %{it 'reads from keys like a Hash' do
|
1177
|
+
store[#{key1}].should be_nil
|
1178
|
+
store.load(#{key1}).should be_nil
|
1139
1179
|
end
|
1140
1180
|
|
1141
|
-
it
|
1181
|
+
it 'guarantees that the same value is returned when setting a key' do
|
1142
1182
|
value = #{val1}
|
1143
1183
|
(store[#{key1}] = value).should equal(value)
|
1144
|
-
|
1145
|
-
value = #{val2}
|
1146
|
-
(store[#{key2}] = value).should equal(value)
|
1147
1184
|
end
|
1148
1185
|
|
1149
|
-
it
|
1150
|
-
store.key?(#{key1}).should
|
1151
|
-
store.key?(#{key2}).should == false
|
1186
|
+
it 'returns false from key? if a key is not available' do
|
1187
|
+
store.key?(#{key1}).should be_false
|
1152
1188
|
end
|
1153
1189
|
|
1154
|
-
it
|
1155
|
-
store.delete(#{key1}).should
|
1156
|
-
store.delete(#{key2}).should == nil
|
1190
|
+
it 'returns nil from delete if a value for a key does not exist' do
|
1191
|
+
store.delete(#{key1}).should be_nil
|
1157
1192
|
end
|
1158
1193
|
|
1159
|
-
it
|
1194
|
+
it 'removes all keys from the store with clear' do
|
1160
1195
|
store[#{key1}] = #{val1}
|
1161
1196
|
store[#{key2}] = #{val2}
|
1162
1197
|
store.clear.should equal(store)
|
1163
|
-
store.key?(#{key1}).
|
1164
|
-
store.key?(#{key2}).
|
1198
|
+
store.key?(#{key1}).should be_false
|
1199
|
+
store.key?(#{key2}).should be_false
|
1165
1200
|
end
|
1166
1201
|
|
1167
|
-
it
|
1202
|
+
it 'fetches a key with a default value with fetch, if the key is not available' do
|
1168
1203
|
store.fetch(#{key1}, #{val1}).should == #{val1}
|
1169
|
-
store.fetch(#{key2}, #{val2}).should == #{val2}
|
1170
1204
|
end
|
1171
1205
|
|
1172
|
-
it
|
1206
|
+
it 'fetches a key with a block with fetch, if the key is not available' do
|
1173
1207
|
key = #{key1}
|
1174
1208
|
value = #{val1}
|
1175
1209
|
store.fetch(key) do |k|
|
1176
1210
|
k.should equal(key)
|
1177
1211
|
value
|
1178
1212
|
end.should equal(value)
|
1179
|
-
|
1180
|
-
key = #{key2}
|
1181
|
-
value = #{val2}
|
1182
|
-
store.fetch(key) do |k|
|
1183
|
-
k.should equal(key)
|
1184
|
-
value
|
1185
|
-
end.should equal(value)
|
1186
1213
|
end
|
1187
1214
|
|
1188
|
-
it '
|
1189
|
-
|
1190
|
-
|
1191
|
-
store.
|
1192
|
-
store.
|
1193
|
-
store.
|
1194
|
-
store.
|
1195
|
-
store.
|
1215
|
+
it 'accepts frozen options' do
|
1216
|
+
options = {:option1 => 1, :options2 => 2}
|
1217
|
+
options.freeze
|
1218
|
+
store.key?(#{key1}, options).should be_false
|
1219
|
+
store.load(#{key1}, options).should be_nil
|
1220
|
+
store.fetch(#{key1}, 42, options).should == 42
|
1221
|
+
store.fetch(#{key1}, options) { 42 }.should == 42
|
1222
|
+
store.delete(#{key1}, options).should be_nil
|
1223
|
+
store.clear(options).should equal(store)
|
1224
|
+
store.store(#{key1}, #{val1}, options).should == #{val1}
|
1196
1225
|
end}
|
1197
|
-
SPECS["null_#{key_type
|
1226
|
+
(SPECS["null_#{key_type}key_#{val_type}value"] ||= []) << code
|
1198
1227
|
|
1199
|
-
code = %{it
|
1228
|
+
code = %{it 'writes values to keys that like a Hash' do
|
1200
1229
|
store[#{key1}] = #{val1}
|
1201
1230
|
store[#{key1}].should == #{val1}
|
1202
1231
|
store.load(#{key1}).should == #{val1}
|
1203
|
-
|
1204
|
-
store[#{key2}] = #{val2}
|
1205
|
-
store[#{key2}].should == #{val2}
|
1206
|
-
store.load(#{key2}).should == #{val2}
|
1207
1232
|
end
|
1208
1233
|
|
1209
|
-
it
|
1234
|
+
it 'returns true from key? if a key is available' do
|
1210
1235
|
store[#{key1}] = #{val1}
|
1211
|
-
store.key?(#{key1}).should
|
1212
|
-
store[#{key2}] = #{val2}
|
1213
|
-
store.key?(#{key2}).should == true
|
1236
|
+
store.key?(#{key1}).should be_true
|
1214
1237
|
end
|
1215
1238
|
|
1216
|
-
it
|
1239
|
+
it 'stores values with #store' do
|
1217
1240
|
value = #{val1}
|
1218
1241
|
store.store(#{key1}, value).should equal(value)
|
1219
1242
|
store[#{key1}].should == #{val1}
|
1220
1243
|
store.load(#{key1}).should == #{val1}
|
1221
|
-
|
1222
|
-
value = #{val2}
|
1223
|
-
store.store(#{key2}, value).should equal(value)
|
1224
|
-
store[#{key2}].should == #{val2}
|
1225
|
-
store.load(#{key2}).should == #{val2}
|
1226
1244
|
end
|
1227
1245
|
|
1228
|
-
it
|
1246
|
+
it 'stores values after clear' do
|
1229
1247
|
store[#{key1}] = #{val1}
|
1230
1248
|
store[#{key2}] = #{val2}
|
1231
1249
|
store.clear.should equal(store)
|
@@ -1234,72 +1252,57 @@ it "stores #{key_type} after clear" do
|
|
1234
1252
|
store[#{key2}].should be_nil
|
1235
1253
|
end
|
1236
1254
|
|
1237
|
-
it
|
1255
|
+
it 'removes and returns a value from the backing store via delete if it exists' do
|
1238
1256
|
store[#{key1}] = #{val1}
|
1239
1257
|
store.delete(#{key1}).should == #{val1}
|
1240
|
-
store.key?(#{key1}).should
|
1241
|
-
|
1242
|
-
store[#{key2}] = #{val2}
|
1243
|
-
store.delete(#{key2}).should == #{val2}
|
1244
|
-
store.key?(#{key2}).should == false
|
1258
|
+
store.key?(#{key1}).should be_false
|
1245
1259
|
end
|
1246
1260
|
|
1247
|
-
it
|
1261
|
+
it 'overwrites existing values' do
|
1248
1262
|
store[#{key1}] = #{val1}
|
1249
1263
|
store[#{key1}].should == #{val1}
|
1250
1264
|
store[#{key1}] = #{val2}
|
1251
1265
|
store[#{key1}].should == #{val2}
|
1252
|
-
end
|
1266
|
+
end}
|
1253
1267
|
|
1254
|
-
|
1268
|
+
if val_type != 'nil'
|
1269
|
+
code << %{
|
1270
|
+
it 'fetches a key with a default value with fetch, if the key is available' do
|
1255
1271
|
store[#{key1}] = #{val1}
|
1256
1272
|
store.fetch(#{key1}, #{val2}).should == #{val1}
|
1257
|
-
end
|
1273
|
+
end
|
1258
1274
|
|
1259
|
-
|
1260
|
-
code << %{
|
1261
|
-
it "does not run the block if the #{key_type} key is available" do
|
1275
|
+
it 'does not run the block in fetch if the key is available' do
|
1262
1276
|
store[#{key1}] = #{val1}
|
1263
1277
|
unaltered = 'unaltered'
|
1264
1278
|
store.fetch(#{key1}) { unaltered = 'altered' }
|
1265
1279
|
unaltered.should == 'unaltered'
|
1266
|
-
|
1267
|
-
store[#{key2}] = #{val2}
|
1268
|
-
unaltered = 'unaltered'
|
1269
|
-
store.fetch(#{key2}) { unaltered = 'altered' }
|
1270
|
-
unaltered.should == 'unaltered'
|
1271
1280
|
end}
|
1272
|
-
|
1281
|
+
end
|
1273
1282
|
|
1274
|
-
|
1283
|
+
(SPECS["store_#{key_type}key_#{val_type}value"] ||= []) << code
|
1275
1284
|
|
1276
|
-
|
1285
|
+
code = %{it 'guarantees that a different value is retrieved' do
|
1277
1286
|
value = #{val1}
|
1278
1287
|
store[#{key1}] = #{val1}
|
1279
1288
|
store[#{key1}].should_not be_equal(#{val1})
|
1280
|
-
|
1281
|
-
value = #{val2}
|
1282
|
-
store[#{key2}] = #{val2}
|
1283
|
-
store[#{key2}].should_not be_equal(#{val2})
|
1284
1289
|
end}
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1290
|
+
if val_type != 'boolean' && val_type != 'nil' && val_type != 'integer'
|
1291
|
+
(SPECS["returndifferent_#{key_type}key_#{val_type}value"] ||= []) << code
|
1292
|
+
end
|
1288
1293
|
|
1289
|
-
|
1294
|
+
code = %{it 'persists values' do
|
1290
1295
|
store[#{key1}] = #{val1}
|
1291
|
-
store[#{key2}] = #{val2}
|
1292
1296
|
store.close
|
1293
1297
|
@store = nil
|
1294
|
-
|
1295
1298
|
store[#{key1}].should == #{val1}
|
1296
|
-
store[#{key2}].should == #{val2}
|
1297
1299
|
end}
|
1298
|
-
|
1300
|
+
(SPECS["persist_#{key_type}key_#{val_type}value"] ||= []) << code
|
1301
|
+
end
|
1299
1302
|
end
|
1300
1303
|
end
|
1301
1304
|
|
1302
|
-
SPECS['not_persist'] = %{it
|
1305
|
+
SPECS['not_persist'] = %{it 'does not persist values' do
|
1303
1306
|
store['key'] = 'val'
|
1304
1307
|
store.close
|
1305
1308
|
@store = nil
|
@@ -1307,34 +1310,34 @@ SPECS['not_persist'] = %{it "does not persist values" do
|
|
1307
1310
|
store['key'].should be_nil
|
1308
1311
|
end}
|
1309
1312
|
|
1310
|
-
SPECS['expires'] = %{it '
|
1313
|
+
SPECS['expires'] = %{it 'supports expires on store and #[]' do
|
1311
1314
|
store.store('key1', 'val1', :expires => 2)
|
1312
1315
|
store['key1'].should == 'val1'
|
1313
1316
|
sleep 1
|
1314
1317
|
store['key1'].should == 'val1'
|
1315
1318
|
sleep 2
|
1316
|
-
store['key1'].should
|
1319
|
+
store['key1'].should be_nil
|
1317
1320
|
end
|
1318
1321
|
|
1319
|
-
it '
|
1322
|
+
it 'supports expires on store and load' do
|
1320
1323
|
store.store('key1', 'val1', :expires => 2)
|
1321
1324
|
store.load('key1').should == 'val1'
|
1322
1325
|
sleep 1
|
1323
1326
|
store.load('key1').should == 'val1'
|
1324
1327
|
sleep 2
|
1325
|
-
store.load('key1').should
|
1328
|
+
store.load('key1').should be_nil
|
1326
1329
|
end
|
1327
1330
|
|
1328
|
-
it '
|
1331
|
+
it 'supports expires on store and key?' do
|
1329
1332
|
store.store('key1', 'val1', :expires => 2)
|
1330
|
-
store.key?('key1').should
|
1333
|
+
store.key?('key1').should be_true
|
1331
1334
|
sleep 1
|
1332
|
-
store.key?('key1').should
|
1335
|
+
store.key?('key1').should be_true
|
1333
1336
|
sleep 2
|
1334
|
-
store.key?('key1').should
|
1337
|
+
store.key?('key1').should be_false
|
1335
1338
|
end
|
1336
1339
|
|
1337
|
-
it '
|
1340
|
+
it 'supports updating the expiration time in load' do
|
1338
1341
|
store.store('key2', 'val2', :expires => 2)
|
1339
1342
|
store['key2'].should == 'val2'
|
1340
1343
|
sleep 1
|
@@ -1343,10 +1346,10 @@ it 'should support updating the expiration time in load' do
|
|
1343
1346
|
sleep 1
|
1344
1347
|
store['key2'].should == 'val2'
|
1345
1348
|
sleep 3
|
1346
|
-
store['key2'].should
|
1349
|
+
store['key2'].should be_nil
|
1347
1350
|
end
|
1348
1351
|
|
1349
|
-
it '
|
1352
|
+
it 'supports updating the expiration time in key?' do
|
1350
1353
|
store.store('key2', 'val2', :expires => 2)
|
1351
1354
|
store['key2'].should == 'val2'
|
1352
1355
|
sleep 1
|
@@ -1355,10 +1358,10 @@ it 'should support updating the expiration time in key?' do
|
|
1355
1358
|
sleep 1
|
1356
1359
|
store['key2'].should == 'val2'
|
1357
1360
|
sleep 3
|
1358
|
-
store['key2'].should
|
1361
|
+
store['key2'].should be_nil
|
1359
1362
|
end
|
1360
1363
|
|
1361
|
-
it '
|
1364
|
+
it 'supports updating the expiration time in fetch' do
|
1362
1365
|
store.store('key1', 'val1', :expires => 2)
|
1363
1366
|
store['key1'].should == 'val1'
|
1364
1367
|
sleep 1
|
@@ -1367,42 +1370,42 @@ it 'should support updating the expiration time in fetch' do
|
|
1367
1370
|
sleep 1
|
1368
1371
|
store['key1'].should == 'val1'
|
1369
1372
|
sleep 3
|
1370
|
-
store['key1'].should
|
1373
|
+
store['key1'].should be_nil
|
1371
1374
|
end
|
1372
1375
|
|
1373
|
-
it '
|
1376
|
+
it 'respects expires in delete' do
|
1374
1377
|
store.store('key2', 'val2', :expires => 2)
|
1375
1378
|
store['key2'].should == 'val2'
|
1376
1379
|
sleep 1
|
1377
1380
|
store['key2'].should == 'val2'
|
1378
1381
|
sleep 2
|
1379
|
-
store.delete('key2').should
|
1382
|
+
store.delete('key2').should be_nil
|
1380
1383
|
end
|
1381
1384
|
|
1382
|
-
it '
|
1385
|
+
it 'supports the #expires syntactic sugar' do
|
1383
1386
|
store['longlive_key'] = 'longlive_value'
|
1384
1387
|
store.expires(2).store('key2', 'val2')
|
1385
1388
|
store['key2'].should == 'val2'
|
1386
1389
|
sleep 1
|
1387
1390
|
store['key2'].should == 'val2'
|
1388
1391
|
sleep 2
|
1389
|
-
store.delete('key2').should
|
1392
|
+
store.delete('key2').should be_nil
|
1390
1393
|
store['longlive_key'].should == 'longlive_value'
|
1391
1394
|
end}
|
1392
1395
|
|
1393
|
-
SPECS['not_increment'] = %{it '
|
1396
|
+
SPECS['not_increment'] = %{it 'does not support #increment' do
|
1394
1397
|
expect do
|
1395
1398
|
store.increment('inckey')
|
1396
1399
|
end.to raise_error(NotImplementedError)
|
1397
1400
|
end
|
1398
1401
|
|
1399
|
-
it '
|
1402
|
+
it 'does not support #decrement' do
|
1400
1403
|
expect do
|
1401
1404
|
store.increment('inckey')
|
1402
1405
|
end.to raise_error(NotImplementedError)
|
1403
1406
|
end}
|
1404
1407
|
|
1405
|
-
SPECS['increment'] = %{it '
|
1408
|
+
SPECS['increment'] = %{it 'initializes in #increment with 1' do
|
1406
1409
|
store.key?('inckey').should be_false
|
1407
1410
|
store.increment('inckey').should == 1
|
1408
1411
|
store.key?('inckey').should be_true
|
@@ -1410,65 +1413,41 @@ SPECS['increment'] = %{it 'should initialize in #increment with 1' do
|
|
1410
1413
|
store.raw.load('inckey').should == '1'
|
1411
1414
|
store.load('inckey', :raw => true).should == '1'
|
1412
1415
|
|
1413
|
-
# WARNING: Undefined behaviour!
|
1414
|
-
result = safe_load_value(store.raw['inckey'])
|
1415
|
-
store['inckey'].should == result
|
1416
|
-
|
1417
1416
|
store.delete('inckey', :raw => true).should == '1'
|
1418
1417
|
store.key?('inckey').should be_false
|
1419
1418
|
end
|
1420
1419
|
|
1421
|
-
it '
|
1420
|
+
it 'initializes in #increment with higher value' do
|
1422
1421
|
store.increment('inckey', 42).should == 42
|
1423
1422
|
store.key?('inckey').should be_true
|
1424
1423
|
store.raw['inckey'].should == '42'
|
1425
|
-
|
1426
|
-
# WARNING: Undefined behaviour!
|
1427
|
-
result = safe_load_value(store.raw['inckey'])
|
1428
|
-
store['inckey'].should == result
|
1429
|
-
|
1430
1424
|
store.delete('inckey', :raw => true).should == '42'
|
1431
1425
|
end
|
1432
1426
|
|
1433
|
-
it '
|
1427
|
+
it 'initializes in #increment with 0' do
|
1434
1428
|
store.increment('inckey', 0).should == 0
|
1435
1429
|
store.key?('inckey').should be_true
|
1436
1430
|
store.raw['inckey'].should == '0'
|
1437
|
-
|
1438
|
-
# WARNING: Undefined behaviour!
|
1439
|
-
result = safe_load_value(store.raw['inckey'])
|
1440
|
-
store['inckey'].should == result
|
1441
|
-
|
1442
1431
|
store.delete('inckey', :raw => true).should == '0'
|
1443
1432
|
end
|
1444
1433
|
|
1445
|
-
it '
|
1446
|
-
store.increment('inckey').should == 1
|
1447
|
-
|
1448
|
-
# WARNING: Undefined behaviour!
|
1449
|
-
result = safe_load_value(store.raw['inckey'])
|
1450
|
-
store.delete('inckey').should == result
|
1451
|
-
|
1452
|
-
store.key?('inckey').should be_false
|
1453
|
-
end
|
1454
|
-
|
1455
|
-
it 'should initialize in #decrement with 0' do
|
1434
|
+
it 'initializes in #decrement with 0' do
|
1456
1435
|
store.decrement('inckey', 0).should == 0
|
1457
1436
|
store.raw['inckey'].should == '0'
|
1458
1437
|
end
|
1459
1438
|
|
1460
|
-
it '
|
1439
|
+
it 'initializes in #decrement with negative value' do
|
1461
1440
|
store.decrement('inckey', -42).should == 42
|
1462
1441
|
store.raw['inckey'].should == '42'
|
1463
1442
|
end
|
1464
1443
|
|
1465
|
-
it '
|
1444
|
+
it 'supports incrementing existing value by value' do
|
1466
1445
|
store.increment('inckey').should == 1
|
1467
1446
|
store.increment('inckey', 42).should == 43
|
1468
1447
|
store.raw['inckey'].should == '43'
|
1469
1448
|
end
|
1470
1449
|
|
1471
|
-
it '
|
1450
|
+
it 'supports decrementing existing value by value' do
|
1472
1451
|
store.increment('inckey').should == 1
|
1473
1452
|
store.decrement('inckey').should == 0
|
1474
1453
|
store.increment('inckey', 42).should == 42
|
@@ -1476,13 +1455,13 @@ it 'should support decrementing existing value by value' do
|
|
1476
1455
|
store.raw['inckey'].should == '40'
|
1477
1456
|
end
|
1478
1457
|
|
1479
|
-
it '
|
1458
|
+
it 'supports incrementing existing value by 0' do
|
1480
1459
|
store.increment('inckey').should == 1
|
1481
1460
|
store.increment('inckey', 0).should == 1
|
1482
1461
|
store.raw['inckey'].should == '1'
|
1483
1462
|
end
|
1484
1463
|
|
1485
|
-
it '
|
1464
|
+
it 'supports decrementing existing value' do
|
1486
1465
|
store.increment('inckey', 10).should == 10
|
1487
1466
|
store.increment('inckey', -5).should == 5
|
1488
1467
|
store.raw['inckey'].should == '5'
|
@@ -1490,20 +1469,20 @@ it 'should support decrementing existing value' do
|
|
1490
1469
|
store.raw['inckey'].should == '0'
|
1491
1470
|
end
|
1492
1471
|
|
1493
|
-
it '
|
1472
|
+
it 'interprets raw value as integer' do
|
1494
1473
|
store.store('inckey', '42', :raw => true)
|
1495
1474
|
store.increment('inckey').should == 43
|
1496
1475
|
store.raw['inckey'].should == '43'
|
1497
1476
|
end
|
1498
1477
|
|
1499
|
-
it '
|
1478
|
+
it 'raises error in #increment on non integer value' do
|
1500
1479
|
store['strkey'] = 'value'
|
1501
1480
|
expect do
|
1502
1481
|
store.increment('strkey')
|
1503
1482
|
end.to raise_error
|
1504
1483
|
end
|
1505
1484
|
|
1506
|
-
it '
|
1485
|
+
it 'raises error in #decrement on non integer value' do
|
1507
1486
|
store['strkey'] = 'value'
|
1508
1487
|
expect do
|
1509
1488
|
store.decrement('strkey')
|
@@ -1580,16 +1559,36 @@ it 'allows to bypass transformer with raw syntactic sugar' do
|
|
1580
1559
|
store.raw['key'].should == 'value2'
|
1581
1560
|
end
|
1582
1561
|
|
1583
|
-
it '
|
1562
|
+
it 'returns unmarshalled value' do
|
1584
1563
|
store.store('key', 'unmarshalled value', :raw => true)
|
1585
1564
|
store.load('key', :raw => true).should == 'unmarshalled value'
|
1586
|
-
|
1587
|
-
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
it 'might raise exception on invalid value' do
|
1568
|
+
store.store('key', 'unmarshalled value', :raw => true)
|
1569
|
+
|
1570
|
+
begin
|
1571
|
+
store['key'].should == load_value('unmarshalled value')
|
1572
|
+
store.delete('key').should == load_value('unmarshalled value')
|
1573
|
+
rescue Exception => ex
|
1574
|
+
expect do
|
1575
|
+
store['key']
|
1576
|
+
end.to raise_error
|
1577
|
+
expect do
|
1578
|
+
store.delete('key')
|
1579
|
+
end.to raise_error
|
1580
|
+
end
|
1588
1581
|
end}
|
1589
1582
|
|
1590
1583
|
SPECS['transform_value_with_expires'] = %{it 'allows to bypass transformer with :raw' do
|
1591
1584
|
store['key'] = 'value'
|
1592
|
-
load_value(store.load('key', :raw => true)).should ==
|
1585
|
+
load_value(store.load('key', :raw => true)).should == 'value'
|
1586
|
+
store['key'] = [1,2,3]
|
1587
|
+
load_value(store.load('key', :raw => true)).should == [[1,2,3]]
|
1588
|
+
store['key'] = nil
|
1589
|
+
load_value(store.load('key', :raw => true)).should == [nil]
|
1590
|
+
store['key'] = false
|
1591
|
+
load_value(store.load('key', :raw => true)).should be_false
|
1593
1592
|
|
1594
1593
|
store.store('key', 'value', :expires => 10)
|
1595
1594
|
load_value(store.load('key', :raw => true)).first.should == 'value'
|
@@ -1600,17 +1599,31 @@ SPECS['transform_value_with_expires'] = %{it 'allows to bypass transformer with
|
|
1600
1599
|
store.delete('key', :raw => true).should == 'value'
|
1601
1600
|
end
|
1602
1601
|
|
1603
|
-
it '
|
1602
|
+
it 'returns unmarshalled value' do
|
1604
1603
|
store.store('key', 'unmarshalled value', :raw => true)
|
1605
1604
|
store.load('key', :raw => true).should == 'unmarshalled value'
|
1606
|
-
|
1607
|
-
|
1605
|
+
end
|
1606
|
+
|
1607
|
+
it 'might raise exception on invalid value' do
|
1608
|
+
store.store('key', 'unmarshalled value', :raw => true)
|
1609
|
+
|
1610
|
+
begin
|
1611
|
+
store['key'].should == load_value('unmarshalled value')
|
1612
|
+
store.delete('key').should == load_value('unmarshalled value')
|
1613
|
+
rescue Exception => ex
|
1614
|
+
expect do
|
1615
|
+
store['key']
|
1616
|
+
end.to raise_error
|
1617
|
+
expect do
|
1618
|
+
store.delete('key')
|
1619
|
+
end.to raise_error
|
1620
|
+
end
|
1608
1621
|
end}
|
1609
1622
|
|
1610
1623
|
specs_code = "#{header}\n"
|
1611
1624
|
SPECS.each do |key, code|
|
1612
1625
|
specs_code << "#################### #{key} ####################\n\n" <<
|
1613
|
-
"shared_examples_for '#{key}' do\n " << code.gsub("\n", "\n ") << "\nend\n\n"
|
1626
|
+
"shared_examples_for '#{key}' do\n " << [code].flatten.join("\n\n").gsub("\n", "\n ") << "\nend\n\n"
|
1614
1627
|
end
|
1615
1628
|
specs_code.gsub!(/\n +\n/, "\n\n")
|
1616
1629
|
File.open(File.join(File.dirname(__FILE__), 'monetaspecs.rb'), 'w') {|out| out << specs_code }
|
@@ -1627,7 +1640,7 @@ TESTS.each do |name, options|
|
|
1627
1640
|
specs_code << " it_should_behave_like '#{s}'" if SPECS[s.to_s]
|
1628
1641
|
specs.key.each do |k|
|
1629
1642
|
specs.value.each do |v|
|
1630
|
-
x = "#{s}_#{k
|
1643
|
+
x = "#{s}_#{k}key_#{v}value"
|
1631
1644
|
specs_code << " it_should_behave_like '#{x}'" if SPECS[x]
|
1632
1645
|
end
|
1633
1646
|
end
|