redis-objects 0.2.1 → 0.2.4

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.
@@ -3,8 +3,10 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
 
4
4
  require 'redis/counter'
5
5
  require 'redis/list'
6
- require 'redis/set'
7
6
  require 'redis/value'
7
+ require 'redis/lock'
8
+ require 'redis/set'
9
+ require 'redis/sorted_set'
8
10
 
9
11
  describe Redis::Value do
10
12
  before :all do
@@ -36,6 +38,19 @@ describe Redis::Value do
36
38
  @value.should be_nil
37
39
  end
38
40
 
41
+ it "should support renaming values" do
42
+ @value.value = 'Peter Pan'
43
+ @value.key.should == 'spec/value'
44
+ @value.rename('spec/value2').should be_true
45
+ @value.key.should == 'spec/value2'
46
+ @value.should == 'Peter Pan'
47
+ old = Redis::Value.new('spec/value')
48
+ old.should be_nil
49
+ old.value = 'Tuff'
50
+ @value.renamenx('spec/value').should be_false
51
+ @value.value.should == 'Peter Pan'
52
+ end
53
+
39
54
  after :all do
40
55
  @value.delete
41
56
  end
@@ -131,12 +146,164 @@ describe Redis::List do
131
146
  @list.last.should == [1,2,3,[4,5]]
132
147
  @list.shift.should == {:json => 'data'}
133
148
  end
149
+
150
+ it "should support renaming lists" do
151
+ @list.should be_empty
152
+ @list << 'a' << 'b' << 'a' << 3
153
+ @list.should == ['a','b','a','3']
154
+ @list.key.should == 'spec/list'
155
+ @list.rename('spec/list3', false).should be_true
156
+ @list.key.should == 'spec/list'
157
+ @list.redis.del('spec/list3')
158
+ @list << 'a' << 'b' << 'a' << 3
159
+ @list.rename('spec/list2').should be_true
160
+ @list.key.should == 'spec/list2'
161
+ @list.redis.lrange(@list.key, 0, 3).should == ['a','b','a','3']
162
+ old = Redis::List.new('spec/list')
163
+ old.should be_empty
164
+ old << 'Tuff'
165
+ old.values.should == ['Tuff']
166
+ @list.renamenx('spec/list').should be_false
167
+ @list.renamenx(old).should be_false
168
+ @list.renamenx('spec/foo').should be_true
169
+ old.values.should == ['Tuff']
170
+ @list.clear
171
+ @list.redis.del('spec/list2')
172
+ end
134
173
 
135
174
  after :all do
136
175
  @list.clear
137
176
  end
138
177
  end
139
178
 
