blob: b0cc527bb78ded1cda9aec8fe626009b9ba77109 [file] [log] [blame]
Kevin Clark3eca0782008-06-18 00:54:53 +00001require File.dirname(__FILE__) + '/spec_helper'
2
Kevin Clark96cc5162008-06-18 00:56:08 +00003shared_examples_for "deprecation" do
4 before(:all) do
5 # ensure deprecation is turned on
6 Thrift.send :remove_const, :DEPRECATION
7 Thrift.const_set :DEPRECATION, true
8 end
9
10 after(:all) do
11 # now turn it off again
12 # no other specs should want it
13 Thrift.send :remove_const, :DEPRECATION
14 Thrift.const_set :DEPRECATION, false
15 end
Kevin Clark03a5fb12008-06-18 01:01:25 +000016
17 def ensure_const_removed(name, &block)
18 begin
19 block.call
20 ensure
21 Object.send :remove_const, name if Object.const_defined? name
22 end
23 end
Kevin Clark96cc5162008-06-18 00:56:08 +000024end
25
Kevin Clark3eca0782008-06-18 00:54:53 +000026describe 'deprecate!' do
Kevin Clark96cc5162008-06-18 00:56:08 +000027 it_should_behave_like "deprecation"
28
Kevin Clarkfc964ee2008-06-18 00:57:46 +000029 def stub_stderr(callstr, offset=1)
Kevin Clark3eca0782008-06-18 00:54:53 +000030 STDERR.should_receive(:puts).with("Warning: calling deprecated method #{callstr}")
Kevin Clarkfc964ee2008-06-18 00:57:46 +000031 line = caller.first[/\d+$/].to_i + offset
32 STDERR.should_receive(:puts).with(" from #{__FILE__}:#{line}")
Kevin Clark3eca0782008-06-18 00:54:53 +000033 end
34
35 it "should work for Module methods" do
36 mod = Module.new do
37 class << self
38 def new
39 "new"
40 end
41 deprecate! :old => :new
42 end
43 end
44 stub_stderr "#{mod.inspect}.old"
45 mod.old.should == "new"
46 end
47
48 it "should work with Modules that extend themselves" do
49 mod = Module.new do
50 extend self
51 def new
52 "new"
53 end
54 deprecate! :old => :new
55 end
56 stub_stderr "#{mod.inspect}.old"
57 mod.old.should == "new"
58 end
59
60 it "should work wtih Class methods" do
61 klass = Class.new do
62 class << self
63 def new
64 "new"
65 end
66 deprecate! :old => :new
67 end
68 end
69 stub_stderr "#{klass.inspect}.old"
70 klass.old.should == "new"
71 end
72
73 it "should work with Classes that include Modules" do
74 mod = Module.new do
75 def new
76 "new"
77 end
78 deprecate! :old => :new
79 end
80 klass = Class.new do
81 include mod
82 end
83 stub_stderr "#{klass.inspect}#old"
84 klass.new.old.should == "new"
85 end
86
87 it "should work with instance methods" do
88 klass = Class.new do
89 def new
90 "new"
91 end
92 deprecate! :old => :new
93 end
94 stub_stderr "#{klass.inspect}#old"
95 klass.new.old.should == "new"
96 end
97
98 it "should work with multiple method names" do
99 klass = Class.new do
100 def new1
101 "new 1"
102 end
103 def new2
104 "new 2"
105 end
106 deprecate! :old1 => :new1, :old2 => :new2
107 end
Kevin Clarkfc964ee2008-06-18 00:57:46 +0000108 stub_stderr("#{klass.inspect}#old1", 3).ordered
109 stub_stderr("#{klass.inspect}#old2", 3).ordered
Kevin Clark3eca0782008-06-18 00:54:53 +0000110 inst = klass.new
111 inst.old1.should == "new 1"
112 inst.old2.should == "new 2"
113 end
114
115 it "should only log a message once, even across multiple instances" do
116 klass = Class.new do
117 def new
118 "new"
119 end
120 deprecate! :old => :new
121 end
122 stub_stderr("#{klass.inspect}#old").once
123 klass.new.old.should == "new"
124 klass.new.old.should == "new"
125 end
126
127 it "should pass arguments" do
128 klass = Class.new do
129 def new(a, b)
130 "new: #{a + b}"
131 end
132 deprecate! :old => :new
133 end
134 stub_stderr("#{klass.inspect}#old")
135 klass.new.old(3, 5).should == "new: 8"
136 end
137
138 it "should pass blocks" do
139 klass = Class.new do
140 def new
141 "new #{yield}"
142 end
143 deprecate! :old => :new
144 end
145 stub_stderr("#{klass.inspect}#old")
146 klass.new.old { "block" }.should == "new block"
147 end
148
149 it "should not freeze the definition of the new method" do
150 klass = Class.new do
151 def new
152 "new"
153 end
154 deprecate! :old => :new
155 end
156 klass.send :define_method, :new do
157 "new 2"
158 end
159 stub_stderr("#{klass.inspect}#old")
160 klass.new.old.should == "new 2"
161 end
Kevin Clarkda40e8d2008-06-18 00:58:04 +0000162
163 it "should call the forwarded method in the same context as the original" do
164 klass = Class.new do
165 def myself
166 self
167 end
168 deprecate! :me => :myself
169 end
170 inst = klass.new
171 stub_stderr("#{klass.inspect}#me")
172 inst.me.should eql(inst.myself)
173 end
Kevin Clark3eca0782008-06-18 00:54:53 +0000174end
175
176describe "deprecate_class!" do
Kevin Clark96cc5162008-06-18 00:56:08 +0000177 it_should_behave_like "deprecation"
178
Kevin Clark8c3e0932008-06-18 01:19:54 +0000179 def stub_stderr_jruby(klass)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000180 return unless defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000181 stub_stderr(klass, nil, caller.first)
182 end
183
184 def stub_stderr_mri(klass, offset=1)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000185 return if defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000186 stub_stderr(klass, offset, caller.first)
187 end
188
189 def stub_stderr(klass, offset=1, called=nil)
Kevin Clarkde7864e2008-06-18 01:02:14 +0000190 STDERR.should_receive(:puts).with("Warning: class #{klass} is deprecated")
Kevin Clark8c3e0932008-06-18 01:19:54 +0000191 if offset
192 line = (called || caller.first)[/\d+$/].to_i + offset
193 STDERR.should_receive(:puts).with(" from #{__FILE__}:#{line}")
194 else
195 STDERR.should_receive(:puts).with(/^ from #{Regexp.escape(__FILE__)}:/)
196 end
Kevin Clark2a8a7312008-06-18 01:01:07 +0000197 end
198
Kevin Clark3eca0782008-06-18 00:54:53 +0000199 it "should create a new global constant that points to the old one" do
Kevin Clark03a5fb12008-06-18 01:01:25 +0000200 ensure_const_removed :DeprecationSpecOldClass do
Kevin Clark3eca0782008-06-18 00:54:53 +0000201 klass = Class.new do
202 def foo
203 "foo"
204 end
205 end
206 deprecate_class! :DeprecationSpecOldClass => klass
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000207 stub_stderr(:DeprecationSpecOldClass)
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000208 ::DeprecationSpecOldClass.should eql(klass)
209 ::DeprecationSpecOldClass.new.foo.should == "foo"
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000210 end
211 end
212
213 it "should create a global constant even from inside a module" do
Kevin Clark03a5fb12008-06-18 01:01:25 +0000214 ensure_const_removed :DeprecationSpecOldClass do
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000215 klass = nil #define scoping
Kevin Clark03a5fb12008-06-18 01:01:25 +0000216 Module.new do
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000217 klass = Class.new do
218 def foo
219 "foo"
220 end
221 end
222 deprecate_class! :DeprecationSpecOldClass => klass
223 end
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000224 stub_stderr(:DeprecationSpecOldClass)
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000225 ::DeprecationSpecOldClass.should eql(klass)
226 ::DeprecationSpecOldClass.new.foo.should == "foo"
Kevin Clark3eca0782008-06-18 00:54:53 +0000227 end
228 end
Kevin Clark2a8a7312008-06-18 01:01:07 +0000229
230 it "should not prevent the deprecated class from being a superclass" do
Kevin Clark03a5fb12008-06-18 01:01:25 +0000231 ensure_const_removed :DeprecationSpecOldClass do
Kevin Clark2a8a7312008-06-18 01:01:07 +0000232 klass = Class.new do
233 def foo
234 "foo"
235 end
236 end
237 deprecate_class! :DeprecationSpecOldClass => klass
Kevin Clark8c3e0932008-06-18 01:19:54 +0000238 stub_stderr_jruby(:DeprecationSpecOldClass)
Kevin Clark2a8a7312008-06-18 01:01:07 +0000239 subklass = Class.new(::DeprecationSpecOldClass) do
240 def foo
241 "subclass #{super}"
242 end
243 end
Kevin Clark8c3e0932008-06-18 01:19:54 +0000244 stub_stderr_mri(:DeprecationSpecOldClass)
Kevin Clark2a8a7312008-06-18 01:01:07 +0000245 subklass.superclass.should eql(klass)
246 subklass.new.foo.should == "subclass foo"
Kevin Clark03a5fb12008-06-18 01:01:25 +0000247 end
248 end
Kevin Clarkfc311642008-06-18 01:01:57 +0000249
250 it "should not bleed info between deprecations" do
251 ensure_const_removed :DeprecationSpecOldClass do
252 ensure_const_removed :DeprecationSpecOldClass2 do
253 klass = Class.new do
254 def foo
255 "foo"
256 end
257 end
258 deprecate_class! :DeprecationSpecOldClass => klass
259 klass2 = Class.new do
260 def bar
261 "bar"
262 end
263 end
264 deprecate_class! :DeprecationSpecOldClass2 => klass2
265 stub_stderr(:DeprecationSpecOldClass)
266 ::DeprecationSpecOldClass.new.foo.should == "foo"
267 stub_stderr(:DeprecationSpecOldClass2)
268 ::DeprecationSpecOldClass2.new.bar.should == "bar"
269 end
270 end
271 end
Kevin Clarka058d022008-06-24 00:33:00 +0000272
273 it "should work when Object.inherited calls a method on self" do
274 ensure_const_removed :DeprecationSpecOldClass do
275 old_inherited = Object.method(:inherited)
276 begin
277 (class << Object;self;end).class_eval do
278 define_method :inherited do |cls|
279 cls.inspect
280 old_inherited.call(cls)
281 end
282 end
283 klass = Class.new do
284 def foo
285 "foo"
286 end
287 end
288 STDERR.should_receive(:puts).exactly(0).times
289 lambda { deprecate_class! :DeprecationSpecOldClass => klass }.should_not raise_error
290 ensure
291 (class << Object;self;end).class_eval do
292 define_method :inherited, old_inherited
293 end
294 end
295 end
296 end
Kevin Clark03a5fb12008-06-18 01:01:25 +0000297end
298
299describe "deprecate_module!" do
300 it_should_behave_like "deprecation"
301
Kevin Clark8c3e0932008-06-18 01:19:54 +0000302 def stub_stderr_jruby(mod)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000303 return unless defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000304 stub_stderr(mod, nil, caller.first)
305 end
306
307 def stub_stderr_mri(mod, offset=1)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000308 return if defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000309 stub_stderr(mod, offset, caller.first)
310 end
311
312 def stub_stderr(mod, offset=1, called=nil)
Kevin Clarkde7864e2008-06-18 01:02:14 +0000313 STDERR.should_receive(:puts).with("Warning: module #{mod} is deprecated")
Kevin Clark8c3e0932008-06-18 01:19:54 +0000314 if offset
315 line = (called || caller.first)[/\d+$/].to_i + offset
316 STDERR.should_receive(:puts).with(" from #{__FILE__}:#{line}")
317 else
318 STDERR.should_receive(:puts).with(/^ from #{Regexp.escape(__FILE__)}:/)
319 end
Kevin Clark03a5fb12008-06-18 01:01:25 +0000320 end
321
322 it "should create a new global constant that points to the old one" do
323 ensure_const_removed :DeprecationSpecOldModule do
324 mod = Module.new do
325 def self.foo
326 "foo"
327 end
328 end
329 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000330 stub_stderr(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000331 ::DeprecationSpecOldModule.should eql(mod)
332 ::DeprecationSpecOldModule.foo.should == "foo"
333 end
334 end
335
336 it "should create a global constant even from inside a module" do
337 ensure_const_removed :DeprecationSpecOldModule do
338 mod = nil # scoping
339 Module.new do
340 mod = Module.new do
341 def self.foo
342 "foo"
343 end
344 end
345 deprecate_module! :DeprecationSpecOldModule => mod
346 end
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000347 stub_stderr(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000348 ::DeprecationSpecOldModule.should eql(mod)
349 ::DeprecationSpecOldModule.foo.should == "foo"
350 end
351 end
352
353 it "should work for modules that extend themselves" do
354 ensure_const_removed :DeprecationSpecOldModule do
355 mod = Module.new do
356 extend self
357 def foo
358 "foo"
359 end
360 end
361 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000362 stub_stderr(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000363 ::DeprecationSpecOldModule.should eql(mod)
364 ::DeprecationSpecOldModule.foo.should == "foo"
365 end
366 end
367
368 it "should work for modules included in other modules" do
369 ensure_const_removed :DeprecationSpecOldModule do
370 mod = Module.new do
371 def foo
372 "foo"
373 end
374 end
375 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clark8c3e0932008-06-18 01:19:54 +0000376 stub_stderr_jruby(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000377 mod2 = Module.new do
378 class << self
379 include ::DeprecationSpecOldModule
380 end
381 end
Kevin Clark8c3e0932008-06-18 01:19:54 +0000382 stub_stderr_mri(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000383 mod2.foo.should == "foo"
384 end
385 end
386
387 it "should work for modules included in classes" do
388 ensure_const_removed :DeprecationSpecOldModule do
389 mod = Module.new do
390 def foo
391 "foo"
392 end
393 end
394 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clark8c3e0932008-06-18 01:19:54 +0000395 stub_stderr_jruby(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000396 klass = Class.new do
397 include ::DeprecationSpecOldModule
398 end
Kevin Clark8c3e0932008-06-18 01:19:54 +0000399 stub_stderr_mri(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000400 klass.new.foo.should == "foo"
Kevin Clark2a8a7312008-06-18 01:01:07 +0000401 end
402 end
Kevin Clarkde7864e2008-06-18 01:02:14 +0000403
404 it "should not bleed info between deprecations" do
405 ensure_const_removed :DeprecationSpecOldModule do
406 ensure_const_removed :DeprecationSpecOldModule2 do
407 mod = Module.new do
408 def self.foo
409 "foo"
410 end
411 end
412 deprecate_module! :DeprecationSpecOldModule => mod
413 mod2 = Module.new do
414 def self.bar
415 "bar"
416 end
417 end
418 deprecate_module! :DeprecationSpecOldModule2 => mod2
419 stub_stderr(:DeprecationSpecOldModule)
420 ::DeprecationSpecOldModule.foo.should == "foo"
421 stub_stderr(:DeprecationSpecOldModule2)
422 ::DeprecationSpecOldModule2.bar.should == "bar"
423 end
424 end
425 end
Kevin Clark3eca0782008-06-18 00:54:53 +0000426end