Changeset 276
- Timestamp:
- 07/12/07 12:01:34 (17 months ago)
- Location:
- trunk
- Files:
-
- 10 removed
- 3 modified
- 1 moved
-
Rakefile (modified) (4 diffs)
-
lib/fm/mixins.rb (modified) (1 diff)
-
spec/gameobject_spec.rb (modified) (1 diff)
-
spec/hookable_spec.rb (moved) (moved from trunk/spec/hookable.tests.rb) (2 diffs)
-
tests/animatedobject.tests.rb (deleted)
-
tests/area.tests.rb (deleted)
-
tests/character.tests.rb (deleted)
-
tests/commandparser.tests.rb (deleted)
-
tests/composedobject.tests.rb (deleted)
-
tests/developmentalobject.tests.rb (deleted)
-
tests/entity.tests.rb (deleted)
-
tests/event.tests.rb (deleted)
-
tests/gameobject.tests.rb (deleted)
-
tests/hookable.tests.rb (deleted)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Rakefile
r270 r276 42 42 LIB_FILES 43 43 44 task :default => 'spec:normal'44 task :default => :spec 45 45 46 46 ########################### … … 49 49 50 50 # Task: rdoc 51 Rake::RDocTask.new {|rdoc|51 Rake::RDocTask.new do |rdoc| 52 52 rdoc.rdoc_dir = 'doc' 53 53 rdoc.title = "FaerieMUD" … … 55 55 rdoc.rdoc_files.include TEXT_FILES 56 56 rdoc.rdoc_files.include LIB_FILES 57 } 57 end 58 58 59 59 … … 62 62 ########################### 63 63 64 desc "Run specs outputting to STDOUT" 65 Spec::Rake::SpecTask.new( :spec ) do |task| 66 task.ruby_opts << '-rubygems' 67 task.libs << 'lib' 68 task.spec_files = SPEC_FILES 69 task.spec_opts = ['-f s', '-r fm', '-c'] 70 end 71 64 72 ### Task: spec 65 73 namespace :spec do 66 desc "Run specs outputting to STDOUT"67 Spec::Rake::SpecTask.new( :normal ) do |task|68 task.ruby_opts << '-rubygems'69 task.libs << 'lib'70 task.spec_files = SPEC_FILES71 task.spec_opts = ['-f s', '-r fm', '-c']72 end73 74 74 desc "Generate plaintext output" 75 75 Spec::Rake::SpecTask.new( :text ) do |task| -
trunk/lib/fm/mixins.rb
r270 r276 445 445 name = symbol.id2name 446 446 447 # If the caller hasn't spe icifed a method, just pop the last one447 # If the caller hasn't specified a method, just pop the last one 448 448 # off the stack. If the caller specified a Proc, subtract it 449 449 # from the stack after making sure it's there for the return -
trunk/spec/gameobject_spec.rb
r275 r276 96 96 97 97 98 class RevClass < FaerieMUD::GameObject 99 SVNRev = 'Rev: 270' 100 end 101 98 102 describe FaerieMUD::GameObject do 99 before( :all ) do100 @class = Class.new( FaerieMUD::GameObject ) do101 SVNRev = 'Rev: 270 '102 end103 end104 105 106 103 it "can extract a numeric version from its subversion rev number" do 107 @class.rev.should == 270104 RevClass.rev.should == 270 108 105 end 109 106 end -
trunk/spec/hookable_spec.rb
r270 r276 1 1 #!/usr/bin/ruby -w 2 2 # 3 # Unit test for the FaerieMUD::Hookable mixin.3 # Specification for the FaerieMUD::GameObject class 4 4 # $Id$ 5 5 # 6 # Copyright (c) 2004 The FaerieMUD Consortium. 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 # 6 # Copyright (c) 2003-2007 The FaerieMUD Consortium. 13 7 # 14 8 … … 18 12 $LOAD_PATH.unshift "#{basedir}/lib" unless 19 13 $LOAD_PATH.include?( "#{basedir}/lib" ) 20 $LOAD_PATH.unshift "#{basedir}/tests/lib" unless 21 $LOAD_PATH.include?( "#{basedir}/tests/lib" ) 22 23 require 'fmtestcase' 14 $LOAD_PATH.unshift "#{basedir}/spec/lib" unless 15 $LOAD_PATH.include?( "#{basedir}/spec/lib" ) 24 16 end 25 17 18 require 'spec/runner' 26 19 require 'fm/mixins' 27 20 28 ### Test case for the FaerieMUD::Hookable mixin. 29 class HookableTestCase < FaerieMUD::TestCase 21 # Hooked class 22 class HookableObject < FaerieMUD::GameObject 23 include FaerieMUD::Hookable 30 24 31 WarkMessage = "Wark! Wark! Some tasty %s greens!" 32 33 TestedHooks = { 34 :tripling => Proc::new {|arg| arg * 3}, 35 :reversing => Proc::new {|arg| arg.reverse}, 36 :uppercasing => Proc::new {|arg| arg.upcase}, 37 :novowels => :extractVowels, 38 } 25 # By default, just return the first argument unmodified 26 def test( msg ) 27 return msg 28 end 29 end 39 30 40 31 41 ### Setup method (aliased for older versions of Test::Unit) 42 def setup 32 describe "An instance of a class which has included FaerieMUD::Hookable" do 43 33 44 # Hooked class 45 @hclass = Class::new( Object ) { 46 include FaerieMUD::Hookable 47 def wark( thing ) 48 msg = WarkMessage % thing 49 debug_msg( msg + "\n" ) 50 return msg 51 end 52 } 53 54 # Derived hooked class 55 @dhclass = Class::new( @hclass ) { 56 include FaerieMUD::Hookable 57 } 58 59 super 60 end 61 alias_method :set_up, :setup 62 63 64 ### Teardown method (aliased for older version of Test::Unit) 65 def teardown 66 @hclass = nil 67 @dhclass = nil 68 69 super 70 end 71 alias_method :tear_down, :teardown 72 73 74 ### Hook method to test method hooks 75 def extractVowels( arg ) 76 arg.gsub( /[aeiou]+/, '' ) 34 before( :each ) do 35 @hookableobj = HookableObject.new 77 36 end 78 37 79 38 80 81 82 ################################################################# 83 ### E X A M P L E S 84 ################################################################# 85 86 ### Test inclusion 87 def test_00_included 88 hobj, dhobj = nil, nil 89 90 assert_nothing_raised { hobj = @hclass::new } 91 assert_nothing_raised { dhobj = @dhclass::new } 92 93 [ :hooks, :hook, :unhook ].each {|sym| 94 assert_respond_to hobj, sym, "Hooked class instance" 95 assert_respond_to dhobj, sym, "Hooked class derivative instance" 96 } 97 98 self.class::addSetupBlock { 99 @hobj, @dhobj = @hclass::new, @dhclass::new 100 } 101 self.class::addTeardownBlock { 102 @hobj = nil 103 @dhobj = nil 104 } 39 it "allows a public method to be intercepted via a hook" do 40 @hookableobj.test( 'thing' ).should == 'thing' 41 @hookableobj.hook( :test ) {|arg| arg.reverse } 42 @hookableobj.test( 'thing' ).should == 'gniht' 105 43 end 106 44 107 45 108 ### Test methods with no hooks 109 def test_01_emptyhooks 110 { 111 @hobj => "Hooked class instance", 112 @dhobj => "Hooked class derivative instance" 113 }.each {|obj, objtype| 114 rval = nil 115 assert_nothing_raised { rval = obj.hooks } 116 assert_equal Hash::new, rval, 117 "#{objtype} #hooks method did not return a Hash." 118 } 46 it "s hooks don't interfere with any other instances of the same class" do 47 @hookableobj2 = HookableObject.new 48 @hookableobj.hook( :test ) { } 119 49 end 50 51 it "knows about any hooks which are applied to it" do 52 # Starts out with no hooks... 53 @hookableobj.hooks.should be_a_kind_of( Hash ) 54 @hookableobj.hooks.should be_empty() 120 55 56 # Hook the #test methodq 57 @hookableobj.hook( :test ) {|arg| arg.reverse } 121 58 122 ### Unhooked method call 123 def test_02_prehook 124 printTestHeader "Unhooked method call" 125 rval = nil 126 greensType = "Tantal" 59 # ...then it should have hooks. The original method should be the first thing 60 # in the list, then a Proc for each hook 61 @hookableobj.hooks.should have(1).keys 62 @hookableobj.hooks[ :test ].should be_an_instance_of( Array ) 63 @hookableobj.hooks[ :test ].should have(2).members 64 @hookableobj.hooks[ :test ].first.should be_an_instance_of( Method ) 65 @hookableobj.hooks[ :test ].last.should be_an_instance_of( Proc ) 66 end 67 68 69 it "allows the last-applied hook to be removed from a method" do 70 hookproc = Proc.new {|arg| :noop } 71 @hookableobj.hook( :test, &hookproc ) 72 @hookableobj.unhook( :test ).should == hookproc 73 end 74 75 76 it "allows a chain of hooks to be applied to a single method, which are called " + 77 "in reverse of the order they are applied" do 78 79 @hookableobj.hook( :test ) {|arg| arg.reverse + '1' } 80 @hookableobj.hook( :test ) {|arg| arg.upcase + '2' } 81 @hookableobj.hook( :test ) {|arg| arg.gsub(/[aeiou]+/i, '') + '3' } 82 83 @hookableobj.test( 'thingerything' ).should == '23GNHTYRGNHT1' 84 end 85 86 87 it "allows a hook to be removed from an arbitrary point in a chain via reference" do 88 @hookableobj.hook( :test ) {|arg| arg.reverse + '1' } 89 upcasehook = @hookableobj.hook( :test ) {|arg| arg.upcase + '2' } 90 @hookableobj.hook( :test ) {|arg| arg.gsub(/[aeiou]+/i, '') + '3' } 91 92 @hookableobj.unhook( :test, upcasehook ) 127 93 128 assert_nothing_raised { rval = @hobj.wark(greensType) } 129 assert_equal WarkMessage % greensType, rval 94 @hookableobj.test( 'thingerything' ).should == '3gnhtyrgnht1' 130 95 end 96 97 98 it "allows all hooks to be removed from a method" do 99 @hookableobj.hook( :test ) {|arg| arg.reverse + '1' } 100 @hookableobj.hook( :test ) {|arg| arg.upcase + '2' } 101 @hookableobj.hook( :test ) {|arg| arg.gsub(/[aeiou]+/i, '') + '3' } 102 103 @hookableobj.unhook_all( :test ) 131 104 105 @hookableobj.test( 'thingerything' ).should == 'thingerything' 106 end 107 108 109 it "sets up an alias for the unhooked version of a hooked method" do 110 @hookableobj.hook( :test ) {|arg| arg.reverse + '1' } 111 @hookableobj.hook( :test ) {|arg| arg.upcase + '2' } 112 @hookableobj.hook( :test ) {|arg| arg.gsub(/[aeiou]+/i, '') + '3' } 132 113 133 ### Test hooks 134 def test_03_hooks 135 printTestHeader "Hooked method calls" 136 hook, msg = nil, nil 137 greensType = "Tantal" 138 procs = [] 139 count = 0 140 141 # For each hook in TestedHooks, add the proc as a hook and test the object 142 TestedHooks.sort {|a,b| a[0].to_s <=> b[0].to_s}.each {|name,proc| 143 count += 1 144 proc = method( proc ).to_proc if proc.is_a?( Symbol ) 145 procs.push( proc ) 146 147 assert_nothing_raised { 148 hook = @hobj.hook( :wark, &proc ) 149 } 150 assert_instance_of Proc, hook 151 assert_equal proc.to_proc, hook 152 153 assert_nothing_raised { msg = @hobj.wark(greensType) } 154 debug_msg "Wark, after #{count} hook/s: #{msg.inspect}" 155 expectedMsg = greensType 156 procs.each {|proc| expectedMsg.replace( proc.call(expectedMsg) )} 157 assert_equal WarkMessage % expectedMsg, msg 158 } 159 160 # Add setup to to hook @hobj for each successive test 161 self.class::addSetupBlock { 162 @hooks = [] 163 TestedHooks.sort {|a,b| a[0].to_s <=> b[0].to_s}.each {|name,proc| 164 proc = method( proc ).to_proc if proc.is_a?( Symbol ) 165 @hooks.push( proc ) 166 @hobj.hook( :wark, &proc ) 167 } 168 } 169 self.class::addTeardownBlock { 170 @hooks = nil 171 } 172 end 173 174 ### Test second instance of the same class as the hooked object 175 def test_04_second_instance 176 printTestHeader "Testing second instance of the hooked object's class" 177 msg = nil 178 179 assert_nothing_raised { 180 msg = @hclass::new.wark( "Gysal" ) 181 } 182 debug_msg msg.inspect 183 assert_equal WarkMessage % "Gysal", msg 184 end 185 186 187 ### Test the instance of the derivative class 188 def test_05_derivative_instance 189 printTestHeader "Testing the derivative class instance" 190 msg = nil 191 192 assert_nothing_raised { 193 msg = @dhobj.wark( "Pahsana" ) 194 } 195 debug_msg msg.inspect 196 assert_equal WarkMessage % "Pahsana", msg 197 end 198 199 ### Test to make sure the unhooked method can still be called through the 200 ### __unhooked_ alias. 201 def test_06_unhooked_variant 202 debug_msg "Trying @hobj's unhooked alias" 203 msg = nil 204 205 assert_nothing_raised { 206 msg = @hobj.__unhooked_wark( "Reagan" ) 207 } 208 debug_msg msg.inspect 209 assert_equal WarkMessage % "Reagan", msg 210 end 211 212 ### Test removal of last hook. 213 def test_07_unhook_onearg 214 printTestHeader "Testing unhook( symbol )" 215 hook, msg = nil, nil 216 greensType = "Curiel" 217 218 # Last hook 219 debug_msg "Removing last hook added:" 220 assert_nothing_raised { 221 hook = @hobj.unhook( :wark ) 222 } 223 assert_equal @hooks.last, hook 224 @hooks.pop 225 226 debug_msg "Hooks: %s" % @hobj.hooks.inspect 227 228 debug_msg "First wark after unhook: " 229 assert_nothing_raised { 230 msg = @hobj.wark( greensType ) 231 } 232 debug_msg msg.inspect 233 expectedMsg = greensType 234 @hooks.each {|proc| expectedMsg.replace( proc.call(expectedMsg) )} 235 assert_equal WarkMessage % expectedMsg, msg 236 end 237 238 239 ### Test removal of a specific hook, out of order. 240 def test_08_unhook_twoargs 241 printTestHeader "Testing unhook( symbol, hook )" 242 hook, msg = nil, nil 243 greensType = "Curiel" 244 245 # First hook (out of order) 246 debug_msg "Removing first hook (out of order):" 247 assert_nothing_raised { 248 hook = @hobj.unhook( :wark, @hooks.first ) 249 } 250 assert_equal @hooks.first, hook 251 @hooks.shift 252 253 debug_msg "Hooks: %s" % @hobj.hooks.inspect 254 255 assert_nothing_raised { 256 msg = @hobj.wark( greensType ) 257 } 258 debug_msg msg.inspect 259 expectedMsg = greensType 260 @hooks.each {|proc| expectedMsg.replace( proc.call(expectedMsg) )} 261 assert_equal WarkMessage % expectedMsg, msg 262 end 263 264 265 ### Test removing all hooks 266 def test_09_unhook_all 267 printTestHeader "Testing behaviour after all hooks are unhooked" 268 hook, msg = nil, nil 269 greensType = "Curiel" 270 271 # Remaining hook 272 debug_msg "Removing all hooks:" 273 assert_nothing_raised { 274 @hobj.unhook_all( :wark ) 275 } 276 277 debug_msg "Hooks: %s" % @hobj.hooks.inspect 278 279 debug_msg "Wark after unhook all: " 280 assert_nothing_raised { 281 msg = @hobj.wark( greensType ) 282 } 283 debug_msg msg.inspect 284 assert_equal WarkMessage % greensType, msg 285 286 # Test to be sure #wark is unhooked 287 debug_msg "Should be completely unhooked now:" 288 assert_equal @hobj.method(:__unhooked_wark), @hobj.method( :wark ) 114 @hookableobj.__unhooked_test( 'thingerything' ).should == 'thingerything' 289 115 end 290 116
