redis-objects 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -46,6 +46,24 @@ describe Redis::Value do
46
46
  @value.options[:marshal] = false
47
47
  end
48
48
 
49
+ it "should not erroneously unmarshall a string" do
50
+ json_string = {json: 'value'}
51
+ @value = Redis::Value.new('spec/value', :marshal => true)
52
+ @value.value = json_string
53
+ @value.value.should == json_string
54
+ @value.clear
55
+
56
+ default_json_string = {json: 'default'}
57
+ @value = Redis::Value.new('spec/default', :default => default_json_string, :marshal => true)
58
+ @value.value.should == default_json_string
59
+ @value.clear
60
+
61
+ marshalled_string = Marshal.dump({json: 'marshal'})
62
+ @value = Redis::Value.new('spec/marshal', :default => marshalled_string, :marshal => true)
63
+ @value.value.should == marshalled_string
64
+ @value.clear
65
+ end
66
+
49
67
  it "should support renaming values" do
50
68
  @value.value = 'Peter Pan'
51
69
  @value.key.should == 'spec/value'
@@ -86,6 +104,19 @@ describe Redis::Value do
86
104
  @value.nil?.should == true
87
105
  end
88
106
 
107
+ it 'should set time to live in seconds when expiration option assigned' do
108
+ @value = Redis::Value.new('spec/value', :expiration => 10)
109
+ @value.value = 'monkey'
110
+ @value.ttl.should > 0
111
+ @value.ttl.should <= 10
112
+ end
113
+
114
+ it 'should set expiration when expireat option assigned' do
115
+ @value = Redis::Value.new('spec/value', :expireat => Time.now + 10.seconds)
116
+ @value.value = 'monkey'
117
+ @value.ttl.should > 0
118
+ end
119
+
89
120
  after do
90
121
  @value.delete
91
122
  end
@@ -298,6 +329,20 @@ describe Redis::List do
298
329
  @list.redis.del('spec/list2')
299
330
  end
300
331
 
332
+ it 'should set time to live in seconds when expiration option assigned' do
333
+ @list = Redis::List.new('spec/list', :expiration => 10)
334
+ @list << 'val'
335
+ @list.ttl.should > 0
336
+ @list.ttl.should <= 10
337
+ end
338
+
339
+ it 'should set expiration when expireat option assigned' do
340
+ @list = Redis::List.new('spec/list', :expireat => Time.now + 10.seconds)
341
+ @list << 'val'
342
+ @list.ttl.should > 0
343
+ @list.ttl.should <= 10
344
+ end
345
+
301
346
  after do
302
347
  @list.clear
303
348
  end
@@ -341,6 +386,33 @@ describe Redis::Counter do
341
386
  @counter.should == 111
342
387
  end
343
388
 
389
+ it "should support increment/decrement by float" do
390
+ @counter = Redis::Counter.new('spec/floater')
391
+ @counter.set 10.5
392
+ @counter.incrbyfloat 1
393
+ @counter.incrbyfloat 0.01
394
+ @counter.to_f.should == 11.51
395
+ @counter.set '5.0e3'
396
+ @counter.decrbyfloat -14.31
397
+ @counter.incrbyfloat 2.0e2
398
+ @counter.to_f.should == 5214.31
399
+ @counter.clear
400
+ end
401
+
402
+ it 'should set time to live in seconds when expiration option assigned' do
403
+ @counter = Redis::Counter.new('spec/counter', :expiration => 10)
404
+ @counter.increment
405
+ @counter.ttl.should > 0
406
+ @counter.ttl.should <= 10
407
+ end
408
+
409
+ it 'should set expiration when expireat option assigned' do
410
+ @counter = Redis::Counter.new('spec/counter', :expireat => Time.now + 10.seconds)
411
+ @counter.increment
412
+ @counter.ttl.should > 0
413
+ @counter.ttl.should <= 10
414
+ end
415
+
344
416
  after do
345
417
  @counter.delete
346
418
  end
@@ -473,8 +545,8 @@ describe Redis::HashKey do
473
545
  it "should handle complex marshaled values" do
474
546
  @hash.options[:marshal] = true
475
547
  @hash['abc'].should == nil
