moneta 0.7.0 → 0.7.1

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.
Files changed (179) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +39 -6
  3. data/CHANGES +18 -0
  4. data/README.md +69 -31
  5. data/Rakefile +1 -1
  6. data/SPEC.md +6 -0
  7. data/benchmarks/run.rb +235 -133
  8. data/lib/active_support/cache/moneta_store.rb +1 -0
  9. data/lib/moneta.rb +29 -19
  10. data/lib/moneta/adapters/activerecord.rb +18 -26
  11. data/lib/moneta/adapters/cassandra.rb +5 -7
  12. data/lib/moneta/adapters/client.rb +3 -5
  13. data/lib/moneta/adapters/cookie.rb +2 -0
  14. data/lib/moneta/adapters/couch.rb +1 -3
  15. data/lib/moneta/adapters/datamapper.rb +4 -6
  16. data/lib/moneta/adapters/dbm.rb +1 -3
  17. data/lib/moneta/adapters/file.rb +4 -0
  18. data/lib/moneta/adapters/fog.rb +2 -4
  19. data/lib/moneta/adapters/gdbm.rb +1 -3
  20. data/lib/moneta/adapters/hbase.rb +5 -7
  21. data/lib/moneta/adapters/leveldb.rb +2 -4
  22. data/lib/moneta/adapters/localmemcache.rb +1 -3
  23. data/lib/moneta/adapters/lruhash.rb +1 -3
  24. data/lib/moneta/adapters/memcached.rb +2 -2
  25. data/lib/moneta/adapters/{memcached_dalli.rb → memcached/dalli.rb} +4 -6
  26. data/lib/moneta/adapters/{memcached_native.rb → memcached/native.rb} +8 -7
  27. data/lib/moneta/adapters/mongo.rb +8 -9
  28. data/lib/moneta/adapters/pstore.rb +1 -3
  29. data/lib/moneta/adapters/redis.rb +2 -4
  30. data/lib/moneta/adapters/riak.rb +3 -5
  31. data/lib/moneta/adapters/sdbm.rb +1 -13
  32. data/lib/moneta/adapters/sequel.rb +3 -5
  33. data/lib/moneta/adapters/sqlite.rb +2 -4
  34. data/lib/moneta/adapters/tokyocabinet.rb +2 -4
  35. data/lib/moneta/base.rb +22 -2
  36. data/lib/moneta/builder.rb +3 -3
  37. data/lib/moneta/cache.rb +1 -1
  38. data/lib/moneta/expires.rb +27 -35
  39. data/lib/moneta/lock.rb +1 -3
  40. data/lib/moneta/logger.rb +3 -5
  41. data/lib/moneta/net.rb +7 -3
  42. data/lib/moneta/proxy.rb +2 -1
  43. data/lib/moneta/server.rb +33 -21
  44. data/lib/moneta/shared.rb +11 -7
  45. data/lib/moneta/stack.rb +1 -1
  46. data/lib/moneta/transformer.rb +15 -13
  47. data/lib/moneta/transformer/config.rb +33 -31
  48. data/lib/moneta/version.rb +1 -1
  49. data/lib/rack/cache/moneta.rb +6 -0
  50. data/lib/rack/moneta_cookies.rb +1 -0
  51. data/lib/rack/session/moneta.rb +1 -0
  52. data/moneta.gemspec +1 -1
  53. data/spec/generate.rb +403 -232
  54. data/spec/helper.rb +23 -2
  55. data/spec/moneta/adapter_activerecord_spec.rb +3 -2
  56. data/spec/moneta/adapter_cassandra_spec.rb +4 -3
  57. data/spec/moneta/adapter_client_spec.rb +4 -3
  58. data/spec/moneta/adapter_cookie_spec.rb +3 -2
  59. data/spec/moneta/adapter_couch_spec.rb +3 -2
  60. data/spec/moneta/adapter_datamapper_spec.rb +3 -2
  61. data/spec/moneta/adapter_dbm_spec.rb +3 -2
  62. data/spec/moneta/adapter_file_spec.rb +3 -2
  63. data/spec/moneta/adapter_fog_spec.rb +3 -2
  64. data/spec/moneta/adapter_gdbm_spec.rb +3 -2
  65. data/spec/moneta/adapter_hbase_spec.rb +3 -2
  66. data/spec/moneta/adapter_leveldb_spec.rb +3 -2
  67. data/spec/moneta/adapter_localmemcache_spec.rb +3 -2
  68. data/spec/moneta/adapter_lruhash_spec.rb +3 -2
  69. data/spec/moneta/adapter_memcached_dalli_spec.rb +4 -3
  70. data/spec/moneta/adapter_memcached_native_spec.rb +4 -3
  71. data/spec/moneta/adapter_memcached_spec.rb +4 -3
  72. data/spec/moneta/adapter_memory_spec.rb +50 -1
  73. data/spec/moneta/adapter_mongo_spec.rb +3 -2
  74. data/spec/moneta/adapter_pstore_spec.rb +124 -4
  75. data/spec/moneta/adapter_redis_spec.rb +4 -3
  76. data/spec/moneta/adapter_riak_spec.rb +3 -2
  77. data/spec/moneta/adapter_sdbm_spec.rb +3 -2
  78. data/spec/moneta/adapter_sequel_spec.rb +3 -2
  79. data/spec/moneta/adapter_sqlite_spec.rb +3 -2
  80. data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +3 -2
  81. data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +3 -2
  82. data/spec/moneta/adapter_yaml_spec.rb +32 -5
  83. data/spec/moneta/cache_file_memory_spec.rb +3 -2
  84. data/spec/moneta/cache_memory_null_spec.rb +3 -2
  85. data/spec/moneta/expires_file_spec.rb +23 -41
  86. data/spec/moneta/expires_memory_spec.rb +69 -13
  87. data/spec/moneta/lock_spec.rb +50 -1
  88. data/spec/moneta/null_adapter_spec.rb +26 -0
  89. data/spec/moneta/proxy_expires_memory_spec.rb +51 -12
  90. data/spec/moneta/proxy_redis_spec.rb +4 -3
  91. data/spec/moneta/shared_spec.rb +4 -3
  92. data/spec/moneta/simple_activerecord_spec.rb +105 -12
  93. data/spec/moneta/simple_activerecord_with_expires_spec.rb +106 -13
  94. data/spec/moneta/simple_cassandra_spec.rb +106 -13
  95. data/spec/moneta/simple_client_tcp_spec.rb +106 -13
  96. data/spec/moneta/simple_client_unix_spec.rb +106 -14
  97. data/spec/moneta/simple_couch_spec.rb +105 -12
  98. data/spec/moneta/simple_couch_with_expires_spec.rb +106 -13
  99. data/spec/moneta/simple_datamapper_spec.rb +105 -12
  100. data/spec/moneta/simple_datamapper_with_expires_spec.rb +106 -13
  101. data/spec/moneta/simple_datamapper_with_repository_spec.rb +105 -12
  102. data/spec/moneta/simple_dbm_spec.rb +105 -12
  103. data/spec/moneta/simple_dbm_with_expires_spec.rb +106 -13
  104. data/spec/moneta/simple_file_spec.rb +105 -12
  105. data/spec/moneta/simple_file_with_expires_spec.rb +106 -13
  106. data/spec/moneta/simple_fog_spec.rb +105 -12
  107. data/spec/moneta/simple_fog_with_expires_spec.rb +106 -13
  108. data/spec/moneta/simple_gdbm_spec.rb +105 -12
  109. data/spec/moneta/simple_gdbm_with_expires_spec.rb +106 -13
  110. data/spec/moneta/simple_hashfile_spec.rb +105 -12
  111. data/spec/moneta/simple_hashfile_with_expires_spec.rb +106 -13
  112. data/spec/moneta/simple_hbase_spec.rb +105 -12
  113. data/spec/moneta/simple_hbase_with_expires_spec.rb +106 -13
  114. data/spec/moneta/simple_leveldb_spec.rb +105 -12
  115. data/spec/moneta/simple_leveldb_with_expires_spec.rb +106 -13
  116. data/spec/moneta/simple_localmemcache_spec.rb +105 -12
  117. data/spec/moneta/simple_localmemcache_with_expires_spec.rb +106 -13
  118. data/spec/moneta/simple_lruhash_spec.rb +70 -12
  119. data/spec/moneta/simple_lruhash_with_expires_spec.rb +71 -13
  120. data/spec/moneta/simple_memcached_dalli_spec.rb +106 -13
  121. data/spec/moneta/simple_memcached_native_spec.rb +106 -13
  122. data/spec/moneta/simple_memcached_spec.rb +106 -13
  123. data/spec/moneta/simple_memory_spec.rb +70 -12
  124. data/spec/moneta/simple_memory_with_compress_spec.rb +70 -12
  125. data/spec/moneta/simple_memory_with_expires_spec.rb +71 -13
  126. data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +41 -15
  127. data/spec/moneta/simple_memory_with_json_serializer_spec.rb +24 -11
  128. data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +45 -14
  129. data/spec/moneta/simple_memory_with_prefix_spec.rb +70 -12
  130. data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +70 -12
  131. data/spec/moneta/simple_mongo_spec.rb +105 -12
  132. data/spec/moneta/simple_mongo_with_expires_spec.rb +106 -13
  133. data/spec/moneta/simple_null_spec.rb +36 -1
  134. data/spec/moneta/simple_pstore_spec.rb +105 -12
  135. data/spec/moneta/simple_pstore_with_expires_spec.rb +106 -13
  136. data/spec/moneta/simple_redis_spec.rb +106 -13
  137. data/spec/moneta/simple_riak_spec.rb +105 -12
  138. data/spec/moneta/simple_riak_with_expires_spec.rb +106 -13
  139. data/spec/moneta/simple_sdbm_spec.rb +105 -12
  140. data/spec/moneta/simple_sdbm_with_expires_spec.rb +106 -13
  141. data/spec/moneta/simple_sequel_spec.rb +105 -12
  142. data/spec/moneta/simple_sequel_with_expires_spec.rb +106 -13
  143. data/spec/moneta/simple_sqlite_spec.rb +105 -12
  144. data/spec/moneta/simple_sqlite_with_expires_spec.rb +106 -13
  145. data/spec/moneta/simple_tokyocabinet_spec.rb +105 -12
  146. data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +106 -13
  147. data/spec/moneta/simple_yaml_spec.rb +104 -11
  148. data/spec/moneta/simple_yaml_with_expires_spec.rb +105 -12
  149. data/spec/moneta/stack_file_memory_spec.rb +3 -2
  150. data/spec/moneta/stack_memory_file_spec.rb +3 -1
  151. data/spec/moneta/transformer_bencode_spec.rb +23 -10
  152. data/spec/moneta/transformer_bert_spec.rb +23 -10
  153. data/spec/moneta/transformer_bson_spec.rb +23 -10
  154. data/spec/moneta/transformer_bzip2_spec.rb +13 -3
  155. data/spec/moneta/transformer_json_spec.rb +23 -10
  156. data/spec/moneta/transformer_lzma_spec.rb +13 -3
  157. data/spec/moneta/transformer_lzo_spec.rb +13 -3
  158. data/spec/moneta/transformer_marshal_base64_spec.rb +70 -12
  159. data/spec/moneta/transformer_marshal_escape_spec.rb +70 -12
  160. data/spec/moneta/transformer_marshal_hmac_spec.rb +70 -12
  161. data/spec/moneta/transformer_marshal_md5_spec.rb +70 -12
  162. data/spec/moneta/transformer_marshal_md5_spread_spec.rb +70 -12
  163. data/spec/moneta/transformer_marshal_prefix_spec.rb +70 -12
  164. data/spec/moneta/transformer_marshal_rmd160_spec.rb +70 -12
  165. data/spec/moneta/transformer_marshal_sha1_spec.rb +70 -12
  166. data/spec/moneta/transformer_marshal_sha256_spec.rb +70 -12
  167. data/spec/moneta/transformer_marshal_sha384_spec.rb +70 -12
  168. data/spec/moneta/transformer_marshal_sha512_spec.rb +70 -12
  169. data/spec/moneta/transformer_marshal_truncate_spec.rb +70 -12
  170. data/spec/moneta/transformer_marshal_uuencode_spec.rb +70 -12
  171. data/spec/moneta/transformer_msgpack_spec.rb +23 -10
  172. data/spec/moneta/transformer_ox_spec.rb +67 -9
  173. data/spec/moneta/transformer_quicklz_spec.rb +13 -3
  174. data/spec/moneta/transformer_snappy_spec.rb +13 -3
  175. data/spec/moneta/transformer_tnet_spec.rb +23 -10
  176. data/spec/moneta/transformer_yaml_spec.rb +67 -9
  177. data/spec/moneta/transformer_zlib_spec.rb +13 -3
  178. data/spec/monetaspecs.rb +4649 -1096
  179. metadata +8 -5
