PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/test/ruby/test_class.rb

http://github.com/ruby/ruby
Ruby | 686 lines | 575 code | 97 blank | 14 comment | 2 complexity | ecd632702d745b207035d1068d9a8627 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: false
  2. require 'test/unit'
  3. class TestClass < Test::Unit::TestCase
  4. # ------------------
  5. # Various test classes
  6. # ------------------
  7. class ClassOne
  8. attr :num_args
  9. @@subs = []
  10. def initialize(*args)
  11. @num_args = args.size
  12. @args = args
  13. end
  14. def [](n)
  15. @args[n]
  16. end
  17. def ClassOne.inherited(klass)
  18. @@subs.push klass
  19. end
  20. def subs
  21. @@subs
  22. end
  23. end
  24. class ClassTwo < ClassOne
  25. end
  26. class ClassThree < ClassOne
  27. end
  28. class ClassFour < ClassThree
  29. end
  30. # ------------------
  31. # Start of tests
  32. # ------------------
  33. def test_s_inherited
  34. assert_equal([ClassTwo, ClassThree, ClassFour], ClassOne.new.subs)
  35. end
  36. def test_s_new
  37. c = Class.new
  38. assert_same(Class, c.class)
  39. assert_same(Object, c.superclass)
  40. c = Class.new(Integer)
  41. assert_same(Class, c.class)
  42. assert_same(Integer, c.superclass)
  43. end
  44. def test_00_new_basic
  45. a = ClassOne.new
  46. assert_equal(ClassOne, a.class)
  47. assert_equal(0, a.num_args)
  48. a = ClassOne.new(1, 2, 3)
  49. assert_equal(3, a.num_args)
  50. assert_equal(1, a[0])
  51. end
  52. def test_01_new_inherited
  53. a = ClassTwo.new
  54. assert_equal(ClassTwo, a.class)
  55. assert_equal(0, a.num_args)
  56. a = ClassTwo.new(1, 2, 3)
  57. assert_equal(3, a.num_args)
  58. assert_equal(1, a[0])
  59. end
  60. def test_superclass
  61. assert_equal(ClassOne, ClassTwo.superclass)
  62. assert_equal(Object, ClassTwo.superclass.superclass)
  63. assert_equal(BasicObject, ClassTwo.superclass.superclass.superclass)
  64. end
  65. def test_class_cmp
  66. assert_raise(TypeError) { Class.new <= 1 }
  67. assert_raise(TypeError) { Class.new >= 1 }
  68. assert_nil(Class.new <=> 1)
  69. end
  70. def test_class_initialize
  71. assert_raise(TypeError) do
  72. Class.new.instance_eval { initialize }
  73. end
  74. end
  75. def test_instantiate_singleton_class
  76. c = class << Object.new; self; end
  77. assert_raise(TypeError) { c.new }
  78. end
  79. def test_superclass_of_basicobject
  80. assert_equal(nil, BasicObject.superclass)
  81. end
  82. def test_module_function
  83. c = Class.new
  84. assert_raise(TypeError) do
  85. Module.instance_method(:module_function).bind(c).call(:foo)
  86. end
  87. end
  88. def test_extend_object
  89. c = Class.new
  90. assert_raise(TypeError) do
  91. Module.instance_method(:extend_object).bind(c).call(Object.new)
  92. end
  93. end
  94. def test_append_features
  95. c = Class.new
  96. assert_raise(TypeError) do
  97. Module.instance_method(:append_features).bind(c).call(Module.new)
  98. end
  99. end
  100. def test_prepend_features
  101. c = Class.new
  102. assert_raise(TypeError) do
  103. Module.instance_method(:prepend_features).bind(c).call(Module.new)
  104. end
  105. end
  106. def test_module_specific_methods
  107. assert_empty(Class.private_instance_methods(true) &
  108. [:module_function, :extend_object, :append_features, :prepend_features])
  109. end
  110. def test_visibility_inside_method
  111. assert_warn(/calling private without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do
  112. Class.new do
  113. def self.foo
  114. private
  115. end
  116. foo
  117. end
  118. end
  119. assert_warn(/calling protected without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do
  120. Class.new do
  121. def self.foo
  122. protected
  123. end
  124. foo
  125. end
  126. end
  127. assert_warn(/calling public without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do
  128. Class.new do
  129. def self.foo
  130. public
  131. end
  132. foo
  133. end
  134. end
  135. assert_warn(/calling private without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do
  136. Class.new do
  137. class << self
  138. alias priv private
  139. end
  140. def self.foo
  141. priv
  142. end
  143. foo
  144. end
  145. end
  146. end
  147. def test_method_redefinition
  148. feature2155 = '[ruby-dev:39400]'
  149. line = __LINE__+4
  150. stderr = EnvUtil.verbose_warning do
  151. Class.new do
  152. def foo; end
  153. def foo; end
  154. end
  155. end
  156. assert_match(/:#{line}: warning: method redefined; discarding old foo/, stderr)
  157. assert_match(/:#{line-1}: warning: previous definition of foo/, stderr, feature2155)
  158. assert_warning '' do
  159. Class.new do
  160. def foo; end
  161. alias bar foo
  162. def foo; end
  163. end
  164. end
  165. assert_warning '' do
  166. Class.new do
  167. def foo; end
  168. alias bar foo
  169. alias bar foo
  170. end
  171. end
  172. line = __LINE__+4
  173. stderr = EnvUtil.verbose_warning do
  174. Class.new do
  175. define_method(:foo) do end
  176. def foo; end
  177. end
  178. end
  179. assert_match(/:#{line}: warning: method redefined; discarding old foo/, stderr)
  180. assert_match(/:#{line-1}: warning: previous definition of foo/, stderr, feature2155)
  181. assert_warning '' do
  182. Class.new do
  183. define_method(:foo) do end
  184. alias bar foo
  185. alias bar foo
  186. end
  187. end
  188. assert_warning '' do
  189. Class.new do
  190. def foo; end
  191. undef foo
  192. end
  193. end
  194. end
  195. def test_check_inheritable
  196. assert_raise(TypeError) { Class.new(Object.new) }
  197. o = Object.new
  198. c = class << o; self; end
  199. assert_raise(TypeError) { Class.new(c) }
  200. assert_raise(TypeError) { Class.new(Class) }
  201. assert_raise(TypeError) { eval("class Foo < Class; end") }
  202. m = "M\u{1f5ff}"
  203. o = Class.new {break eval("class #{m}; self; end.new")}
  204. assert_raise_with_message(TypeError, /#{m}/) {Class.new(o)}
  205. end
  206. def test_initialize_copy
  207. c = Class.new
  208. assert_raise(TypeError) { c.instance_eval { initialize_copy(1) } }
  209. o = Object.new
  210. c = class << o; self; end
  211. assert_raise(TypeError) { c.dup }
  212. assert_raise(TypeError) { BasicObject.dup }
  213. end
  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. assert_in_out_err([], <<-INPUT, %w(:foo :foo true true), [])
  220. module Foo; def foo; :foo; end; end
  221. false.extend(Foo)
  222. true.extend(Foo)
  223. p false.foo
  224. p true.foo
  225. p FalseClass.include?(Foo)
  226. p TrueClass.include?(Foo)
  227. INPUT
  228. end
  229. def test_uninitialized
  230. assert_raise(TypeError) { Class.allocate.new }
  231. assert_raise(TypeError) { Class.allocate.superclass }
  232. bug6863 = '[ruby-core:47148]'
  233. assert_raise(TypeError, bug6863) { Class.new(Class.allocate) }
  234. allocator = Class.instance_method(:allocate)
  235. assert_raise_with_message(TypeError, /prohibited/) {
  236. allocator.bind(Rational).call
  237. }
  238. assert_raise_with_message(TypeError, /prohibited/) {
  239. allocator.bind_call(Rational)
  240. }
  241. end
  242. def test_nonascii_name
  243. c = eval("class ::C\u{df}; self; end")
  244. assert_equal("C\u{df}", c.name, '[ruby-core:24600]')
  245. c = eval("class C\u{df}; self; end")
  246. assert_equal("TestClass::C\u{df}", c.name, '[ruby-core:24600]')
  247. end
  248. def test_invalid_next_from_class_definition
  249. assert_syntax_error("class C; next; end", /Invalid next/)
  250. end
  251. def test_invalid_break_from_class_definition
  252. assert_syntax_error("class C; break; end", /Invalid break/)
  253. end
  254. def test_invalid_redo_from_class_definition
  255. assert_syntax_error("class C; redo; end", /Invalid redo/)
  256. end
  257. def test_invalid_retry_from_class_definition
  258. assert_syntax_error("class C; retry; end", /Invalid retry/)
  259. end
  260. def test_invalid_return_from_class_definition
  261. assert_syntax_error("class C; return; end", /Invalid return/)
  262. end
  263. def test_invalid_yield_from_class_definition
  264. assert_raise(SyntaxError) {
  265. EnvUtil.suppress_warning {eval("class C; yield; end")}
  266. }
  267. end
  268. def test_clone
  269. original = Class.new {
  270. def foo
  271. return super()
  272. end
  273. }
  274. mod = Module.new {
  275. def foo
  276. return "mod#foo"
  277. end
  278. }
  279. copy = original.clone
  280. copy.send(:include, mod)
  281. assert_equal("mod#foo", copy.new.foo)
  282. end
  283. def test_nested_class_removal
  284. assert_normal_exit('File.__send__(:remove_const, :Stat); at_exit{File.stat(".")}; GC.start')
  285. end
  286. class PrivateClass
  287. end
  288. private_constant :PrivateClass
  289. def test_redefine_private_class
  290. assert_raise(NameError) do
  291. eval("class ::TestClass::PrivateClass; end")
  292. end
  293. eval <<-END
  294. class ::TestClass
  295. class PrivateClass
  296. def foo; 42; end
  297. end
  298. end
  299. END
  300. assert_equal(42, PrivateClass.new.foo)
  301. end
  302. StrClone = String.clone
  303. Class.new(StrClone)
  304. def test_cloned_class
  305. bug5274 = StrClone.new("[ruby-dev:44460]")
  306. assert_equal(bug5274, Marshal.load(Marshal.dump(bug5274)))
  307. end
  308. def test_cannot_reinitialize_class_with_initialize_copy # [ruby-core:50869]
  309. assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", ["Object"], [])
  310. begin;
  311. class Class
  312. def initialize_copy(*); super; end
  313. end
  314. class A; end
  315. class B; end
  316. A.send(:initialize_copy, Class.new(B)) rescue nil
  317. p A.superclass
  318. end;
  319. end
  320. class CloneTest
  321. def foo; TEST; end
  322. end
  323. CloneTest1 = CloneTest.clone
  324. CloneTest2 = CloneTest.clone
  325. class CloneTest1
  326. TEST = :C1
  327. end
  328. class CloneTest2
  329. TEST = :C2
  330. end
  331. def test_constant_access_from_method_in_cloned_class
  332. assert_equal :C1, CloneTest1.new.foo, '[Bug #15877]'
  333. assert_equal :C2, CloneTest2.new.foo, '[Bug #15877]'
  334. end
  335. def test_invalid_superclass
  336. assert_raise(TypeError) do
  337. eval <<-'end;'
  338. class C < nil
  339. end
  340. end;
  341. end
  342. assert_raise(TypeError) do
  343. eval <<-'end;'
  344. class C < false
  345. end
  346. end;
  347. end
  348. assert_raise(TypeError) do
  349. eval <<-'end;'
  350. class C < true
  351. end
  352. end;
  353. end
  354. assert_raise(TypeError) do
  355. eval <<-'end;'
  356. class C < 0
  357. end
  358. end;
  359. end
  360. assert_raise(TypeError) do
  361. eval <<-'end;'
  362. class C < ""
  363. end
  364. end;
  365. end
  366. m = Module.new
  367. n = "M\u{1f5ff}"
  368. c = m.module_eval "class #{n}; new; end"
  369. assert_raise_with_message(TypeError, /#{n}/) {
  370. eval <<-"end;"
  371. class C < c
  372. end
  373. end;
  374. }
  375. assert_raise_with_message(TypeError, /#{n}/) {
  376. Class.new(c)
  377. }
  378. assert_raise_with_message(TypeError, /#{n}/) {
  379. m.module_eval "class #{n} < Class.new; end"
  380. }
  381. end
  382. define_method :test_invalid_reset_superclass do
  383. class A; end
  384. class SuperclassCannotBeReset < A
  385. end
  386. assert_equal A, SuperclassCannotBeReset.superclass
  387. assert_raise_with_message(TypeError, /superclass mismatch/) {
  388. class SuperclassCannotBeReset < String
  389. end
  390. }
  391. assert_raise_with_message(TypeError, /superclass mismatch/, "[ruby-core:75446]") {
  392. class SuperclassCannotBeReset < Object
  393. end
  394. }
  395. assert_equal A, SuperclassCannotBeReset.superclass
  396. end
  397. def test_cloned_singleton_method_added
  398. bug5283 = '[ruby-dev:44477]'
  399. added = []
  400. c = Class.new
  401. c.singleton_class.class_eval do
  402. define_method(:singleton_method_added) {|mid| added << [self, mid]}
  403. def foo; :foo; end
  404. end
  405. added.clear
  406. d = c.clone
  407. assert_empty(added.grep(->(k) {c == k[0]}), bug5283)
  408. assert_equal(:foo, d.foo)
  409. end
  410. def test_singleton_class_p
  411. feature7609 = '[ruby-core:51087] [Feature #7609]'
  412. assert_predicate(self.singleton_class, :singleton_class?, feature7609)
  413. assert_not_predicate(self.class, :singleton_class?, feature7609)
  414. end
  415. def test_freeze_to_s
  416. assert_nothing_raised("[ruby-core:41858] [Bug #5828]") {
  417. Class.new.freeze.clone.to_s
  418. }
  419. end
  420. def test_singleton_class_of_frozen_object
  421. obj = Object.new
  422. c = obj.singleton_class
  423. obj.freeze
  424. assert_raise_with_message(FrozenError, /frozen object/) {
  425. c.class_eval {def f; end}
  426. }
  427. end
  428. def test_singleton_class_message
  429. c = Class.new.freeze
  430. assert_raise_with_message(FrozenError, /frozen Class/) {
  431. def c.f; end
  432. }
  433. end
  434. def test_singleton_class_should_has_own_namespace
  435. # CONST in singleton class
  436. objs = []
  437. $i = 0
  438. 2.times{
  439. objs << obj = Object.new
  440. class << obj
  441. CONST = ($i += 1)
  442. def foo
  443. CONST
  444. end
  445. end
  446. }
  447. assert_equal(1, objs[0].foo, '[Bug #10943]')
  448. assert_equal(2, objs[1].foo, '[Bug #10943]')
  449. # CONST in block in singleton class
  450. objs = []
  451. $i = 0
  452. 2.times{
  453. objs << obj = Object.new
  454. class << obj
  455. 1.times{
  456. CONST = ($i += 1)
  457. }
  458. def foo
  459. [nil].map{
  460. CONST
  461. }
  462. end
  463. end
  464. }
  465. assert_equal([1], objs[0].foo, '[Bug #10943]')
  466. assert_equal([2], objs[1].foo, '[Bug #10943]')
  467. # class def in singleton class
  468. objs = []
  469. $xs = []
  470. $i = 0
  471. 2.times{
  472. objs << obj = Object.new
  473. class << obj
  474. CONST = ($i += 1)
  475. class X
  476. $xs << self
  477. CONST = ($i += 1)
  478. def foo
  479. CONST
  480. end
  481. end
  482. def x
  483. X
  484. end
  485. end
  486. }
  487. assert_not_equal($xs[0], $xs[1], '[Bug #10943]')
  488. assert_not_equal(objs[0].x, objs[1].x, '[Bug #10943]')
  489. assert_equal(2, $xs[0]::CONST, '[Bug #10943]')
  490. assert_equal(2, $xs[0].new.foo, '[Bug #10943]')
  491. assert_equal(4, $xs[1]::CONST, '[Bug #10943]')
  492. assert_equal(4, $xs[1].new.foo, '[Bug #10943]')
  493. # class def in block in singleton class
  494. objs = []
  495. $xs = []
  496. $i = 0
  497. 2.times{
  498. objs << obj = Object.new
  499. class << obj
  500. 1.times{
  501. CONST = ($i += 1)
  502. }
  503. 1.times{
  504. class X
  505. $xs << self
  506. CONST = ($i += 1)
  507. def foo
  508. CONST
  509. end
  510. end
  511. def x
  512. X
  513. end
  514. }
  515. end
  516. }
  517. assert_not_equal($xs[0], $xs[1], '[Bug #10943]')
  518. assert_not_equal(objs[0].x, objs[1].x, '[Bug #10943]')
  519. assert_equal(2, $xs[0]::CONST, '[Bug #10943]')
  520. assert_equal(2, $xs[0].new.foo, '[Bug #10943]')
  521. assert_equal(4, $xs[1]::CONST, '[Bug #10943]')
  522. assert_equal(4, $xs[1].new.foo, '[Bug #10943]')
  523. # method def in singleton class
  524. ms = []
  525. ps = $test_singleton_class_shared_cref_ps = []
  526. 2.times{
  527. ms << Module.new do
  528. class << self
  529. $test_singleton_class_shared_cref_ps << Proc.new{
  530. def xyzzy
  531. self
  532. end
  533. }
  534. end
  535. end
  536. }
  537. ps.each{|p| p.call} # define xyzzy methods for each singleton classes
  538. ms.each{|m|
  539. assert_equal(m, m.xyzzy, "Bug #10871")
  540. }
  541. end
  542. def test_namescope_error_message
  543. m = Module.new
  544. o = m.module_eval "class A\u{3042}; self; end.new"
  545. assert_raise_with_message(TypeError, /A\u{3042}/) {
  546. o::Foo
  547. }
  548. end
  549. def test_redefinition_mismatch
  550. m = Module.new
  551. m.module_eval "A = 1", __FILE__, line = __LINE__
  552. e = assert_raise_with_message(TypeError, /is not a class/) {
  553. m.module_eval "class A; end"
  554. }
  555. assert_include(e.message, "#{__FILE__}:#{line}: previous definition")
  556. n = "M\u{1f5ff}"
  557. m.module_eval "#{n} = 42", __FILE__, line = __LINE__
  558. e = assert_raise_with_message(TypeError, /#{n} is not a class/) {
  559. m.module_eval "class #{n}; end"
  560. }
  561. assert_include(e.message, "#{__FILE__}:#{line}: previous definition")
  562. assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}")
  563. begin;
  564. Date = (class C\u{1f5ff}; self; end).new
  565. assert_raise_with_message(TypeError, /C\u{1f5ff}/) {
  566. require 'date'
  567. }
  568. end;
  569. end
  570. def test_should_not_expose_singleton_class_without_metaclass
  571. assert_normal_exit "#{<<~"begin;"}\n#{<<~'end;'}", '[Bug #11740]'
  572. begin;
  573. klass = Class.new(Array)
  574. # The metaclass of +klass+ should handle #bla since it should inherit methods from meta:meta:Array
  575. def (Array.singleton_class).bla; :bla; end
  576. hidden = ObjectSpace.each_object(Class).find { |c| klass.is_a? c and c.inspect.include? klass.inspect }
  577. raise unless hidden.nil?
  578. end;
  579. assert_normal_exit "#{<<~"begin;"}\n#{<<~'end;'}", '[Bug #11740]'
  580. begin;
  581. klass = Class.new(Array)
  582. klass.singleton_class
  583. # The metaclass of +klass+ should handle #bla since it should inherit methods from meta:meta:Array
  584. def (Array.singleton_class).bla; :bla; end
  585. hidden = ObjectSpace.each_object(Class).find { |c| klass.is_a? c and c.inspect.include? klass.inspect }
  586. raise if hidden.nil?
  587. end;
  588. end
  589. end