Ruby-MemCache 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.irbrc +38 -0
- data/README +69 -0
- data/docs/CATALOG +9 -0
- data/docs/makedocs.rb +191 -0
- data/install.rb +185 -0
- data/lib/memcache.rb +1266 -0
- data/test.rb +126 -0
- data/tests/errorhandling.tests.rb +120 -0
- data/tests/getset.tests.rb +365 -0
- data/tests/instantiation.tests.rb +226 -0
- data/tests/mctestcase.rb +379 -0
- data/tests/require.tests.rb +37 -0
- data/tests/stats.tests.rb +216 -0
- data/utils.rb +672 -0
- metadata +61 -0
@@ -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
|
+
|
data/tests/mctestcase.rb
ADDED
@@ -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
|
+
|