data/lib/moneta/stack.rb CHANGED
@@ -2,7 +2,7 @@ module Moneta
2
2
  # Combines multiple stores. Reads return the result from the first store,
3
3
  # writes go to all stores.
4
4
  #
5
- # @example Add stack to chain
5
+ # @example Add `Moneta::Stack` to proxy stack
6
6
  # Moneta.build do
7
7
  # use(:Stack) do
8
8
  # add { adapter :Redis }
@@ -2,7 +2,7 @@ module Moneta
2
2
  # Transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...).
3
3
  # You can bypass the transformer (e.g. serialization) by using the `:raw` option.
4
4
  #
5
- # @example Add transformer to chain
5
+ # @example Add `Moneta::Transformer` to proxy stack
6
6
  # Moneta.build do
7
7
  # transformer :key => [:marshal, :escape], :value => [:marshal]
8
8
  # adapter :File, :dir => 'data'
@@ -25,14 +25,13 @@ module Moneta
25
25
  #
26
26
  # @param [Moneta store] adapter The underlying store
27
27
  # @param [Hash] options
28
- #
29
- # Options:
30
- # * :key - List of key transformers in the order in which they should be applied
31
- # * :value - List of value transformers in the order in which they should be applied
32
- # * :prefix - Prefix string for key namespacing (Used by the :prefix key transformer)
33
- # * :secret - HMAC secret to verify values (Used by the :hmac value transformer)
34
- # * :maxlen - Maximum key length (Used by the :truncate key transformer)
35
- # * :quiet - Disable error message
28
+ # @return [Transformer] new Moneta transformer
29
+ # @option options [Array] :key List of key transformers in the order in which they should be applied
30
+ # @option options [Array] :value List of value transformers in the order in which they should be applied
31
+ # @option options [String] :prefix Prefix string for key namespacing (Used by the :prefix key transformer)
32
+ # @option options [String] :secret HMAC secret to verify values (Used by the :hmac value transformer)
33
+ # @option options [Integer] :maxlen Maximum key length (Used by the :truncate key transformer)
34
+ # @option options [Boolean] :quiet Disable error message
36
35
  def new(adapter, options = {})
37
36
  keys = [options[:key]].flatten.compact
38
37
  values = [options[:value]].flatten.compact
@@ -46,8 +45,11 @@ module Moneta
46
45
  private
47
46
 
48
47
  def compile(options, keys, values)
49
- raise ArgumentError, 'Invalid key transformer chain' if KEY_TRANSFORMER !~ keys.map(&:inspect).join
50
- raise ArgumentError, 'Invalid value transformer chain' if VALUE_TRANSFORMER !~ values.map(&:inspect).join
48
+ @key_validator ||= compile_validator(KEY_TRANSFORMER)
49
+ @value_validator ||= compile_validator(VALUE_TRANSFORMER)
50
+
51
+ raise ArgumentError, 'Invalid key transformer chain' if @key_validator !~ keys.map(&:inspect).join
52
+ raise ArgumentError, 'Invalid value transformer chain' if @value_validator !~ values.map(&:inspect).join
51
53
 
52
54
  key = compile_transformer(keys, 'key')
53
55
 
@@ -140,9 +142,9 @@ module Moneta
140
142
  require t[3] if t[3]
141
143
  code = t[i]
142
144
  if t[0] == :serialize && var == 'key'
143
- "(tmp = #{value}; String === tmp ? tmp : #{code.gsub('value', 'tmp')})"
145
+ "(tmp = #{value}; String === tmp ? tmp : #{code % 'tmp'})"
144
146
  else
145
- code.gsub('value', value)
147
+ code % value
146
148
  end
147
149
  end
148
150
  end
@@ -2,41 +2,43 @@ module Moneta
2
2
  class Transformer
3
3
  # Available key/value transformers
4
4
  TRANSFORMER = {
5
- # Name => [ Type, Load, Dump, Library ],
6
- :bencode => [ :serialize, '::BEncode.load(value)', '::BEncode.dump(value)', 'bencode' ],
7
- :bert => [ :serialize, '::BERT.decode(value)', '::BERT.encode(value)', 'bert' ],
8
- :bson => [ :serialize, "::BSON.deserialize(value)['v']", "::BSON.serialize('v'=>value).to_s", 'bson' ],
9
- :json => [ :serialize, '::MultiJson.load(value).first', '::MultiJson.dump([value])', 'multi_json' ],
10
- :marshal => [ :serialize, '::Marshal.load(value)', '::Marshal.dump(value)' ],
11
- :msgpack => [ :serialize, '::MessagePack.unpack(value)', '::MessagePack.pack(value)', 'msgpack' ],
12
- :ox => [ :serialize, '::Ox.parse_obj(value)', '::Ox.dump(value)', 'ox' ],
13
- :tnet => [ :serialize, '::TNetstring.parse(value).first', '::TNetstring.dump(value)', 'tnetstring' ],
14
- :yaml => [ :serialize, '::YAML.load(value)', '::YAML.dump(value)', 'yaml' ],
15
- :bzip2 => [ :compress, '::Bzip2.uncompress(value)', '::Bzip2.compress(value)', 'bzip2' ],
16
- :lzma => [ :compress, '::LZMA.decompress(value)', '::LZMA.compress(value)', 'lzma' ],
17
- :lzo => [ :compress, '::LZO.decompress(value)', '::LZO.compress(value)', 'lzoruby' ],
18
- :snappy => [ :compress, '::Snappy.inflate(value)', '::Snappy.deflate(value)', 'snappy' ],
19
- :quicklz => [ :compress, '::QuickLZ.decompress(value)', '::QuickLZ.compress(value)', 'qlzruby' ],
20
- :zlib => [ :compress, '::Zlib::Inflate.inflate(value)', '::Zlib::Deflate.deflate(value)', 'zlib' ],
21
- :base64 => [ :encode, "value.unpack('m').first", "[value].pack('m').strip" ],
22
- :uuencode => [ :encode, "value.unpack('u').first", "[value].pack('u').strip" ],
23
- :escape => [ :encode, 'Helper.unescape(value)', 'Helper.escape(value)' ],
24
- :hmac => [ :hmac, 'Helper.hmacverify(value, @secret)', 'Helper.hmacsign(value, @secret)', 'openssl' ],
25
- :truncate => [ :truncate, nil, 'Helper.truncate(value, @maxlen)', 'digest/md5' ],
26
- :md5 => [ :digest, nil, '::Digest::MD5.hexdigest(value)', 'digest/md5' ],
27
- :rmd160 => [ :digest, nil, '::Digest::RMD160.hexdigest(value)', 'digest/rmd160' ],
28
- :sha1 => [ :digest, nil, '::Digest::SHA1.hexdigest(value)', 'digest/sha1' ],
29
- :sha256 => [ :digest, nil, '::Digest::SHA256.hexdigest(value)', 'digest/sha2' ],
30
- :sha384 => [ :digest, nil, '::Digest::SHA384.hexdigest(value)', 'digest/sha2' ],
31
- :sha512 => [ :digest, nil, '::Digest::SHA512.hexdigest(value)', 'digest/sha2' ],
32
- :prefix => [ :prefix, nil, '(options[:prefix]||@prefix)+value' ],
33
- :spread => [ :spread, nil, 'Helper.spread(value)' ],
5
+ # Name => [ Type, Load, Dump, Library ],
6
+ :bencode => [ :serialize, '::BEncode.load(%s)', '::BEncode.dump(%s)', 'bencode' ],
7
+ :bert => [ :serialize, '::BERT.decode(%s)', '::BERT.encode(%s)', 'bert' ],
8
+ :bson => [ :serialize, "::BSON.deserialize(%s)['v']", "::BSON.serialize('v'=>%s).to_s", 'bson' ],
9
+ :json => [ :serialize, '::MultiJson.load(%s).first', '::MultiJson.dump([%s])', 'multi_json' ],
10
+ :marshal => [ :serialize, '::Marshal.load(%s)', '::Marshal.dump(%s)' ],
11
+ :msgpack => [ :serialize, '::MessagePack.unpack(%s)', '::MessagePack.pack(%s)', 'msgpack' ],
12
+ :ox => [ :serialize, '::Ox.parse_obj(%s)', '::Ox.dump(%s)', 'ox' ],
13
+ :tnet => [ :serialize, '::TNetstring.parse(%s).first', '::TNetstring.dump(%s)', 'tnetstring' ],
14
+ :yaml => [ :serialize, '::YAML.load(%s)', '::YAML.dump(%s)', 'yaml' ],
15
+ :bzip2 => [ :compress, '::Bzip2.uncompress(%s)', '::Bzip2.compress(%s)', 'bzip2' ],
16
+ :lzma => [ :compress, '::LZMA.decompress(%s)', '::LZMA.compress(%s)', 'lzma' ],
17
+ :lzo => [ :compress, '::LZO.decompress(%s)', '::LZO.compress(%s)', 'lzoruby' ],
18
+ :snappy => [ :compress, '::Snappy.inflate(%s)', '::Snappy.deflate(%s)', 'snappy' ],
19
+ :quicklz => [ :compress, '::QuickLZ.decompress(%s)', '::QuickLZ.compress(%s)', 'qlzruby' ],
20
+ :zlib => [ :compress, '::Zlib::Inflate.inflate(%s)', '::Zlib::Deflate.deflate(%s)', 'zlib' ],
21
+ :uuencode => [ :encode, "%s.unpack('u').first", "[%s].pack('u').strip" ],
22
+ :base64 => RUBY_VERSION > '1.9' ?
23
+ [ :encode, "%s.unpack('m0').first", "[%s].pack('m0')" ] :
24
+ [ :encode, "%s.unpack('m').first", "[%s].pack('m').gsub(\"\n\", '')" ],
25
+ :escape => [ :encode, 'Helper.unescape(%s)', 'Helper.escape(%s)' ],
26
+ :hmac => [ :hmac, 'Helper.hmacverify(%s, @secret)', 'Helper.hmacsign(%s, @secret)', 'openssl' ],
27
+ :truncate => [ :truncate, nil, 'Helper.truncate(%s, @maxlen)', 'digest/md5' ],
28
+ :md5 => [ :digest, nil, '::Digest::MD5.hexdigest(%s)', 'digest/md5' ],
29
+ :rmd160 => [ :digest, nil, '::Digest::RMD160.hexdigest(%s)', 'digest/rmd160' ],
30
+ :sha1 => [ :digest, nil, '::Digest::SHA1.hexdigest(%s)', 'digest/sha1' ],
31
+ :sha256 => [ :digest, nil, '::Digest::SHA256.hexdigest(%s)', 'digest/sha2' ],
32
+ :sha384 => [ :digest, nil, '::Digest::SHA384.hexdigest(%s)', 'digest/sha2' ],
33
+ :sha512 => [ :digest, nil, '::Digest::SHA512.hexdigest(%s)', 'digest/sha2' ],
34
+ :prefix => [ :prefix, nil, '(options[:prefix]||@prefix)+%s' ],
35
+ :spread => [ :spread, nil, 'Helper.spread(%s)' ],
34
36
  }
35
37
 
36
38
  # Allowed value transformers (Read it like a regular expression!)
37
- VALUE_TRANSFORMER = compile_validator('serialize? compress? hmac? encode?')
39
+ VALUE_TRANSFORMER = 'serialize? compress? hmac? encode?'
38
40
 
39
41
  # Allowed key transformers (Read it like a regular expression!)
40
- KEY_TRANSFORMER = compile_validator('serialize? prefix? ((encode? truncate?) | (digest spread?))?')
42
+ KEY_TRANSFORMER = 'serialize? prefix? ((encode? truncate?) | (digest spread?))?'
41
43
  end
