torquebox-cache 2.0.0.beta1-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,375 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require File.dirname(__FILE__) + '/spec_helper'
18
+ require 'dm-core'
19
+ require 'datamapper/model'
20
+
21
+ describe DataMapper::Adapters::InfinispanAdapter do
22
+
23
+ before :all do
24
+ @adapter = DataMapper.setup(:default, :adapter => 'infinispan')
25
+ @heffalump_index = File.join( File.dirname(__FILE__), '..', 'rubyobj.Heffalump' )
26
+ class ::Heffalump
27
+ include DataMapper::Resource
28
+
29
+ property :id, Serial
30
+ property :color, String
31
+ property :num_spots, Integer
32
+ property :striped, Boolean
33
+ end
34
+
35
+ DataMapper.finalize
36
+ Heffalump.auto_migrate!
37
+ end
38
+
39
+ it "should use the infinispan search manager" do
40
+ @adapter.search_manager.should_not be_nil
41
+ end
42
+
43
+ after :all do
44
+ @adapter.stop
45
+ FileUtils.rm_rf @heffalump_index
46
+ end
47
+
48
+ describe '#auto_migrate!' do
49
+ it 'should clear the cache' do
50
+ Heffalump.create(:color => 'magenta')
51
+ Heffalump.all.size.should == 1
52
+ Heffalump.auto_migrate!
53
+ Heffalump.all.size.should == 0
54
+ end
55
+ end
56
+
57
+ describe '#auto_upgrade!' do
58
+ it 'should not clear the cache' do
59
+ Heffalump.create(:color => 'magenta')
60
+ Heffalump.all.size.should == 1
61
+ Heffalump.auto_upgrade!
62
+ Heffalump.all.size.should == 1
63
+ end
64
+ end
65
+
66
+ describe '#create' do
67
+ it 'should not raise any errors' do
68
+ lambda {
69
+ Heffalump.create(:color => 'peach')
70
+ }.should_not raise_error
71
+ end
72
+
73
+ it 'should set the identity field for the resource' do
74
+ heffalump = Heffalump.new(:color => 'peach')
75
+ heffalump.id.should be_nil
76
+ heffalump.save
77
+ heffalump.id.should_not be_nil
78
+ end
79
+ end
80
+
81
+ describe '#read' do
82
+ before :all do
83
+ @heffalump = Heffalump.create(:color => 'brownish hue')
84
+ end
85
+
86
+ it 'should not raise any errors' do
87
+ lambda {
88
+ Heffalump.all()
89
+ }.should_not raise_error
90
+ end
91
+
92
+ it 'should return stuff' do
93
+ Heffalump.all.should be_include(@heffalump)
94
+ end
95
+ end
96
+
97
+ describe '#update' do
98
+ before do
99
+ @heffalump = Heffalump.create(:color => 'indigo')
100
+ end
101
+
102
+ it 'should not raise any errors' do
103
+ lambda {
104
+ @heffalump.color = 'violet'
105
+ @heffalump.save
106
+ }.should_not raise_error
107
+ end
108
+
109
+ it 'should not alter the identity field' do
110
+ id = @heffalump.id
111
+ @heffalump.color = 'violet'
112
+ @heffalump.save
113
+ @heffalump.id.should == id
114
+ end
115
+
116
+ it 'should update altered fields' do
117
+ @heffalump.color = 'violet'
118
+ @heffalump.save
119
+ Heffalump.get(*@heffalump.key).color.should == 'violet'
120
+ end
121
+
122
+ it 'should not alter other fields' do
123
+ color = @heffalump.color
124
+ @heffalump.num_spots = 3
125
+ @heffalump.save
126
+ Heffalump.get(*@heffalump.key).color.should == color
127
+ end
128
+ end
129
+
130
+ describe '#delete' do
131
+ before do
132
+ @heffalump = Heffalump.create(:color => 'forest green')
133
+ end
134
+
135
+ it 'should not raise any errors' do
136
+ lambda {
137
+ @heffalump.destroy
138
+ }.should_not raise_error
139
+ end
140
+
141
+ it 'should delete the requested resource' do
142
+ id = @heffalump.id
143
+ @heffalump.destroy
144
+ Heffalump.get(id).should be_nil
145
+ end
146
+ end
147
+
148
+ describe 'query matching' do
149
+ before :all do
150
+ Heffalump.auto_migrate!
151
+ @red = Heffalump.create(:color => 'red')
152
+ @two = Heffalump.create(:num_spots => 2)
153
+ @five = Heffalump.create(:num_spots => 5)
154
+ end
155
+
156
+ describe 'conditions' do
157
+ describe 'eql' do
158
+ it 'should be able to search for objects included in an inclusive range of values' do
159
+ Heffalump.all(:num_spots => 1..5).should be_include(@five)
160
+ end
161
+
162
+ it 'should be able to search for objects included in an exclusive range of values' do
163
+ Heffalump.all(:num_spots => 1...6).should be_include(@five)
164
+ end
165
+
166
+ it 'should not be able to search for values not included in an inclusive range of values' do
167
+ Heffalump.all(:num_spots => 1..4).should_not be_include(@five)
168
+ end
169
+
170
+ it 'should not be able to search for values not included in an exclusive range of values' do
171
+ Heffalump.all(:num_spots => 1...5).should_not be_include(@five)
172
+ end
173
+ end
174
+
175
+ describe 'not' do
176
+ it 'should be able to search for objects with not equal value' do
177
+ Heffalump.all(:color.not => 'red').should_not be_include(@red)
178
+ end
179
+
180
+ it 'should include objects that are not like the value' do
181
+ Heffalump.all(:color.not => 'black').should be_include(@red)
182
+ end
183
+
184
+ it 'should be able to search for objects with not nil value' do
185
+ Heffalump.all(:color.not => nil).should be_include(@red)
186
+ end
187
+
188
+ it 'should not include objects with a nil value' do
189
+ Heffalump.all(:color.not => nil).should_not be_include(@two)
190
+ end
191
+
192
+ it 'should be able to search for object with a nil value using required properties' do
193
+ Heffalump.all(:id.not => nil).should == [ @red, @two, @five ]
194
+ end
195
+
196
+ it 'should be able to search for objects not in an empty list (match all)' do
197
+ Heffalump.all(:color.not => []).should == [ @red, @two, @five ]
198
+ end
199
+
200
+ it 'should be able to search for objects in an empty list and another OR condition (match none on the empty list)' do
201
+ Heffalump.all(
202
+ :conditions => DataMapper::Query::Conditions::Operation.new(
203
+ :or,
204
+ DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:color], []),
205
+ DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:num_spots], [5])
206
+ )
207
+ ).should == [ @five ]
208
+ end
209
+
210
+ it 'should be able to search for objects not included in an array of values' do
211
+ Heffalump.all(:num_spots.not => [ 1, 3, 5, 7 ]).should be_include(@two)
212
+ end
213
+
214
+ it 'should be able to search for objects not included in an array of values' do
215
+ Heffalump.all(:num_spots.not => [ 1, 3, 5, 7 ]).should_not be_include(@five)
216
+ end
217
+
218
+ it 'should be able to search for objects not included in an inclusive range of values' do
219
+ Heffalump.all(:num_spots.not => 1..4).should be_include(@five)
220
+ end
221
+
222
+ it 'should be able to search for objects not included in an exclusive range of values' do
223
+ Heffalump.all(:num_spots.not => 1...5).should be_include(@five)
224
+ end
225
+
226
+ it 'should not be able to search for values not included in an inclusive range of values' do
227
+ Heffalump.all(:num_spots.not => 1..5).should_not be_include(@five)
228
+ end
229
+
230
+ it 'should not be able to search for values not included in an exclusive range of values' do
231
+ Heffalump.all(:num_spots.not => 1...6).should_not be_include(@five)
232
+ end
233
+ end
234
+
235
+ describe 'like' do
236
+ it 'should be able to search for objects that match value' do
237
+ Heffalump.all(:color.like => '%ed').should be_include(@red)
238
+ end
239
+
240
+ it 'should not search for objects that do not match the value' do
241
+ Heffalump.all(:color.like => '%blak%').should_not be_include(@red)
242
+ end
243
+ end
244
+
245
+ describe 'regexp' do
246
+ before do
247
+ if (defined?(DataMapper::Adapters::SqliteAdapter) && @adapter.kind_of?(DataMapper::Adapters::SqliteAdapter) ||
248
+ defined?(DataMapper::Adapters::SqlserverAdapter) && @adapter.kind_of?(DataMapper::Adapters::SqlserverAdapter))
249
+ pending 'delegate regexp matches to same system that the InMemory and YAML adapters use'
250
+ end
251
+ end
252
+
253
+ it 'should be able to search for objects that match value' do
254
+ Heffalump.all(:color => /ed/).should be_include(@red)
255
+ end
256
+
257
+ it 'should not be able to search for objects that do not match the value' do
258
+ Heffalump.all(:color => /blak/).should_not be_include(@red)
259
+ end
260
+
261
+ it 'should be able to do a negated search for objects that match value' do
262
+ Heffalump.all(:color.not => /blak/).should be_include(@red)
263
+ end
264
+
265
+ it 'should not be able to do a negated search for objects that do not match value' do
266
+ Heffalump.all(:color.not => /ed/).should_not be_include(@red)
267
+ end
268
+
269
+ end
270
+
271
+ describe 'gt' do
272
+ it 'should be able to search for objects with value greater than' do
273
+ Heffalump.all(:num_spots.gt => 1).should be_include(@two)
274
+ end
275
+
276
+ it 'should not find objects with a value less than' do
277
+ Heffalump.all(:num_spots.gt => 3).should_not be_include(@two)
278
+ end
279
+ end
280
+
281
+ describe 'gte' do
282
+ it 'should be able to search for objects with value greater than' do
283
+ Heffalump.all(:num_spots.gte => 1).should be_include(@two)
284
+ end
285
+
286
+ it 'should be able to search for objects with values equal to' do
287
+ Heffalump.all(:num_spots.gte => 2).should be_include(@two)
288
+ end
289
+
290
+ it 'should not find objects with a value less than' do
291
+ Heffalump.all(:num_spots.gte => 3).should_not be_include(@two)
292
+ end
293
+ end
294
+
295
+ describe 'lt' do
296
+ it 'should be able to search for objects with value less than' do
297
+ Heffalump.all(:num_spots.lt => 3).should be_include(@two)
298
+ end
299
+
300
+ it 'should not find objects with a value less than' do
301
+ Heffalump.all(:num_spots.gt => 2).should_not be_include(@two)
302
+ end
303
+ end
304
+
305
+ describe 'lte' do
306
+ it 'should be able to search for objects with value less than' do
307
+ Heffalump.all(:num_spots.lte => 3).should be_include(@two)
308
+ end
309
+
310
+ it 'should be able to search for objects with values equal to' do
311
+ Heffalump.all(:num_spots.lte => 2).should be_include(@two)
312
+ end
313
+
314
+ it 'should not find objects with a value less than' do
315
+ Heffalump.all(:num_spots.lte => 1).should_not be_include(@two)
316
+ end
317
+ end
318
+ end
319
+
320
+ describe 'limits' do
321
+ it 'should be able to limit the objects' do
322
+ Heffalump.all(:limit => 2).length.should == 2
323
+ end
324
+ end
325
+ end
326
+
327
+ describe "with persistence" do
328
+ before :all do
329
+ @configured_dir = File.join( File.dirname(__FILE__), '..', random_string + "-dm-infinispan-adapter.cache" )
330
+ @default_dir = File.join(File.dirname(__FILE__), '..', 'Infinispan-FileCacheStore')
331
+ @snuffy = File.join( File.dirname(__FILE__), '..', 'rubyobj.Snuffleupagus' )
332
+ FileUtils.mkdir( @configured_dir )
333
+ class Snuffleupagus
334
+ include DataMapper::Resource
335
+ property :id, Serial
336
+ property :birthday, Date
337
+ end
338
+ Snuffleupagus.configure_index!
339
+ end
340
+
341
+ after :all do
342
+ #FileUtils.rm_rf( @configured_dir )
343
+ #FileUtils.rm_rf( @default_dir )
344
+ FileUtils.rm_rf( @snuffy )
345
+ end
346
+
347
+ it "should store data in a configured directory" do
348
+ adapter = DataMapper.setup(:dminfinispanadapterconfigured, :adapter => 'infinispan', :persist => @configured_dir.to_s)
349
+ snuffy = Snuffleupagus.create(:birthday=>Date.today)
350
+ File.exist?("#{@configured_dir.to_s}/dminfinispanadapterconfigured").should be_true
351
+ snuffy.should_not be_nil
352
+ adapter.stop
353
+ end
354
+
355
+ it "should store data in a default directory" do
356
+ adapter = DataMapper.setup(:dminfinispanadapterdefault, :adapter => 'infinispan', :persist=>true)
357
+ snuffy = Snuffleupagus.create(:birthday=>Date.today)
358
+ File.exist?( @default_dir ).should be_true
359
+ snuffy.should_not be_nil
360
+ snuffy.id.should_not be_nil
361
+ adapter.stop
362
+ end
363
+
364
+ it "should store dates" do
365
+ adapter = DataMapper.setup(:default, :adapter => 'infinispan', :persist=>true)
366
+ snuffy = Snuffleupagus.create(:birthday => Date.today)
367
+ snuffy.should_not be_nil
368
+ snuffy.getBirthday.should_not be_nil
369
+ adapter.stop
370
+ end
371
+
372
+ end
373
+ end
374
+
375
+
data/spec/spec.opts ADDED
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
5
+
@@ -0,0 +1,29 @@
1
+ #
2
+ # Copyright 2011 Red Hat, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'dm-core/spec/shared/adapter_spec'
18
+ require 'dm-core/spec/lib/pending_helpers'
19
+ require 'datamapper/dm-infinispan-adapter'
20
+ require 'cache'
21
+
22
+ Spec::Runner.configure do |config|
23
+ config.include(DataMapper::Spec::PendingHelpers)
24
+ end
25
+
26
+ def random_string( length = 20 )
27
+ chars = ('a'..'z').to_a + ('A'..'Z').to_a
28
+ dir_string = (0...length).collect { chars[Kernel.rand(chars.length)] }.join
29
+ end
@@ -0,0 +1,220 @@
1
+ require 'active_support/cache/torque_box_store'
2
+ require 'logger'
3
+
4
+ java_import org.infinispan.config.Configuration::CacheMode
5
+ include ActiveSupport::Cache
6
+
7
+ TORQUEBOX_APP_NAME = 'active-support-unit-test'
8
+
9
+ describe ActiveSupport::Cache::TorqueBoxStore do
10
+
11
+ before(:each) do
12
+ TorqueBox::ServiceRegistry.service_registry = nil
13
+ @cache = ActiveSupport::Cache::TorqueBoxStore.new()
14
+ end
15
+
16
+ describe "basics" do
17
+
18
+ it "should write and read a string" do
19
+ @cache.write("key", "value").should be_true
20
+ @cache.read("key").should == "value"
21
+ end
22
+
23
+ it "should write and read a number" do
24
+ @cache.write("key", 42).should be_true
25
+ @cache.read("key").should == 42
26
+ end
27
+
28
+ it "should exist after writing" do
29
+ @cache.write("key", 42).should be_true
30
+ @cache.exist?("key").should be_true
31
+ end
32
+
33
+ it "should be gone after deleting" do
34
+ @cache.write("key", 42).should be_true
35
+ @cache.read("key").should == 42
36
+ @cache.delete("key").should be_true
37
+ @cache.read("key").should be_nil
38
+ end
39
+
40
+ it "should overwrite an existing key" do
41
+ @cache.write("key", 42).should be_true
42
+ @cache.read("key").should == 42
43
+ @cache.write("key", 44).should be_true
44
+ @cache.read("key").should == 44
45
+ end
46
+
47
+ end
48
+
49
+ describe "options" do
50
+
51
+ it "should be expirable" do
52
+ @cache.write("key", 42, :expires_in => 1.second).should be_true
53
+ @cache.read("key").should == 42
54
+ sleep(1.1)
55
+ @cache.read("key").should be_nil
56
+ end
57
+
58
+ it "should optionally not overwrite an existing key" do
59
+ @cache.write("key", 42).should be_true
60
+ @cache.read("key").should == 42
61
+ @cache.write("key", 44, :unless_exist => true).should be_true
62
+ @cache.read("key").should == 42
63
+ end
64
+
65
+ it "should merge initialized options" do
66
+ @cache = ActiveSupport::Cache::TorqueBoxStore.new(:expires_in => 1.second)
67
+ @cache.write("key", 42).should be_true
68
+ @cache.read("key").should == 42
69
+ sleep(1.1)
70
+ @cache.read("key").should be_nil
71
+ end
72
+
73
+ end
74
+
75
+ describe "fetching" do
76
+
77
+ it "should fetch existing keys" do
78
+ @cache.write("today", "Monday")
79
+ @cache.fetch("today").should == "Monday"
80
+ end
81
+
82
+ it "should fetch block values for missing keys" do
83
+ @cache.fetch("city").should be_nil
84
+ @cache.fetch("city") {
85
+ "Duckburgh"
86
+ }.should == "Duckburgh"
87
+ @cache.fetch("city").should == "Duckburgh"
88
+ end
89
+
90
+ it "should fetch block values when forced" do
91
+ @cache.write("today", "Monday")
92
+ @cache.fetch("today").should == "Monday"
93
+ @cache.fetch("today", :force => true) { "Tuesday" }.should == "Tuesday"
94
+ end
95
+
96
+ it "should support :race_condition_ttl" do
97
+ database = mock('database')
98
+ fetch_options = { :expires_in => 0.1.seconds, :race_condition_ttl => 30.seconds }
99
+ # First fetch looks up from database and populates
100
+ database.should_receive(:town).and_return("Pantsville")
101
+ @cache.fetch("town", fetch_options) {
102
+ database.town
103
+ }.should == "Pantsville"
104
+ # Sleep until the entry is expired
105
+ sleep(0.2)
106
+ # Create a set of CountDownLatches to test :race_condition_ttl
107
+ # without relying on sleep calls
108
+ read_latch = java.util.concurrent.CountDownLatch.new(1)
109
+ write_latch = java.util.concurrent.CountDownLatch.new(1)
110
+ # Read the cache from two threads but only one should hit our database
111
+ database.should_receive(:town).once.and_return {
112
+ # Trigger the read latch so the other thread can read the cached value
113
+ read_latch.count_down
114
+ write_latch.await(15, java.util.concurrent.TimeUnit::SECONDS)
115
+ "NoPantsville"
116
+ }
117
+ other_thread = Thread.new {
118
+ read_latch.await(15, java.util.concurrent.TimeUnit::SECONDS)
119
+ @cache.fetch("town", fetch_options) {
120
+ database.town
121
+ }.should == "Pantsville"
122
+ # Trigger the write latch to update the cached value
123
+ write_latch.count_down
124
+ }
125
+ @cache.fetch("town", fetch_options) {
126
+ database.town
127
+ }.should == "NoPantsville"
128
+ other_thread.join
129
+ @cache.read("town").should == "NoPantsville"
130
+ end
131
+
132
+ end
133
+
134
+ describe "multiples" do
135
+
136
+ before(:each) do
137
+ @cache.write("john", "guitar")
138
+ @cache.write("paul", "bass")
139
+ @cache.write("george", "lead")
140
+ @cache.write("ringo", "drums")
141
+ end
142
+
143
+ it "should delete by regexp" do
144
+ @cache.delete_matched /g/
145
+ @cache.read("george").should be_nil
146
+ @cache.read("ringo").should be_nil
147
+ @cache.read("john").should == "guitar"
148
+ @cache.read("paul").should == "bass"
149
+ end
150
+
151
+ it "should clear all entries" do
152
+ @cache.clear
153
+ @cache.read("george").should be_nil
154
+ @cache.read("ringo").should be_nil
155
+ @cache.read("john").should be_nil
156
+ @cache.read("paul").should be_nil
157
+ end
158
+
159
+ it "should cleanup expired entries" do
160
+ @cache.write("jimi", "guitar", :expires_in => 1.second)
161
+ @cache.exist?("jimi").should be_true
162
+ sleep(1.1)
163
+ @cache.cleanup
164
+ @cache.exist?("jimi").should be_false
165
+ @cache.exist?("ringo").should be_true
166
+ end
167
+
168
+ it "should read multiple values" do
169
+ @cache.read_multi("john", "paul").should == {"john" => "guitar", "paul" => "bass"}
170
+ end
171
+
172
+ end
173
+
174
+ describe "advanced" do
175
+
176
+ it "should support incrementation" do
177
+ @cache.write("key", 42).should be_true
178
+ @cache.read("key").should == 42
179
+ @cache.increment("key").should == 43
180
+ @cache.read("key").should == 43
181
+ end
182
+
183
+ it "should support decrementation" do
184
+ @cache.write("key", 42).should be_true
185
+ @cache.read("key").should == 42
186
+ @cache.decrement("key").should == 41
187
+ @cache.read("key").should == 41
188
+ end
189
+
190
+ end
191
+
192
+ describe "clustering" do
193
+
194
+ it "should default to invalidation mode" do
195
+ @cache.clustering_mode.should == CacheMode::INVALIDATION_ASYNC
196
+ TorqueBoxStore.new(:mode => :unknown).clustering_mode.should == CacheMode::INVALIDATION_ASYNC
197
+ end
198
+
199
+ [:repl, :dist, :invalidation].each do |mode|
200
+ it "should be configurable in #{mode} mode" do
201
+ TorqueBoxStore.new(:mode => mode).clustering_mode.to_s.should == "#{mode.to_s.upcase}_ASYNC"
202
+ TorqueBoxStore.new(:mode => mode, :sync => true).clustering_mode.to_s.should == "#{mode.to_s.upcase}_SYNC"
203
+ end
204
+ end
205
+
206
+ it "should support replicated mode" do
207
+ [:r, :repl, :replicated, :replication].each do |mode|
208
+ TorqueBoxStore.new(:mode => mode).clustering_mode.should be_replicated
209
+ end
210
+ end
211
+
212
+ it "should support distributed mode" do
213
+ [:d, :dist, :distributed, :distribution].each do |mode|
214
+ TorqueBoxStore.new(:mode => mode).clustering_mode.should be_distributed
215
+ end
216
+ end
217
+
218
+ end
219
+
220
+ end