juno 0.1.0 → 0.1.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 (47) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +2 -5
  3. data/Gemfile +21 -8
  4. data/README.md +3 -1
  5. data/{unsupported/benchmarks.rb → benchmarks/run.rb} +20 -83
  6. data/lib/juno.rb +4 -4
  7. data/lib/juno/activerecord.rb +2 -5
  8. data/lib/juno/base.rb +4 -0
  9. data/{unsupported → lib/juno}/cassandra.rb +11 -11
  10. data/lib/juno/datamapper.rb +1 -1
  11. data/{unsupported → lib/juno}/fog.rb +7 -19
  12. data/lib/juno/null.rb +23 -0
  13. data/lib/juno/redis.rb +13 -1
  14. data/lib/juno/sequel.rb +3 -6
  15. data/lib/juno/stack.rb +41 -0
  16. data/lib/juno/version.rb +1 -1
  17. data/test/helper.rb +160 -130
  18. data/test/{test_active_record.rb → test_activerecord.rb} +2 -5
  19. data/{unsupported → test}/test_cassandra.rb +1 -1
  20. data/test/test_couch.rb +1 -1
  21. data/test/test_datamapper.rb +2 -2
  22. data/test/test_dbm.rb +1 -1
  23. data/test/test_expires.rb +1 -2
  24. data/test/test_file.rb +1 -1
  25. data/test/test_fog.rb +17 -0
  26. data/test/test_gdbm.rb +1 -1
  27. data/test/test_hashfile.rb +1 -1
  28. data/test/test_localmemcache.rb +1 -1
  29. data/test/test_memcached.rb +1 -2
  30. data/test/test_memcached_dalli.rb +1 -2
  31. data/test/test_memcached_native.rb +1 -2
  32. data/test/test_memory.rb +1 -1
  33. data/test/test_mongodb.rb +1 -1
  34. data/test/test_null.rb +9 -0
  35. data/test/test_proxy.rb +1 -1
  36. data/test/test_pstore.rb +1 -1
  37. data/test/test_redis.rb +1 -1
  38. data/test/test_riak.rb +1 -1
  39. data/test/test_sdbm.rb +1 -1
  40. data/test/test_sequel.rb +4 -4
  41. data/test/test_sqlite.rb +1 -1
  42. data/test/test_stack.rb +10 -0
  43. data/test/test_tokyocabinet.rb +1 -1
  44. data/test/test_yaml.rb +1 -1
  45. metadata +20 -13
  46. data/unsupported/test_rackspace.rb +0 -15
  47. data/unsupported/test_s3.rb +0 -15
data/lib/juno/sequel.rb CHANGED
@@ -6,13 +6,10 @@ module Juno
6
6
  raise 'No option :db specified' unless db = options.delete(:db)
7
7
  @table = options.delete(:table) || :juno
8
8
  @db = ::Sequel.connect(db, options)
9
- end
10
-
11
- def migrate
12
- @db.create_table @table do
9
+ @db.create_table?(@table) do
13
10
  primary_key :k
14
- String :k
15
- String :v
11
+ blob :k
12
+ blob :v
16
13
  end
17
14
  end
18
15
 
data/lib/juno/stack.rb ADDED
@@ -0,0 +1,41 @@
1
+ module Juno
2
+ class Stack < Base
3
+ def initialize(options = {})
4
+ raise 'No option :stores specified' unless @stores = options[:stores]
5
+ end
6
+
7
+ def key?(key, options = {})
8
+ @stores.any? {|s| s.key?(key) }
9
+ end
10
+
11
+ def [](key)
12
+ @stores.each do |s|
13
+ value = s[key]
14
+ return value if value
15
+ end
16
+ nil
17
+ end
18
+
19
+ def store(key, value, options = {})
20
+ @stores.each {|s| s.store(key, value, options) }
21
+ value
22
+ end
23
+
24
+ def delete(key, options = {})
25
+ @stores.inject(nil) do |value, s|
26
+ v = s.delete(key, options)
27
+ value || v
28
+ end
29
+ end
30
+
31
+ def clear(options = {})
32
+ @stores.each {|s| s.clear }
33
+ nil
34
+ end
35
+
36
+ def close
37
+ @stores.each {|s| s.close }
38
+ nil
39
+ end
40
+ end
41
+ end
data/lib/juno/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Juno
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
data/test/helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'minitest/autorun'
2
3
  require 'juno'
