redis-actionpack-json 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/.gitignore +15 -0
  2. data/.travis.yml +7 -0
  3. data/CHANGELOG +450 -0
  4. data/README.md +23 -0
  5. data/redis-actionpack-json/.gitignore +4 -0
  6. data/redis-actionpack-json/Gemfile +6 -0
  7. data/redis-actionpack-json/MIT-LICENSE +20 -0
  8. data/redis-actionpack-json/Rakefile +8 -0
  9. data/redis-actionpack-json/lib/action_dispatch/middleware/session/redis_store_json.rb +24 -0
  10. data/redis-actionpack-json/lib/redis-actionpack-json.rb +4 -0
  11. data/redis-actionpack-json/lib/redis/actionpack/version.rb +5 -0
  12. data/redis-actionpack-json/redis-actionpack-json.gemspec +32 -0
  13. data/redis-actionpack-json/test/dummy/.gitignore +1 -0
  14. data/redis-actionpack-json/test/dummy/Rakefile +7 -0
  15. data/redis-actionpack-json/test/dummy/app/controllers/test_controller.rb +37 -0
  16. data/redis-actionpack-json/test/dummy/config.ru +4 -0
  17. data/redis-actionpack-json/test/dummy/config/application.rb +29 -0
  18. data/redis-actionpack-json/test/dummy/config/boot.rb +10 -0
  19. data/redis-actionpack-json/test/dummy/config/environment.rb +5 -0
  20. data/redis-actionpack-json/test/dummy/config/initializers/secret_token.rb +7 -0
  21. data/redis-actionpack-json/test/dummy/config/initializers/session_store.rb +11 -0
  22. data/redis-actionpack-json/test/dummy/config/routes.rb +3 -0
  23. data/redis-actionpack-json/test/dummy/script/rails +6 -0
  24. data/redis-actionpack-json/test/fixtures/session_autoload_test/session_autoload_test/foo.rb +10 -0
  25. data/redis-actionpack-json/test/integration/redis_store_integration_test.rb +130 -0
  26. data/redis-actionpack-json/test/integration/redis_store_json_integration_test.rb +130 -0
  27. data/redis-actionpack-json/test/redis/actionpack/version_test.rb +7 -0
  28. data/redis-actionpack-json/test/test_helper.rb +23 -0
  29. data/redis-rack-json/.gitignore +5 -0
  30. data/redis-rack-json/Gemfile +5 -0
  31. data/redis-rack-json/MIT-LICENSE +20 -0
  32. data/redis-rack-json/Rakefile +8 -0
  33. data/redis-rack-json/lib/rack/session/redis.rb +69 -0
  34. data/redis-rack-json/lib/redis-rack-json.rb +3 -0
  35. data/redis-rack-json/lib/redis/rack/version.rb +6 -0
  36. data/redis-rack-json/redis-rack-json.gemspec +29 -0
  37. data/redis-rack-json/test/rack/session/redis_test.rb +289 -0
  38. data/redis-rack-json/test/redis/rack/version_test.rb +7 -0
  39. data/redis-rack-json/test/test_helper.rb +7 -0
  40. data/redis-store-json/Gemfile +4 -0
  41. data/redis-store-json/MIT-LICENSE +20 -0
  42. data/redis-store-json/Rakefile +7 -0
  43. data/redis-store-json/lib/redis-store-json.rb +11 -0
  44. data/redis-store-json/lib/redis/distributed_store.rb +46 -0
  45. data/redis-store-json/lib/redis/factory.rb +41 -0
  46. data/redis-store-json/lib/redis/store.rb +47 -0
  47. data/redis-store-json/lib/redis/store/interface.rb +21 -0
  48. data/redis-store-json/lib/redis/store/namespace.rb +66 -0
  49. data/redis-store-json/lib/redis/store/strategy.rb +60 -0
  50. data/redis-store-json/lib/redis/store/strategy/json.rb +49 -0
  51. data/redis-store-json/lib/redis/store/strategy/json_session.rb +67 -0
  52. data/redis-store-json/lib/redis/store/strategy/marshal.rb +16 -0
  53. data/redis-store-json/lib/redis/store/strategy/yaml.rb +16 -0
  54. data/redis-store-json/lib/redis/store/ttl.rb +37 -0
  55. data/redis-store-json/lib/redis/store/version.rb +5 -0
  56. data/redis-store-json/lib/tasks/redis.tasks.rb +167 -0
  57. data/redis-store-json/redis-store-json.gemspec +29 -0
  58. data/redis-store-json/test/config/node-one.conf +46 -0
  59. data/redis-store-json/test/config/node-two.conf +46 -0
  60. data/redis-store-json/test/config/redis.conf +46 -0
  61. data/redis-store-json/test/redis/distributed_store_test.rb +53 -0
  62. data/redis-store-json/test/redis/factory_test.rb +120 -0
  63. data/redis-store-json/test/redis/store/interface_test.rb +27 -0
  64. data/redis-store-json/test/redis/store/namespace_test.rb +103 -0
  65. data/redis-store-json/test/redis/store/strategy/json_session_test.rb +160 -0
  66. data/redis-store-json/test/redis/store/strategy/json_test.rb +108 -0
  67. data/redis-store-json/test/redis/store/strategy/marshal_test.rb +121 -0
  68. data/redis-store-json/test/redis/store/strategy/yaml_test.rb +105 -0
  69. data/redis-store-json/test/redis/store/ttl_test.rb +107 -0
  70. data/redis-store-json/test/redis/store/version_test.rb +7 -0
  71. data/redis-store-json/test/redis/store_test.rb +45 -0
  72. data/redis-store-json/test/test_helper.rb +22 -0
  73. metadata +279 -0