179
+ describe Redis::Counter do
180
+ before :all do
181
+ @counter = Redis::Counter.new('spec/counter')
182
+ @counter2 = Redis::Counter.new('spec/counter')
183
+ end
184
+
185
+ before :each do
186
+ @counter.reset
187
+ end
188
+
189
+ it "should support increment/decrement of counters" do
190
+ @counter.key.should == 'spec/counter'
191
+ @counter.incr(10)
192
+ @counter.should == 10
193
+
194
+ # math proxy ops
195
+ (@counter == 10).should be_true
196
+ (@counter <= 10).should be_true
197
+ (@counter < 11).should be_true
198
+ (@counter > 9).should be_true
199
+ (@counter >= 10).should be_true
200
+ "#{@counter}".should == "10"
201
+
202
+ @counter.increment.should == 11
203
+ @counter.increment.should == 12
204
+ @counter2.increment.should == 13
205
+ @counter2.increment(2).should == 15
206
+ @counter.decrement.should == 14
207
+ @counter2.decrement.should == 13
208
+ @counter.decrement.should == 12
209
+ @counter2.decrement(4).should == 8
210
+ @counter.should == 8
211
+ @counter.reset.should be_true
212
+ @counter.should == 0
213
+ @counter.reset(15).should be_true
214
+ @counter.should == 15
215
+ end
216
+
217
+ after :all do
218
+ @counter.delete
219
+ end
220
+ end
221
+
222
+ describe Redis::Lock do
223
+ before :each do
224
+ $redis.flushall
225
+ end
226
+
227
+ it "should set the value to the expiration" do
228
+ start = Time.now
229
+ expiry = 15
230
+ lock = Redis::Lock.new(:test_lock, :expiration => expiry)
231
+ lock.lock do
232
+ expiration = $redis.get("test_lock").to_f
233
+
234
+ # The expiration stored in redis should be 15 seconds from when we started
235
+ # or a little more
236
+ expiration.should be_close((start + expiry).to_f, 2.0)
237
+ end
238
+
239
+ # key should have been cleaned up
240
+ $redis.get("test_lock").should be_nil
241
+ end
242
+
243
+ it "should set value to 1 when no expiration is set" do
244
+ lock = Redis::Lock.new(:test_lock)
245
+ lock.lock do
246
+ $redis.get('test_lock').should == '1'
247
+ end
248
+
249
+ # key should have been cleaned up
250
+ $redis.get("test_lock").should be_nil
251
+ end
252
+
253
+ it "should let lock be gettable when lock is expired" do
254
+ expiry = 15
255
+ lock = Redis::Lock.new(:test_lock, :expiration => expiry, :timeout => 0.1)
256
+
257
+ # create a fake lock in the past
258
+ $redis.set("test_lock", Time.now-(expiry + 60))
259
+
260
+ gotit = false
261
+ lock.lock do
262
+ gotit = true
263
+ end
264
+
265
+ # should get the lock because it has expired
266
+ gotit.should be_true
267
+ $redis.get("test_lock").should be_nil
268
+ end
269
+
270
+ it "should not let non-expired locks be gettable" do
271
+ expiry = 15
272
+ lock = Redis::Lock.new(:test_lock, :expiration => expiry, :timeout => 0.1)
273
+
274
+ # create a fake lock
275
+ $redis.set("test_lock", (Time.now + expiry).to_f)
276
+
277
+ gotit = false
278
+ error = nil
279
+ begin
280
+ lock.lock do
281
+ gotit = true
282
+ end
283
+ rescue => error
284
+ end
285
+
286
+ error.should be_kind_of(Redis::Lock::LockTimeout)
287
+
288
+ # should not have the lock
289
+ gotit.should_not be_true
290
+
291
+ # lock value should still be set
292
+ $redis.get("test_lock").should_not be_nil
293
+ end
294
+
295
+ it "should not remove the key if lock is held past expiration" do
296
+ lock = Redis::Lock.new(:test_lock, :expiration => 0.0)
297
+
298
+ lock.lock do
299
+ sleep 1.1
300
+ end
301
+
302
+ # lock value should still be set since the lock was held for more than the expiry
303
+ $redis.get("test_lock").should_not be_nil
304
+ end
305
+ end
306
+
140
307
  describe Redis::Set do
141
308
  before :all do
142
309
  @set = Redis::Set.new('spec/set')
@@ -191,7 +358,7 @@ describe Redis::Set do
191
358
  @set.sort.should == ['a','b','c']
192
359
  end
193
360
 
194
- it "should handle set intersections and unions" do
361
+ it "should handle set intersections, unions, and diffs" do
195
362
  @set_1 << 'a' << 'b' << 'c' << 'd' << 'e'
196
363
  @set_2 << 'c' << 'd' << 'e' << 'f' << 'g'
197
364
  @set_3 << 'a' << 'd' << 'g' << 'l' << 'm'
@@ -216,6 +383,34 @@ describe Redis::Set do
216
383
  @set_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g']
217
384
  @set_1.unionstore(UNIONSTORE_KEY, @set_2, @set_3).should == 9
218
385
  @set_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g','l','m']
