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.
- 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
|
+
|