Ruby-MemCache 0.0.1

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,226 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # Unit test for instantiation of MemCache objects
4
+ # $Id: instantiation.tests.rb 12 2004-10-03 21:04:34Z ged $
5
+ #
6
+ # Copyright (c) 2004 RubyCrafters, LLC. Most rights reserved.
7
+ #
8
+ # This work is licensed under the Creative Commons Attribution-ShareAlike
9
+ # License. To view a copy of this license, visit
10
+ # http://creativecommons.org/licenses/by-sa/1.0/ or send a letter to Creative
11
+ # Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
12
+ #
13
+ #
14
+
15
+ unless defined? MemCache::TestCase
16
+ testsdir = File::dirname( File::expand_path(__FILE__) )
17
+ basedir = File::dirname( testsdir )
18
+ $LOAD_PATH.unshift "#{basedir}/lib" unless
19
+ $LOAD_PATH.include?( "#{basedir}/lib" )
20
+ $LOAD_PATH.unshift "#{basedir}/tests" unless
21
+ $LOAD_PATH.include?( "#{basedir}/tests" )
22
+
23
+ require 'mctestcase'
24
+ end
25
+
26
+
27
+ ### Collection of tests for the instantiation class.
28
+ class InstantiationTestCase < MemCache::TestCase
29
+
30
+
31
+ TestServerSets = {
32
+ :simple => [
33
+ {
34
+ :name => 'One IP (unweighted)',
35
+ :servers => %w[ 127.0.0.1 ],
36
+ },
37
+ {
38
+ :name => 'Two IPs (unweighted)',
39
+ :servers => %w[ 127.0.0.1 10.1.0.1 ],
40
+ },
41
+ ],
42
+
43
+ :weighted => [
44
+ {
45
+ :name => 'One IP (weighted)',
46
+ :servers => [['127.0.0.1', 1]],
47
+ },
48
+ {
49
+ :name => 'Two IPs (weighted)',
50
+ :servers => [['127.0.0.1', 1], ['10.1.0.1', 2]],
51
+ },
52
+ ],
53
+
54
+ :ports => [
55
+ {
56
+ :name => 'One IP (w/port)',
57
+ :servers => %w[ 127.0.0.1:11211 ]
58
+ },
59
+ {
60
+ :name => 'Two IPs (w/ports)',
61
+ :servers => %w[ 127.0.0.1:123123 10.1.0.1:11292 ],
62
+ },
63
+ ],
64
+
65
+ :weighted_ports => [
66
+ {
67
+ :name => 'One IP (weighted w/port)',
68
+ :servers => [['127.0.0.1:11001', 1]],
69
+ },
70
+ {
71
+ :name => 'Two IPs (weighted w/ports)',
72
+ :servers => [['127.0.0.1:11211', 1], ['10.1.0.11:11320', 2]],
73
+ },
74
+ ],
75
+
76
+ :with_opts => [
77
+ {
78
+ :name => 'One IP (weighted w/port)',
79
+ :servers => [['127.0.0.1:11001', 1]],
80
+ :opts => { :compression => true },
81
+ },
82
+ {
83
+ :name => 'Two IPs (weighted w/ports)',
84
+ :servers => [['127.0.0.1:11211', 1], ['10.1.0.11:11320', 2]],
85
+ :opts => { :compression => true },
86
+ },
87
+ ],
88
+ }
89
+
90
+ #################################################################
91
+ ### T E S T S
92
+ #################################################################
93
+
94
+ ### Instantiate with no args
95
+ def test_00_no_args
96
+ printTestHeader "Instantiation: No-args construction"
97
+ rval = cache = nil
98
+
99
+ assert_nothing_raised { cache = MemCache::new }
100
+ assert_instance_of MemCache, cache
101
+
102
+ assert_nothing_raised { rval = cache.servers }
103
+ assert_instance_of Array, rval
104
+ assert_equal 0, rval.nitems
105
+ end
106
+
107
+
108
+ ### Instantiate with one or more server args
109
+ def test_01_with_servers
110
+ printTestHeader "Instantiation: Server args"
111
+ rval = cache = nil
112
+
113
+ TestServerSets.each {|key, sets|
114
+ sets.each do |set|
115
+ debugMsg "Testing #{key} sets"
116
+
117
+ # Instantiate with various args specified by the set
118
+ if set.key?( :opts )
119
+ args = set[:servers].dup
120
+ args.push( set[:opts] )
121
+ assert_nothing_raised( set[:name] ) {
122
+ cache = MemCache::new( *args )
123
+ }
124
+ else
125
+ assert_nothing_raised( set[:name] ) {
126
+ cache = MemCache::new( *(set[:servers]) )
127
+ }
128
+ end
129
+
130
+ assert_instance_of MemCache, cache
131
+
132
+ # Check to be sure we can get the server list back out
133
+ assert_nothing_raised { rval = cache.servers }
134
+ assert_instance_of Array, rval
135
+ assert_equal set[:servers].nitems, rval.nitems
136
+
137
+ # Test the #active method while we're at it
138
+ assert_nothing_raised { rval = cache.active? }
139
+ assert_equal true, rval
140
+ end
141
+ }
142
+ end
143
+
144
+
145
+ ### Compression option
146
+ def test_10_compression_opt
147
+ printTestHeader "Instantiation: Compression option"
148
+ rval = cache = nil
149
+
150
+ # Test getter with default value
151
+ cache = MemCache::new
152
+ assert_nothing_raised { rval = cache.compression }
153
+ assert_equal true, rval
154
+
155
+ # Test setting via constructor and getter
156
+ assert_nothing_raised { cache = MemCache::new(:compression => false) }
157
+ assert_nothing_raised { rval = cache.compression }
158
+ assert_equal false, rval
159
+ end
160
+
161
+
162
+ ### Compression threshold option
163
+ def test_20_compression_threshold_opt
164
+ printTestHeader "Instantiation: Compression threshold option"
165
+ rval = cache = nil
166
+
167
+ # Test getter with default value
168
+ cache = MemCache::new
169
+ assert_nothing_raised { rval = cache.c_threshold }
170
+ assert_equal MemCache::DefaultCThreshold, rval
171
+
172
+ # Test setting via constructor with various sizes and getter
173
+ 16.times do |factor|
174
+ thresh = 2 ** factor
175
+
176
+ assert_nothing_raised { cache = MemCache::new(:c_threshold => thresh) }
177
+ assert_nothing_raised { rval = cache.c_threshold }
178
+ assert_equal thresh, rval
179
+ assert_nothing_raised { cache.c_threshold = 2 ** (factor-1) }
180
+ end
181
+ end
182
+
183
+
184
+ ### Compression option
185
+ def test_30_debug_opt
186
+ printTestHeader "Instantiation: Debug option"
187
+ rval = cache = nil
188
+
189
+ # Test default value and getter
190
+ cache = MemCache::new
191
+ assert_nothing_raised { rval = cache.debug }
192
+ assert_equal false, rval
193
+
194
+ # Test <<-style debugging object (String)
195
+ rval = ''
196
+ assert_nothing_raised { cache = MemCache::new(:debug => rval) }
197
+ assert_nothing_raised {
198
+ cache.servers = TestServerSets[:simple][0][:servers]
199
+ }
200
+ assert !rval.empty?, "Rval should not be empty"
201
+ assert_match( /Transforming/, rval )
202
+
203
+ # Test <<-style debugging object (Array)
204
+ rval = []
205
+ assert_nothing_raised { cache = MemCache::new(:debug => rval) }
206
+ assert_nothing_raised {
207
+ cache.servers = TestServerSets[:simple][0][:servers]
208
+ }
209
+ assert !rval.empty?, "Rval should not be empty"
210
+ assert_match( /Transforming/, rval[0] )
211
+
212
+ # Test call-style debugging object (Proc)
213
+ rval = ''
214
+ func = lambda {|msg| rval << msg }
215
+ assert_nothing_raised { cache = MemCache::new(:debug => func) }
216
+ assert_nothing_raised {
217
+ cache.servers = TestServerSets[:simple][0][:servers]
218
+ }
219
+ assert !rval.empty?, "Rval should not be empty"
220
+ assert_match( /Transforming/, rval )
221
+
222
+ end
223
+
224
+ end
225
+
226
+
@@ -0,0 +1,379 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # This is an abstract test case class for building Test::Unit unit tests for the
4
+ # MemCache module. It consolidates most of the maintenance work that must be
5
+ # done to build a test file by adjusting the $LOAD_PATH appropriately, as well
6
+ # as adding some other useful methods that make building and maintaining the
7
+ # tests much easier (IMHO). See the docs for Test::Unit for more info on the
8
+ # particulars of unit testing.
9
+ #
10
+ # == Synopsis
11
+ #
12
+ # # Allow the unit test to be run from the base dir, or from tests/ or
13
+ # # similar:
14
+ # begin
15
+ # require 'tests/mctestcase'
16
+ # rescue
17
+ # require '../mctestcase'
18
+ # end
19
+ #
20
+ # class MySomethingTest < MemCache::TestCase
21
+ # def setup
22
+ # super()
23
+ # @foo = 'bar'
24
+ # end
25
+ #
26
+ # def test_00_something
27
+ # obj = nil
28
+ # assert_nothing_raised { obj = MySomething::new }
29
+ # assert_instance_of MySomething, obj
30
+ # assert_respond_to :myMethod, obj
31
+ # end
32
+ # end
33
+ #
34
+ # == Subversion ID
35
+ #
36
+ # $Id: mctestcase.rb 29 2004-11-13 17:31:44Z ged $
37
+ #
38
+ # == Authors
39
+ #
40
+ # * Michael Granger <ged@FaerieMUD.org>
41
+ #
42
+ #:include: COPYRIGHT
43
+ #
44
+ #---
45
+ #
46
+ # Please see the file COPYRIGHT in the 'docs' directory for licensing details.
47
+ #
48
+
49
+ begin
50
+ basedir = File::dirname( File::dirname(__FILE__) )
51
+ unless $LOAD_PATH.include?( "#{basedir}/lib" )
52
+ $LOAD_PATH.unshift "#{basedir}/lib"
53
+ end
54
+ end
55
+
56
+ require 'test/unit'
57
+ require 'memcache'
58
+
59
+ class MemCache::TestCase < Test::Unit::TestCase
60
+
61
+ # The name of the file containing marshalled configuration values
62
+ ConfigSaveFile = "test.cfg"
63
+
64
+ @methodCounter = 0
65
+ @setupBlocks = []
66
+ @teardownBlocks = []
67
+ class << self
68
+ attr_accessor :methodCounter, :setupBlocks, :teardownBlocks
69
+ end
70
+
71
+
72
+ ### Inheritance callback -- adds @setupBlocks and @teardownBlocks ivars
73
+ ### and accessors to the inheriting class.
74
+ def self::inherited( klass )
75
+ klass.module_eval {
76
+ @setupBlocks = []
77
+ @teardownBlocks = []
78
+
79
+ class << self
80
+ attr_accessor :setupBlocks, :teardownBlocks
81
+ end
82
+ }
83
+ klass.methodCounter = 0
84
+ end
85
+
86
+
87
+
88
+ ### Output the specified <tt>msgs</tt> joined together to
89
+ ### <tt>STDERR</tt> if <tt>$DEBUG</tt> is set.
90
+ def self::debugMsg( *msgs )
91
+ return unless $DEBUG
92
+ self.message "DEBUG>>> %s" % msgs.join('')
93
+ end
94
+
95
+ ### Output the specified <tt>msgs</tt> joined together to
96
+ ### <tt>STDOUT</tt>.
97
+ def self::message( *msgs )
98
+ $stderr.puts msgs.join('')
99
+ $stderr.flush
100
+ end
101
+
102
+
103
+ ### Add a setup block for the current testcase
104
+ def self::addSetupBlock( &block )
105
+ self.methodCounter += 1
106
+ newMethodName = "setup_#{self.methodCounter}".intern
107
+ define_method( newMethodName, &block )
108
+ self.setupBlocks.push newMethodName
109
+ end
110
+
111
+ ### Add a teardown block for the current testcase
112
+ def self::addTeardownBlock( &block )
113
+ self.methodCounter += 1
114
+ newMethodName = "teardown_#{self.methodCounter}".intern
115
+ define_method( newMethodName, &block )
116
+ self.teardownBlocks.unshift newMethodName
117
+ end
118
+
119
+
120
+ #############################################################
121
+ ### I N S T A N C E M E T H O D S
122
+ #############################################################
123
+
124
+ def initialize( *args )
125
+ if $Memcached
126
+ # If there's no readable config file, prompt the user for configuration
127
+ # values and make sure the logs are present and empty.
128
+ unless File::readable?( ConfigSaveFile )
129
+ File::open(ConfigSaveFile, File::CREAT|File::TRUNC|File::WRONLY) {|ofh|
130
+ config = self.promptForConfigValues()
131
+ Marshal::dump( config, ofh )
132
+ }
133
+ end
134
+
135
+ File::open( ConfigSaveFile, File::RDONLY ) {|ifh|
136
+ @config = Marshal::load( ifh )
137
+ }
138
+
139
+
140
+ # If the user said to skip when prompted, kill the config object.
141
+ @config = nil if @config[:server] == :skip
142
+ else
143
+ @config = nil
144
+ end
145
+
146
+ super
147
+ rescue => e
148
+ File::unlink( ConfigSaveFile ) if File::exists?( ConfigSaveFile )
149
+ Kernel::raise( e )
150
+ end
151
+
152
+
153
+ ### Prompt the user with the given <tt>promptString</tt> via #prompt, or
154
+ ### #promptWithDefault if a default is given, and return the answer after
155
+ ### testing to make sure it's been filled. If it has not, a RuntimeError is
156
+ ### raised.
157
+ def promptForRequiredValue( promptString, default=nil )
158
+ res = nil
159
+
160
+ if default
161
+ res = promptWithDefault( promptString, default )
162
+ else
163
+ res = prompt( promptString )
164
+ end
165
+
166
+ if res.nil? || res.empty?
167
+ raise RuntimeError,
168
+ "Cannot test: missing required config value"
169
+ end
170
+
171
+ return res
172
+ end
173
+
174
+
175
+ ### Prompt for configuration values
176
+ def promptForConfigValues
177
+ puts "The test suite can run quite a lot of tests against ",
178
+ "a real memcache server, if you have one running."
179
+ ans = promptWithDefault( "Do you want to run these tests?", "y" )
180
+
181
+ unless /^y/i.match( ans )
182
+ return { :server => :skip }
183
+ end
184
+
185
+ config = {}
186
+ config[:server] =
187
+ promptForRequiredValue( "Memcached host or ip", "localhost" )
188
+ config[:port] =
189
+ promptForRequiredValue( "Memcached port", "11211" )
190
+
191
+ return config
192
+ end
193
+
194
+
195
+ ### A dummy test method to allow this Test::Unit::TestCase to be
196
+ ### subclassed without complaining about the lack of tests.
197
+ def test_0_dummy
198
+ end
199
+
200
+
201
+ ### Forward-compatibility method for namechange in Test::Unit
202
+ def setup( *args )
203
+ self.class.setupBlocks.each {|sblock|
204
+ debugMsg "Calling setup block method #{sblock}"
205
+ self.send( sblock )
206
+ }
207
+ super( *args )
208
+ end
209
+ alias_method :set_up, :setup
210
+
211
+
212
+ ### Forward-compatibility method for namechange in Test::Unit
213
+ def teardown( *args )
214
+ super( *args )
215
+ self.class.teardownBlocks.each {|tblock|
216
+ debugMsg "Calling teardown block method #{tblock}"
217
+ self.send( tblock )
218
+ }
219
+ end
220
+ alias_method :tear_down, :teardown
221
+
222
+
223
+ ### Skip the current step (called from #setup) with the +reason+ given.
224
+ def skip( reason=nil )
225
+ if reason
226
+ msg = "Skipping %s: %s" % [ @method_name, reason ]
227
+ else
228
+ msg = "Skipping %s: No reason given." % @method_name
229
+ end
230
+
231
+ $stderr.puts( msg ) if $VERBOSE
232
+ @method_name = :skipped_test
233
+ end
234
+
235
+
236
+ def skipped_test # :nodoc:
237
+ end
238
+
239
+
240
+ ### Add the specified +block+ to the code that gets executed by #setup.
241
+ def addSetupBlock( &block ); self.class.addSetupBlock( &block ); end
242
+
243
+
244
+ ### Add the specified +block+ to the code that gets executed by #teardown.
245
+ def addTeardownBlock( &block ); self.class.addTeardownBlock( &block ); end
246
+
247
+
248
+ ### Instance alias for the like-named class method.
249
+ def message( *msgs )
250
+ self.class.message( *msgs )
251
+ end
252
+
253
+
254
+ ### Instance alias for the like-named class method
255
+ def debugMsg( *msgs )
256
+ self.class.debugMsg( *msgs )
257
+ end
258
+
259
+
260
+ ### Output a separator line made up of <tt>length</tt> of the specified
261
+ ### <tt>char</tt>.
262
+ def writeLine( length=75, char="-" )
263
+ $stderr.puts "\r" + (char * length )
264
+ end
265
+
266
+
267
+ ### Output a header for delimiting tests
268
+ def printTestHeader( desc )
269
+ return unless $VERBOSE || $DEBUG
270
+ message ">>> %s <<<" % desc
271
+ end
272
+
273
+
274
+ ### Try to force garbage collection to start.
275
+ def collectGarbage
276
+ a = []
277
+ 1000.times { a << {} }
278
+ a = nil
279
+ GC.start
280
+ end
281
+
282
+
283
+ ### Output the name of the test as it's running if in verbose mode.
284
+ def run( result )
285
+ $stderr.puts self.name if $VERBOSE || $DEBUG
286
+
287
+ # Support debugging for individual tests
288
+ olddb = nil
289
+ if $DebugPattern && $DebugPattern =~ @method_name
290
+ olddb = $DEBUG
291
+ $DEBUG = true
292
+ end
293
+
294
+ super
295
+
296
+ $DEBUG = olddb unless olddb.nil?
297
+ end
298
+
299
+
300
+ #############################################################
301
+ ### E X T R A A S S E R T I O N S
302
+ #############################################################
303
+
304
+ ### Negative of assert_respond_to
305
+ def assert_not_respond_to( obj, meth )
306
+ msg = "%s expected NOT to respond to '%s'" %
307
+ [ obj.inspect, meth ]
308
+ assert_block( msg ) {
309
+ !obj.respond_to?( meth )
310
+ }
311
+ rescue Test::Unit::AssertionFailedError => err
312
+ cutframe = err.backtrace.reverse.find {|frame|
313
+ /assert_not_respond_to/ =~ frame
314
+ }
315
+ firstIdx = (err.backtrace.rindex( cutframe )||0) + 1
316
+ Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] )
317
+ end
318
+
319
+
320
+ ### Assert that the instance variable specified by +sym+ of an +object+
321
+ ### is equal to the specified +value+. The '@' at the beginning of the
322
+ ### +sym+ will be prepended if not present.
323
+ def assert_ivar_equal( value, object, sym )
324
+ sym = "@#{sym}".intern unless /^@/ =~ sym.to_s
325
+ msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" %
326
+ [ sym, object.inspect, value.inspect ]
327
+ msg += "\tbut was: <%s>" % object.instance_variable_get(sym)
328
+ assert_block( msg ) {
329
+ value == object.instance_variable_get(sym)
330
+ }
331
+ rescue Test::Unit::AssertionFailedError => err
332
+ cutframe = err.backtrace.reverse.find {|frame|
333
+ /assert_ivar_equal/ =~ frame
334
+ }
335
+ firstIdx = (err.backtrace.rindex( cutframe )||0) + 1
336
+ Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] )
337
+ end
338
+
339
+
340
+ ### Assert that the specified +object+ has an instance variable which
341
+ ### matches the specified +sym+. The '@' at the beginning of the +sym+
342
+ ### will be prepended if not present.
343
+ def assert_has_ivar( sym, object )
344
+ sym = "@#{sym}" unless /^@/ =~ sym.to_s
345
+ msg = "Object <%s> expected to have an instance variable <%s>" %
346
+ [ object.inspect, sym ]
347
+ assert_block( msg ) {
348
+ object.instance_variables.include?( sym.to_s )
349
+ }
350
+ rescue Test::Unit::AssertionFailedError => err
351
+ cutframe = err.backtrace.reverse.find {|frame|
352
+ /assert_has_ivar/ =~ frame
353
+ }
354
+ firstIdx = (err.backtrace.rindex( cutframe )||0) + 1
355
+ Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] )
356
+ end
357
+
358
+
359
+ ### Assert that the specified +object+ is either nil or equal (via #eql?) to
360
+ ### the given +value+. This is to test return values from the cache, which
361
+ ### should return either the original value or +nil+ if the value has
362
+ ### expired from the cache.
363
+ def assert_nil_or_equal( value, object, msg="" )
364
+ msg += "\n" unless msg.empty?
365
+ msg += "Object <%p> expected to be nil or equal to <%p>" %
366
+ [ object, value ]
367
+ assert_block( msg ) {
368
+ object.nil? || object.eql?( value )
369
+ }
370
+ rescue Test::Unit::AssertionFailedError => err
371
+ cutframe = err.backtrace.reverse.find {|frame|
372
+ /assert_nil_or_equal/ =~ frame
373
+ }
374
+ firstIdx = (err.backtrace.rindex( cutframe )||0) + 1
375
+ Kernel::raise( err, err.message, err.backtrace[firstIdx..-1] )
376
+ end
377
+
378
+ end # class MemCache::TestCase
379
+