386
+
387
+ (@set_1 ^ @set_2).sort.should == ["a", "b"]
388
+ (@set_1 - @set_2).sort.should == ["a", "b"]
389
+ (@set_2 - @set_1).sort.should == ["f", "g"]
390
+ @set_1.difference(@set_2).sort.should == ["a", "b"]
391
+ @set_1.diff(@set_2).sort.should == ["a", "b"]
392
+ @set_1.difference(@set_2, @set_3).sort.should == ['b']
393
+ @set_1.diffstore(DIFFSTORE_KEY, @set_2).should == 2
394
+ @set_1.redis.smembers(DIFFSTORE_KEY).sort.should == ['a','b']
395
+ @set_1.diffstore(DIFFSTORE_KEY, @set_2, @set_3).should == 1
396
+ @set_1.redis.smembers(DIFFSTORE_KEY).sort.should == ['b']
397
+ end
398
+
399
+ it "should support renaming sets" do
400
+ @set.should be_empty
401
+ @set << 'a' << 'b' << 'a' << 3
402
+ @set.sort.should == ['3','a','b']
403
+ @set.key.should == 'spec/set'
404
+ @set.rename('spec/set2').should be_true
405
+ @set.key.should == 'spec/set2'
406
+ old = Redis::Set.new('spec/set')
407
+ old.should be_empty
408
+ old << 'Tuff'
409
+ @set.renamenx('spec/set').should be_false
410
+ @set.renamenx(old).should be_false
411
+ @set.renamenx('spec/foo').should be_true
412
+ @set.clear
413
+ @set.redis.del('spec/set2')
219
414
  end
220
415
 
221
416
  after :all do
@@ -226,45 +421,157 @@ describe Redis::Set do
226
421
  end
227
422
  end
228
423
 
229
- describe Redis::Counter do
424
+ describe Redis::SortedSet do
230
425
  before :all do
231
- @counter = Redis::Counter.new('spec/counter')
232
- @counter2 = Redis::Counter.new('spec/counter')
426
+ @set = Redis::SortedSet.new('spec/zset')
427
+ @set_1 = Redis::SortedSet.new('spec/zset_1')
428
+ @set_2 = Redis::SortedSet.new('spec/zset_2')
429
+ @set_3 = Redis::SortedSet.new('spec/zset_3')
233
430
  end
234
431
 
235
432
  before :each do
236
- @counter.reset
433
+ @set.clear
434
+ @set_1.clear
435
+ @set_2.clear
436
+ @set_3.clear
237
437
  end
238
438
 
239
- it "should support increment/decrement of counters" do
240
- @counter.key.should == 'spec/counter'
241
- @counter.incr(10)
242
- @counter.should == 10
439
+ it "should handle sets of simple values" do
440
+ @set.should be_empty
441
+ @set['a'] = 11
442
+ @set['a'] = 21
443
+ @set.add('a', 5)
444
+ @set.score('a').should == 5
445
+ @set['a'] = 3
446
+ @set['b'] = 5
447
+ @set['c'] = 4
448
+
449
+ @set[0,-1].should == ['a','c','b']
450
+ @set.range(0,-1).should == ['a','c','b']
451
+ @set.revrange(0,-1).should == ['b','c','a']
452
+ @set[0..1].should == ['a','c']
453
+ @set[1].should == 'c'
454
+ @set.at(1).should == 'c'
455
+ @set.first.should == 'a'
456
+ @set.last.should == 'b'
457
+
458
+ @set.members.should == ['a','c','b']
459
+ @set.members(:withscores => true).should == [['a',3],['c',4],['b',5]]
460
+
461
+ @set['b'] = 5
462
+ @set['b'] = 6
463
+ @set.score('b').should == 6
464
+ @set.delete('c')
465
+ @set.to_s.should == 'a, b'
466
+ @set.should == ['a','b']
467
+ @set.members.should == ['a','b']
468
+ @set['d'] = 0
243
469
 
