test_blankslate.rb 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #!/usr/bin/env ruby
  2. #--
  3. # Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org).
  4. # Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net).
  5. # All rights reserved.
  6. # Permission is granted for use, copying, modification, distribution,
  7. # and distribution of modified versions of this work as long as the
  8. # above copyright notice is included.
  9. #++
  10. require 'test/unit'
  11. require 'test/preload'
  12. require 'builder/blankslate'
  13. require 'stringio'
  14. # Methods to be introduced into the Object class late.
  15. module LateObject
  16. def late_object
  17. 33
  18. end
  19. def LateObject.included(mod)
  20. # Modules defining an included method should not prevent blank
  21. # slate erasure!
  22. end
  23. end
  24. # Methods to be introduced into the Kernel module late.
  25. module LateKernel
  26. def late_kernel
  27. 44
  28. end
  29. def LateKernel.included(mod)
  30. # Modules defining an included method should not prevent blank
  31. # slate erasure!
  32. end
  33. end
  34. # Introduce some late methods (both module and direct) into the Kernel
  35. # module.
  36. module Kernel
  37. include LateKernel
  38. def late_addition
  39. 1234
  40. end
  41. def double_late_addition
  42. 11
  43. end
  44. def double_late_addition
  45. 22
  46. end
  47. end
  48. # Introduce some late methods (both module and direct) into the Object
  49. # class.
  50. class Object
  51. include LateObject
  52. def another_late_addition
  53. 4321
  54. end
  55. end
  56. # Introduce some late methods by inclusion.
  57. module GlobalModule
  58. def global_inclusion
  59. 42
  60. end
  61. end
  62. include GlobalModule
  63. def direct_global
  64. 43
  65. end
  66. ######################################################################
  67. # Test case for blank slate.
  68. #
  69. class TestBlankSlate < Test::Unit::TestCase
  70. if Object::const_defined?(:BasicObject)
  71. def self.suite
  72. # skip tests if :BasicObject is present
  73. Test::Unit::TestSuite.new(name)
  74. end
  75. end
  76. def setup
  77. @bs = BlankSlate.new
  78. end
  79. def test_undefined_methods_remain_undefined
  80. assert_raise(NoMethodError) { @bs.no_such_method }
  81. assert_raise(NoMethodError) { @bs.nil? }
  82. end
  83. # NOTE: NameError is acceptable because the lack of a '.' means that
  84. # Ruby can't tell if it is a method or a local variable.
  85. def test_undefined_methods_remain_undefined_during_instance_eval
  86. assert_raise(NoMethodError, NameError) do
  87. @bs.instance_eval do nil? end
  88. end
  89. assert_raise(NoMethodError, NameError) do
  90. @bs.instance_eval do no_such_method end
  91. end
  92. end
  93. def test_private_methods_are_undefined
  94. assert_raise(NoMethodError) do
  95. @bs.puts "HI"
  96. end
  97. end
  98. def test_targetted_private_methods_are_undefined_during_instance_eval
  99. assert_raise(NoMethodError, NameError) do
  100. @bs.instance_eval do self.puts "HI" end
  101. end
  102. end
  103. def test_untargetted_private_methods_are_defined_during_instance_eval
  104. oldstdout = $stdout
  105. $stdout = StringIO.new
  106. @bs.instance_eval do
  107. puts "HI"
  108. end
  109. ensure
  110. $stdout = oldstdout
  111. end
  112. def test_methods_added_late_to_kernel_remain_undefined
  113. assert_equal 1234, nil.late_addition
  114. assert_raise(NoMethodError) { @bs.late_addition }
  115. end
  116. def test_methods_added_late_to_object_remain_undefined
  117. assert_equal 4321, nil.another_late_addition
  118. assert_raise(NoMethodError) { @bs.another_late_addition }
  119. end
  120. def test_methods_added_late_to_global_remain_undefined
  121. assert_equal 42, global_inclusion
  122. assert_raise(NoMethodError) { @bs.global_inclusion }
  123. end
  124. def test_preload_method_added
  125. assert Kernel.k_added_names.include?(:late_addition)
  126. assert Object.o_added_names.include?(:another_late_addition)
  127. end
  128. def test_method_defined_late_multiple_times_remain_undefined
  129. assert_equal 22, nil.double_late_addition
  130. assert_raise(NoMethodError) { @bs.double_late_addition }
  131. end
  132. def test_late_included_module_in_object_is_ok
  133. assert_equal 33, 1.late_object
  134. assert_raise(NoMethodError) { @bs.late_object }
  135. end
  136. def test_late_included_module_in_kernel_is_ok
  137. assert_raise(NoMethodError) { @bs.late_kernel }
  138. end
  139. def test_revealing_previously_hidden_methods_are_callable
  140. with_to_s = Class.new(BlankSlate) do
  141. reveal :to_s
  142. end
  143. assert_match /^#<.*>$/, with_to_s.new.to_s
  144. end
  145. def test_revealing_previously_hidden_methods_are_callable_with_block
  146. Object.class_eval <<-EOS
  147. def given_block(&block)
  148. block
  149. end
  150. EOS
  151. with_given_block = Class.new(BlankSlate) do
  152. reveal :given_block
  153. end
  154. assert_not_nil with_given_block.new.given_block {}
  155. end
  156. def test_revealing_a_hidden_method_twice_is_ok
  157. with_to_s = Class.new(BlankSlate) do
  158. reveal :to_s
  159. reveal :to_s
  160. end
  161. assert_match /^#<.*>$/, with_to_s.new.to_s
  162. end
  163. def test_revealing_unknown_hidden_method_is_an_error
  164. assert_raises(RuntimeError) do
  165. Class.new(BlankSlate) do
  166. reveal :xyz
  167. end
  168. end
  169. end
  170. def test_global_includes_still_work
  171. assert_nothing_raised do
  172. assert_equal 42, global_inclusion
  173. assert_equal 42, Object.new.global_inclusion
  174. assert_equal 42, "magic number".global_inclusion
  175. assert_equal 43, direct_global
  176. end
  177. end
  178. def test_reveal_should_not_bind_to_an_instance
  179. with_object_id = Class.new(BlankSlate) do
  180. reveal(:object_id)
  181. end
  182. obj1 = with_object_id.new
  183. obj2 = with_object_id.new
  184. assert obj1.object_id != obj2.object_id,
  185. "Revealed methods should not be bound to a particular instance"
  186. end
  187. end