42
44
  end
@@ -1,5 +1,5 @@
1
1
  module Moneta
2
2
  # Moneta version number
3
3
  # @api public
4
- VERSION = '0.7.0'
4
+ VERSION = '0.7.1'
5
5
  end
@@ -5,8 +5,10 @@ require 'rack/cache/entitystore'
5
5
 
6
6
  module Rack
7
7
  module Cache
8
+ # @api public
8
9
  Moneta = {}
9
10
 
11
+ # @api private
10
12
  module MonetaResolver
11
13
  include Rack::Utils
12
14
 
@@ -29,6 +31,7 @@ module Rack
29
31
  end
30
32
 
31
33
  class MetaStore
34
+ # @api public
32
35
  class Moneta < MetaStore
33
36
  extend MonetaResolver
34
37
 
@@ -50,10 +53,12 @@ module Rack
50
53
  end
51
54
  end
52
55
 
56
+ # @api public
53
57
  MONETA = Moneta
54
58
  end
55
59
 
56
60
  class EntityStore
61
+ # @api public
57
62
  class Moneta < EntityStore
58
63
  extend MonetaResolver
59
64
 
@@ -87,6 +92,7 @@ module Rack
87
92
  end
88
93
  end
89
94
 
95
+ # @api public
90
96
  MONETA = Moneta
91
97
  end
92
98
  end
@@ -33,6 +33,7 @@ module Rack
33
33
  # [200, {}, []]
34
34
  # end
35
35
  #
36
+ # @api public
36
37
  class MonetaCookies
37
38
  def initialize(app, options = {}, &block)
38
39
  @app, @pool = app, []
@@ -4,6 +4,7 @@ require 'thread'
4
4
 
5
5
  module Rack
6
6
  module Session
7
+ # @api public
7
8
  class Moneta < Abstract::ID
8
9
  attr_reader :mutex, :pool
9
10
 
data/moneta.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.name = 'moneta'
7
7
  s.version = Moneta::VERSION
8
8
  s.date = Date.today.to_s
9
- s.authors = ['Daniel Mendler', 'Yehuda Katz' 'Hannes Georg']
9
+ s.authors = ['Daniel Mendler', 'Yehuda Katz', 'Hannes Georg']
10
10
  s.email = %w{mail@daniel-mendler.de wycats@gmail.com hannes.georg@googlemail.com}
11
11
  s.description = 'A unified interface to key/value stores'
12
12
  s.extra_rdoc_files = %w{README.md SPEC.md LICENSE}
data/spec/generate.rb CHANGED
@@ -1,26 +1,111 @@
1
- ADAPTER_SPECS = [:null_stringkey_stringvalue, :store_stringkey_stringvalue, :returndifferent_stringkey_stringvalue, :not_increment]
2
- SIMPLE_SPECS = [:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :not_increment]
3
- EXPIRES_SPECS = [:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :expires_stringkey_stringvalue, :transform_value_with_expires, :not_increment]
4
- NATIVE_EXPIRES_SPECS = SIMPLE_SPECS + [:expires_stringkey_stringvalue]
5
- TRANSFORMER_SPECS = [:null, :store, :returndifferent, :transform_value]
6
- ADAPTER_EXPIRES_SPECS = ADAPTER_SPECS + [:expires_stringkey_stringvalue]
7
-
8
- EXPIRES_INCR_SPECS = EXPIRES_SPECS.reject {|s| s == :not_increment } + [:increment]
9
- NATIVE_EXPIRES_INCR_SPECS = NATIVE_EXPIRES_SPECS.reject {|s| s == :not_increment } + [:increment]
10
- SIMPLE_INCR_SPECS = SIMPLE_SPECS.reject {|s| s == :not_increment } + [:increment]
11
- ADAPTER_INCR_SPECS = ADAPTER_SPECS.reject {|s| s == :not_increment } + [:increment]
12
- ADAPTER_EXPIRES_INCR_SPECS = ADAPTER_EXPIRES_SPECS.reject {|s| s == :not_increment } + [:increment]
13
- PSTORE_SPECS = ADAPTER_INCR_SPECS + [:null_stringkey_objectvalue,
14
- :store_stringkey_objectvalue,
15
- :returndifferent_stringkey_objectvalue]
1
+ class Specs
2
+ attr_reader :key, :value, :specs
3
+
4
+ def initialize(specs, key = nil, value = nil)
5
+ @specs = specs
6
+ @key = key || %w(Object String Hash Boolean Nil Integer)
7
+ @value = value || %w(Object String Hash Boolean Nil Integer)
8
+ end
9
+
10
+ def stringkeys_only
11
+ Specs.new(specs, %w(String), value)
12
+ end
13
+
14
+ def stringvalues_only
15
+ Specs.new(specs, key, %w(String))
16
+ end
17
+
18
+ def simplekeys_only
19
+ Specs.new(specs, %w(String Hash Integer), value)
20
+ end
21
+
22
+ def simplevalues_only
23
+ Specs.new(specs, key, %w(String Hash Integer))
24
+ end
25
+
26
+ def without_increment
27
+ a = specs.dup
28
+ a.delete(:increment)
29
+ a << :not_increment
30
+ Specs.new(a, key, value)
31
+ end
32
+
33
+ def without_persist
34
+ a = specs.dup
35
+ a.delete(:persist)
36
+ a << :not_persist
37
+ Specs.new(a, key, value)
38
+ end
39
+
40
+ def with_expires
41
+ a = specs.dup
42
+ if a.include?(:transform_value)
43
+ a.delete(:transform_value)
44
+ a << :transform_value_with_expires
45
+ end
46
+ a << :expires
47
+ Specs.new(a, key, value)
48
+ end
49
+
50
+ def with_native_expires
51
+ a = specs.dup
52
+ a << :expires
53
+ Specs.new(a, key, value)
54
+ end
55
+
56
+ def without_marshallable
57
+ a = specs.dup
58
+ a.delete(:marshallable_value)
59
+ a.delete(:marshallable_key)
60
+ Specs.new(a, key, value)
61
+ end
62
+
63
+ def without_transform
64
+ a = specs.dup
65
+ a.delete(:marshallable_value)
66
+ a.delete(:marshallable_key)
67
+ a.delete(:transform_value)
68
+ Specs.new(a, key, value)
69
+ end
70
+
71
+ def without_returndifferent
72
+ a = specs.dup
73
+ a.delete(:returndifferent)
74
+ Specs.new(a, key, value)
75
+ end
76
+
77
+ def without_marshallable_key
78
+ a = specs.dup
79
+ a.delete(:marshallable_key)
80
+ Specs.new(a, key, value)
81
+ end
82
+
83
+ def without_marshallable_value
84
+ a = specs.dup
85
+ a.delete(:marshallable_value)
86
+ Specs.new(a, key, value)
87
+ end
88
+
89
+ def without_store
90
+ a = specs.dup
91
+ a.delete(:store)
92
+ a.delete(:transform_value)
93
+ a.delete(:marshallable_value)
94
+ Specs.new(a, key, value)
95
+ end
96
+ end
97
+
98
+ ADAPTER_SPECS = Specs.new([:null, :store, :returndifferent, :increment, :persist], %w(String), %w(String))
99
+ STANDARD_SPECS = Specs.new([:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :increment, :persist])
100
+ TRANSFORMER_SPECS = Specs.new([:null, :store, :returndifferent, :transform_value, :increment])
16
101
 
17
102
  header = "# Generated by #{__FILE__}\n"
18
103
 