476
- @hash['abc'] = {:json => 'data'}
477
- @hash['abc'].should == {:json => 'data'}
548
+ @hash['abc'] = {:json => 'hash marshal'}
549
+ @hash['abc'].should == {:json => 'hash marshal'}
478
550
 
479
551
  # no marshaling
480
552
  @hash.options[:marshal] = false
@@ -544,6 +616,29 @@ describe Redis::HashKey do
544
616
  end
545
617
  end
546
618
 
619
+ it "should handle increment/decrement" do
620
+ @hash['integer'] = 1
621
+ @hash.incrby('integer')
622
+ @hash.incrby('integer', 2)
623
+ @hash.get('integer').to_i.should == 4
624
+
625
+ @hash['integer'] = 9
626
+ @hash.decrby('integer')
627
+ @hash.decrby('integer', 6)
628
+ @hash.get('integer').to_i.should == 2
629
+
630
+ @hash['float'] = 12.34
631
+ @hash.decrbyfloat('float')
632
+ @hash.decrbyfloat('float', 6.3)
633
+ @hash.get('float').to_f.should == 5.04
634
+
635
+ @hash['float'] = '5.0e3'
636
+ @hash.incrbyfloat('float')
637
+ @hash.incrbyfloat('float', '1.23e3')
638
+ @hash.incrbyfloat('float', 45.3)
639
+ @hash.get('float').to_f.should == 6276.3
640
+ end
641
+
547
642
  it "should respond to each_value" do
548
643
  @hash['foo'] = 'bar'
549
644
  @hash.each_value do |val|
@@ -603,6 +698,31 @@ describe Redis::HashKey do
603
698
  end
604
699
  end
605
700
 
701
+ it "should fetch default values" do
702
+ @hash['abc'] = "123"
703
+
704
+ value = @hash.fetch('missing_key','default_value')
705
+ block = @hash.fetch("missing_key") {|key| "oops: #{key}" }
706
+ no_error = @hash.fetch("abc") rescue "error"
707
+
708
+ no_error.should == "123"
709
+ value.should == "default_value"
710
+ block.should == "oops: missing_key"
711
+ end
712
+
713
+ it 'should set time to live in seconds when expiration option assigned' do
714
+ @hash = Redis::HashKey.new('spec/hash_key', :expiration => 10)
715
+ @hash['foo'] = 'bar'
716
+ @hash.ttl.should > 0
717
+ @hash.ttl.should <= 10
718
+ end
719
+
720
+ it 'should set expiration when expireat option assigned' do
721
+ @hash = Redis::HashKey.new('spec/hash_key', :expireat => Time.now + 10.seconds)
722
+ @hash['foo'] = 'bar'
723
+ @hash.ttl.should > 0
724
+ end
725
+
606
726
  after do
607
727
  @hash.clear
608
728
  end
@@ -665,6 +785,17 @@ describe Redis::Set do
665
785
  @set.sort.should == ['a','b','c']
666
786
  @set.delete_if{|m| m == 'c'}
667
787
  @set.sort.should == ['a','b']
788
+
789
+ @set << nil
790
+ @set.include?("").should.be.true
791
+ end
792
+
793
+ it "should handle empty array adds" do
794
+ should.not.raise(Redis::CommandError) { @set.add([]) }
795
+ @set.should.be.empty
796
+
797
+ should.not.raise(Redis::CommandError) { @set << [] }
798
+ @set.should.be.empty
668
799
  end
669
800
 
670
801
  it "should handle set intersections, unions, and diffs" do
@@ -764,7 +895,20 @@ describe Redis::Set do
764
895
  @set_1.redis.del val1.key
765
896
  @set_1.redis.del val2.key
766
897
  @set_1.redis.del SORT_STORE[:store]
898
+ end
899
+
900
+ it 'should set time to live in seconds when expiration option assigned' do
901
+ @set = Redis::Set.new('spec/set', :expiration => 10)
902
+ @set << 'val'
903
+ @set.ttl.should > 0
904
+ @set.ttl.should <= 10
905
+ end
767
906
 
907
+ it 'should set expiration when expireat option assigned' do
908
+ @set = Redis::Set.new('spec/set', :expireat => Time.now + 10.seconds)
909
+ @set << 'val'
910
+ @set.ttl.should > 0
911
+ @set.ttl.should <= 10
768
912
  end