244
- # math proxy ops
245
- (@counter == 10).should be_true
246
- (@counter <= 10).should be_true
247
- (@counter < 11).should be_true
248
- (@counter > 9).should be_true
249
- (@counter >= 10).should be_true
250
- "#{@counter}".should == "10"
470
+ @set.rangebyscore(0, 4).should == ['d','a']
471
+ @set.rangebyscore(0, 4, :count => 1).should == ['d']
472
+ @set.rangebyscore(0, 4, :count => 2).should == ['d','a']
473
+ @set.rangebyscore(0, 4, :limit => 2).should == ['d','a']
251
474
 
252
- @counter.increment.should == 11
253
- @counter.increment.should == 12
254
- @counter2.increment.should == 13
255
- @counter2.increment(2).should == 15
256
- @counter.decrement.should == 14
257
- @counter2.decrement.should == 13
258
- @counter.decrement.should == 12
259
- @counter2.decrement(4).should == 8
260
- @counter.should == 8
261
- @counter.reset.should be_true
262
- @counter.should == 0
263
- @counter.reset(15).should be_true
264
- @counter.should == 15
475
+ # Redis 1.3.5
476
+ # @set.rangebyscore(0,4, :withscores => true).should == [['d',4],['a',3]]
477
+ # @set.revrangebyscore(0,4).should == ['d','a']
478
+ # @set.revrangebyscore(0,4, :count => 2).should == ['a','d']
479
+ # @set.rank('b').should == 2
480
+ # @set.revrank('b').should == 3
481
+
482
+ @set['f'] = 100
483
+ @set['g'] = 110
484
+ @set['h'] = 120
485
+ @set['j'] = 130
486
+ @set.incr('h', 20)
487
+ @set.remrangebyscore(100, 120)
488
+ @set.members.should == ['d','a','b','j','h']
489
+
490
+ # Redis 1.3.5
491
+ # @set['h'] = 12
492
+ # @set['j'] = 13
493
+ # @set.remrangebyrank(4,-1)
494
+ # @set.members.should == ['d','a','b']
495
+
496
+ @set.delete('d')
497
+ @set['c'] = 200
498
+ @set.members.should == ['a','b','j','h','c']
499
+ @set.delete('c')
500
+ @set.length.should == 4
501
+ @set.size.should == 4
502
+ end
503
+
504
+ # Not until Redis 1.3.5 with hashes
505
+ xit "Redis 1.3.5: should handle set intersections, unions, and diffs" do
506
+ @set_1['a'] = 5
507
+ @set_2['b'] = 18
508
+ @set_2['c'] = 12
509
+
510
+ @set_2['a'] = 10
511
+ @set_2['b'] = 15
512
+ @set_2['c'] = 15
513
+
514
+ (@set_1 & @set_2).sort.should == ['c','d','e']
515
+
516
+ @set_1 << 'a' << 'b' << 'c' << 'd' << 'e'
517
+ @set_2 << 'c' << 'd' << 'e' << 'f' << 'g'
518
+ @set_3 << 'a' << 'd' << 'g' << 'l' << 'm'
519
+ @set_1.sort.should == %w(a b c d e)
520
+ @set_2.sort.should == %w(c d e f g)
521
+ @set_3.sort.should == %w(a d g l m)
522
+ (@set_1 & @set_2).sort.should == ['c','d','e']
523
+ @set_1.intersection(@set_2).sort.should == ['c','d','e']
524
+ @set_1.intersection(@set_2, @set_3).sort.should == ['d']
525
+ @set_1.intersect(@set_2).sort.should == ['c','d','e']
526
+ @set_1.inter(@set_2, @set_3).sort.should == ['d']
527
+ @set_1.interstore(INTERSTORE_KEY, @set_2).should == 3
528
+ @set_1.redis.smembers(INTERSTORE_KEY).sort.should == ['c','d','e']
529
+ @set_1.interstore(INTERSTORE_KEY, @set_2, @set_3).should == 1
530
+ @set_1.redis.smembers(INTERSTORE_KEY).sort.should == ['d']
531
+
532
+ (@set_1 | @set_2).sort.should == ['a','b','c','d','e','f','g']
533
+ (@set_1 + @set_2).sort.should == ['a','b','c','d','e','f','g']
534
+ @set_1.union(@set_2).sort.should == ['a','b','c','d','e','f','g']
535
+ @set_1.union(@set_2, @set_3).sort.should == ['a','b','c','d','e','f','g','l','m']
536
+ @set_1.unionstore(UNIONSTORE_KEY, @set_2).should == 7
537
+ @set_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g']
538
+ @set_1.unionstore(UNIONSTORE_KEY, @set_2, @set_3).should == 9
539
+ @set_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g','l','m']
540
+
541
+ (@set_1 ^ @set_2).sort.should == ["a", "b"]
542
+ (@set_1 - @set_2).sort.should == ["a", "b"]
543
+ (@set_2 - @set_1).sort.should == ["f", "g"]
544
+ @set_1.difference(@set_2).sort.should == ["a", "b"]
545
+ @set_1.diff(@set_2).sort.should == ["a", "b"]
546
+ @set_1.difference(@set_2, @set_3).sort.should == ['b']
547
+ @set_1.diffstore(DIFFSTORE_KEY, @set_2).should == 2
548
+ @set_1.redis.smembers(DIFFSTORE_KEY).sort.should == ['a','b']
549
+ @set_1.diffstore(DIFFSTORE_KEY, @set_2, @set_3).should == 1
550
+ @set_1.redis.smembers(DIFFSTORE_KEY).sort.should == ['b']
551
+ end
552
+
553
+ it "should support renaming sets" do
554
+ @set.should be_empty
555
+ @set['zynga'] = 151
556
+ @set['playfish'] = 202
557
+ @set.members.should == ['zynga','playfish']
558
+ @set.key.should == 'spec/zset'
559
+ @set.rename('spec/zset2').should be_true
560
+ @set.key.should == 'spec/zset2'
561
+ old = Redis::SortedSet.new('spec/zset')
562
+ old.should be_empty
563
+ old['tuff'] = 54
564
+ @set.renamenx('spec/zset').should be_false
565
+ @set.renamenx(old).should be_false
566
+ @set.renamenx('spec/zfoo').should be_true
567
+ @set.clear
568
+ @set.redis.del('spec/zset2')
265
569
  end
