1require 'test/unit' 2require_relative 'envutil' 3 4class TestClass < Test::Unit::TestCase 5 # ------------------ 6 # Various test classes 7 # ------------------ 8 9 class ClassOne 10 attr :num_args 11 @@subs = [] 12 def initialize(*args) 13 @num_args = args.size 14 @args = args 15 end 16 def [](n) 17 @args[n] 18 end 19 def ClassOne.inherited(klass) 20 @@subs.push klass 21 end 22 def subs 23 @@subs 24 end 25 end 26 27 class ClassTwo < ClassOne 28 end 29 30 class ClassThree < ClassOne 31 end 32 33 class ClassFour < ClassThree 34 end 35 36 # ------------------ 37 # Start of tests 38 # ------------------ 39 40 def test_s_inherited 41 assert_equal([ClassTwo, ClassThree, ClassFour], ClassOne.new.subs) 42 end 43 44 def test_s_new 45 c = Class.new 46 assert_same(Class, c.class) 47 assert_same(Object, c.superclass) 48 49 c = Class.new(Fixnum) 50 assert_same(Class, c.class) 51 assert_same(Fixnum, c.superclass) 52 end 53 54 def test_00_new_basic 55 a = ClassOne.new 56 assert_equal(ClassOne, a.class) 57 assert_equal(0, a.num_args) 58 59 a = ClassOne.new(1, 2, 3) 60 assert_equal(3, a.num_args) 61 assert_equal(1, a[0]) 62 end 63 64 def test_01_new_inherited 65 a = ClassTwo.new 66 assert_equal(ClassTwo, a.class) 67 assert_equal(0, a.num_args) 68 69 a = ClassTwo.new(1, 2, 3) 70 assert_equal(3, a.num_args) 71 assert_equal(1, a[0]) 72 end 73 74 def test_superclass 75 assert_equal(ClassOne, ClassTwo.superclass) 76 assert_equal(Object, ClassTwo.superclass.superclass) 77 assert_equal(BasicObject, ClassTwo.superclass.superclass.superclass) 78 end 79 80 def test_class_cmp 81 assert_raise(TypeError) { Class.new <= 1 } 82 assert_raise(TypeError) { Class.new >= 1 } 83 assert_nil(Class.new <=> 1) 84 end 85 86 def test_class_initialize 87 assert_raise(TypeError) do 88 Class.new.instance_eval { initialize } 89 end 90 end 91 92 def test_instanciate_singleton_class 93 c = class << Object.new; self; end 94 assert_raise(TypeError) { c.new } 95 end 96 97 def test_superclass_of_basicobject 98 assert_equal(nil, BasicObject.superclass) 99 end 100 101 def test_module_function 102 c = Class.new 103 assert_raise(TypeError) do 104 Module.instance_method(:module_function).bind(c).call(:foo) 105 end 106 end 107 108 def test_extend_object 109 c = Class.new 110 assert_raise(TypeError) do 111 Module.instance_method(:extend_object).bind(c).call(Object.new) 112 end 113 end 114 115 def test_append_features 116 c = Class.new 117 assert_raise(TypeError) do 118 Module.instance_method(:append_features).bind(c).call(Module.new) 119 end 120 end 121 122 def test_prepend_features 123 c = Class.new 124 assert_raise(TypeError) do 125 Module.instance_method(:prepend_features).bind(c).call(Module.new) 126 end 127 end 128 129 def test_module_specific_methods 130 assert_empty(Class.private_instance_methods(true) & 131 [:module_function, :extend_object, :append_features, :prepend_features]) 132 end 133 134 def test_method_redefinition 135 feature2155 = '[ruby-dev:39400]' 136 137 line = __LINE__+4 138 stderr = EnvUtil.verbose_warning do 139 Class.new do 140 def foo; end 141 def foo; end 142 end 143 end 144 assert_match(/:#{line}: warning: method redefined; discarding old foo/, stderr) 145 assert_match(/:#{line-1}: warning: previous definition of foo/, stderr, feature2155) 146 147 stderr = EnvUtil.verbose_warning do 148 Class.new do 149 def foo; end 150 alias bar foo 151 def foo; end 152 end 153 end 154 assert_equal("", stderr) 155 156 stderr = EnvUtil.verbose_warning do 157 Class.new do 158 def foo; end 159 alias bar foo 160 alias bar foo 161 end 162 end 163 assert_equal("", stderr) 164 165 line = __LINE__+4 166 stderr = EnvUtil.verbose_warning do 167 Class.new do 168 define_method(:foo) do end 169 def foo; end 170 end 171 end 172 assert_match(/:#{line}: warning: method redefined; discarding old foo/, stderr) 173 assert_match(/:#{line-1}: warning: previous definition of foo/, stderr, feature2155) 174 175 stderr = EnvUtil.verbose_warning do 176 Class.new do 177 define_method(:foo) do end 178 alias bar foo 179 alias bar foo 180 end 181 end 182 assert_equal("", stderr) 183 184 stderr = EnvUtil.verbose_warning do 185 Class.new do 186 def foo; end 187 undef foo 188 end 189 end 190 assert_equal("", stderr) 191 end 192 193 def test_check_inheritable 194 assert_raise(TypeError) { Class.new(Object.new) } 195 196 o = Object.new 197 c = class << o; self; end 198 assert_raise(TypeError) { Class.new(c) } 199 assert_raise(TypeError) { Class.new(Class) } 200 assert_raise(TypeError) { eval("class Foo < Class; end") } 201 end 202 203 def test_initialize_copy 204 c = Class.new 205 assert_raise(TypeError) { c.instance_eval { initialize_copy(1) } } 206 207 o = Object.new 208 c = class << o; self; end 209 assert_raise(TypeError) { c.dup } 210 211 assert_raise(TypeError) { BasicObject.dup } 212 end 213 214 def test_singleton_class 215 assert_raise(TypeError) { 1.extend(Module.new) } 216 assert_raise(TypeError) { 1.0.extend(Module.new) } 217 assert_raise(TypeError) { (2.0**1000).extend(Module.new) } 218 assert_raise(TypeError) { :foo.extend(Module.new) } 219 220 assert_in_out_err([], <<-INPUT, %w(:foo :foo true true), []) 221 module Foo; def foo; :foo; end; end 222 false.extend(Foo) 223 true.extend(Foo) 224 p false.foo 225 p true.foo 226 p FalseClass.include?(Foo) 227 p TrueClass.include?(Foo) 228 INPUT 229 end 230 231 def test_uninitialized 232 assert_raise(TypeError) { Class.allocate.new } 233 assert_raise(TypeError) { Class.allocate.superclass } 234 bug6863 = '[ruby-core:47148]' 235 assert_raise(TypeError, bug6863) { Class.new(Class.allocate) } 236 end 237 238 def test_nonascii_name 239 c = eval("class ::C\u{df}; self; end") 240 assert_equal("C\u{df}", c.name, '[ruby-core:24600]') 241 c = eval("class C\u{df}; self; end") 242 assert_equal("TestClass::C\u{df}", c.name, '[ruby-core:24600]') 243 end 244 245 def test_invalid_jump_from_class_definition 246 assert_raise(SyntaxError) { eval("class C; next; end") } 247 assert_raise(SyntaxError) { eval("class C; break; end") } 248 assert_raise(SyntaxError) { eval("class C; redo; end") } 249 assert_raise(SyntaxError) { eval("class C; retry; end") } 250 assert_raise(SyntaxError) { eval("class C; return; end") } 251 assert_raise(SyntaxError) { eval("class C; yield; end") } 252 end 253 254 def test_clone 255 original = Class.new { 256 def foo 257 return super() 258 end 259 } 260 mod = Module.new { 261 def foo 262 return "mod#foo" 263 end 264 } 265 copy = original.clone 266 copy.send(:include, mod) 267 assert_equal("mod#foo", copy.new.foo) 268 end 269 270 def test_nested_class_removal 271 assert_normal_exit('File.__send__(:remove_const, :Stat); at_exit{File.stat(".")}; GC.start') 272 end 273 274 class PrivateClass 275 end 276 private_constant :PrivateClass 277 278 def test_redefine_private_class 279 assert_raise(NameError) do 280 eval("class ::TestClass::PrivateClass; end") 281 end 282 eval <<-END 283 class ::TestClass 284 class PrivateClass 285 def foo; 42; end 286 end 287 end 288 END 289 assert_equal(42, PrivateClass.new.foo) 290 end 291 292 StrClone = String.clone 293 Class.new(StrClone) 294 295 def test_cloned_class 296 bug5274 = StrClone.new("[ruby-dev:44460]") 297 assert_equal(bug5274, Marshal.load(Marshal.dump(bug5274))) 298 end 299 300 def test_cannot_reinitialize_class_with_initialize_copy # [ruby-core:50869] 301 assert_in_out_err([], <<-'end;', ["Object"], []) 302 class Class 303 def initialize_copy(*); super; end 304 end 305 306 class A; end 307 class B; end 308 309 A.send(:initialize_copy, Class.new(B)) rescue nil 310 311 p A.superclass 312 end; 313 end 314 315 module M 316 C = 1 317 318 def self.m 319 C 320 end 321 end 322 323 def test_constant_access_from_method_in_cloned_module # [ruby-core:47834] 324 m = M.dup 325 assert_equal 1, m::C 326 assert_equal 1, m.m 327 end 328 329 def test_invalid_superclass 330 assert_raise(TypeError) do 331 eval <<-'end;' 332 class C < nil 333 end 334 end; 335 end 336 337 assert_raise(TypeError) do 338 eval <<-'end;' 339 class C < false 340 end 341 end; 342 end 343 344 assert_raise(TypeError) do 345 eval <<-'end;' 346 class C < true 347 end 348 end; 349 end 350 351 assert_raise(TypeError) do 352 eval <<-'end;' 353 class C < 0 354 end 355 end; 356 end 357 358 assert_raise(TypeError) do 359 eval <<-'end;' 360 class C < "" 361 end 362 end; 363 end 364 end 365 366 def test_cloned_singleton_method_added 367 bug5283 = '[ruby-dev:44477]' 368 added = [] 369 c = Class.new 370 c.singleton_class.class_eval do 371 define_method(:singleton_method_added) {|mid| added << [self, mid]} 372 def foo; :foo; end 373 end 374 added.clear 375 d = c.clone 376 assert_empty(added.grep(->(k) {c == k[0]}), bug5283) 377 assert_equal(:foo, d.foo) 378 end 379end 380