769
913
 
770
914
  after do
@@ -882,6 +1026,17 @@ describe Redis::SortedSet do
882
1026
  @set.size.should == 3
883
1027
  end
884
1028
 
1029
+ it "should handle inserting multiple values at once" do
1030
+ @set.merge({ 'a' => 1, 'b' => 2 })
1031
+ @set.merge([['a', 4], ['c', 5]])
1032
+ @set.merge({d: 0, e: 9 })
1033
+
1034
+ @set.members.should == ["d", "b", "a", "c", "e"]
1035
+
1036
+ @set[:f] = 3
1037
+ @set.members.should == ["d", "b", "f", "a", "c", "e"]
1038
+ end
1039
+
885
1040
  it "should support marshaling key names" do
886
1041
  @set_4[Object] = 1.20
887
1042
  @set_4[Module] = 2.30
@@ -909,6 +1064,20 @@ describe Redis::SortedSet do
909
1064
  @set.redis.del('spec/zset2')
910
1065
  end
911
1066
 
1067
+ it 'should set time to live in seconds when expiration option assigned' do
1068
+ @set = Redis::SortedSet.new('spec/zset', :expiration => 10)
1069
+ @set['val'] = 1
1070
+ @set.ttl.should > 0
1071
+ @set.ttl.should <= 10
1072
+ end
1073
+
1074
+ it 'should set expiration when expireat option assigned' do
1075
+ @set = Redis::SortedSet.new('spec/zset', :expireat => Time.now + 10.seconds)
1076
+ @set['val'] = 1
1077
+ @set.ttl.should > 0
1078
+ @set.ttl.should <= 10
1079
+ end
1080
+
912
1081
  after do
913
1082
  @set.clear
914
1083
  @set_1.clear
@@ -33,6 +33,20 @@ class Roster
33
33
  #callable as key
34
34
  counter :daily, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" }
35
35
 
36
+ # set default expiration
37
+ value :value_with_expiration, :expiration => 10
38
+ value :value_with_expireat, :expireat => Time.now + 10.seconds
39
+ set :set_with_expiration, :expiration => 10
40
+ set :set_with_expireat, :expireat => Time.now + 10.seconds
41
+ list :list_with_expiration, :expiration => 10
42
+ list :list_with_expireat, :expireat => Time.now + 10.seconds
43
+ hash_key :hash_with_expiration, :expiration => 10
44
+ hash_key :hash_with_expireat, :expireat => Time.now + 10.seconds
45
+ counter :counter_with_expiration, :expiration => 10
46
+ counter :counter_with_expireat, :expireat => Time.now + 10.seconds
47
+ sorted_set :sorted_set_with_expiration,:expiration => 10
48
+ sorted_set :sorted_set_with_expireat, :expireat => Time.now + 10.seconds
49
+
36
50
  def initialize(id=1) @id = id end
37
51
  def id; @id; end
38
52
  def username; "user#{id}"; end
@@ -594,19 +608,23 @@ describe Redis::Objects do
594
608
  @roster_1.outfielders.intersection(@roster_2.outfielders, @roster_3.outfielders).sort.should == ['d']
595
609
  @roster_1.outfielders.intersect(@roster_2.outfielders).sort.should == ['c','d','e']
596
610
  @roster_1.outfielders.inter(@roster_2.outfielders, @roster_3.outfielders).sort.should == ['d']
611
+
597
612
  @roster_1.outfielders.interstore(INTERSTORE_KEY, @roster_2.outfielders).should == 3
598
- @roster_1.redis.smembers(INTERSTORE_KEY).sort.should == ['c','d','e']
613
+ @roster_1.redis.smembers(INTERSTORE_KEY).sort.map{|v| Marshal.restore(v)}.should == ['c','d','e']
614
+
599
615
  @roster_1.outfielders.interstore(INTERSTORE_KEY, @roster_2.outfielders, @roster_3.outfielders).should == 1
600
- @roster_1.redis.smembers(INTERSTORE_KEY).sort.should == ['d']
616
+ @roster_1.redis.smembers(INTERSTORE_KEY).sort.map{|v| Marshal.restore(v)}.should == ['d']
601
617
 
