jashmenn-dalli 1.0.3

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.
@@ -0,0 +1,37 @@
1
+ class Dalli::Server::KSocket < Socket
2
+ attr_accessor :options
3
+
4
+ def self.open(host, port, options = {})
5
+ # All this ugly code to ensure proper Socket connect timeout
6
+ addr = Socket.getaddrinfo(host, nil)
7
+ sock = new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
8
+ sock.options = { :host => host, :port => port }.merge(options)
9
+ begin
10
+ sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3]))
11
+ rescue Errno::EINPROGRESS
12
+ resp = IO.select(nil, [sock], nil, sock.options[:timeout])
13
+ begin
14
+ sock.connect_nonblock(Socket.pack_sockaddr_in(port, addr[0][3]))
15
+ rescue Errno::EISCONN
16
+ end
17
+ end
18
+ sock
19
+ end
20
+
21
+ def readfull(count)
22
+ value = ''
23
+ begin
24
+ loop do
25
+ value << sysread(count - value.bytesize)
26
+ break if value.bytesize == count
27
+ end
28
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
29
+ if IO.select([self], nil, nil, options[:timeout])
30
+ retry
31
+ else
32
+ raise Timeout::Error, "IO timeout: #{options.inspect}"
33
+ end
34
+ end
35
+ value
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module Dalli
2
+ VERSION = '1.0.3'
3
+ end
@@ -0,0 +1,284 @@
1
+ # Used to test the full Rails stack.
2
+ # Stolen from the Rails 3.0 source.
3
+ # Needed for the session store tests.
4
+ require 'active_support/core_ext/kernel/reporting'
5
+ require 'active_support/core_ext/string/encoding'
6
+ if "ruby".encoding_aware?
7
+ # These are the normal settings that will be set up by Railties
8
+ # TODO: Have these tests support other combinations of these values
9
+ silence_warnings do
10
+ Encoding.default_internal = "UTF-8"
11
+ Encoding.default_external = "UTF-8"
12
+ end
13
+ end
14
+
15
+ require 'test/unit'
16
+ require 'abstract_controller'
17
+ require 'action_controller'
18
+ require 'action_view'
19
+ require 'action_dispatch'
20
+ require 'active_support/dependencies'
21
+ require 'action_controller/caching'
22
+ require 'action_controller/caching/sweeping'
23
+
24
+ require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
25
+
26
+ module Rails
27
+ def self.logger
28
+ @logger ||= begin
29
+ l = Logger.new(STDOUT)
30
+ l.level = Logger::INFO; l
31
+ end
32
+ end
33
+ end
34
+
35
+ # Monkey patch the old routes initialization to be silenced.
36
+ class ActionDispatch::Routing::DeprecatedMapper
37
+ def initialize_with_silencer(*args)
38
+ ActiveSupport::Deprecation.silence { initialize_without_silencer(*args) }
39
+ end
40
+ alias_method_chain :initialize, :silencer
41
+ end
42
+
43
+ ActiveSupport::Dependencies.hook!
44
+
45
+ # Show backtraces for deprecated behavior for quicker cleanup.
46
+ ActiveSupport::Deprecation.debug = true
47
+
48
+ ORIGINAL_LOCALES = I18n.available_locales.map {|locale| locale.to_s }.sort
49
+
50
+ module RackTestUtils
51
+ def body_to_string(body)
52
+ if body.respond_to?(:each)
53
+ str = ""
54
+ body.each {|s| str << s }
55
+ str
56
+ else
57
+ body
58
+ end
59
+ end
60
+ extend self
61
+ end
62
+
63
+ module SetupOnce
64
+ extend ActiveSupport::Concern
65
+
66
+ included do
67
+ cattr_accessor :setup_once_block
68
+ self.setup_once_block = nil
69
+
70
+ setup :run_setup_once
71
+ end
72
+
73
+ module ClassMethods
74
+ def setup_once(&block)
75
+ self.setup_once_block = block
76
+ end
77
+ end
78
+
79
+ private
80
+ def run_setup_once
81
+ if self.setup_once_block
82
+ self.setup_once_block.call
83
+ self.setup_once_block = nil
84
+ end
85
+ end
86
+ end
87
+
88
+ SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
89
+
90
+ module ActiveSupport
91
+ class TestCase
92
+ include SetupOnce
93
+ # Hold off drawing routes until all the possible controller classes
94
+ # have been loaded.
95
+ setup_once do
96
+ SharedTestRoutes.draw do |map|
97
+ # FIXME: match ':controller(/:action(/:id))'
98
+ map.connect ':controller/:action/:id'
99
+ end
100
+
101
+ ActionController::IntegrationTest.app.routes.draw do |map|
102
+ # FIXME: match ':controller(/:action(/:id))'
103
+ map.connect ':controller/:action/:id'
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ class RoutedRackApp
110
+ attr_reader :routes
111
+
112
+ def initialize(routes, &blk)
113
+ @routes = routes
114
+ @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
115
+ end
116
+
117
+ def call(env)
118
+ @stack.call(env)
119
+ end
120
+ end
121
+
122
+ class BasicController
123
+ attr_accessor :request
124
+
125
+ def config
126
+ @config ||= ActiveSupport::InheritableOptions.new(ActionController::Base.config).tap do |config|
127
+ # VIEW TODO: View tests should not require a controller
128
+ public_dir = File.expand_path("../fixtures/public", __FILE__)
129
+ config.assets_dir = public_dir
130
+ config.javascripts_dir = "#{public_dir}/javascripts"
131
+ config.stylesheets_dir = "#{public_dir}/stylesheets"
132
+ config
133
+ end
134
+ end
135
+ end
136
+
137
+ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
138
+ setup do
139
+ @routes = SharedTestRoutes
140
+ end
141
+ end
142
+
143
+ class ActionController::IntegrationTest < ActiveSupport::TestCase
144
+ def self.build_app(routes = nil)
145
+ RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware|
146
+ middleware.use "ActionDispatch::ShowExceptions"
147
+ middleware.use "ActionDispatch::Callbacks"
148
+ middleware.use "ActionDispatch::ParamsParser"
149
+ middleware.use "ActionDispatch::Cookies"
150
+ middleware.use "ActionDispatch::Flash"
151
+ middleware.use "ActionDispatch::Head"
152
+ yield(middleware) if block_given?
153
+ end
154
+ end
155
+
156
+ self.app = build_app
157
+
158
+ # Stub Rails dispatcher so it does not get controller references and
159
+ # simply return the controller#action as Rack::Body.
160
+ class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
161
+ protected
162
+ def controller_reference(controller_param)
163
+ controller_param
164
+ end
165
+
166
+ def dispatch(controller, action, env)
167
+ [200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]]
168
+ end
169
+ end
170
+
171
+ def self.stub_controllers
172
+ old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher
173
+ ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
174
+ ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher }
175
+ yield ActionDispatch::Routing::RouteSet.new
176
+ ensure
177
+ ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
178
+ ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher }
179
+ end
180
+
181
+ def with_routing(&block)
182
+ temporary_routes = ActionDispatch::Routing::RouteSet.new
183
+ old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes)
184
+ old_routes = SharedTestRoutes
185
+ silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) }
186
+
187
+ yield temporary_routes
188
+ ensure
189
+ self.class.app = old_app
190
+ silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) }
191
+ end
192
+
193
+ def with_autoload_path(path)
194
+ path = File.join(File.dirname(__FILE__), "fixtures", path)
195
+ if ActiveSupport::Dependencies.autoload_paths.include?(path)
196
+ yield
197
+ else
198
+ begin
199
+ ActiveSupport::Dependencies.autoload_paths << path
200
+ yield
201
+ ensure
202
+ ActiveSupport::Dependencies.autoload_paths.reject! {|p| p == path}
203
+ ActiveSupport::Dependencies.clear
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ # Temporary base class
210
+ class Rack::TestCase < ActionController::IntegrationTest
211
+ def self.testing(klass = nil)
212
+ if klass
213
+ @testing = "/#{klass.name.underscore}".sub!(/_controller$/, '')
214
+ else
215
+ @testing
216
+ end
217
+ end
218
+
219
+ def get(thing, *args)
220
+ if thing.is_a?(Symbol)
221
+ super("#{self.class.testing}/#{thing}", *args)
222
+ else
223
+ super
224
+ end
225
+ end
226
+
227
+ def assert_body(body)
228
+ assert_equal body, Array.wrap(response.body).join
229
+ end
230
+
231
+ def assert_status(code)
232
+ assert_equal code, response.status
233
+ end
234
+
235
+ def assert_response(body, status = 200, headers = {})
236
+ assert_body body
237
+ assert_status status
238
+ headers.each do |header, value|
239
+ assert_header header, value
240
+ end
241
+ end
242
+
243
+ def assert_content_type(type)
244
+ assert_equal type, response.headers["Content-Type"]
245
+ end
246
+
247
+ def assert_header(name, value)
248
+ assert_equal value, response.headers[name]
249
+ end
250
+ end
251
+
252
+ class ActionController::Base
253
+ def self.test_routes(&block)
254
+ routes = ActionDispatch::Routing::RouteSet.new
255
+ routes.draw(&block)
256
+ include routes.url_helpers
257
+ end
258
+ end
259
+
260
+ class ::ApplicationController < ActionController::Base
261
+ end
262
+
263
+ module ActionController
264
+ class Base
265
+ include ActionController::Testing
266
+ end
267
+
268
+ Base.view_paths = []
269
+
270
+ class TestCase
271
+ include ActionDispatch::TestProcess
272
+
273
+ setup do
274
+ @routes = SharedTestRoutes
275
+ end
276
+ end
277
+ end
278
+
279
+ # This stub emulates the Railtie including the URL helpers from a Rails application
280
+ module ActionController
281
+ class Base
282
+ include SharedTestRoutes.url_helpers
283
+ end
284
+ end
@@ -0,0 +1,170 @@
1
+ require 'helper'
2
+ require 'benchmark'
3
+
4
+ class TestBenchmark < Test::Unit::TestCase
5
+
6
+ def setup
7
+ puts "Testing #{Dalli::VERSION} with #{RUBY_DESCRIPTION}"
8
+ # We'll use a simple @value to try to avoid spending time in Marshal,
9
+ # which is a constant penalty that both clients have to pay
10
+ @value = []
11
+ @marshalled = Marshal.dump(@value)
12
+
13
+ @servers = ['127.0.0.1:19122', 'localhost:19122']
14
+ @key1 = "Short"
15
+ @key2 = "Sym1-2-3::45"*8
16
+ @key3 = "Long"*40
17
+ @key4 = "Medium"*8
18
+ # 5 and 6 are only used for multiget miss test
19
+ @key5 = "Medium2"*8
20
+ @key6 = "Long3"*40
21
+ @counter = 'counter'
22
+ end
23
+
24
+ def test_benchmark
25
+ memcached do
26
+
27
+ Benchmark.bm(31) do |x|
28
+
29
+ n = 2500
30
+
31
+ @m = Dalli::Client.new(@servers)
32
+ x.report("set:plain:dalli") do
33
+ n.times do
34
+ @m.set @key1, @marshalled, 0, :raw => true
35
+ @m.set @key2, @marshalled, 0, :raw => true
36
+ @m.set @key3, @marshalled, 0, :raw => true
37
+ @m.set @key1, @marshalled, 0, :raw => true
38
+ @m.set @key2, @marshalled, 0, :raw => true
39
+ @m.set @key3, @marshalled, 0, :raw => true
40
+ end
41
+ end
42
+
43
+ @m = Dalli::Client.new(@servers)
44
+ x.report("setq:plain:dalli") do
45
+ @m.multi do
46
+ n.times do
47
+ @m.set @key1, @marshalled, 0, :raw => true
48
+ @m.set @key2, @marshalled, 0, :raw => true
49
+ @m.set @key3, @marshalled, 0, :raw => true
50
+ @m.set @key1, @marshalled, 0, :raw => true
51
+ @m.set @key2, @marshalled, 0, :raw => true
52
+ @m.set @key3, @marshalled, 0, :raw => true
53
+ end
54
+ end
55
+ end
56
+
57
+ @m = Dalli::Client.new(@servers)
58
+ x.report("set:ruby:dalli") do
59
+ n.times do
60
+ @m.set @key1, @value
61
+ @m.set @key2, @value
62
+ @m.set @key3, @value
63
+ @m.set @key1, @value
64
+ @m.set @key2, @value
65
+ @m.set @key3, @value
66
+ end
67
+ end
68
+
69
+ @m = Dalli::Client.new(@servers)
70
+ x.report("get:plain:dalli") do
71
+ n.times do
72
+ @m.get @key1, :raw => true
73
+ @m.get @key2, :raw => true
74
+ @m.get @key3, :raw => true
75
+ @m.get @key1, :raw => true
76
+ @m.get @key2, :raw => true
77
+ @m.get @key3, :raw => true
78
+ end
79
+ end
80
+
81
+ @m = Dalli::Client.new(@servers)
82
+ x.report("get:ruby:dalli") do
83
+ n.times do
84
+ @m.get @key1
85
+ @m.get @key2
86
+ @m.get @key3
87
+ @m.get @key1
88
+ @m.get @key2
89
+ @m.get @key3
90
+ end
91
+ end
92
+
93
+ @m = Dalli::Client.new(@servers)
94
+ x.report("multiget:ruby:dalli") do
95
+ n.times do
96
+ # We don't use the keys array because splat is slow
97
+ @m.get_multi @key1, @key2, @key3, @key4, @key5, @key6
98
+ end
99
+ end
100
+
101
+ @m = Dalli::Client.new(@servers)
102
+ x.report("missing:ruby:dalli") do
103
+ n.times do
104
+ begin @m.delete @key1; rescue; end
105
+ begin @m.get @key1; rescue; end
106
+ begin @m.delete @key2; rescue; end
107
+ begin @m.get @key2; rescue; end
108
+ begin @m.delete @key3; rescue; end
109
+ begin @m.get @key3; rescue; end
110
+ end
111
+ end
112
+
113
+ @m = Dalli::Client.new(@servers)
114
+ x.report("mixed:ruby:dalli") do
115
+ n.times do
116
+ @m.set @key1, @value
117
+ @m.set @key2, @value
118
+ @m.set @key3, @value
119
+ @m.get @key1
120
+ @m.get @key2
121
+ @m.get @key3
122
+ @m.set @key1, @value
123
+ @m.get @key1
124
+ @m.set @key2, @value
125
+ @m.get @key2
126
+ @m.set @key3, @value
127
+ @m.get @key3
128
+ end
129
+ end
130
+
131
+ @m = Dalli::Client.new(@servers)
132
+ x.report("mixedq:ruby:dalli") do
133
+ @m.multi do
134
+ n.times do
135
+ @m.set @key1, @value
136
+ @m.set @key2, @value
137
+ @m.set @key3, @value
138
+ @m.get @key1
139
+ @m.get @key2
140
+ @m.get @key3
141
+ @m.set @key1, @value
142
+ @m.get @key1
143
+ @m.set @key2, @value
144
+ @m.replace @key2, @value
145
+ @m.delete @key3
146
+ @m.add @key3, @value
147
+ @m.get @key2
148
+ @m.set @key3, @value
149
+ @m.get @key3
150
+ end
151
+ end
152
+ end
153
+
154
+ @m = Dalli::Client.new(@servers)
155
+ x.report("incr:ruby:dalli") do
156
+ n.times do
157
+ @m.incr @counter, 1, 0, 1
158
+ end
159
+ n.times do
160
+ @m.decr @counter, 1
161
+ end
162
+
163
+ assert_equal 0, @m.incr(@counter, 0)
164
+ end
165
+
166
+ end
167
+ end
168
+
169
+ end
170
+ end