266
570
 
267
571
  after :all do
268
- @counter.delete
572
+ @set.clear
573
+ @set_1.clear
574
+ @set_2.clear
575
+ @set_3.clear
269
576
  end
270
- end
577
+ end
@@ -9,12 +9,17 @@ class Roster
9
9
  counter :available_slots, :start => 10
10
10
  counter :pitchers, :limit => :max_pitchers
11
11
  counter :basic
12
- counter :all_players_online, :global => true
13
12
  lock :resort, :timeout => 2
14
13
  value :starting_pitcher
15
14
  list :player_stats
16
15
  set :outfielders
17
16
 
17
+ # global class counters
18
+ counter :total_players_online, :global => true
19
+ list :all_player_stats, :global => true
20
+ set :all_players_online, :global => true
21
+ value :last_player, :global => true
22
+
18
23
  def initialize(id=1) @id = id end
19
24
  def id; @id; end
20
25
  def max_pitchers; 3; end
@@ -43,11 +48,17 @@ describe Redis::Objects do
43
48
  @roster_3.outfielders.clear
44
49
  @roster.redis.del(UNIONSTORE_KEY)
45
50
  @roster.redis.del(INTERSTORE_KEY)
51
+ @roster.redis.del(DIFFSTORE_KEY)
52
+
53
+ Roster.total_players_online.reset
54
+ Roster.all_player_stats.clear
55
+ Roster.all_players_online.clear
56
+ Roster.last_player.delete
46
57
  end
47
58
 
48
59
  it "should provide a connection method" do
49
60
  Roster.redis.should == Redis::Objects.redis
50
- Roster.redis.should be_kind_of(Redis)
61
+ # Roster.redis.should be_kind_of(Redis)
51
62
  end
52
63
 
53
64
  it "should create counter accessors" do