19
104
  TESTS = {
20
105
  'simple_client_tcp' => {
21
- :preamble => "$tcp_server ||= Moneta::Server.new(Moneta::Adapters::Memory.new)\n",
106
+ :preamble => "start_server(Moneta::Adapters::Memory.new)\n",
22
107
  :store => :Client,
23
- :specs => SIMPLE_INCR_SPECS,
108
+ :specs => STANDARD_SPECS,
24
109
  :tests => %{
25
110
  it 'should support multiple clients' do
26
111
  client = Moneta.new(:Client)
@@ -39,214 +124,209 @@ end
39
124
  }
40
125
  },
41
126
  'simple_client_unix' => {
42
- :preamble => "$unix_server ||= Moneta::Server.new(Moneta::Adapters::Memory.new, :file => File.join(make_tempdir, 'simple_client_unix'))\nafter(:all) { $unix_server.stop; $unix_server = nil }\n",
127
+ :preamble => "start_server(Moneta::Adapters::Memory.new, :file => File.join(make_tempdir, 'simple_client_unix'))\n",
43
128
  :store => :Client,
44
129
  :options => ":file => File.join(make_tempdir, 'simple_client_unix')",
45
- :specs => SIMPLE_INCR_SPECS
130
+ :specs => STANDARD_SPECS
46
131
  },
47
132
  'simple_memory' => {
48
133
  :store => :Memory,
49
- :specs => SIMPLE_INCR_SPECS
134
+ :specs => STANDARD_SPECS.without_persist
50
135
  },
51
136
  'simple_memory_with_expires' => {
52
137
  :store => :Memory,
53
138
  :options => ':expires => true',
54
- :specs => EXPIRES_SPECS,
55
- :specs => EXPIRES_INCR_SPECS
139
+ :specs => STANDARD_SPECS.with_expires.without_persist
56
140
  },
57
141
  'simple_memory_with_compress' => {
58
142
  :store => :Memory,
59
143
  :options => ':compress => true',
60
144
  :load_value => 'Marshal.load(::Zlib::Inflate.inflate(value))',
61
- :specs => SIMPLE_INCR_SPECS
145
+ :specs => STANDARD_SPECS.without_persist
62
146
  },
63
147
  'simple_memory_with_prefix' => {
64
148
  :store => :Memory,
65
149
  :options => ':prefix => "moneta"',
66
- :specs => SIMPLE_INCR_SPECS
150
+ :specs => STANDARD_SPECS.without_persist
67
151
  },
68
152
  'simple_memory_with_json_serializer' => {
69
153
  :store => :Memory,
70
154
  :options => ':serializer => :json',
71
155
  :load_value => '::MultiJson.load(value).first',
72
- :key => %w(Hash String),
73
- :value => %w(Hash String),
74
- :specs => [:null, :store, :returndifferent, :transform_value, :increment],
156
+ :specs => STANDARD_SPECS.without_marshallable.simplekeys_only.simplevalues_only.without_persist
75
157
  },
76
158
  'simple_memory_with_json_key_serializer' => {
77
159
  :store => :Memory,
78
160
  :options => ':key_serializer => :json',
79
- :key => %w(Hash String),
80
- :specs => [:null, :store, :returndifferent, :increment],
161
+ :specs => STANDARD_SPECS.without_marshallable_key.simplekeys_only.without_persist,
81
162
  },
82
163
  'simple_memory_with_json_value_serializer' => {
83
164
  :store => :Memory,
84
165
  :options => ':value_serializer => :json',
85
- :value => %w(Hash String),
86
- :specs => [:null, :store, :returndifferent, :marshallable_key, :transform_value, :increment],
166
+ :specs => STANDARD_SPECS.without_marshallable_value.simplevalues_only.without_persist,
87
167
  :load_value => '::MultiJson.load(value).first'
88
168
  },
89
169
  'simple_memory_with_snappy_compress' => {
90
170
  :store => :Memory,
91
171
  :options => ':compress => :snappy',
92
172
  :load_value => 'Marshal.load(::Snappy.inflate(value))',
93
- :specs => SIMPLE_INCR_SPECS
173
+ :specs => STANDARD_SPECS.without_persist
94
174
  },
95
175
  'simple_lruhash' => {
96
176
  :store => :LRUHash,
97
- :specs => SIMPLE_INCR_SPECS
177
+ :specs => STANDARD_SPECS.without_persist
98
178
  },
99
179
  'simple_lruhash_with_expires' => {
100
180
  :store => :LRUHash,
101
181
  :options => ':expires => true',
102
- :specs => EXPIRES_INCR_SPECS,
182
+ :specs => STANDARD_SPECS.with_expires.without_persist,
103
183
  },
104
184
  'simple_file' => {
105
185
  :store => :File,
106
186
  :options => ':dir => File.join(make_tempdir, "simple_file")',
107
- :specs => SIMPLE_INCR_SPECS
187
+ :specs => STANDARD_SPECS
108
188
  },
109
189
  'simple_file_with_expires' => {
110
190
  :store => :File,
111
191
  :options => ':dir => File.join(make_tempdir, "simple_file_with_expires"), :expires => true',
112
- :specs => EXPIRES_INCR_SPECS
192
+ :specs => STANDARD_SPECS.with_expires
113
193
  },
114
194
  'simple_hashfile' => {
115
195
  :store => :HashFile,
116
196
  :options => ':dir => File.join(make_tempdir, "simple_hashfile")',
117
- :specs => SIMPLE_INCR_SPECS
197
+ :specs => STANDARD_SPECS
118
198
  },
119
199
  'simple_hashfile_with_expires' => {
120
200
  :store => :HashFile,
121
201
  :options => ':dir => File.join(make_tempdir, "simple_hashfile_with_expires"), :expires => true',
122
- :specs => EXPIRES_INCR_SPECS
202
+ :specs => STANDARD_SPECS.with_expires
123
203
  },
124
204
  'simple_cassandra' => {
125
205
  :store => :Cassandra,
126
206
  :options => ':keyspace => "simple_cassandra"',
127
- :specs => NATIVE_EXPIRES_SPECS,
207
+ :specs => STANDARD_SPECS.without_increment.with_native_expires,
128
208
  },
129
209
  'simple_hbase' => {
130
210
  :store => :HBase,
131
211
  :options => ':table => "simple_hbase"',
132
- :specs => SIMPLE_INCR_SPECS
212
+ :specs => STANDARD_SPECS
133
213
  },
134
214
  'simple_hbase_with_expires' => {
135
215
  :store => :HBase,
136
216
  :options => ':table => "simple_hbase", :expires => true',
137
- :specs => EXPIRES_INCR_SPECS,
217
+ :specs => STANDARD_SPECS.with_expires,
138
218
  },
139
219
  'simple_dbm' => {
140
220
  :store => :DBM,
141
221
  :options => ':file => File.join(make_tempdir, "simple_dbm")',
142
- :specs => SIMPLE_INCR_SPECS
222
+ :specs => STANDARD_SPECS
143
223
  },
144
224
  'simple_dbm_with_expires' => {
145
225
  :store => :DBM,
146
226
  :options => ':file => File.join(make_tempdir, "simple_dbm_with_expires"), :expires => true',
147
- :specs => EXPIRES_INCR_SPECS
227
+ :specs => STANDARD_SPECS.with_expires
148
228
  },
149
229
  'simple_gdbm' => {
150
230
  :store => :GDBM,
151
231
  :options => ':file => File.join(make_tempdir, "simple_gdbm")',
152
- :specs => SIMPLE_INCR_SPECS
232
+ :specs => STANDARD_SPECS
153
233
  },
154
234
  'simple_gdbm_with_expires' => {
155
235
  :store => :GDBM,
156
236
  :options => ':file => File.join(make_tempdir, "simple_gdbm_with_expires"), :expires => true',
157
- :specs => EXPIRES_INCR_SPECS
237
+ :specs => STANDARD_SPECS.with_expires
158
238
  },
159
239
  'simple_sdbm' => {
160
240
  :store => :SDBM,
161
241
  :options => ':file => File.join(make_tempdir, "simple_sdbm")',
162
- :specs => SIMPLE_INCR_SPECS
242
+ :specs => STANDARD_SPECS
163
243
  },
164
244
  'simple_sdbm_with_expires' => {
165
245
  :store => :SDBM,
166
246
  :options => ':file => File.join(make_tempdir, "simple_sdbm_with_expires"), :expires => true',
167
- :specs => EXPIRES_INCR_SPECS
247
+ :specs => STANDARD_SPECS.with_expires
168
248
  },
169
249
  'simple_leveldb' => {
170
250
  :store => :LevelDB,
171
251
  :options => ':dir => File.join(make_tempdir, "simple_leveldb")',
172
- :specs => SIMPLE_INCR_SPECS
252
+ :specs => STANDARD_SPECS
173
253
  },
174
254
  'simple_leveldb_with_expires' => {
175
255
  :store => :LevelDB,
176
256
  :options => ':dir => File.join(make_tempdir, "simple_leveldb_with_expires"), :expires => true',
177
- :specs => EXPIRES_INCR_SPECS
257
+ :specs => STANDARD_SPECS.with_expires
178
258
  },
179
259
  'simple_pstore' => {
180
260
  :store => :PStore,
181
261
  :options => ':file => File.join(make_tempdir, "simple_pstore")',
182
262
  :load_value => 'value',
183
- :specs => SIMPLE_INCR_SPECS
263
+ :specs => STANDARD_SPECS
184
264
  },
185
265
  'simple_pstore_with_expires' => {
186
266
  :store => :PStore,
187
267
  :options => ':file => File.join(make_tempdir, "simple_pstore_with_expires"), :expires => true',
188
268
  :load_value => 'value',
189
- :specs => EXPIRES_INCR_SPECS
269
+ :specs => STANDARD_SPECS.with_expires
190
270
  },
191
271
  'simple_yaml' => {
192
272
  :store => :YAML,
193
273
  :options => ':file => File.join(make_tempdir, "simple_yaml")',
194
- :specs => [:null, :store, :returndifferent, :marshallable_key, :increment, :transform_value],
274
+ :specs => STANDARD_SPECS.without_marshallable_value,
195
275
  :load_value => 'value'
196
276
  },
197
277
  'simple_yaml_with_expires' => {
198
278
  :store => :YAML,
199
279
  :options => ':file => File.join(make_tempdir, "simple_yaml_with_expires"), :expires => true',
200
- :specs => [:null, :store, :returndifferent, :marshallable_key, :expires_stringkey_stringvalue, :increment, :transform_value_with_expires],
280
+ :specs => STANDARD_SPECS.without_marshallable_value.with_expires,
201
281
  :load_value => 'value'
202
282
  },
203
283
  'simple_localmemcache' => {
204
284
  :store => :LocalMemCache,
205
285
  :options => ':file => File.join(make_tempdir, "simple_localmemcache")',
206
- :specs => SIMPLE_SPECS
286
+ :specs => STANDARD_SPECS.without_increment
207
287
  },
208
288
  'simple_localmemcache_with_expires' => {
209
289
  :store => :LocalMemCache,
210
290
  :options => ':file => File.join(make_tempdir, "simple_localmemcache_with_expires"), :expires => true',
211
- :specs => EXPIRES_SPECS
291
+ :specs => STANDARD_SPECS.without_increment.with_expires
212
292
  },
213
293
  'simple_tokyocabinet' => {
214
294
  :store => :TokyoCabinet,
215
295
  :options => ':file => File.join(make_tempdir, "simple_tokyocabinet")',
216
- :specs => SIMPLE_INCR_SPECS
296
+ :specs => STANDARD_SPECS
217
297
  },
218
298
  'simple_tokyocabinet_with_expires' => {
219
299
  :store => :TokyoCabinet,
220
300
  :options => ':file => File.join(make_tempdir, "simple_tokyocabinet_with_expires"), :expires => true',
221
- :specs => EXPIRES_INCR_SPECS
301
+ :specs => STANDARD_SPECS.with_expires
222
302
  },
223
303
  'simple_sqlite' => {
224
304
  :store => :Sqlite,
225
305
  :options => ':file => File.join(make_tempdir, "simple_sqlite")',
226
- :specs => SIMPLE_INCR_SPECS
306
+ :specs => STANDARD_SPECS
227
307
  },
228
308
  'simple_sqlite_with_expires' => {
229
309
  :store => :Sqlite,
230
310
  :options => ':file => File.join(make_tempdir, "simple_sqlite_with_expires"), :expires => true',
231
- :specs => EXPIRES_INCR_SPECS
311
+ :specs => STANDARD_SPECS.with_expires
232
312
  },
233
313
  'simple_redis' => {
234
314
  :store => :Redis,
235
- :specs => NATIVE_EXPIRES_INCR_SPECS,
315
+ :specs => STANDARD_SPECS.with_native_expires,
236
316
  },
237
317
  'simple_memcached' => {
238
318
  :store => :Memcached,
239
- :specs => NATIVE_EXPIRES_INCR_SPECS,
319
+ :specs => STANDARD_SPECS.with_native_expires,
240
320
  :options => ':namespace => "simple_memcached"'
241
321
  },
242
322
  'simple_memcached_dalli' => {
243
323
  :store => :MemcachedDalli,
244
- :specs => NATIVE_EXPIRES_INCR_SPECS,
324
+ :specs => STANDARD_SPECS.with_native_expires,
245
325
  :options => ':namespace => "simple_memcached_dalli"'
246
326
  },
247
327
  'simple_memcached_native' => {
248
328
  :store => :MemcachedNative,
249
- :specs => NATIVE_EXPIRES_INCR_SPECS,
329
+ :specs => STANDARD_SPECS.with_native_expires,
250
330
  :options => ':namespace => "simple_memcached_native"'
251
331
  },
252
332
  'simple_riak' => {
@@ -254,60 +334,60 @@ end
254
334
  :options => ":bucket => 'simple_riak'",
255
335
  # We don't want Riak warnings in tests
256
336
  :preamble => "require 'riak'\n\nRiak.disable_list_keys_warnings = true\n\n",
257
- :specs => SIMPLE_SPECS
337
+ :specs => STANDARD_SPECS.without_increment
258
338
  },
259
339
  'simple_riak_with_expires' => {
260
340
  :store => :Riak,
261
341
  :options => ":bucket => 'simple_riak_with_expires', :expires => true",
262
342
  # We don't want Riak warnings in tests
263
343
  :preamble => "require 'riak'\n\nRiak.disable_list_keys_warnings = true\n\n",
264
- :specs => EXPIRES_SPECS
344
+ :specs => STANDARD_SPECS.without_increment.with_expires
265
345
  },
266
346
  'simple_couch' => {
267
347
  :store => :Couch,
268
348
  :options => ":db => 'simple_couch'",
269
349
  :load_value => '::Marshal.load(value.unpack(\'m\').first)',
270
- :specs => SIMPLE_SPECS
350
+ :specs => STANDARD_SPECS.without_increment
271
351
  },
272
352
  'simple_couch_with_expires' => {
273
353
  :store => :Couch,
274
354
  :options => ":db => 'simple_couch_with_expires', :expires => true",
275
- :specs => EXPIRES_SPECS,
355
+ :specs => STANDARD_SPECS.without_increment.with_expires,
276
356
  :load_value => '::Marshal.load(value.unpack(\'m\').first)'
277
357
  },
278
358
  'simple_mongo' => {
279
359
  :store => :Mongo,
280
360
  :options => ":db => 'simple_mongo'",
281
- :specs => SIMPLE_SPECS
361
+ :specs => STANDARD_SPECS.without_increment
282
362
  },
283
363
  'simple_mongo_with_expires' => {
284
364
  :store => :Mongo,
285
365
  :options => ":db => 'simple_mongo_with_expires', :expires => true",
286
- :specs => EXPIRES_SPECS
366
+ :specs => STANDARD_SPECS.without_increment.with_expires
287
367
  },
288
368
  'simple_null' => {
289
369
  :store => :Null,
290
- :specs => [:null, :marshallable_key, :returndifferent]
370
+ :specs => STANDARD_SPECS.without_increment.without_store.without_persist
291
371
  },
292
372
  'null_adapter' => {
293
373
  :build => 'Moneta::Adapters::Null.new',
294
- :specs => [:null]
374
+ :specs => Specs.new([:null, :not_increment, :not_persist])
295
375
  },
296
376
  'simple_sequel' => {
297
377
  :store => :Sequel,
298
378
  :options => ':db => (defined?(JRUBY_VERSION) ? "jdbc:sqlite:" : "sqlite:") + File.join(make_tempdir, "simple_sequel")',
299
379
  :load_value => '::Marshal.load(value.unpack(\'m\').first)',
300
- :specs => SIMPLE_INCR_SPECS
380
+ :specs => STANDARD_SPECS
301
381
  },
302
382
  'simple_sequel_with_expires' => {
303
383
  :store => :Sequel,
304
384
  :options => ':db => (defined?(JRUBY_VERSION) ? "jdbc:sqlite:" : "sqlite:") + File.join(make_tempdir, "simple_sequel_with_expires"), :expires => true',
305
- :specs => EXPIRES_INCR_SPECS,
385
+ :specs => STANDARD_SPECS.with_expires,
306
386
  :load_value => '::Marshal.load(value.unpack(\'m\').first)'
307
387
  },
308
388
  'simple_datamapper' => {
309
389
  :store => :DataMapper,
310
- :specs => SIMPLE_SPECS,
390
+ :specs => STANDARD_SPECS.without_increment,
311
391
  :options => ':setup => "sqlite3://#{make_tempdir}/simple_datamapper"',
312
392
  # DataMapper needs default repository to be setup
313
393
  :preamble => "require 'dm-core'\nDataMapper.setup(:default, :adapter => :in_memory)\n",
@@ -318,12 +398,12 @@ end
318
398
  :options => ':setup => "sqlite3://#{make_tempdir}/simple_datamapper_with_expires", :expires => true',
319
399
  # DataMapper needs default repository to be setup
320
400
  :preamble => "require 'dm-core'\nDataMapper.setup(:default, :adapter => :in_memory)\n",
321
- :specs => EXPIRES_SPECS,
401
+ :specs => STANDARD_SPECS.without_increment.with_expires,
322
402
  :load_value => '::Marshal.load(value.unpack(\'m\').first)'
323
403
  },
324
404
  'simple_datamapper_with_repository' => {
325
405
  :store => :DataMapper,
326
- :specs => SIMPLE_SPECS,
406
+ :specs => STANDARD_SPECS.without_increment,
327
407
  :options => ':repository => :repo, :setup => "sqlite3://#{make_tempdir}/simple_datamapper_with_repository"',
328
408
  # DataMapper needs default repository to be setup
329
409
  :preamble => "require 'dm-core'\nDataMapper.setup(:default, :adapter => :in_memory)\n",
@@ -331,19 +411,19 @@ end
331
411
  },
332
412
  'simple_activerecord' => {
333
413
  :store => :ActiveRecord,
334
- :specs => SIMPLE_INCR_SPECS,
414
+ :specs => STANDARD_SPECS,
335
415
  :options => ":connection => { :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'simple_activerecord') }",
336
416
  :load_value => '::Marshal.load(value.unpack(\'m\').first)'
337
417
  },
338
418
  'simple_activerecord_with_expires' => {
339
419
  :store => :ActiveRecord,
340
420
  :options => ":connection => { :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'simple_activerecord_with_expires') }, :expires => true",
341
- :specs => EXPIRES_INCR_SPECS,
421
+ :specs => STANDARD_SPECS.with_expires,
342
422
  :load_value => '::Marshal.load(value.unpack(\'m\').first)'
343
423
  },
344
424
  'simple_fog' => {
345
425
  :store => :Fog,
346
- :specs => SIMPLE_SPECS,
426
+ :specs => STANDARD_SPECS.without_increment,
347
427
  :options => ":aws_access_key_id => 'fake_access_key_id',
348
428
  :aws_secret_access_key => 'fake_secret_access_key',
349
429
  :provider => 'AWS',
@@ -360,14 +440,14 @@ end
360
440
  :expires => true",
361
441
  # Put Fog into testing mode
362
442
  :preamble => "require 'fog'\nFog.mock!\n",
363
- :specs => EXPIRES_SPECS
443
+ :specs => STANDARD_SPECS.without_increment.with_expires
364
444
  },
365
445
  'expires_memory' => {
366
446
  :build => %{Moneta.build do
367
447
  use :Expires
368
448
  adapter :Memory
369
449
  end},
370
- :specs => [:null, :store, :expires, :increment],
450
+ :specs => STANDARD_SPECS.without_transform.with_expires.without_persist,
371
451
  :tests => %{
372
452
  it 'should support default expiration time' do
373
453
  store = Moneta.new(:Memory, :expires => 2)
@@ -387,7 +467,7 @@ end}
387
467
  use :Transformer, :key => [:marshal, :escape], :value => :marshal
388
468
  adapter :File, :dir => File.join(make_tempdir, "expires-file")
389
469
  end},
390
- :specs => [:null, :store, :expires, :returndifferent, :marshallable_key, :increment],
470
+ :specs => STANDARD_SPECS.with_expires.stringvalues_only,
391
471
  :tests => %{
392
472
  it 'should delete expired value in underlying file storage' do
393
473
  store.store('foo', 'bar', :expires => 2)
@@ -407,7 +487,7 @@ end
407
487
  use :Proxy
408
488
  adapter :Redis
409
489
  end},
410
- :specs => ADAPTER_EXPIRES_INCR_SPECS
490
+ :specs => ADAPTER_SPECS.with_expires
411
491
  },
