* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / ruby / test_variable.rb
blobf8a7c68fd380fb38716b22e17f053eb89a2611e3
1 # frozen_string_literal: false
2 require 'test/unit'
4 class TestVariable < Test::Unit::TestCase
5   class Gods
6     @@rule = "Uranus"
7     def ruler0
8       @@rule
9     end
11     def self.ruler1             # <= per method definition style
12       @@rule
13     end
14     class << self                       # <= multiple method definition style
15       def ruler2
16         @@rule
17       end
18     end
19   end
21   module Olympians
22     @@rule ="Zeus"
23     def ruler3
24       @@rule
25     end
26   end
28   class Titans < Gods
29     @@rule = "Cronus"                   # modifies @@rule in Gods
30     include Olympians
31     def ruler4
32       @@rule
33     end
34   end
36   def test_setting_class_variable_on_module_through_inheritance
37     mod = Module.new
38     mod.class_variable_set(:@@foo, 1)
39     mod.freeze
40     c = Class.new { include(mod) }
41     assert_raise(FrozenError) { c.class_variable_set(:@@foo, 2) }
42     assert_raise(FrozenError) { c.class_eval("@@foo = 2") }
43     assert_equal(1, c.class_variable_get(:@@foo))
44   end
46   def test_singleton_class_included_class_variable
47     c = Class.new
48     c.extend(Olympians)
49     assert_empty(c.singleton_class.class_variables)
50     assert_raise(NameError){ c.singleton_class.class_variable_get(:@@rule) }
51     c.class_variable_set(:@@foo, 1)
52     assert_equal([:@@foo], c.singleton_class.class_variables)
53     assert_equal(1, c.singleton_class.class_variable_get(:@@foo))
55     c = Class.new
56     c.extend(Olympians)
57     sc = Class.new(c)
58     assert_empty(sc.singleton_class.class_variables)
59     assert_raise(NameError){ sc.singleton_class.class_variable_get(:@@rule) }
60     c.class_variable_set(:@@foo, 1)
61     assert_equal([:@@foo], sc.singleton_class.class_variables)
62     assert_equal(1, sc.singleton_class.class_variable_get(:@@foo))
64     c = Class.new
65     o = c.new
66     o.extend(Olympians)
67     assert_equal([:@@rule], o.singleton_class.class_variables)
68     assert_equal("Zeus", o.singleton_class.class_variable_get(:@@rule))
69     c.class_variable_set(:@@foo, 1)
70     assert_equal([:@@foo, :@@rule], o.singleton_class.class_variables.sort)
71     assert_equal(1, o.singleton_class.class_variable_get(:@@foo))
72   end
74   def test_cvar_overtaken_by_parent_class
75     error = eval <<~EORB
76       class Parent
77       end
79       class Child < Parent
80         @@cvar = 1
82         def self.cvar
83           @@cvar
84         end
85       end
87       assert_equal 1, Child.cvar
89       class Parent
90         @@cvar = 2
91       end
93       assert_raise RuntimeError do
94         Child.cvar
95       end
96     EORB
98     assert_equal "class variable @@cvar of TestVariable::Child is overtaken by TestVariable::Parent", error.message
99   ensure
100     TestVariable.send(:remove_const, :Child) rescue nil
101     TestVariable.send(:remove_const, :Parent) rescue nil
102   end
104   def test_cvar_overtaken_by_module
105     error = eval <<~EORB
106       class ParentForModule
107         @@cvar = 1
109         def self.cvar
110           @@cvar
111         end
112       end
114       assert_equal 1, ParentForModule.cvar
116       module Mixin
117         @@cvar = 2
118       end
120       class ParentForModule
121         include Mixin
122       end
124       assert_raise RuntimeError do
125         ParentForModule.cvar
126       end
127     EORB
129     assert_equal "class variable @@cvar of TestVariable::ParentForModule is overtaken by TestVariable::Mixin", error.message
130   ensure
131     TestVariable.send(:remove_const, :Mixin) rescue nil
132     TestVariable.send(:remove_const, :ParentForModule) rescue nil
133   end
135   class IncludeRefinedModuleClassVariableNoWarning
136     module Mod
137       @@_test_include_refined_module_class_variable = true
138     end
140     module Mod2
141       refine Mod do
142       end
143     end
145     include Mod
147     def t
148       @@_test_include_refined_module_class_variable
149     end
150   end
152   def test_include_refined_module_class_variable
153     assert_warning('') do
154       IncludeRefinedModuleClassVariableNoWarning.new.t
155     end
156   end
158   def test_variable
159     assert_instance_of(Integer, $$)
161     # read-only variable
162     assert_raise(NameError) do
163       $$ = 5
164     end
165     assert_normal_exit("$*=0; $*", "[ruby-dev:36698]")
167     foobar = "foobar"
168     $_ = foobar
169     assert_equal(foobar, $_)
171     assert_equal("Cronus", Gods.new.ruler0)
172     assert_equal("Cronus", Gods.ruler1)
173     assert_equal("Cronus", Gods.ruler2)
174     assert_equal("Cronus", Titans.ruler1)
175     assert_equal("Cronus", Titans.ruler2)
176     atlas = Titans.new
177     assert_equal("Cronus", atlas.ruler0)
178     assert_equal("Zeus", atlas.ruler3)
179     assert_raise(RuntimeError) { atlas.ruler4 }
180     assert_nothing_raised do
181       class << Gods
182         defined?(@@rule) && @@rule
183       end
184     end
185   end
187   def test_local_variables
188     lvar = 1
189     assert_instance_of(Symbol, local_variables[0], "[ruby-dev:34008]")
190     lvar
191   end
193   def test_local_variables2
194     x = 1
195     proc do |y|
196       assert_equal([:x, :y], local_variables.sort)
197     end.call
198     x
199   end
201   def test_local_variables3
202     x = 1
203     proc do |y|
204       1.times do |z|
205         assert_equal([:x, :y, :z], local_variables.sort)
206       end
207     end.call
208     x
209   end
211   def test_shadowing_local_variables
212     bug9486 = '[ruby-core:60501] [Bug #9486]'
213     assert_equal([:x, :bug9486], tap {|x| break local_variables}, bug9486)
214   end
216   def test_shadowing_block_local_variables
217     bug9486 = '[ruby-core:60501] [Bug #9486]'
218     assert_equal([:x, :bug9486], tap {|;x| x = x; break local_variables}, bug9486)
219   end
221   def test_global_variables
222     gv = global_variables
223     assert_empty(gv.grep(/\A(?!\$)/))
224     assert_nil($~)
225     assert_not_include(gv, :$1)
226     /(\w)(\d)?(.)(.)(.)(.)(.)(.)(.)(.)(\d)?(.)/ =~ "globalglobalglobal"
227     assert_not_nil($~)
228     gv = global_variables - gv
229     assert_include(gv, :$1)
230     assert_not_include(gv, :$2)
231     assert_not_include(gv, :$11)
232     assert_include(gv, :$12)
233   end
235   def test_global_variable_0
236     assert_in_out_err(["-e", "$0='t'*1000;print $0"], "", /\At+\z/, [])
237   end
239   def test_global_variable_popped
240     assert_nothing_raised {
241       EnvUtil.suppress_warning {
242         eval("$foo; 1")
243       }
244     }
245   end
247   def test_constant_popped
248     assert_nothing_raised {
249       EnvUtil.suppress_warning {
250         eval("TestVariable::Gods; 1")
251       }
252     }
253   end
255   def test_special_constant_ivars
256     [ true, false, :symbol, "dsym#{rand(9999)}".to_sym, 1, 1.0 ].each do |v|
257       assert_empty v.instance_variables
258       msg = "can't modify frozen #{v.class}: #{v.inspect}"
260       assert_raise_with_message(FrozenError, msg) do
261         v.instance_variable_set(:@foo, :bar)
262       end
264       assert_nil EnvUtil.suppress_warning {v.instance_variable_get(:@foo)}
265       assert_not_send([v, :instance_variable_defined?, :@foo])
267       assert_raise_with_message(FrozenError, msg) do
268         v.remove_instance_variable(:@foo)
269       end
270     end
271   end
273   class ExIvar < Hash
274     def initialize
275       @a = 1
276       @b = 2
277       @c = 3
278     end
280     def ivars
281       [@a, @b, @c]
282     end
283   end
285   def test_external_ivars
286     3.times{
287       # check inline cache for external ivar access
288       assert_equal [1, 2, 3], ExIvar.new.ivars
289     }
290   end
292   def test_local_variables_with_kwarg
293     bug11674 = '[ruby-core:71437] [Bug #11674]'
294     v = with_kwargs_11(v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8,v9:9,v10:10,v11:11)
295     assert_equal(%i(v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11), v, bug11674)
296   end
298   private
299   def with_kwargs_11(v1:, v2:, v3:, v4:, v5:, v6:, v7:, v8:, v9:, v10:, v11:)
300     local_variables
301   end