@@ -97,6 +108,24 @@ describe Redis::Objects do
97
108
  Roster.get_counter(:available_slots, @roster.id).should == 10
98
109
  end
99
110
 
111
+ it "should support class-level increment/decrement of global counters" do
112
+ Roster.total_players_online.should == 0
113
+ Roster.total_players_online.increment.should == 1
114
+ Roster.total_players_online.decrement.should == 0
115
+ Roster.total_players_online.increment(3).should == 3
116
+ Roster.total_players_online.decrement(2).should == 1
117
+ Roster.total_players_online.reset.should be_true
118
+ Roster.total_players_online.should == 0
119
+
120
+ Roster.get_counter(:total_players_online).should == 0
121
+ Roster.increment_counter(:total_players_online).should == 1
122
+ Roster.increment_counter(:total_players_online, nil, 3).should == 4
123
+ Roster.decrement_counter(:total_players_online, nil, 2).should == 2
124
+ Roster.decrement_counter(:total_players_online).should == 1
125
+ Roster.reset_counter(:total_players_online).should == true
126
+ Roster.get_counter(:total_players_online).should == 0
127
+ end
128
+
100
129
  it "should take an atomic block for increment/decrement" do
101
130
  a = false
102
131
  @roster.available_slots.should == 10
@@ -253,12 +282,27 @@ describe Redis::Objects do
253
282
  end
254
283
  error.should be_kind_of(NoMethodError)
255
284
  end
285
+
286
+ it "should support obtain_lock as a class method" do
287
+ error = nil
288
+ begin
289
+ Roster.obtain_lock(:resort, 2) do
290
+ Roster.redis.get("roster:2:resort_lock").should_not be_nil
291
+ end
292
+ rescue => error
293
+ end
294
+
295
+ error.should be_nil
296
+ Roster.redis.get("roster:2:resort_lock").should be_nil
297
+ end
256
298
 
257
299
  it "should handle simple values" do
258
300
  @roster.starting_pitcher.should == nil
259
301
  @roster.starting_pitcher = 'Trevor Hoffman'
260
302
  @roster.starting_pitcher.should == 'Trevor Hoffman'
261
303
  @roster.starting_pitcher.get.should == 'Trevor Hoffman'
304
+ @roster.starting_pitcher = 'Tom Selleck'
305
+ @roster.starting_pitcher.should == 'Tom Selleck'
262
306
  @roster.starting_pitcher.del.should be_true
263
307
  @roster.starting_pitcher.should be_nil
264
308
  end
@@ -409,6 +453,162 @@ describe Redis::Objects do
409
453
  @roster_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g','l','m']
410
454
  end
411
455
 