412
492
  'proxy_expires_memory' => {
413
493
  :build => %{Moneta.build do
@@ -416,7 +496,7 @@ end},
416
496
  use :Proxy
417
497
  adapter :Memory
418
498
  end},
419
- :specs => [:null, :store, :expires]
499
+ :specs => STANDARD_SPECS.without_transform.with_expires.without_returndifferent.without_persist
420
500
  },
421
501
  'cache_file_memory' => {
422
502
  :build => %{Moneta.build do
@@ -425,7 +505,7 @@ end},
425
505
  cache { adapter :Memory }
426
506
  end
427
507
  end},
428
- :specs => ADAPTER_INCR_SPECS,
508
+ :specs => ADAPTER_SPECS,
429
509
  :tests => %{
430
510
  it 'should store loaded values in cache' do
431
511
  store.backend['foo'] = 'bar'
@@ -446,15 +526,15 @@ end
446
526
  cache(Moneta::Adapters::Null.new)
447
527
  end
448
528
  end},
449
- :specs => ADAPTER_INCR_SPECS
529
+ :specs => ADAPTER_SPECS.without_persist
450
530
  },
451
531
  'shared' => {
452
532
  :build => %{Moneta.build do
453
- use(:Shared) do
533
+ use(:Shared, :port => 9001) do
454
534
  adapter :Memory
455
535
  end
456
536
  end},
457
- :specs => ADAPTER_INCR_SPECS,
537
+ :specs => ADAPTER_SPECS.without_persist,
458
538
  :tests => %{
459
539
  it 'should share values' do
460
540
  store['shared_key'] = 'shared_value'
@@ -474,7 +554,7 @@ end
474
554
  add { adapter :Memory }
475
555
  end
476
556
  end},
477
- :specs => ADAPTER_SPECS
557
+ :specs => ADAPTER_SPECS.without_increment
478
558
  },
479
559
  'stack_memory_file' => {
480
560
  :build => %{Moneta.build do
@@ -485,22 +565,21 @@ end},
485
565
  add { adapter :File, :dir => File.join(make_tempdir, "stack-file2") }
486
566
  end
487
567
  end},
488
- :specs => [:null_stringkey_stringvalue, :store_stringkey_stringvalue, :not_increment]
568
+ :specs => STANDARD_SPECS.without_increment.without_transform.stringkeys_only.stringvalues_only
489
569
  },
490
570
  'lock' => {
491
571
  :build => %{Moneta.build do
492
572
  use :Lock
493
573
  adapter :Memory
494
574
  end},
495
- :specs => [:null, :store, :increment]
575
+ :specs => STANDARD_SPECS.without_transform.without_returndifferent.without_persist
496
576
  },
497
577
  'transformer_zlib' => {
498
578
  :build => %{Moneta.build do
499
579
  use :Transformer, :value => :zlib
500
580
  adapter :Memory
501
581
  end},
502
- :value => %w(String),
503
- :specs => TRANSFORMER_SPECS,
582
+ :specs => TRANSFORMER_SPECS.stringvalues_only,
504
583
  :load_value => '::Zlib::Inflate.inflate(value)'
505
584
  },
506
585
  'transformer_bzip2' => {
@@ -508,8 +587,7 @@ end},
508
587
  use :Transformer, :value => :bzip2
509
588
  adapter :Memory
510
589
  end},
511
- :value => %w(String),
512
- :specs => TRANSFORMER_SPECS,
590
+ :specs => TRANSFORMER_SPECS.stringvalues_only,
513
591
  :load_value => '::Bzip2.uncompress(value)'
514
592
  },
515
593
  'transformer_lzo' => {
@@ -517,8 +595,7 @@ end},
517
595
  use :Transformer, :value => :lzo
518
596
  adapter :Memory
519
597
  end},
520
- :value => %w(String),
521
- :specs => TRANSFORMER_SPECS,
598
+ :specs => TRANSFORMER_SPECS.stringvalues_only,
522
599
  :load_value => '::LZO.decompress(value)'
523
600
  },
524
601
  'transformer_lzma' => {
@@ -526,8 +603,7 @@ end},
526
603
  use :Transformer, :value => :lzma
527
604
  adapter :Memory
528
605
  end},
529
- :value => %w(String),
530
- :specs => TRANSFORMER_SPECS,
606
+ :specs => TRANSFORMER_SPECS.stringvalues_only,
531
607
  :load_value => '::LZMA.decompress(value)'
532
608
  },
533
609
  'transformer_snappy' => {
@@ -535,8 +611,7 @@ end},
535
611
  use :Transformer, :value => :snappy
536
612
  adapter :Memory
537
613
  end},
538
- :value => %w(String),
539
- :specs => TRANSFORMER_SPECS,
614
+ :specs => TRANSFORMER_SPECS.stringvalues_only,
540
615
  :load_value => '::Snappy.inflate(value)'
541
616
  },
542
617
  'transformer_quicklz' => {
@@ -544,8 +619,7 @@ end},
544
619
  use :Transformer, :value => :quicklz
545
620
  adapter :Memory
546
621
  end},
547
- :value => %w(String),
548
- :specs => TRANSFORMER_SPECS,
622
+ :specs => TRANSFORMER_SPECS.stringvalues_only,
549
623
  :load_value => '::QuickLZ.decompress(value)'
550
624
  },
551
625
  'transformer_json' => {
@@ -553,9 +627,7 @@ end},
553
627
  use :Transformer, :key => :json, :value => :json
554
628
  adapter :Memory
555
629
  end},
556
- :key => %w(Hash String),
557
- :value => %w(Hash String),
558
- :specs => TRANSFORMER_SPECS,
630
+ :specs => TRANSFORMER_SPECS.simplekeys_only.simplevalues_only,
559
631
  :load_value => '::MultiJson.load(value).first'
560
632
  },
561
633
  'transformer_bert' => {
@@ -563,9 +635,7 @@ end},
563
635
  use :Transformer, :key => :bert, :value => :bert
564
636
  adapter :Memory
565
637
  end},
566
- :key => %w(Hash String),
567
- :value => %w(Hash String),
568
- :specs => TRANSFORMER_SPECS,
638
+ :specs => TRANSFORMER_SPECS.simplekeys_only.simplevalues_only,
569
639
  :load_value => '::BERT.decode(value)'
570
640
  },
571
641
  'transformer_bencode' => {
@@ -573,9 +643,7 @@ end},
573
643
  use :Transformer, :key => :bencode, :value => :bencode
574
644
  adapter :Memory
575
645
  end},
576
- :key => %w(Hash String),
577
- :value => %w(Hash String),
578
- :specs => TRANSFORMER_SPECS,
646
+ :specs => TRANSFORMER_SPECS.simplekeys_only.simplevalues_only,
579
647
  :load_value => '::BEncode.load(value)'
580
648
  },
581
649
  'transformer_bson' => {
@@ -583,9 +651,7 @@ end},
583
651
  use :Transformer, :key => :bson, :value => :bson
584
652
  adapter :Memory
585
653
  end},
586
- :key => %w(Hash String),
587
- :value => %w(Hash String),
588
- :specs => TRANSFORMER_SPECS,
654
+ :specs => TRANSFORMER_SPECS.simplekeys_only.simplevalues_only,
589
655
  :load_value => "::BSON.deserialize(value)['v']"
590
656
  },
591
657
  'transformer_ox' => {
@@ -601,9 +667,7 @@ end},
601
667
  use :Transformer, :key => :tnet, :value => :tnet
602
668
  adapter :Memory
603
669
  end},
