blob: 77786d81329c06d684f1893d43ebd71a842eed57 [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
Kevin Clark28744ab2008-06-26 18:45:29 +000017 before(:each) do
18 Thrift::DeprecationProxy.reset_deprecation_warnings
19 end
20
Kevin Clark03a5fb12008-06-18 01:01:25 +000021 def ensure_const_removed(name, &block)
22 begin
23 block.call
24 ensure
25 Object.send :remove_const, name if Object.const_defined? name
26 end
27 end
Kevin Clark96cc5162008-06-18 00:56:08 +000028end
29
Kevin Clark3eca0782008-06-18 00:54:53 +000030describe 'deprecate!' do
Kevin Clark96cc5162008-06-18 00:56:08 +000031 it_should_behave_like "deprecation"
32
Kevin Clarkfc964ee2008-06-18 00:57:46 +000033 def stub_stderr(callstr, offset=1)
Kevin Clark3eca0782008-06-18 00:54:53 +000034 STDERR.should_receive(:puts).with("Warning: calling deprecated method #{callstr}")
Kevin Clarkfc964ee2008-06-18 00:57:46 +000035 line = caller.first[/\d+$/].to_i + offset
36 STDERR.should_receive(:puts).with(" from #{__FILE__}:#{line}")
Kevin Clark3eca0782008-06-18 00:54:53 +000037 end
38
39 it "should work for Module methods" do
40 mod = Module.new do
41 class << self
42 def new
43 "new"
44 end
45 deprecate! :old => :new
46 end
47 end
48 stub_stderr "#{mod.inspect}.old"
49 mod.old.should == "new"
50 end
51
52 it "should work with Modules that extend themselves" do
53 mod = Module.new do
54 extend self
55 def new
56 "new"
57 end
58 deprecate! :old => :new
59 end
60 stub_stderr "#{mod.inspect}.old"
61 mod.old.should == "new"
62 end
63
64 it "should work wtih Class methods" do
65 klass = Class.new do
66 class << self
67 def new
68 "new"
69 end
70 deprecate! :old => :new
71 end
72 end
73 stub_stderr "#{klass.inspect}.old"
74 klass.old.should == "new"
75 end
76
77 it "should work with Classes that include Modules" do
78 mod = Module.new do
79 def new
80 "new"
81 end
82 deprecate! :old => :new
83 end
84 klass = Class.new do
85 include mod
86 end
87 stub_stderr "#{klass.inspect}#old"
88 klass.new.old.should == "new"
89 end
90
91 it "should work with instance methods" do
92 klass = Class.new do
93 def new
94 "new"
95 end
96 deprecate! :old => :new
97 end
98 stub_stderr "#{klass.inspect}#old"
99 klass.new.old.should == "new"
100 end
101
102 it "should work with multiple method names" do
103 klass = Class.new do
104 def new1
105 "new 1"
106 end
107 def new2
108 "new 2"
109 end
110 deprecate! :old1 => :new1, :old2 => :new2
111 end
Kevin Clarkfc964ee2008-06-18 00:57:46 +0000112 stub_stderr("#{klass.inspect}#old1", 3).ordered
113 stub_stderr("#{klass.inspect}#old2", 3).ordered
Kevin Clark3eca0782008-06-18 00:54:53 +0000114 inst = klass.new
115 inst.old1.should == "new 1"
116 inst.old2.should == "new 2"
117 end
118
119 it "should only log a message once, even across multiple instances" do
120 klass = Class.new do
121 def new
122 "new"
123 end
124 deprecate! :old => :new
125 end
126 stub_stderr("#{klass.inspect}#old").once
127 klass.new.old.should == "new"
128 klass.new.old.should == "new"
129 end
130
131 it "should pass arguments" do
132 klass = Class.new do
133 def new(a, b)
134 "new: #{a + b}"
135 end
136 deprecate! :old => :new
137 end
138 stub_stderr("#{klass.inspect}#old")
139 klass.new.old(3, 5).should == "new: 8"
140 end
141
142 it "should pass blocks" do
143 klass = Class.new do
144 def new
145 "new #{yield}"
146 end
147 deprecate! :old => :new
148 end
149 stub_stderr("#{klass.inspect}#old")
150 klass.new.old { "block" }.should == "new block"
151 end
152
153 it "should not freeze the definition of the new method" do
154 klass = Class.new do
155 def new
156 "new"
157 end
158 deprecate! :old => :new
159 end
160 klass.send :define_method, :new do
161 "new 2"
162 end
163 stub_stderr("#{klass.inspect}#old")
164 klass.new.old.should == "new 2"
165 end
Kevin Clarkda40e8d2008-06-18 00:58:04 +0000166
167 it "should call the forwarded method in the same context as the original" do
168 klass = Class.new do
169 def myself
170 self
171 end
172 deprecate! :me => :myself
173 end
174 inst = klass.new
175 stub_stderr("#{klass.inspect}#me")
176 inst.me.should eql(inst.myself)
177 end
Kevin Clark3eca0782008-06-18 00:54:53 +0000178end
179
180describe "deprecate_class!" do
Kevin Clark96cc5162008-06-18 00:56:08 +0000181 it_should_behave_like "deprecation"
182
Kevin Clark8c3e0932008-06-18 01:19:54 +0000183 def stub_stderr_jruby(klass)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000184 return unless defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000185 stub_stderr(klass, nil, caller.first)
186 end
187
188 def stub_stderr_mri(klass, offset=1)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000189 return if defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000190 stub_stderr(klass, offset, caller.first)
191 end
192
193 def stub_stderr(klass, offset=1, called=nil)
Kevin Clarkde7864e2008-06-18 01:02:14 +0000194 STDERR.should_receive(:puts).with("Warning: class #{klass} is deprecated")
Kevin Clark8c3e0932008-06-18 01:19:54 +0000195 if offset
196 line = (called || caller.first)[/\d+$/].to_i + offset
197 STDERR.should_receive(:puts).with(" from #{__FILE__}:#{line}")
198 else
199 STDERR.should_receive(:puts).with(/^ from #{Regexp.escape(__FILE__)}:/)
200 end
Kevin Clark2a8a7312008-06-18 01:01:07 +0000201 end
202
Kevin Clark3eca0782008-06-18 00:54:53 +0000203 it "should create a new global constant that points to the old one" do
Kevin Clark03a5fb12008-06-18 01:01:25 +0000204 ensure_const_removed :DeprecationSpecOldClass do
Kevin Clark3eca0782008-06-18 00:54:53 +0000205 klass = Class.new do
206 def foo
207 "foo"
208 end
209 end
210 deprecate_class! :DeprecationSpecOldClass => klass
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000211 stub_stderr(:DeprecationSpecOldClass)
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000212 ::DeprecationSpecOldClass.should eql(klass)
213 ::DeprecationSpecOldClass.new.foo.should == "foo"
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000214 end
215 end
216
217 it "should create a global constant even from inside a module" do
Kevin Clark03a5fb12008-06-18 01:01:25 +0000218 ensure_const_removed :DeprecationSpecOldClass do
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000219 klass = nil #define scoping
Kevin Clark03a5fb12008-06-18 01:01:25 +0000220 Module.new do
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000221 klass = Class.new do
222 def foo
223 "foo"
224 end
225 end
226 deprecate_class! :DeprecationSpecOldClass => klass
227 end
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000228 stub_stderr(:DeprecationSpecOldClass)
Kevin Clarkf5754ac2008-06-18 01:00:12 +0000229 ::DeprecationSpecOldClass.should eql(klass)
230 ::DeprecationSpecOldClass.new.foo.should == "foo"
Kevin Clark3eca0782008-06-18 00:54:53 +0000231 end
232 end
Kevin Clark2a8a7312008-06-18 01:01:07 +0000233
234 it "should not prevent the deprecated class from being a superclass" do
Kevin Clark03a5fb12008-06-18 01:01:25 +0000235 ensure_const_removed :DeprecationSpecOldClass do
Kevin Clark2a8a7312008-06-18 01:01:07 +0000236 klass = Class.new do
237 def foo
238 "foo"
239 end
240 end
241 deprecate_class! :DeprecationSpecOldClass => klass
Kevin Clark8c3e0932008-06-18 01:19:54 +0000242 stub_stderr_jruby(:DeprecationSpecOldClass)
Kevin Clark2a8a7312008-06-18 01:01:07 +0000243 subklass = Class.new(::DeprecationSpecOldClass) do
244 def foo
245 "subclass #{super}"
246 end
247 end
Kevin Clark8c3e0932008-06-18 01:19:54 +0000248 stub_stderr_mri(:DeprecationSpecOldClass)
Kevin Clark2a8a7312008-06-18 01:01:07 +0000249 subklass.superclass.should eql(klass)
250 subklass.new.foo.should == "subclass foo"
Kevin Clark03a5fb12008-06-18 01:01:25 +0000251 end
252 end
Kevin Clarkfc311642008-06-18 01:01:57 +0000253
254 it "should not bleed info between deprecations" do
255 ensure_const_removed :DeprecationSpecOldClass do
256 ensure_const_removed :DeprecationSpecOldClass2 do
257 klass = Class.new do
258 def foo
259 "foo"
260 end
261 end
262 deprecate_class! :DeprecationSpecOldClass => klass
263 klass2 = Class.new do
264 def bar
265 "bar"
266 end
267 end
268 deprecate_class! :DeprecationSpecOldClass2 => klass2
269 stub_stderr(:DeprecationSpecOldClass)
270 ::DeprecationSpecOldClass.new.foo.should == "foo"
271 stub_stderr(:DeprecationSpecOldClass2)
272 ::DeprecationSpecOldClass2.new.bar.should == "bar"
273 end
274 end
275 end
Kevin Clarka058d022008-06-24 00:33:00 +0000276
277 it "should work when Object.inherited calls a method on self" do
278 ensure_const_removed :DeprecationSpecOldClass do
279 old_inherited = Object.method(:inherited)
280 begin
281 (class << Object;self;end).class_eval do
282 define_method :inherited do |cls|
283 cls.inspect
284 old_inherited.call(cls)
285 end
286 end
287 klass = Class.new do
288 def foo
289 "foo"
290 end
291 end
292 STDERR.should_receive(:puts).exactly(0).times
293 lambda { deprecate_class! :DeprecationSpecOldClass => klass }.should_not raise_error
294 ensure
295 (class << Object;self;end).class_eval do
296 define_method :inherited, old_inherited
297 end
298 end
299 end
300 end
Kevin Clark03a5fb12008-06-18 01:01:25 +0000301end
302
303describe "deprecate_module!" do
304 it_should_behave_like "deprecation"
305
Kevin Clark8c3e0932008-06-18 01:19:54 +0000306 def stub_stderr_jruby(mod)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000307 return unless defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000308 stub_stderr(mod, nil, caller.first)
309 end
310
311 def stub_stderr_mri(mod, offset=1)
Kevin Clarkcd72bef2008-06-24 01:05:55 +0000312 return if defined? JRUBY_VERSION
Kevin Clark8c3e0932008-06-18 01:19:54 +0000313 stub_stderr(mod, offset, caller.first)
314 end
315
316 def stub_stderr(mod, offset=1, called=nil)
Kevin Clarkde7864e2008-06-18 01:02:14 +0000317 STDERR.should_receive(:puts).with("Warning: module #{mod} is deprecated")
Kevin Clarkf2e4d102008-06-26 18:45:19 +0000318 source = Regexp.escape(__FILE__) + ":"
Kevin Clark8c3e0932008-06-18 01:19:54 +0000319 if offset
320 line = (called || caller.first)[/\d+$/].to_i + offset
Kevin Clarkf2e4d102008-06-26 18:45:19 +0000321 source += Regexp.escape(line.to_s)
Kevin Clark8c3e0932008-06-18 01:19:54 +0000322 else
Kevin Clarkf2e4d102008-06-26 18:45:19 +0000323 source += "\d+"
Kevin Clark8c3e0932008-06-18 01:19:54 +0000324 end
Kevin Clarkf2e4d102008-06-26 18:45:19 +0000325 STDERR.should_receive(:puts).with(/^ from #{source}(?::in `[^']+')?$/)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000326 end
327
328 it "should create a new global constant that points to the old one" do
329 ensure_const_removed :DeprecationSpecOldModule do
330 mod = Module.new do
331 def self.foo
332 "foo"
333 end
334 end
335 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000336 stub_stderr(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000337 ::DeprecationSpecOldModule.should eql(mod)
338 ::DeprecationSpecOldModule.foo.should == "foo"
339 end
340 end
341
342 it "should create a global constant even from inside a module" do
343 ensure_const_removed :DeprecationSpecOldModule do
344 mod = nil # scoping
345 Module.new do
346 mod = Module.new do
347 def self.foo
348 "foo"
349 end
350 end
351 deprecate_module! :DeprecationSpecOldModule => mod
352 end
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000353 stub_stderr(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000354 ::DeprecationSpecOldModule.should eql(mod)
355 ::DeprecationSpecOldModule.foo.should == "foo"
356 end
357 end
358
359 it "should work for modules that extend themselves" do
360 ensure_const_removed :DeprecationSpecOldModule do
361 mod = Module.new do
362 extend self
363 def foo
364 "foo"
365 end
366 end
367 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clarkeff97fc2008-06-18 01:01:40 +0000368 stub_stderr(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000369 ::DeprecationSpecOldModule.should eql(mod)
370 ::DeprecationSpecOldModule.foo.should == "foo"
371 end
372 end
373
374 it "should work for modules included in other modules" do
375 ensure_const_removed :DeprecationSpecOldModule do
376 mod = Module.new do
377 def foo
378 "foo"
379 end
380 end
381 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clark8c3e0932008-06-18 01:19:54 +0000382 stub_stderr_jruby(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000383 mod2 = Module.new do
384 class << self
385 include ::DeprecationSpecOldModule
386 end
387 end
Kevin Clark8c3e0932008-06-18 01:19:54 +0000388 stub_stderr_mri(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000389 mod2.foo.should == "foo"
390 end
391 end
392
393 it "should work for modules included in classes" do
394 ensure_const_removed :DeprecationSpecOldModule do
395 mod = Module.new do
396 def foo
397 "foo"
398 end
399 end
400 deprecate_module! :DeprecationSpecOldModule => mod
Kevin Clark8c3e0932008-06-18 01:19:54 +0000401 stub_stderr_jruby(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000402 klass = Class.new do
403 include ::DeprecationSpecOldModule
404 end
Kevin Clark8c3e0932008-06-18 01:19:54 +0000405 stub_stderr_mri(:DeprecationSpecOldModule)
Kevin Clark03a5fb12008-06-18 01:01:25 +0000406 klass.new.foo.should == "foo"
Kevin Clark2a8a7312008-06-18 01:01:07 +0000407 end
408 end
Kevin Clarkde7864e2008-06-18 01:02:14 +0000409
410 it "should not bleed info between deprecations" do
411 ensure_const_removed :DeprecationSpecOldModule do
412 ensure_const_removed :DeprecationSpecOldModule2 do
413 mod = Module.new do
414 def self.foo
415 "foo"
416 end
417 end
418 deprecate_module! :DeprecationSpecOldModule => mod
419 mod2 = Module.new do
420 def self.bar
421 "bar"
422 end
423 end
424 deprecate_module! :DeprecationSpecOldModule2 => mod2
425 stub_stderr(:DeprecationSpecOldModule)
426 ::DeprecationSpecOldModule.foo.should == "foo"
427 stub_stderr(:DeprecationSpecOldModule2)
428 ::DeprecationSpecOldModule2.bar.should == "bar"
429 end
430 end
431 end
Kevin Clarkf2e4d102008-06-26 18:45:19 +0000432
433 it "should skip thrift library code when printing caller" do
434 klass = Class.new do
435 include ThriftStruct
436 FIELDS = {
437 1 => {:name => "foo", :type => Thrift::Types::STRING}
438 }
439 end
440 stub_stderr('ThriftStruct')
441 klass.new(:foo => "foo")
442 end
Kevin Clark3eca0782008-06-18 00:54:53 +0000443end