602
618
  (@roster_1.outfielders | @roster_2.outfielders).sort.should == ['a','b','c','d','e','f','g']
603
619
  (@roster_1.outfielders + @roster_2.outfielders).sort.should == ['a','b','c','d','e','f','g']
604
620
  @roster_1.outfielders.union(@roster_2.outfielders).sort.should == ['a','b','c','d','e','f','g']
605
621
  @roster_1.outfielders.union(@roster_2.outfielders, @roster_3.outfielders).sort.should == ['a','b','c','d','e','f','g','l','m']
622
+
606
623
  @roster_1.outfielders.unionstore(UNIONSTORE_KEY, @roster_2.outfielders).should == 7
607
- @roster_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g']
624
+ @roster_1.redis.smembers(UNIONSTORE_KEY).map{|v| Marshal.restore(v)}.sort.should == ['a','b','c','d','e','f','g']
625
+
608
626
  @roster_1.outfielders.unionstore(UNIONSTORE_KEY, @roster_2.outfielders, @roster_3.outfielders).should == 9
609
- @roster_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g','l','m']
627
+ @roster_1.redis.smembers(UNIONSTORE_KEY).map{|v| Marshal.restore(v)}.sort.should == ['a','b','c','d','e','f','g','l','m']
610
628
  end
611
629
 
612
630
  it "should handle class-level global lists of simple values" do
@@ -920,4 +938,52 @@ describe Redis::Objects do
920
938
  extended_roster.extended_sorted_set.should.be.kind_of(Redis::SortedSet)
921
939
  @roster.respond_to?(:extended_sorted_set).should == false
922
940
  end
941
+
942
+ it "should set time to live in seconds when expiration option assigned" do
943
+ @roster.value_with_expiration.value = 'val'
944
+ @roster.value_with_expiration.ttl.should > 0
945
+ @roster.value_with_expiration.ttl.should <= 10
946
+
947
+ @roster.set_with_expiration << 'val'
948
+ @roster.set_with_expiration.ttl.should > 0
949
+ @roster.set_with_expiration.ttl.should <= 10
950
+
951
+ @roster.list_with_expiration << 'val'
952
+ @roster.list_with_expiration.ttl.should > 0
953
+ @roster.list_with_expiration.ttl.should <= 10
954
+
955
+ @roster.hash_with_expiration[:foo] = :bar
956
+ @roster.hash_with_expiration.ttl.should > 0
957
+ @roster.hash_with_expiration.ttl.should <= 10
958
+
959
+ @roster.counter_with_expiration.increment
960
+ @roster.counter_with_expiration.ttl.should > 0
961
+ @roster.counter_with_expiration.ttl.should <= 10
962
+
963
+ @roster.sorted_set_with_expiration[:foo] = 1
964
+ @roster.sorted_set_with_expiration.ttl.should > 0
965
+ @roster.sorted_set_with_expiration.ttl.should <= 10
966
+ end
967
+
968
+ it "should set expiration when expireat option assigned" do
969
+ @roster.value_with_expireat.value = 'val'
970
+ @roster.value_with_expireat.ttl.should > 0
971
+ @roster.value_with_expireat.ttl.should <= 10
972
+
973
+ @roster.set_with_expireat << 'val'
974
+ @roster.set_with_expireat.ttl.should > 0
975
+ @roster.set_with_expireat.ttl.should <= 10
976
+
977
+ @roster.list_with_expireat << 'val'
978
+ @roster.list_with_expireat.ttl.should > 0
979
+ @roster.list_with_expireat.ttl.should <= 10
980
+
981
+ @roster.hash_with_expireat[:foo] = :bar
982
+ @roster.hash_with_expireat.ttl.should > 0
983
+ @roster.hash_with_expireat.ttl.should <= 10
984
+
985
+ @roster.sorted_set_with_expireat[:foo] = 1
986
+ @roster.sorted_set_with_expireat.ttl.should > 0
987
+ @roster.sorted_set_with_expireat.ttl.should <= 10
988
+ end
923
989
  end
data/spec/spec_helper.rb CHANGED
@@ -19,26 +19,31 @@ DIFFSTORE_KEY = 'test:diffstore'
19
19
  REDIS_BIN = 'redis-server'
20
20
  REDIS_PORT = ENV['REDIS_PORT'] || 9212