604
- :key => %w(Hash String),
605
- :value => %w(Hash String),
606
- :specs => TRANSFORMER_SPECS,
670
+ :specs => TRANSFORMER_SPECS.simplekeys_only.simplevalues_only,
607
671
  :load_value => '::TNetstring.parse(value).first'
608
672
  },
609
673
  'transformer_msgpack' => {
@@ -611,9 +675,7 @@ end},
611
675
  use :Transformer, :key => :msgpack, :value => :msgpack
612
676
  adapter :Memory
613
677
  end},
614
- :key => %w(Hash String),
615
- :value => %w(Hash String),
616
- :specs => TRANSFORMER_SPECS,
678
+ :specs => TRANSFORMER_SPECS.simplekeys_only.simplevalues_only,
617
679
  :load_value => '::MessagePack.unpack(value)'
618
680
  },
619
681
  'transformer_yaml' => {
@@ -629,7 +691,7 @@ end},
629
691
  use :Transformer, :key => :marshal, :value => [:marshal, :hmac], :secret => 'secret'
630
692
  adapter :Memory
631
693
  end},
632
- :specs => SIMPLE_INCR_SPECS,
694
+ :specs => STANDARD_SPECS.without_persist,
633
695
  :load_value => '::Marshal.load(::Moneta::Transformer::Helper.hmacverify(value, \'secret\'))'
634
696
  },
635
697
  'transformer_marshal_base64' => {
@@ -637,7 +699,7 @@ end},
637
699
  use :Transformer, :key => [:marshal, :base64], :value => [:marshal, :base64]
638
700
  adapter :Memory
639
701
  end},
640
- :specs => SIMPLE_INCR_SPECS,
702
+ :specs => STANDARD_SPECS.without_persist,
641
703
  :load_value => '::Marshal.load(value.unpack(\'m\').first)'
642
704
  },
643
705
  'transformer_marshal_prefix' => {
@@ -645,14 +707,14 @@ end},
645
707
  use :Transformer, :key => [:marshal, :prefix], :value => :marshal, :prefix => 'moneta'
646
708
  adapter :Memory
647
709
  end},
648
- :specs => SIMPLE_INCR_SPECS
710
+ :specs => STANDARD_SPECS.without_persist
649
711
  },
650
712
  'transformer_marshal_uuencode' => {
651
713
  :build => %{Moneta.build do
652
714
  use :Transformer, :key => [:marshal, :uuencode], :value => [:marshal, :uuencode]
653
715
  adapter :Memory
654
716
  end},
655
- :specs => SIMPLE_INCR_SPECS,
717
+ :specs => STANDARD_SPECS.without_persist,
656
718
  :load_value => '::Marshal.load(value.unpack(\'u\').first)'
657
719
  },
658
720
  'transformer_marshal_escape' => {
@@ -660,67 +722,67 @@ end},
660
722
  use :Transformer, :key => [:marshal, :escape], :value => :marshal
661
723
  adapter :Memory
662
724
  end},
663
- :specs => SIMPLE_INCR_SPECS
725
+ :specs => STANDARD_SPECS.without_persist
664
726
  },
665
727
  'transformer_marshal_md5' => {
666
728
  :build => %{Moneta.build do
667
729
  use :Transformer, :key => [:marshal, :md5], :value => :marshal
668
730
  adapter :Memory
669
731
  end},
670
- :specs => SIMPLE_INCR_SPECS,
732
+ :specs => STANDARD_SPECS.without_persist,
671
733
  },
672
734
  'transformer_marshal_sha1' => {
673
735
  :build => %{Moneta.build do
674
736
  use :Transformer, :key => [:marshal, :sha1], :value => :marshal
675
737
  adapter :Memory
676
738
  end},
677
- :specs => SIMPLE_INCR_SPECS,
739
+ :specs => STANDARD_SPECS.without_persist,
678
740
  },
679
741
  'transformer_marshal_sha256' => {
680
742
  :build => %{Moneta.build do
681
743
  use :Transformer, :key => [:marshal, :sha256], :value => :marshal
682
744
  adapter :Memory
683
745
  end},
684
- :specs => SIMPLE_INCR_SPECS,
746
+ :specs => STANDARD_SPECS.without_persist,
685
747
  },
686
748
  'transformer_marshal_sha384' => {
687
749
  :build => %{Moneta.build do
688
750
  use :Transformer, :key => [:marshal, :sha384], :value => :marshal
689
751
  adapter :Memory
690
752
  end},
691
- :specs => SIMPLE_INCR_SPECS,
753
+ :specs => STANDARD_SPECS.without_persist,
692
754
  },
693
755
  'transformer_marshal_sha512' => {
694
756
  :build => %{Moneta.build do
695
757
  use :Transformer, :key => [:marshal, :sha512], :value => :marshal
696
758
  adapter :Memory
697
759
  end},
698
- :specs => SIMPLE_INCR_SPECS,
760
+ :specs => STANDARD_SPECS.without_persist,
699
761
  },
700
762
  'transformer_marshal_rmd160' => {
701
763
  :build => %{Moneta.build do
702
764
  use :Transformer, :key => [:marshal, :rmd160], :value => :marshal
703
765
  adapter :Memory
704
766
  end},
705
- :specs => SIMPLE_INCR_SPECS,
767
+ :specs => STANDARD_SPECS.without_persist,
706
768
  },
707
769
  'transformer_marshal_md5_spread' => {
708
770
  :build => %{Moneta.build do
709
771
  use :Transformer, :key => [:marshal, :md5, :spread], :value => :marshal
710
772
  adapter :Memory
711
773
  end},
712
- :specs => SIMPLE_INCR_SPECS,
774
+ :specs => STANDARD_SPECS.without_persist,
713
775
  },
714
776
  'transformer_marshal_truncate' => {
715
777
  :build => %{Moneta.build do
716
778
  use :Transformer, :key => [:marshal, :truncate], :value => :marshal, :maxlen => 64
717
779
  adapter :Memory
718
780
  end},
719
- :specs => SIMPLE_INCR_SPECS,
781
+ :specs => STANDARD_SPECS.without_persist,
720
782
  },
721
783
  'adapter_activerecord' => {
722
784
  :build => "Moneta::Adapters::ActiveRecord.new(:connection => { :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'adapter_activerecord') })",
723
- :specs => ADAPTER_INCR_SPECS,
785
+ :specs => ADAPTER_SPECS,
724
786
  :tests => %{
725
787
  it 'updates an existing key/value' do
726
788
  store['foo/bar'] = '1'
@@ -738,13 +800,13 @@ end
738
800
  }
739
801
  },
740
802
  'adapter_client' => {
741
- :preamble => "$tcp_server ||= Moneta::Server.new(Moneta::Adapters::Memory.new)\n",
803
+ :preamble => "start_server(Moneta::Adapters::Memory.new)\n",
742
804
  :build => "Moneta::Adapters::Client.new",
743
- :specs => ADAPTER_INCR_SPECS
805
+ :specs => ADAPTER_SPECS
744
806
  },
745
807
  'adapter_cassandra' => {
746
808
  :build => "Moneta::Adapters::Cassandra.new(:keyspace => 'adapter_cassandra')",
747
- :specs => ADAPTER_EXPIRES_SPECS,
809
+ :specs => ADAPTER_SPECS.without_increment.with_expires,
748
810
  :tests => %{
749
811
  it 'should support default expiration time' do
750
812
  store = Moneta::Adapters::Cassandra.new(:expires => 2, :keyspace => 'adapter_cassandra')
@@ -760,21 +822,21 @@ end}
760
822
  },
761
823
  'adapter_hbase' => {
762
824
  :build => "Moneta::Adapters::HBase.new(:table => 'adapter_hbase')",
763
- :specs => ADAPTER_INCR_SPECS
825
+ :specs => ADAPTER_SPECS
764
826
  },
765
827
  'adapter_cookie' => {
766
828
  :build => 'Moneta::Adapters::Cookie.new',
767
- :specs => ADAPTER_INCR_SPECS
829
+ :specs => ADAPTER_SPECS.without_persist
768
830
  },
769
831
  'adapter_couch' => {
770
832
  :build => "Moneta::Adapters::Couch.new(:db => 'adapter_couch')",
771
- :specs => ADAPTER_SPECS
833
+ :specs => ADAPTER_SPECS.without_increment
772
834
  },
773
835
  'adapter_datamapper' => {
774
836
  :build => 'Moneta::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/adapter_datamapper")',
775
837
  # DataMapper needs default repository to be setup
776
838
  :preamble => "require 'dm-core'\nDataMapper.setup(:default, :adapter => :in_memory)\n",
777
- :specs => ADAPTER_SPECS,
839
+ :specs => ADAPTER_SPECS.without_increment,
778
840
  :tests => %q{
779
841
  it 'does not cross contaminate when storing' do
780
842
  first = Moneta::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/datamapper-first")
@@ -808,11 +870,11 @@ end
808
870
  },
809
871
  'adapter_dbm' => {
810
872
  :build => 'Moneta::Adapters::DBM.new(:file => File.join(make_tempdir, "adapter_dbm"))',
811
- :specs => ADAPTER_INCR_SPECS
873
+ :specs => ADAPTER_SPECS
812
874
  },
813
875
  'adapter_file' => {
814
876
  :build => 'Moneta::Adapters::File.new(:dir => File.join(make_tempdir, "adapter_file"))',
815
- :specs => ADAPTER_INCR_SPECS
877
+ :specs => ADAPTER_SPECS
816
878
  },
817
879
  'adapter_fog' => {
818
880
  :build => "Moneta::Adapters::Fog.new(:aws_access_key_id => 'fake_access_key_id',
@@ -821,19 +883,19 @@ end
821
883
  :dir => 'moneta')",
822
884
  # Put Fog into testing mode
823
885
  :preamble => "require 'fog'\nFog.mock!\n",
824
- :specs => ADAPTER_SPECS
886
+ :specs => ADAPTER_SPECS.without_increment
825
887
  },
826
888
  'adapter_gdbm' => {
827
889
  :build => 'Moneta::Adapters::GDBM.new(:file => File.join(make_tempdir, "adapter_gdbm"))',
828
- :specs => ADAPTER_INCR_SPECS
890
+ :specs => ADAPTER_SPECS
829
891
  },
830
892
  'adapter_localmemcache' => {
831
893
  :build => 'Moneta::Adapters::LocalMemCache.new(:file => File.join(make_tempdir, "adapter_localmemcache"))',
832
- :specs => ADAPTER_SPECS
894
+ :specs => ADAPTER_SPECS.without_increment
833
895
  },
834
896
  'adapter_memcached_dalli' => {
835
897
  :build => 'Moneta::Adapters::MemcachedDalli.new(:namespace => "adapter_memcached_dalli")',
836
- :specs => ADAPTER_EXPIRES_INCR_SPECS,
898
+ :specs => ADAPTER_SPECS.with_expires,
837
899
  :tests => %{
838
900
  it 'should support default expiration time' do
839
901
  store = Moneta::Adapters::MemcachedDalli.new(:expires => 2, :namespace => "adapter_memcached_dalli")
@@ -849,7 +911,7 @@ end}
849
911
  },