@@ -0,0 +1,120 @@
1
+ require 'test_helper'
2
+
3
+ describe "Redis::Factory" do
4
+ describe ".create" do
5
+ describe "when not given any arguments" do
6
+ it "instantiates Redis::Store" do
7
+ store = Redis::Factory.create
8
+ store.must_be_kind_of(Redis::Store)
9
+ store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0")
10
+ end
11
+ end
12
+
13
+ describe "when given a Hash" do
14
+ it "uses specified host" do
15
+ store = Redis::Factory.create :host => "localhost"
16
+ store.to_s.must_equal("Redis Client connected to localhost:6379 against DB 0")
17
+ end
18
+
19
+ it "uses specified port" do
20
+ store = Redis::Factory.create :host => "localhost", :port => 6380
21
+ store.to_s.must_equal("Redis Client connected to localhost:6380 against DB 0")
22
+ end
23
+
24
+ it "uses specified db" do
25
+ store = Redis::Factory.create :host => "localhost", :port => 6380, :db => 13
26
+ store.to_s.must_equal("Redis Client connected to localhost:6380 against DB 13")
27
+ end
28
+
29
+ it "uses specified namespace" do
30
+ store = Redis::Factory.create :namespace => "theplaylist"
31
+ store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist")
32
+ end
33
+
34
+ it "uses specified key_prefix as namespace" do
35
+ store = Redis::Factory.create :key_prefix => "theplaylist"
36
+ store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist")
37
+ end
38
+
39
+ it "uses specified password" do
40
+ store = Redis::Factory.create :password => "secret"
41
+ store.instance_variable_get(:@client).password.must_equal("secret")
42
+ end
43
+
44
+ it "allows json strategy option" do
45
+ store = Redis::Factory.create :strategy => :json
46
+ store.must_be_kind_of(Redis::Store::Strategy::Json)
47
+ end
48
+
49
+ it "allows marshal strategy option" do
50
+ store = Redis::Factory.create :strategy => :marshal
51
+ store.must_be_kind_of(Redis::Store::Strategy::Marshal)
52
+ end
53
+
54
+ it "allows yaml strategy option" do
55
+ store = Redis::Factory.create :strategy => :yaml
56
+ store.must_be_kind_of(Redis::Store::Strategy::Yaml)
57
+ end
58
+
59
+ it "allows false strategy option" do
60
+ store = Redis::Factory.create :strategy => false
61
+ store.wont_be_kind_of(Redis::Store::Strategy::Json)
62
+ store.wont_be_kind_of(Redis::Store::Strategy::Marshal)
63
+ store.wont_be_kind_of(Redis::Store::Strategy::Yaml)
64
+ end
65
+
66
+ it "defaults to marshal strategy" do
67
+ store = Redis::Factory.create
68
+ store.must_be_kind_of(Redis::Store::Strategy::Marshal)
69
+ end
70
+
71
+ it "should instantiate a Redis::DistributedStore store" do
72
+ store = Redis::Factory.create(
73
+ {:host => "localhost", :port => 6379},
74
+ {:host => "localhost", :port => 6380}
75
+ )
76
+ store.must_be_kind_of(Redis::DistributedStore)
77
+ store.nodes.map {|node| node.to_s }.must_equal([
78
+ "Redis Client connected to localhost:6379 against DB 0",
79
+ "Redis Client connected to localhost:6380 against DB 0",
80
+ ])
81
+ end
82
+ end
83
+
84
+ describe "when given a String" do
85
+ it "uses specified host" do
86
+ store = Redis::Factory.create "redis://127.0.0.1"
87
+ store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0")
88
+ end
89
+
90
+ it "uses specified port" do
91
+ store = Redis::Factory.create "redis://127.0.0.1:6380"
92
+ store.to_s.must_equal("Redis Client connected to 127.0.0.1:6380 against DB 0")
93
+ end
94
+
95
+ it "uses specified db" do
96
+ store = Redis::Factory.create "redis://127.0.0.1:6380/13"
97
+ store.to_s.must_equal("Redis Client connected to 127.0.0.1:6380 against DB 13")
98
+ end
99
+
100
+ it "uses specified namespace" do
101
+ store = Redis::Factory.create "redis://127.0.0.1:6379/0/theplaylist"
102
+ store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist")
103
+ end
104
+
105
+ it "uses specified password" do
106
+ store = Redis::Factory.create "redis://:secret@127.0.0.1:6379/0/theplaylist"
107
+ store.instance_variable_get(:@client).password.must_equal("secret")
108
+ end
109
+
110
+ it "instantiates Redis::DistributedStore" do
111
+ store = Redis::Factory.create "redis://127.0.0.1:6379", "redis://127.0.0.1:6380"
112
+ store.must_be_kind_of(Redis::DistributedStore)
113
+ store.nodes.map {|node| node.to_s }.must_equal([
114
+ "Redis Client connected to 127.0.0.1:6379 against DB 0",
115
+ "Redis Client connected to 127.0.0.1:6380 against DB 0",
116
+ ])
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class InterfacedRedis < Redis
4
+ include Redis::Store::Interface
5
+ end
6
+
7
+ describe Redis::Store::Interface do
8
+ before do
9
+ @r = InterfacedRedis.new
10
+ end
11
+
12
+ it "should get an element" do
13
+ lambda { @r.get("key", :option => true) } #.wont_raise ArgumentError
14
+ end
15
+
16
+ it "should set an element" do
17
+ lambda { @r.set("key", "value", :option => true) } #.wont_raise ArgumentError
18
+ end
19
+
20
+ it "should setnx an element" do
21
+ lambda { @r.setnx("key", "value", :option => true) } #.wont_raise ArgumentError
22
+ end
23
+
24
+ it "should setex an element" do
25
+ lambda { @r.setex("key", 1, "value", :option => true) } #.wont_raise ArgumentError
26
+ end
27
+ end
@@ -0,0 +1,103 @@
1
+ require 'test_helper'
2
+
3
+ describe "Redis::Store::Namespace" do
4
+ def setup
5
+ @namespace = "theplaylist"
6
+ @store = Redis::Store.new :namespace => @namespace, :strategy => false
7
+ @client = @store.instance_variable_get(:@client)
8
+ @rabbit = "bunny"
9
+ end
10
+
11
+ def teardown
12
+ @store.quit
13
+ end
14
+
15
+ it "only decorates instances that need to be namespaced" do
16
+ store = Redis::Store.new
17
+ client = store.instance_variable_get(:@client)
18
+ client.expects(:call).with([:get, "rabbit"])
19
+ store.get("rabbit")
20
+ end
21
+
22
+ it "doesn't namespace a key which is already namespaced" do
23
+ @store.send(:interpolate, "#{@namespace}:rabbit").must_equal("#{@namespace}:rabbit")
24
+ end
25
+
26
+ it "should only delete namespaced keys" do
27
+ other_store = Redis::Store.new
28
+
29
+ other_store.set 'abc', 'cba'
30
+ @store.set 'def', 'fed'
31
+
32
+ @store.flushdb
33
+ @store.get('def').must_equal(nil)
34
+ other_store.get('abc').must_equal('cba')
35
+ end
36
+
37
+ it "should not try to delete missing namespaced keys" do
38
+ empty_store = Redis::Store.new :namespace => 'empty'
39
+ empty_store.flushdb
40
+ empty_store.keys.must_be_empty
41
+ end
42
+
43
+ it "namespaces get"
44
+ it "namespaces set"
45
+ it "namespaces setnx"
46
+ it "namespaces del with single key"
47
+ it "namespaces del with multiple keys"
48
+ it "namespaces keys"
49
+ it "namespaces exists"
50
+ it "namespaces incrby"
51
+ it "namespaces decrby"
52
+ it "namespaces mget"
53
+
54
+ # it "should namespace get" do
55
+ # @client.expects(:call).with([:get, "#{@namespace}:rabbit"]).once
56
+ # @store.get("rabbit")
57
+ # end
58
+ #
59
+ # it "should namespace set" do
60
+ # @client.should_receive(:call).with([:set, "#{@namespace}:rabbit", @rabbit])
61
+ # @store.set "rabbit", @rabbit
62
+ # end
63
+ #
64
+ # it "should namespace setnx" do
65
+ # @client.should_receive(:call).with([:setnx, "#{@namespace}:rabbit", @rabbit])
66
+ # @store.setnx "rabbit", @rabbit
67
+ # end
68
+ #
69
+ # it "should namespace del with single key" do
70
+ # @client.should_receive(:call).with([:del, "#{@namespace}:rabbit"])
71
+ # @store.del "rabbit"
72
+ # end
73
+ #
74
+ # it "should namespace del with multiple keys" do
75
+ # @client.should_receive(:call).with([:del, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"])
76
+ # @store.del "rabbit", "white_rabbit"
77
+ # end
78
+ #
79
+ # it "should namespace keys" do
80
+ # @store.set "rabbit", @rabbit
81
+ # @store.keys("rabb*").should == [ "rabbit" ]
82
+ # end
83
+ #
84
+ # it "should namespace exists" do
85
+ # @client.should_receive(:call).with([:exists, "#{@namespace}:rabbit"])
86
+ # @store.exists "rabbit"
87
+ # end
88
+ #
89
+ # it "should namespace incrby" do
90
+ # @client.should_receive(:call).with([:incrby, "#{@namespace}:counter", 1])
91
+ # @store.incrby "counter", 1
92
+ # end
93
+ #
94
+ # it "should namespace decrby" do
95
+ # @client.should_receive(:call).with([:decrby, "#{@namespace}:counter", 1])
96
+ # @store.decrby "counter", 1
97
+ # end
98
+ #
99
+ # it "should namespace mget" do
100
+ # @client.should_receive(:call).with([:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"])
101
+ # @store.mget "rabbit", "white_rabbit"
102
+ # end
103
+ end
@@ -0,0 +1,160 @@
1
+ require 'test_helper'
2
+
3
+ # For faking rails flash objects retrieved from session
4
+ module FakeActionDispatch
5
+ class Flash
6
+ class FlashHash < Hash
7
+ end
8
+ end
9
+ end
10
+
11
+ describe "Redis::Store::Strategy::JsonSession" do
12
+ def setup
13
+ @marshal_store = Redis::Store.new :strategy => :marshal
14
+ @store = Redis::Store.new :strategy => :json_session
15
+ @rabbit = {:name => "rabbit", :legs => 4}
16
+ @peter = { :name => "Peter Cottontail",
17
+ :race => @rabbit }
18
+ @bunnicula = { :name => "Bunnicula",
19
+ :race => @rabbit,
20
+ :friends => [@peter],
21
+ :age => 3.1,
22
+ :alive => true }
23
+ @store.set "rabbit", @bunnicula
24
+ @store.del "rabbit2"
25
+ end
26
+
27
+ def teardown
28
+ @store.quit
29
+ end
30
+
31
+ it "unmarshals on get" do
32
+ @store.get("rabbit").must_equal(@bunnicula)
33
+ end
34
+
35
+ it "marshals on set" do
36
+ @store.set "rabbit", @peter
37
+ @store.get("rabbit").must_equal(@peter)
38
+ end
39
+
40
+ it "doesn't unmarshal on get if raw option is true" do
41
+ race = @rabbit.to_json
42
+ @store.get("rabbit", :raw => true).must_equal(%({"name":"Bunnicula","race":#{race},"friends":[{"name":"Peter Cottontail","race":#{race}}],"age":3.1,"alive":true}))
43
+ end
44
+
45
+ it "doesn't marshal on set if raw option is true" do
46
+ race = @rabbit
47
+ @store.set "rabbit", @peter, :raw => true
48
+ @store.get("rabbit", :raw => true).must_equal(%({:name=>"Peter Cottontail", :race=>#{race.inspect}}))
49
+ end
50
+
51
+ it "doesn't set an object if already exist" do
52
+ @store.setnx "rabbit", @peter
53
+ @store.get("rabbit").must_equal(@bunnicula)
54
+ end
55
+
56
+ it "marshals on set unless exists" do
57
+ @store.setnx "rabbit2", @peter
58
+ @store.get("rabbit2").must_equal(@peter)
59
+ end
60
+
61
+ it "doesn't marshal on set unless exists if raw option is true" do
62
+ @store.setnx "rabbit2", @peter, :raw => true
63
+ race = @rabbit
64
+ @store.get("rabbit2", :raw => true).must_equal(%({:name=>"Peter Cottontail", :race=>#{race.inspect}}))
65
+ end
66
+
67
+ it "doesn't unmarshal on multi get" do
68
+ @store.set "rabbit2", @peter
69
+ rabbit, rabbit2 = @store.mget "rabbit", "rabbit2"
70
+ rabbit.must_equal(@bunnicula)
71
+ rabbit2.must_equal(@peter)
72
+ end
73
+
74
+ it "doesn't unmarshal on multi get if raw option is true" do
75
+ @store.set "rabbit", @bunnicula
76
+ @store.set "rabbit2", @peter
77
+ rabbit, rabbit2 = @store.mget "rabbit", "rabbit2", :raw => true
78
+ race = @rabbit.to_json
79
+ rabbit.must_equal(%({"name":"Bunnicula","race":#{race},"friends":[{"name":"Peter Cottontail","race":#{race}}],"age":3.1,"alive":true}))
80
+ rabbit2.must_equal(%({"name":"Peter Cottontail","race":#{race}}))
81
+ end
82
+
83
+ it "will throw an error if an object isn't supported" do
84
+ lambda{
85
+ @store.set "rabbit2", OpenStruct.new(foo:'bar')
86
+ }.must_raise Redis::Store::Strategy::JsonSession::SerializationError
87
+ end
88
+
89
+ it "is able to bring out data that is marshalled using Ruby" do
90
+ @marshal_store.set "rabbit", @peter
91
+ rabbit = @store.get "rabbit"
92
+ rabbit.must_equal(@peter)
93
+ end
94
+
95
+ it "can set a Set object" do
96
+ @store.set "set_object", Set.new([1,2])
97
+ set_object = @store.get("set_object")
98
+ set_object.must_equal([1,2])
99
+ end
100
+
101
+ describe "flash key value" do
102
+
103
+ before do
104
+ @flash_value = {:show_login => true }
105
+ @flash_data = {:flash => @flash_value}
106
+ end
107
+
108
+ describe "when ActionDispatch is available" do
109
+
110
+ before do
111
+ ActionDispatch = FakeActionDispatch
112
+ @store.class.send(:include, ActionDispatch)
113
+ end
114
+
115
+ it "returns a flash object instead of a hash" do
116
+ @store.set "flash", @flash_data
117
+ flash_store = @store.get "flash"
118
+ flash_hash = flash_store[:flash]
119
+ flash_hash.class.must_equal(FakeActionDispatch::Flash::FlashHash)
120
+ flash_hash.must_equal(@flash_value)
121
+ end
122
+
123
+ end
124
+
125
+ it "returns a hash" do
126
+ @store.set "flash", @flash_data
127
+ flash = @store.get "flash"
128
+ flash.must_equal(@flash_data)
129
+ end
130
+
131
+ end
132
+
133
+ describe "binary safety" do
134
+ before do
135
+ @utf8_key = [51339].pack("U*")
136
+ @ascii_string = [128].pack("C*")
137
+ @ascii_rabbit = {:name => "rabbit", :legs => 4, :ascii_string => @ascii_string}
138
+ end
139
+
140
+ it "gets and sets raw values" do
141
+ @store.set(@utf8_key, @ascii_string, :raw => true)
142
+ @store.get(@utf8_key, :raw => true).bytes.to_a.must_equal(@ascii_string.bytes.to_a)
143
+ end
144
+
145
+ it "marshals objects on setnx" do
146
+ @store.del(@utf8_key)
147
+ @store.setnx(@utf8_key, @ascii_rabbit)
148
+ retrievied_ascii_rabbit = @store.get(@utf8_key)
149
+ JSON.load(JSON.generate(retrievied_ascii_rabbit.delete(:ascii_string))).must_equal(@ascii_string)
150
+ @ascii_rabbit.delete(:ascii_string)
151
+ retrievied_ascii_rabbit.must_equal(@ascii_rabbit)
152
+ end
153
+
154
+ it "gets and sets raw values on setnx" do
155
+ @store.del(@utf8_key)
156
+ @store.setnx(@utf8_key, @ascii_string, :raw => true)
157
+ @store.get(@utf8_key, :raw => true).bytes.to_a.must_equal(@ascii_string.bytes.to_a)
158
+ end
159
+ end if defined?(Encoding)
160
+ end
@@ -0,0 +1,108 @@
1
+ require 'test_helper'
2
+
3
+ describe "Redis::Store::Strategy::Json" do
4
+ def setup
5
+ @store = Redis::Store.new :strategy => :json
6
+ @rabbit = OpenStruct.new :name => 'rabbit', :legs => 4
7
+ @peter = { :name => "Peter Cottontail",
8
+ :race => @rabbit }
9
+ @bunnicula = { :name => "Bunnicula",
10
+ :race => @rabbit,
11
+ :friends => [@peter],
12
+ :age => 3.1,
13
+ :alive => true }
14
+ @store.set "rabbit", @bunnicula
15
+ @store.del "rabbit2"
16
+ end
17
+
18
+ def teardown
19
+ @store.quit
20
+ end
21
+
22
+ it "unmarshals on get" do
23
+ @store.get("rabbit").must_equal(@bunnicula)
24
+ end
25
+
26
+ it "marshals on set" do
27
+ @store.set "rabbit", @peter
28
+ @store.get("rabbit").must_equal(@peter)
29
+ end
30
+
31
+ it "doesn't unmarshal on get if raw option is true" do
32
+ race = Marshal.dump(@rabbit).to_json
33
+ @store.get("rabbit", :raw => true).must_equal(%({"name":"Bunnicula","race":#{race},"friends":[{"name":"Peter Cottontail","race":#{race}}],"age":3.1,"alive":true}))
34
+ end
35
+
36
+ it "doesn't marshal on set if raw option is true" do
37
+ race = Marshal.dump(@rabbit)
38
+ @store.set "rabbit", @peter, :raw => true
39
+ @store.get("rabbit", :raw => true).must_equal(%({:name=>"Peter Cottontail", :race=>#{race.inspect}}))
40
+ end
41
+
42
+ it "doesn't set an object if already exist" do
43
+ @store.setnx "rabbit", @peter
44
+ @store.get("rabbit").must_equal(@bunnicula)
45
+ end
46
+
47
+ it "marshals on set unless exists" do
48
+ @store.setnx "rabbit2", @peter
49
+ @store.get("rabbit2").must_equal(@peter)
50
+ end
51
+
52
+ it "doesn't marshal on set unless exists if raw option is true" do
53
+ @store.setnx "rabbit2", @peter, :raw => true
54
+ race = Marshal.dump(@rabbit)
55
+ @store.get("rabbit2", :raw => true).must_equal(%({:name=>"Peter Cottontail", :race=>#{race.inspect}}))
56
+ end
57
+
58
+ it "marshals on set expire" do
59
+ @store.setex "rabbit2", 1, @peter
60
+ @store.get("rabbit2").must_equal(@peter)
61
+ sleep 2
62
+ @store.get("rabbit2").must_be_nil
63
+ end
64
+
65
+ it "doesn't unmarshal on multi get" do
66
+ @store.set "rabbit2", @peter
67
+ rabbit, rabbit2 = @store.mget "rabbit", "rabbit2"
68
+ rabbit.must_equal(@bunnicula)
69
+ rabbit2.must_equal(@peter)
70
+ end
71
+
72
+ it "doesn't unmarshal on multi get if raw option is true" do
73
+ @store.set "rabbit", @bunnicula
74
+ @store.set "rabbit2", @peter
75
+ rabbit, rabbit2 = @store.mget "rabbit", "rabbit2", :raw => true
76
+ race = Marshal.dump(@rabbit).to_json
77
+ rabbit.must_equal(%({"name":"Bunnicula","race":#{race},"friends":[{"name":"Peter Cottontail","race":#{race}}],"age":3.1,"alive":true}))
78
+ rabbit2.must_equal(%({"name":"Peter Cottontail","race":#{race}}))
79
+ end
80
+
81
+ describe "binary safety" do
82
+ before do
83
+ @utf8_key = [51339].pack("U*")
84
+ @ascii_string = [128].pack("C*")
85
+ @ascii_rabbit = OpenStruct.new(:name => @ascii_string)
86
+ end
87
+
88
+ it "marshals objects"
89
+ # @store.set(@utf8_key, @ascii_rabbit)
90
+ # @store.get(@utf8_key).must_equal(@ascii_rabbit)
91
+
92
+ it "gets and sets raw values" do
93
+ @store.set(@utf8_key, @ascii_string, :raw => true)
94
+ @store.get(@utf8_key, :raw => true).bytes.to_a.must_equal(@ascii_string.bytes.to_a)
95
+ end
96
+
97
+ it "marshals objects on setnx"
98
+ # @store.del(@utf8_key)
99
+ # @store.setnx(@utf8_key, @ascii_rabbit)
100
+ # @store.get(@utf8_key).must_equal(@ascii_rabbit)
101
+
102
+ it "gets and sets raw values on setnx" do
103
+ @store.del(@utf8_key)
104
+ @store.setnx(@utf8_key, @ascii_string, :raw => true)
105
+ @store.get(@utf8_key, :raw => true).bytes.to_a.must_equal(@ascii_string.bytes.to_a)
106
+ end
107
+ end if defined?(Encoding)
108
+ end