3
4
  require 'fileutils'
@@ -10,173 +11,202 @@ module Helper
10
11
  end
11
12
  end
12
13
 
13
- JunoSpecification = proc do
14
- include Helper
15
-
16
- before do
17
- @store = new_store
18
- @store.clear
19
- end
20
-
21
- after do
22
- @store.close.must_equal nil if @store
23
- end
24
-
25
- types = {
14
+ module Juno
15
+ TYPES = {
26
16
  'String' => ['key', 'key2'],
27
17
  'Object' => [{:foo => :bar}, {:bar => :baz}]
28
18
  }
29
19
 
30
- types.each do |type, (key, key2)|
31
- it "reads from keys that are #{type}s like a Hash" do
32
- @store[key].must_equal nil
33
- end
20
+ NullSpecification = proc do
21
+ include Helper
34
22
 
35
- it "writes String values to keys that are #{type}s like a Hash" do
36
- @store[key] = 'value'
37
- @store[key].must_equal 'value'
23
+ before do
24
+ @store = new_store
25
+ @store.clear
38
26
  end
39
27
 
40
- it "guarantees that a different String value is retrieved from the #{type} key" do
41
- value = 'value'
42
- (@store[key] = value).must_be_same_as value
43
- @store[key].wont_be_same_as(value)
28
+ after do
29
+ @store.close.must_equal nil if @store
44
30
  end
45
31
 
46
- it "writes Object values to keys that are #{type}s like a Hash" do
47
- value = {:foo => :bar}
48
- (@store[key] = value).must_be_same_as value
49
- @store[key].must_equal(:foo => :bar)
50
- end
32
+ TYPES.each do |type, (key, key2)|
33
+ it "reads from keys that are #{type}s like a Hash" do
34
+ @store[key].must_equal nil
35
+ end
51
36
 
52
- it "guarantees that a different Object value is retrieved from the #{type} key" do
53
- value = {:foo => :bar}
54
- @store[key] = value
55
- @store[key].wont_be_same_as(:foo => :bar)
56
- end
37
+ it "guarantees that the same String value is returned when setting a #{type} key" do
38
+ value = 'value'
39
+ (@store[key] = value).must_be_same_as value
40
+ end
57
41
 
58
- it "returns false from key? if a #{type} key is not available" do
59
- @store.key?(key).must_equal false
60
- end
42
+ it "guarantees that the same Object value is returned when setting a #{type} key" do
43
+ value = {:foo => :bar}
44
+ (@store[key] = value).must_be_same_as value
45
+ end
61
46
 
62
- it "returns true from key? if a #{type} key is available" do
63
- @store[key] = 'value'
64
- @store.key?(key).must_equal true
65
- end
47
+ it "returns false from key? if a #{type} key is not available" do
48
+ @store.key?(key).must_equal false
49
+ end
66
50
 
67
- it "removes and returns an element with a #{type} key from the backing store via delete if it exists" do
68
- @store[key] = 'value'
69
- @store.delete(key).must_equal 'value'
70
- @store.key?(key).must_equal false
71
- end
51
+ it "returns nil from delete if an element for a #{type} key does not exist" do
52
+ @store.delete(key).must_equal nil
53
+ end
72
54
 
73
- it "returns nil from delete if an element for a #{type} key does not exist" do
74
- @store.delete(key).must_equal nil
75
- end
55
+ it "removes all #{type} keys from the store with clear" do
56
+ @store[key] = 'value'
57
+ @store[key2] = 'value2'
58
+ @store.clear.must_equal nil
59
+ @store.key?(key).wont_equal true
60
+ @store.key?(key2).wont_equal true
61
+ end
76
62
 
77
- it "removes all #{type} keys from the store with clear" do
78
- @store[key] = 'value'
79
- @store[key2] = 'value2'
80
- @store.clear.must_equal nil
81
- @store.key?(key).wont_equal true
82
- @store.key?(key2).wont_equal true
83
- end
63
+ it "fetches a #{type} key with a default value with fetch, if the key is not available" do
64
+ @store.fetch(key, 'value').must_equal 'value'
65
+ end
84
66
 
85
- it "fetches a #{type} key with a default value with fetch, if the key is not available" do
86
- @store.fetch(key, 'value').must_equal 'value'
87
- end
67
+ it "fetches a #{type} key with a block with fetch, if the key is not available" do
68
+ @store.fetch(key) { |k| 'value' }.must_equal 'value'
69
+ end
88
70
 
89
- it "fetches a #{type} key with a block with fetch, if the key is not available" do
90
- @store.fetch(key) { |k| 'value' }.must_equal 'value'
71
+ it 'must accept options' do
72
+ @store.key?(key, :foo => 42).must_equal false
73
+ @store.fetch(key, nil, :foo => 42).must_equal nil
74
+ @store.delete(key, :foo => 42).must_equal nil
75
+ @store.clear(:foo => 42).must_equal nil
76
+ @store.store(key, 'value', :foo => 42).must_equal 'value'
77
+ end
91
78
  end
79
+ end
92
80
 
93
- it "does not run the block if the #{type} key is available" do
94
- @store[key] = 'value'
95
- unaltered = "unaltered"
96
- @store.fetch(key) { unaltered = "altered" }
97
- unaltered.must_equal "unaltered"
98
- end
81
+ Specification = proc do
82
+ class_eval(&NullSpecification)
83
+
84
+ TYPES.each do |type, (key, key2)|
85
+ it "writes String values to keys that are #{type}s like a Hash" do
86
+ @store[key] = 'value'
87
+ @store[key].must_equal 'value'
88
+ end
89
+
90
+ it "writes Object values to keys that are #{type}s like a Hash" do
91
+ value = {:foo => :bar}
92
+ @store[key] = value
93
+ @store[key].must_equal(:foo => :bar)
94
+ end
95
+
96
+ it "guarantees that a different String value is retrieved from the #{type} key" do
97
+ value = 'value'
98
+ @store[key] = value
99
+ @store[key].wont_be_same_as(value)
100
+ end
101
+
102
+ it "guarantees that a different Object value is retrieved from the #{type} key" do
103
+ value = {:foo => :bar}
104
+ @store[key] = value
105
+ @store[key].wont_be_same_as(:foo => :bar)
106
+ end
107
+
108
+ it "returns true from key? if a #{type} key is available" do
109
+ @store[key] = 'value'
110
+ @store.key?(key).must_equal true
111
+ end
112
+
113
+ it "removes and returns an element with a #{type} key from the backing store via delete if it exists" do
114
+ @store[key] = 'value'
115
+ @store.delete(key).must_equal 'value'
116
+ @store.key?(key).must_equal false
117
+ end
99
118
 
100
- it "fetches a #{type} key with a default value with fetch, if the key is available" do
101
- @store[key] = 'value2'
102
- @store.fetch(key, 'value').must_equal 'value2'
119
+ it "does not run the block if the #{type} key is available" do
120
+ @store[key] = 'value'
121
+ unaltered = "unaltered"
122
+ @store.fetch(key) { unaltered = "altered" }
123
+ unaltered.must_equal "unaltered"
124
+ end
125
+
126
+ it "fetches a #{type} key with a default value with fetch, if the key is available" do
127
+ @store[key] = 'value2'
128
+ @store.fetch(key, 'value').must_equal 'value2'
129
+ end
130
+
131
+ it "stores #{key} values with #store" do
132
+ @store.store(key, 'value').must_equal 'value'
133
+ @store[key].must_equal 'value'
134
+ end
103
135
  end
104
136
 
105
- it "stores #{key} values with #store" do
106
- @store.store(key, 'value').must_equal 'value'
107
- @store[key].must_equal 'value'
137
+ def marshal_error
138
+ # HACK: Marshalling structs in rubinius without class name throws
139
+ # NoMethodError (to_sym). TODO: Create an issue for rubinius!
140
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
141
+ RUBY_VERSION < '1.9' ? ArgumentError : NoMethodError
142
+ else
143
+ TypeError
144
+ end
108
145
  end
109
146
 
110
- it 'must accept options' do
111
- @store.store(key, 'value', :foo => 42).must_equal 'value'
112
- @store.key?(key, :foo => 42).must_equal true
113
- @store.fetch(key, nil, :foo => 42).must_equal 'value'
114
- @store.delete(key, :foo => 42).must_equal 'value'
115
- @store.key?(key, :foo => 42).must_equal false
116
- @store.clear(:foo => 42).must_equal nil
147
+ it "refuses to #[] from keys that cannot be marshalled" do
148
+ lambda do
149
+ @store[Struct.new(:foo).new(:bar)]
150
+ end.must_raise(marshal_error)
117
151
  end
118
- end
119
152
 
120
- it "refuses to #[] from keys that cannot be marshalled" do
121
- lambda do
122
- @store[Struct.new(:foo).new(:bar)]
123
- end.must_raise(TypeError)
124
- end
153
+ it "refuses to fetch from keys that cannot be marshalled" do
154
+ lambda do
155
+ @store.fetch(Struct.new(:foo).new(:bar), true)
156
+ end.must_raise(marshal_error)
157
+ end
125
158
 
126
- it "refuses to fetch from keys that cannot be marshalled" do
127
- lambda do
128
- @store.fetch(Struct.new(:foo).new(:bar), true)
129
- end.must_raise(TypeError)
130
- end
159
+ it "refuses to #[]= to keys that cannot be marshalled" do
160
+ lambda do
161
+ @store[Struct.new(:foo).new(:bar)] = 'value'
162
+ end.must_raise(marshal_error)
163
+ end
131
164
 
132
- it "refuses to #[]= to keys that cannot be marshalled" do
133
- lambda do
134
- @store[Struct.new(:foo).new(:bar)] = 'value'
135
- end.must_raise(TypeError)
136
- end
165
+ it "refuses to store to keys that cannot be marshalled" do
166
+ lambda do
167
+ @store.store Struct.new(:foo).new(:bar), 'value'
168
+ end.must_raise(marshal_error)
169
+ end
137
170
 
138
- it "refuses to store to keys that cannot be marshalled" do
139
- lambda do
140
- @store.store Struct.new(:foo).new(:bar), 'value'
141
- end.must_raise(TypeError)
142
- end
171
+ it "refuses to check for key? if the key cannot be marshalled" do
172
+ lambda do
173
+ @store.key? Struct.new(:foo).new(:bar)
174
+ end.must_raise(marshal_error)
175
+ end
143
176
 
144
- it "refuses to check for key? if the key cannot be marshalled" do
145
- lambda do
146
- @store.key? Struct.new(:foo).new(:bar)
147
- end.must_raise(TypeError)
177
+ it "refuses to delete a key if the key cannot be marshalled" do
178
+ lambda do
179
+ @store.delete Struct.new(:foo).new(:bar)
180
+ end.must_raise(marshal_error)
181
+ end
148
182
  end
149
183
 
150
- it "refuses to delete a key if the key cannot be marshalled" do
151
- lambda do
152
- @store.delete Struct.new(:foo).new(:bar)
153
- end.must_raise(TypeError)
154
- end
155
- end
184
+ ExpiresSpecification = proc do
185
+ class_eval(&Specification)
156
186
 
157
- JunoExpiresSpecification = proc do
158
- it 'should support expires on store' do
159
- @store.store('key', 'value', :expires => 2)
160
- @store['key'].must_equal 'value'
161
- sleep 3
162
- @store['key'].must_equal nil
163
- end
187
+ it 'should support expires on store' do
188
+ @store.store('key', 'value', :expires => 2)
189
+ @store['key'].must_equal 'value'
190
+ sleep 3
191
+ @store['key'].must_equal nil
192
+ end
164
193
 
165
- it 'should support updating the expiration time in fetch' do
166
- @store.store('key2', 'value2', :expires => 2)
167
- @store['key2'].must_equal 'value2'
168
- sleep 1
169
- @store.fetch('key2', nil, :expires => 3).must_equal 'value2'
170
- sleep 1
171
- @store['key2'].must_equal 'value2'
172
- sleep 3
173
- @store['key2'].must_equal nil
174
- end
194
+ it 'should support updating the expiration time in fetch' do
195
+ @store.store('key2', 'value2', :expires => 2)
196
+ @store['key2'].must_equal 'value2'
197
+ sleep 1
198
+ @store.fetch('key2', nil, :expires => 3).must_equal 'value2'
199
+ sleep 1
200
+ @store['key2'].must_equal 'value2'
201
+ sleep 3
202
+ @store['key2'].must_equal nil
203
+ end
175
204
 
176
- it 'should respect expires in delete' do
177
- @store.store('key', 'value', :expires => 2)
205
+ it 'should respect expires in delete' do
206
+ @store.store('key', 'value', :expires => 2)
178
207
  @store['key'].must_equal 'value'
179
208
  sleep 3
180
209
  @store.delete('key').must_equal nil
181
210
  end
182
211
  end
212
+ end
@@ -4,12 +4,10 @@ begin
4
4
  describe Juno::ActiveRecord do
5
5
  describe 'with connection option set' do
6
6
  def new_store
7
- store = Juno::ActiveRecord.new(:connection => { :adapter => 'sqlite3', :database => File.join(make_tempdir, 'db.sqlite3')})
8
- store.migrate
9
- store
7
+ Juno::ActiveRecord.new(:connection => { :adapter => 'sqlite3', :database => File.join(make_tempdir, 'db.sqlite3')})
10
8
  end
11
9
 
12
- class_eval(&JunoSpecification)
10
+ class_eval(&Juno::Specification)
13
11
 
14
12
  it 'updates an existing key/value' do
15
13
  @store['foo/bar'] = 4
@@ -26,7 +24,6 @@ begin
26
24
  ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => File.join(make_tempdir, 'db.sqlite3')
27
25
 
28
26
  store = Juno::ActiveRecord.new
29
- store.migrate
30
27
  store.table.table_exists?.must_equal true
31
28
  end
32
29
  end
@@ -6,7 +6,7 @@ begin
6
6
  Juno::Cassandra.new
7
7
  end
8
8
 
9
- class_eval(&JunoSpecification)
9
+ class_eval(&Juno::ExpiresSpecification)
10
10
  end
11
11
  rescue LoadError => ex
12
12
  puts "Juno::Cassandra not tested: #{ex.message}"
data/test/test_couch.rb CHANGED
@@ -6,7 +6,7 @@ begin
6
6
  Juno::Couch.new :db => 'juno'
7
7
  end
8
8
 
9
- class_eval(&JunoSpecification)
9
+ class_eval(&Juno::Specification)
10
10
  end
11
11
  rescue LoadError => ex
12
12
  puts "Juno::Couch not tested: #{ex.message}"
@@ -15,7 +15,7 @@ begin
15
15
  Juno::DataMapper::Store.auto_migrate!(:juno)
16
16
  end
17
17
 
18
- class_eval(&JunoSpecification)
18
+ class_eval(&Juno::Specification)
19
19
  end
20
20
 
21
21
  describe 'when :repository specified' do
@@ -27,7 +27,7 @@ begin
27
27
  Juno::DataMapper::Store.auto_migrate!(:sample)
28
28
  end
29
29
 
30
- class_eval(&JunoSpecification)
30
+ class_eval(&Juno::Specification)
31
31
  end
32
32
 
33
33
  describe 'with multiple stores' do