850
912
  'adapter_memcached_native' => {
851
913
  :build => 'Moneta::Adapters::MemcachedNative.new(:namespace => "adapter_memcached_native")',
852
- :specs => ADAPTER_EXPIRES_INCR_SPECS,
914
+ :specs => ADAPTER_SPECS.with_expires,
853
915
  :tests => %{
854
916
  it 'should support default expiration time' do
855
917
  store = Moneta::Adapters::MemcachedNative.new(:expires => 2, :namespace => "adapter_memcached_native")
@@ -866,7 +928,7 @@ end
866
928
  },
867
929
  'adapter_memcached' => {
868
930
  :build => 'Moneta::Adapters::Memcached.new(:namespace => "adapter_memcached")',
869
- :specs => ADAPTER_EXPIRES_INCR_SPECS,
931
+ :specs => ADAPTER_SPECS.with_expires,
870
932
  :tests => %{
871
933
  it 'should support default expiration time' do
872
934
  store = Moneta::Adapters::Memcached.new(:expires => 2, :namespace => "adapter_memcached")
@@ -882,11 +944,11 @@ end}
882
944
  },
883
945
  'adapter_memory' => {
884
946
  :build => 'Moneta::Adapters::Memory.new',
885
- :specs => [:null, :store, :increment]
947
+ :specs => STANDARD_SPECS.without_transform.without_returndifferent.without_persist
886
948
  },
887
949
  'adapter_lruhash' => {
888
950
  :build => 'Moneta::Adapters::LRUHash.new',
889
- :specs => ADAPTER_INCR_SPECS,
951
+ :specs => ADAPTER_SPECS.without_persist,
890
952
  :tests => %{
891
953
  it 'should delete oldest' do
892
954
  store = Moneta::Adapters::LRUHash.new(:max_size => 10)
@@ -904,15 +966,15 @@ end}
904
966
  },
905
967
  'adapter_mongo' => {
906
968
  :build => 'Moneta::Adapters::Mongo.new(:db => "adapter_mongo")',
907
- :specs => ADAPTER_SPECS
969
+ :specs => ADAPTER_SPECS.without_increment
908
970
  },
909
971
  'adapter_pstore' => {
910
972
  :build => 'Moneta::Adapters::PStore.new(:file => File.join(make_tempdir, "adapter_pstore"))',
911
- :specs => PSTORE_SPECS
973
+ :specs => STANDARD_SPECS.without_transform
912
974
  },
913
975
  'adapter_redis' => {
914
976
  :build => 'Moneta::Adapters::Redis.new',
915
- :specs => ADAPTER_EXPIRES_INCR_SPECS,
977
+ :specs => ADAPTER_SPECS.with_expires,
916
978
  :tests => %{
917
979
  it 'should support default expiration time' do
918
980
  store = Moneta::Adapters::Redis.new(:expires => 2)
@@ -929,41 +991,41 @@ end}
929
991
  'adapter_riak' => {
930
992
  :build => 'Moneta::Adapters::Riak.new',
931
993
  :options => ":bucket => 'adapter_riak'",
932
- :specs => ADAPTER_SPECS,
994
+ :specs => ADAPTER_SPECS.without_increment,
933
995
  # We don't want Riak warnings in tests
934
996
  :preamble => "require 'riak'\n\nRiak.disable_list_keys_warnings = true\n\n"
935
997
  },
936
998
  'adapter_sdbm' => {
937
999
  :build => 'Moneta::Adapters::SDBM.new(:file => File.join(make_tempdir, "adapter_sdbm"))',
938
- :specs => ADAPTER_INCR_SPECS
1000
+ :specs => ADAPTER_SPECS
939
1001
  },
940
1002
  'adapter_leveldb' => {
941
1003
  :build => 'Moneta::Adapters::LevelDB.new(:dir => File.join(make_tempdir, "adapter_leveldb"))',
942
- :specs => ADAPTER_INCR_SPECS
1004
+ :specs => ADAPTER_SPECS
943
1005
  },
944
1006
  'adapter_sequel' => {
945
1007
  :build => 'Moneta::Adapters::Sequel.new(:db => (defined?(JRUBY_VERSION) ? "jdbc:sqlite:" : "sqlite:") + File.join(make_tempdir, "adapter_sequel"))',
946
- :specs => ADAPTER_INCR_SPECS
1008
+ :specs => ADAPTER_SPECS
947
1009
  },
948
1010
  'adapter_sqlite' => {
949
1011
  :build => 'Moneta::Adapters::Sqlite.new(:file => File.join(make_tempdir, "adapter_sqlite"))',
950
- :specs => ADAPTER_INCR_SPECS
1012
+ :specs => ADAPTER_SPECS
951
1013
  },
952
1014
  'adapter_tokyocabinet_bdb' => {
953
1015
  :build => 'Moneta::Adapters::TokyoCabinet.new(:file => File.join(make_tempdir, "adapter_tokyocabinet_bdb"), :type => :bdb)',
954
- :specs => ADAPTER_INCR_SPECS
1016
+ :specs => ADAPTER_SPECS
955
1017
  },
956
1018
  'adapter_tokyocabinet_hdb' => {
957
1019
  :build => 'Moneta::Adapters::TokyoCabinet.new(:file => File.join(make_tempdir, "adapter_tokyocabinet_hdb"), :type => :hdb)',
958
- :specs => ADAPTER_INCR_SPECS
1020
+ :specs => ADAPTER_SPECS
959
1021
  },
960
1022
  'adapter_yaml' => {
961
1023
  :build => 'Moneta::Adapters::YAML.new(:file => File.join(make_tempdir, "adapter_yaml"))',
962
- :specs => PSTORE_SPECS
1024
+ :specs => STANDARD_SPECS.simplevalues_only.simplekeys_only.without_transform
963
1025
  },
964
1026
  'optionmerger' => {
965
1027
  :store => :Memory,
966
- :specs => [],
1028
+ :specs => Specs.new([]),
967
1029
  :tests => %{
968
1030
  it '#with should return OptionMerger' do
969
1031
  options = {:optionname => :optionvalue}
@@ -1048,13 +1110,18 @@ end}
1048
1110
  SPECS = {}
1049
1111
 
1050
1112
  KEYS = {
1113
+ 'Nil' => [0, 'nil'],
1114
+ 'Integer' => [-10, 42],
1115
+ 'Boolean' => [true, false],
1051
1116
  'String' => ['strkey1', 'strkey2'].map(&:inspect),
1052
1117
  'Object' => ['Value.new(:objkey1)', 'Value.new(:objkey2)'],
1053
1118
  'Hash' => [{'hashkey1' => 'hashkey2'}, {'hashkey3' => 'hashkey4'}].map(&:inspect)
1054
1119
  }
1055
1120
 
1056
1121
  VALUES = {
1057
- 'Boolean' => [true, false],
1122
+ 'Nil' => [0, 'nil'],
1123
+ 'Integer' => [41, -12],
1124
+ 'Boolean' => [false, true],
1058
1125
  'String' => ['strval1', 'strval2'].map(&:inspect),
1059
1126
  'Hash' => [{'hashval1' => ['array1', 1]}, {'hashval3' => ['array2', {'hashval4' => 42}]}].map(&:inspect),
1060
1127
  'Object' => ['Value.new(:objval1)', 'Value.new(:objval2)'],
@@ -1066,19 +1133,27 @@ KEYS.each do |key_type, (key1,key2)|
1066
1133
  code = %{it "reads from keys that are #{key_type}s like a Hash" do
1067
1134
  store[#{key1}].should == nil
1068
1135
  store.load(#{key1}).should == nil
1136
+
1137
+ store[#{key2}].should == nil
1138
+ store.load(#{key2}).should == nil
1069
1139
  end
1070
1140
 
1071
1141
  it "guarantees that the same #{val_type} value is returned when setting a #{key_type} key" do
1072
1142
  value = #{val1}
1073
1143
  (store[#{key1}] = value).should equal(value)
1144
+
1145
+ value = #{val2}
1146
+ (store[#{key2}] = value).should equal(value)
1074
1147
  end
1075
1148
 
1076
1149
  it "returns false from key? if a #{key_type} key is not available" do
1077
1150
  store.key?(#{key1}).should == false
1151
+ store.key?(#{key2}).should == false
1078
1152
  end
1079
1153
 
1080
1154
  it "returns nil from delete if an element for a #{key_type} key does not exist" do
1081
1155
  store.delete(#{key1}).should == nil
1156
+ store.delete(#{key2}).should == nil
1082
1157
  end
1083
1158
 
1084
1159
  it "removes all #{key_type} keys from the store with clear" do
@@ -1091,6 +1166,7 @@ end
1091
1166
 
1092
1167
  it "fetches a #{key_type} key with a default value with fetch, if the key is not available" do
1093
1168
  store.fetch(#{key1}, #{val1}).should == #{val1}
1169
+ store.fetch(#{key2}, #{val2}).should == #{val2}
1094
1170
  end
1095
1171
 
1096
1172
  it "fetches a #{key_type} key with a block with fetch, if the key is not available" do
@@ -1100,6 +1176,13 @@ it "fetches a #{key_type} key with a block with fetch, if the key is not availab
1100
1176
  k.should equal(key)
1101
1177
  value
1102
1178
  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)
1103
1186
  end
1104
1187
 
1105
1188
  it 'should accept options' do
@@ -1117,6 +1200,10 @@ end}
1117
1200
  store[#{key1}] = #{val1}
1118
1201
  store[#{key1}].should == #{val1}
1119
1202
  store.load(#{key1}).should == #{val1}
1203
+
1204
+ store[#{key2}] = #{val2}
1205
+ store[#{key2}].should == #{val2}
1206
+ store.load(#{key2}).should == #{val2}
1120
1207
  end
1121
1208
 
1122
1209
  it "returns true from key? if a #{key_type} key is available" do
@@ -1131,6 +1218,11 @@ it "stores #{val_type} values with #{key_type} keys with #store" do
1131
1218
  store.store(#{key1}, value).should equal(value)
1132
1219
  store[#{key1}].should == #{val1}
1133
1220
  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}
1134
1226
  end
1135
1227
 
1136
1228
  it "stores #{key_type} after clear" do
@@ -1146,6 +1238,10 @@ it "removes and returns a #{val_type} element with a #{key_type} key from the ba
1146
1238
  store[#{key1}] = #{val1}
1147
1239
  store.delete(#{key1}).should == #{val1}
1148
1240
  store.key?(#{key1}).should == false
1241
+
1242
+ store[#{key2}] = #{val2}
1243
+ store.delete(#{key2}).should == #{val2}
1244
+ store.key?(#{key2}).should == false
1149
1245
  end
1150
1246
 
1151
1247
  it "overwrites existing #{val_type} values with #{key_type}" do
@@ -1155,166 +1251,235 @@ it "overwrites existing #{val_type} values with #{key_type}" do
1155
1251
  store[#{key1}].should == #{val2}
1156
1252
  end
1157
1253
 
1158
- it "does not run the block if the #{key_type} key is available" do
1159
- store[#{key1}] = #{val1}
1160
- unaltered = "unaltered"
1161
- store.fetch(#{key1}) { unaltered = "altered" }
1162
- unaltered.should == "unaltered"
1163
- end
1164
-
1165
1254
  it "fetches a #{key_type} key with a default value with fetch, if the key is available" do
1166
1255
  store[#{key1}] = #{val1}
1167
1256
  store.fetch(#{key1}, #{val2}).should == #{val1}
1168
1257
  end}
1258
+
1259
+ if val_type != 'Nil'
1260
+ code << %{
1261
+ it "does not run the block if the #{key_type} key is available" do
1262
+ store[#{key1}] = #{val1}
1263
+ unaltered = 'unaltered'
1264
+ store.fetch(#{key1}) { unaltered = 'altered' }
1265
+ unaltered.should == 'unaltered'
1266
+
1267
+ store[#{key2}] = #{val2}
1268
+ unaltered = 'unaltered'
1269
+ store.fetch(#{key2}) { unaltered = 'altered' }
1270
+ unaltered.should == 'unaltered'
1271
+ end}
1272
+ end
1273
+
1169
1274
  SPECS["store_#{key_type.downcase}key_#{val_type.downcase}value"] = code
1170
1275
 
1171
1276
  code = %{it "guarantees that a different #{val_type} value is retrieved from the #{key_type} key" do
1172
1277
  value = #{val1}
1173
1278
  store[#{key1}] = #{val1}
1174
1279
  store[#{key1}].should_not be_equal(#{val1})
1280
+
1281
+ value = #{val2}
1282
+ store[#{key2}] = #{val2}
1283
+ store[#{key2}].should_not be_equal(#{val2})
1175
1284
  end}
1176
- if val_type != 'Boolean'
1285
+ if val_type != 'Boolean' && val_type != 'Nil' && val_type != 'Integer'
1177
1286
  SPECS["returndifferent_#{key_type.downcase}key_#{val_type.downcase}value"] = code
1178
1287
  end
1179
1288
 
1180
- code = %{it 'should support expires on store and #[]' do
1181
- store.store(#{key1}, #{val1}, :expires => 2)
1289
+ code = %{it "persists #{val_type} values with #{key_type} keys" do
1290
+ store[#{key1}] = #{val1}
1291
+ store[#{key2}] = #{val2}
1292
+ store.close
1293
+ @store = nil
1294
+
1182
1295
  store[#{key1}].should == #{val1}
1296
+ store[#{key2}].should == #{val2}
1297
+ end}
1298
+ SPECS["persist_#{key_type.downcase}key_#{val_type.downcase}value"] = code
1299
+ end
1300
+ end
1301
+
1302
+ SPECS['not_persist'] = %{it "does not persist values" do
1303
+ store['key'] = 'val'
1304
+ store.close
1305
+ @store = nil
1306
+
1307
+ store['key'].should be_nil
1308
+ end}
1309
+
1310
+ SPECS['expires'] = %{it 'should support expires on store and #[]' do
1311
+ store.store('key1', 'val1', :expires => 2)
1312
+ store['key1'].should == 'val1'
1183
1313
  sleep 1
1184
- store[#{key1}].should == #{val1}
1314
+ store['key1'].should == 'val1'
1185
1315
  sleep 2
1186
- store[#{key1}].should == nil
1316
+ store['key1'].should == nil
1187
1317
  end
1188
1318
 
1189
1319
  it 'should support expires on store and load' do
1190
- store.store(#{key1}, #{val1}, :expires => 2)
1191
- store.load(#{key1}).should == #{val1}
1320
+ store.store('key1', 'val1', :expires => 2)
1321
+ store.load('key1').should == 'val1'
1192
1322
  sleep 1
1193
- store.load(#{key1}).should == #{val1}
1323
+ store.load('key1').should == 'val1'
1194
1324
  sleep 2
1195
- store.load(#{key1}).should == nil
1325
+ store.load('key1').should == nil
1196
1326
  end
1197
1327
 
1198
1328
  it 'should support expires on store and key?' do
1199
- store.store(#{key1}, #{val1}, :expires => 2)
1200
- store.key?(#{key1}).should == true
1329
+ store.store('key1', 'val1', :expires => 2)
1330
+ store.key?('key1').should == true
1201
1331
  sleep 1
1202
- store.key?(#{key1}).should == true
1332
+ store.key?('key1').should == true
1203
1333
  sleep 2
1204
- store.key?(#{key1}).should == false
1334
+ store.key?('key1').should == false
1205
1335
  end
1206
1336
 
1207
1337
  it 'should support updating the expiration time in load' do
1208
- store.store(#{key2}, #{val2}, :expires => 2)
1209
- store[#{key2}].should == #{val2}
1338
+ store.store('key2', 'val2', :expires => 2)
1339
+ store['key2'].should == 'val2'
1210
1340
  sleep 1
1211
- store.load(#{key2}, :expires => 3).should == #{val2}
1212
- store[#{key2}].should == #{val2}
1341
+ store.load('key2', :expires => 3).should == 'val2'
1342
+ store['key2'].should == 'val2'
1213
1343
  sleep 1
1214
- store[#{key2}].should == #{val2}
1344
+ store['key2'].should == 'val2'
1215
1345
  sleep 3
1216
- store[#{key2}].should == nil
1346
+ store['key2'].should == nil
1217
1347
  end
1218
1348
 
1219
1349
  it 'should support updating the expiration time in key?' do
1220
- store.store(#{key2}, #{val2}, :expires => 2)
1221
- store[#{key2}].should == #{val2}
1350
+ store.store('key2', 'val2', :expires => 2)
1351
+ store['key2'].should == 'val2'
1222
1352
  sleep 1
1223
- store.key?(#{key2}, :expires => 3).should be_true
1224
- store[#{key2}].should == #{val2}
1353
+ store.key?('key2', :expires => 3).should be_true
1354
+ store['key2'].should == 'val2'
1225
1355
  sleep 1
1226
- store[#{key2}].should == #{val2}
1356
+ store['key2'].should == 'val2'
1227
1357
  sleep 3
1228
- store[#{key2}].should == nil
1358
+ store['key2'].should == nil
1229
1359
  end
1230
1360
 
1231
1361
  it 'should support updating the expiration time in fetch' do
1232
- store.store(#{key1}, #{val1}, :expires => 2)
1233
- store[#{key1}].should == #{val1}
1362
+ store.store('key1', 'val1', :expires => 2)
1363
+ store['key1'].should == 'val1'
1234
1364
  sleep 1
1235
- store.fetch(#{key1}, nil, :expires => 3).should == #{val1}
1236
- store[#{key1}].should == #{val1}
1365
+ store.fetch('key1', nil, :expires => 3).should == 'val1'
1366
+ store['key1'].should == 'val1'
1237
1367
  sleep 1
1238
- store[#{key1}].should == #{val1}
1368
+ store['key1'].should == 'val1'
1239
1369
  sleep 3
1240
- store[#{key1}].should == nil
1370
+ store['key1'].should == nil
1241
1371
  end
1242
1372
 
1243
1373
  it 'should respect expires in delete' do
1244
- store.store(#{key2}, #{val2}, :expires => 2)
1245
- store[#{key2}].should == #{val2}
1374
+ store.store('key2', 'val2', :expires => 2)
1375
+ store['key2'].should == 'val2'
1246
1376
  sleep 1
1247
- store[#{key2}].should == #{val2}
1377
+ store['key2'].should == 'val2'
1248
1378
  sleep 2
1249
- store.delete(#{key2}).should == nil
1379
+ store.delete('key2').should == nil
1250
1380
  end
1251
1381
 
1252
1382
  it 'should support the #expires syntactic sugar' do
1253
1383
  store['longlive_key'] = 'longlive_value'
1254
- store.expires(2).store(#{key2}, #{val2})
1255
- store[#{key2}].should == #{val2}
1384
+ store.expires(2).store('key2', 'val2')
1385
+ store['key2'].should == 'val2'
1256
1386
  sleep 1
1257
- store[#{key2}].should == #{val2}
1387
+ store['key2'].should == 'val2'
1258
1388
  sleep 2
1259
- store.delete(#{key2}).should == nil
1389
+ store.delete('key2').should == nil
1260
1390
  store['longlive_key'].should == 'longlive_value'
1261
1391
  end}
1262
- SPECS["expires_#{key_type.downcase}key_#{val_type.downcase}value"] = code
1263
1392
 
1264
- end
1393
+ SPECS['not_increment'] = %{it 'should not support #increment' do
1394
+ expect do
1395
+ store.increment('inckey')
1396
+ end.to raise_error(NotImplementedError)
1265
1397
  end
1266
1398
 
1267
- SPECS['not_increment'] = %{it 'should not support increment' do
1399
+ it 'should not support #decrement' do
1268
1400
  expect do
1269
1401
  store.increment('inckey')
1270
1402
  end.to raise_error(NotImplementedError)
1271
1403
  end}
1272
1404
 
1273
- SPECS['increment'] = %{it 'should initialize in increment with 1' do
1405
+ SPECS['increment'] = %{it 'should initialize in #increment with 1' do
1274
1406
  store.key?('inckey').should be_false
1275
1407
  store.increment('inckey').should == 1
1276
1408
  store.key?('inckey').should be_true
1277
1409
  store.raw['inckey'].should == '1'
1278
1410
  store.raw.load('inckey').should == '1'
1279
1411
  store.load('inckey', :raw => true).should == '1'
1280
- store['inckey'].should == '1'
1412
+
1413
+ # WARNING: Undefined behaviour!
1414
+ result = safe_load_value(store.raw['inckey'])
1415
+ store['inckey'].should == result
1281
1416
 
1282
1417
  store.delete('inckey', :raw => true).should == '1'
1283
1418
  store.key?('inckey').should be_false
1284
1419
  end
1285
1420
 
1286
- it 'should initialize in increment with higher value' do
1421
+ it 'should initialize in #increment with higher value' do
1287
1422
  store.increment('inckey', 42).should == 42
1288
1423
  store.key?('inckey').should be_true
1289
1424
  store.raw['inckey'].should == '42'
1290
- store['inckey'].should == '42'
1425
+
1426
+ # WARNING: Undefined behaviour!
1427
+ result = safe_load_value(store.raw['inckey'])
1428
+ store['inckey'].should == result
1429
+
1291
1430
  store.delete('inckey', :raw => true).should == '42'
1292
1431
  end
1293
1432
 
1294
- it 'should initialize in increment with 0' do
1433
+ it 'should initialize in #increment with 0' do
1295
1434
  store.increment('inckey', 0).should == 0
1296
1435
  store.key?('inckey').should be_true
1297
1436
  store.raw['inckey'].should == '0'
1298
- store['inckey'].should == '0'
1437
+
1438
+ # WARNING: Undefined behaviour!
1439
+ result = safe_load_value(store.raw['inckey'])
1440
+ store['inckey'].should == result
1441
+
1299
1442
  store.delete('inckey', :raw => true).should == '0'
1300
1443
  end
1301
1444
 
1445
+ it 'should support deleting integer value' do
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
1456
+ store.decrement('inckey', 0).should == 0
1457
+ store.raw['inckey'].should == '0'
1458
+ end
1459
+
1460
+ it 'should initialize in #decrement with negative value' do
1461
+ store.decrement('inckey', -42).should == 42
1462
+ store.raw['inckey'].should == '42'
1463
+ end
1464
+
1302
1465
  it 'should support incrementing existing value by value' do
1303
1466
  store.increment('inckey').should == 1
1304
1467
  store.increment('inckey', 42).should == 43
1305
1468
  store.raw['inckey'].should == '43'
1306
1469
  end
1307
1470
 
1308
- it 'should support incrementing existing value by 0' do
1471
+ it 'should support decrementing existing value by value' do
1309
1472
  store.increment('inckey').should == 1
1310
- store.increment('inckey', 0).should == 1
1311
- store.raw['inckey'].should == '1'
1473
+ store.decrement('inckey').should == 0
1474
+ store.increment('inckey', 42).should == 42
1475
+ store.decrement('inckey', 2).should == 40
1476
+ store.raw['inckey'].should == '40'
1312
1477
  end
1313
1478
 
1314
- it 'should support deleting integer value' do
1479
+ it 'should support incrementing existing value by 0' do
1315
1480
  store.increment('inckey').should == 1
1316
- store.delete('inckey').should == '1'
1317
- store.key?('inckey').should be_false
1481
+ store.increment('inckey', 0).should == 1
1482
+ store.raw['inckey'].should == '1'
1318
1483
  end
1319
1484
 
1320
1485
  it 'should support decrementing existing value' do
@@ -1331,11 +1496,18 @@ it 'interpret raw value as integer' do
1331
1496
  store.raw['inckey'].should == '43'
1332
1497
  end
1333
1498
 
1334
- it 'should raise error on non integer value' do
1499
+ it 'should raise error in #increment on non integer value' do
1335
1500
  store['strkey'] = 'value'
1336
1501
  expect do
1337
1502
  store.increment('strkey')
1338
1503
  end.to raise_error
1504
+ end
1505
+
1506
+ it 'should raise error in #decrement on non integer value' do
1507
+ store['strkey'] = 'value'
1508
+ expect do
1509
+ store.decrement('strkey')
1510
+ end.to raise_error
1339
1511
  end}
1340
1512
 
1341
1513
  SPECS['marshallable_key'] = %{it 'refuses to #[] from keys that cannot be marshalled' do
@@ -1446,16 +1618,15 @@ File.open(File.join(File.dirname(__FILE__), 'monetaspecs.rb'), 'w') {|out| out <
1446
1618
  TESTS.each do |name, options|
1447
1619
  build = options.delete(:build)
1448
1620
  store = options.delete(:store)
1449
- key = [options.delete(:key) || %w(Object String Hash)].flatten
1450
- value = [options.delete(:value) || %w(Object String Hash Boolean)].flatten
1451
1621
 
1452
1622
  load_value = options.delete(:load_value) || 'Marshal.load(value)'
1453
1623
 
1454
1624
  specs_code = []
1455
- options.delete(:specs).each do |s|
1625
+ specs = options.delete(:specs)
1626
+ specs.specs.sort.each do |s|
1456
1627
  specs_code << " it_should_behave_like '#{s}'" if SPECS[s.to_s]
1457
- key.each do |k|
1458
- value.each do |v|
1628
+ specs.key.each do |k|
1629
+ specs.value.each do |v|
1459
1630
  x = "#{s}_#{k.downcase}key_#{v.downcase}value"
1460
1631
  specs_code << " it_should_behave_like '#{x}'" if SPECS[x]
1461
1632
  end