21
21
  REDIS_HOST = ENV['REDIS_HOST'] || 'localhost'
22
- REDIS_PID = File.expand_path 'redis.pid', File.dirname(__FILE__)
23
- REDIS_DUMP = File.expand_path 'redis.rdb', File.dirname(__FILE__)
22
+ REDIS_PID = 'redis.pid' # can't be absolute
23
+ REDIS_DUMP = 'redis.rdb' # can't be absolute
24
+ REDIS_RUNDIR = File.dirname(__FILE__)
24
25
 
25
- describe 'redis-server' do
26
- it "starting redis-server on #{REDIS_HOST}:#{REDIS_PORT}" do
27
- fork_pid = fork do
28
- system "(echo port #{REDIS_PORT}; echo logfile /dev/null; echo daemonize yes; echo pidfile #{REDIS_PID}; echo dbfilename #{REDIS_DUMP}) | #{REDIS_BIN} -"
26
+ if !(defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby")
27
+ describe 'redis-server' do
28
+ it "starting redis-server on #{REDIS_HOST}:#{REDIS_PORT}" do
29
+ fork_pid = fork do
30
+ system "cd #{REDIS_RUNDIR} && (echo port #{REDIS_PORT}; echo logfile /dev/null; echo daemonize yes; echo pidfile #{REDIS_PID}; echo dbfilename #{REDIS_DUMP}; echo databases 32) | #{REDIS_BIN} -"
31
+ end
32
+ fork_pid.should > 0
33
+ sleep 2
29
34
  end
30
- fork_pid.should > 0
31
- sleep 2
32
35
  end
33
- end
34
36
 
35
- at_exit do
36
- pid = File.read(REDIS_PID).to_i
37
- puts "=> Killing #{REDIS_BIN} with pid #{pid}"
38
- Process.kill "TERM", pid
39
- Process.kill "KILL", pid
40
- File.unlink REDIS_PID
41
- File.unlink REDIS_DUMP if File.exists? REDIS_DUMP
37
+ at_exit do
38
+ pidfile = File.expand_path REDIS_PID, REDIS_RUNDIR
39
+ rdbfile = File.expand_path REDIS_DUMP, REDIS_RUNDIR
40
+ pid = File.read(pidfile).to_i
41
+ puts "=> Killing #{REDIS_BIN} with pid #{pid}"
42
+ Process.kill "TERM", pid
43
+ Process.kill "KILL", pid
44
+ File.unlink pidfile
45
+ File.unlink rdbfile if File.exists? rdbfile
46
+ end
42
47
  end
43
48
 
44
49
  def raises_exception(&block)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Wiger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-09 00:00:00.000000000 Z
11
+ date: 2014-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -115,7 +115,6 @@ files:
115
115
  - lib/redis/counter.rb
116
116
  - lib/redis/hash_key.rb
117
117
  - lib/redis/helpers/core_commands.rb
118
- - lib/redis/helpers/serialize.rb
119
118
  - lib/redis/list.rb
120
119
  - lib/redis/lock.rb
121
120
  - lib/redis/objects.rb
@@ -1,41 +0,0 @@
1
- class Redis
2
- module Helpers
3
- module Serialize
4
- include Marshal
5
-
6
- def to_redis(value, marshal=false)
7
- return value unless options[:marshal] || marshal
8
- case value
9
- when String, Fixnum, Bignum, Float
10
- value
11
- else
12
- dump(value)
13
- end
14
- end
15
-
16
- def from_redis(value, marshal=false)
17
- # This was removed because we can't reliably determine
18
- # if a person said @value = "123.4" maybe for space/etc.
19
- #begin
20
- # case value
21
- # when /^\d+$/
22
- # return Integer(value)
23
- # when /^(?:\d+\d.\d*|\d*\.\d+)$/
24
- # return Float(value)
25
- # end
26
- #rescue
27
- # # continue below
28
- #end
29
- return value unless options[:marshal] || marshal
30
- case value
31
- when Array
32
- value.collect{|v| from_redis(v)}
33
- when Hash
34
- value.inject({}) { |h, (k, v)| h[k] = from_redis(v); h }
35
- else
36
- restore(value) rescue value
37
- end
38
- end
39
- end
40
- end
41
- end