456
+ it "should handle class-level global lists of simple values" do
457
+ Roster.all_player_stats.should be_empty
458
+ Roster.all_player_stats << 'a'
459
+ Roster.all_player_stats.should == ['a']
460
+ Roster.all_player_stats.get.should == ['a']
461
+ Roster.all_player_stats.unshift 'b'
462
+ Roster.all_player_stats.to_s.should == 'b, a'
463
+ Roster.all_player_stats.should == ['b','a']
464
+ Roster.all_player_stats.get.should == ['b','a']
465
+ Roster.all_player_stats.push 'c'
466
+ Roster.all_player_stats.should == ['b','a','c']
467
+ Roster.all_player_stats.get.should == ['b','a','c']
468
+ Roster.all_player_stats.first.should == 'b'
469
+ Roster.all_player_stats.last.should == 'c'
470
+ Roster.all_player_stats << 'd'
471
+ Roster.all_player_stats.should == ['b','a','c','d']
472
+ Roster.all_player_stats[1].should == 'a'
473
+ Roster.all_player_stats[0].should == 'b'
474
+ Roster.all_player_stats[2].should == 'c'
475
+ Roster.all_player_stats[3].should == 'd'
476
+ Roster.all_player_stats.include?('c').should be_true
477
+ Roster.all_player_stats.include?('no').should be_false
478
+ Roster.all_player_stats.pop.should == 'd'
479
+ Roster.all_player_stats[0].should == Roster.all_player_stats.at(0)
480
+ Roster.all_player_stats[1].should == Roster.all_player_stats.at(1)
481
+ Roster.all_player_stats[2].should == Roster.all_player_stats.at(2)
482
+ Roster.all_player_stats.should == ['b','a','c']
483
+ Roster.all_player_stats.get.should == ['b','a','c']
484
+ Roster.all_player_stats.shift.should == 'b'
485
+ Roster.all_player_stats.should == ['a','c']
486
+ Roster.all_player_stats.get.should == ['a','c']
487
+ Roster.all_player_stats << 'e' << 'f' << 'e'
488
+ Roster.all_player_stats.should == ['a','c','e','f','e']
489
+ Roster.all_player_stats.get.should == ['a','c','e','f','e']
490
+ Roster.all_player_stats.delete('e').should == 2
491
+ Roster.all_player_stats.should == ['a','c','f']
492
+ Roster.all_player_stats.get.should == ['a','c','f']
493
+ Roster.all_player_stats << 'j'
494
+ Roster.all_player_stats.should == ['a','c','f','j']
495
+ Roster.all_player_stats[0..2].should == ['a','c','f']
496
+ Roster.all_player_stats[1, 3].should == ['c','f','j']
497
+ Roster.all_player_stats.length.should == 4
498
+ Roster.all_player_stats.size.should == 4
499
+ Roster.all_player_stats.should == ['a','c','f','j']
500
+ Roster.all_player_stats.get.should == ['a','c','f','j']
501
+
502
+ i = -1
503
+ Roster.all_player_stats.each do |st|
504
+ st.should == Roster.all_player_stats[i += 1]
505
+ end
506
+ Roster.all_player_stats.should == ['a','c','f','j']
507
+ Roster.all_player_stats.get.should == ['a','c','f','j']
508
+
509
+ Roster.all_player_stats.each_with_index do |st,i|
510
+ st.should == Roster.all_player_stats[i]
511
+ end
512
+ Roster.all_player_stats.should == ['a','c','f','j']
513
+ Roster.all_player_stats.get.should == ['a','c','f','j']
514
+
515
+ coll = Roster.all_player_stats.collect{|st| st}
516
+ coll.should == ['a','c','f','j']
517
+ Roster.all_player_stats.should == ['a','c','f','j']
518
+ Roster.all_player_stats.get.should == ['a','c','f','j']
519
+
520
+ Roster.all_player_stats << 'a'
521
+ coll = Roster.all_player_stats.select{|st| st == 'a'}
522
+ coll.should == ['a','a']
523
+ Roster.all_player_stats.should == ['a','c','f','j','a']
524
+ Roster.all_player_stats.get.should == ['a','c','f','j','a']
525
+ end
526
+
527
+ it "should handle class-level global sets of simple values" do
528
+ Roster.all_players_online.should be_empty
529
+ Roster.all_players_online << 'a' << 'a' << 'a'
530
+ Roster.all_players_online.should == ['a']
531
+ Roster.all_players_online.get.should == ['a']
532
+ Roster.all_players_online << 'b' << 'b'
533
+ Roster.all_players_online.to_s.should == 'a, b'
534
+ Roster.all_players_online.should == ['a','b']
535
+ Roster.all_players_online.members.should == ['a','b']
536
+ Roster.all_players_online.get.should == ['a','b']
537
+ Roster.all_players_online << 'c'
538
+ Roster.all_players_online.sort.should == ['a','b','c']
539
+ Roster.all_players_online.get.sort.should == ['a','b','c']
540
+ Roster.all_players_online.delete('c')
541
+ Roster.all_players_online.should == ['a','b']
542
+ Roster.all_players_online.get.sort.should == ['a','b']
543
+ Roster.all_players_online.length.should == 2
544
+ Roster.all_players_online.size.should == 2
545
+
546
+ i = 0
547
+ Roster.all_players_online.each do |st|
548
+ i += 1
549
+ end
550
+ i.should == Roster.all_players_online.length
551
+
552
+ coll = Roster.all_players_online.collect{|st| st}
553
+ coll.should == ['a','b']
554
+ Roster.all_players_online.should == ['a','b']
555
+ Roster.all_players_online.get.should == ['a','b']
556
+
557
+ Roster.all_players_online << 'c'
558
+ Roster.all_players_online.member?('c').should be_true
559
+ Roster.all_players_online.include?('c').should be_true
560
+ Roster.all_players_online.member?('no').should be_false
561
+ coll = Roster.all_players_online.select{|st| st == 'c'}
562
+ coll.should == ['c']
563
+ Roster.all_players_online.sort.should == ['a','b','c']
564
+ end
565
+
566
+ it "should handle class-level global values" do
567
+ Roster.last_player.should == nil
568
+ Roster.last_player = 'Trevor Hoffman'
569
+ Roster.last_player.should == 'Trevor Hoffman'
570
+ Roster.last_player.get.should == 'Trevor Hoffman'
571
+ Roster.last_player = 'Tom Selleck'
572
+ Roster.last_player.should == 'Tom Selleck'
573
+ Roster.last_player.del.should be_true
574
+ Roster.last_player.should be_nil
575
+ end
576
+
577
+ it "should easily enable @object.class.global_objects" do
578
+ @roster.class.all_players_online.should be_empty
579
+ @roster.class.all_players_online << 'a' << 'a' << 'a'
580
+ @roster.class.all_players_online.should == ['a']
581
+ @roster2.class.all_players_online.should == ['a']
582
+
583
+ @roster.all_players_online.should == ['a']
584
+ @roster2.all_players_online.should == ['a']
585
+
586
+ @roster.class.all_player_stats.should be_empty
587
+ @roster.class.all_player_stats << 'a'
588
+ @roster.class.all_player_stats.should == ['a']
589
+ @roster.class.all_player_stats.get.should == ['a']
590
+ @roster.class.all_player_stats.unshift 'b'
591
+ @roster.class.all_player_stats.to_s.should == 'b, a'
592
+ @roster.class.all_player_stats.should == ['b','a']
593
+ @roster2.class.all_player_stats.should == ['b','a']
594
+
595
+ @roster.all_player_stats.should == ['b','a']
596
+ @roster2.all_player_stats.should == ['b','a']
597
+ @roster2.all_player_stats << 'b'
598
+ @roster.all_player_stats.should == ['b','a','b']
599
+
600
+ @roster.last_player.should == nil
601
+ @roster.class.last_player = 'Trevor Hoffman'
602
+ @roster.last_player.should == 'Trevor Hoffman'
603
+ @roster.last_player.get.should == 'Trevor Hoffman'
604
+ @roster2.last_player.get.should == 'Trevor Hoffman'
605
+ @roster2.last_player = 'Tom Selleck'
606
+ @roster.last_player.should == 'Tom Selleck'
607
+ @roster.last_player.del.should be_true
608
+ @roster.last_player.should be_nil
609
+ @roster2.last_player.should be_nil
610
+ end
611
+
412
612
  it "should handle lists of complex data types" do
413
613
  @roster.player_stats << {:json => 'data'}
414
614
  @roster.player_stats << {:json2 => 'data2'}
@@ -448,4 +648,5 @@ describe Redis::Objects do
448
648
  error.should_not be_nil
449
649
  error.should be_kind_of(Redis::Lock::LockTimeout)
450
650
  end
651
+
451
652
  end
data/spec/spec_helper.rb CHANGED
@@ -5,3 +5,4 @@ $redis = Redis.new(:host => ENV['REDIS_HOST'], :port => ENV['REDIS_PORT'])
5
5
 
6
6
  UNIONSTORE_KEY = 'test:unionstore'
7
7
  INTERSTORE_KEY = 'test:interstore'
8
+ DIFFSTORE_KEY = 'test:diffstore'