redis-store-json 3.0.0

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 (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 +215 -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