Updated MSpec source to a54f23d0.
[rbx.git] / spec / frozen / 1.8 / language / def_spec.rb
blobdf0261c06defc089f711ae602405d076360bfb06
1 require File.dirname(__FILE__) + '/../spec_helper'
3 # Language-level method behaviour
4 describe "Redefining a method" do
5   it "replaces the original method" do
6     def barfoo; 100; end
7     barfoo.should == 100
9     def barfoo; 200; end
10     barfoo.should == 200
11   end
12 end
14 describe "An instance method definition with a splat" do
15   it "accepts an unnamed '*' argument" do
16     def foo(*); end;
18     foo.should == nil
19     foo(1, 2).should == nil
20     foo(1, 2, 3, 4, :a, :b, 'c', 'd').should == nil
21   end
23   it "accepts a named * argument" do
24     def foo(*a); a; end;
25     foo.should == []
26     foo(1, 2).should == [1, 2]
27     foo([:a]).should == [[:a]]
28   end
30   it "accepts non-* arguments before the * argument" do
31     def foo(a, b, c, d, e, *f); [a, b, c, d, e, f]; end
32     foo(1, 2, 3, 4, 5, 6, 7, 8).should == [1, 2, 3, 4, 5, [6, 7, 8]]
33   end
35   it "creates a method that can be invoked with an inline hash argument" do
36     def foo(a,b,*c); [a,b,c] end
38     foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit', *[789, 'yeah']).
39       should ==
40       ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit'}, [789, 'yeah']]
41   end
43   it "creates a method that can be invoked with an inline hash and a block" do
44     def foo(a,b,*c,&d); [a,b,c,yield(d)] end
46     foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit', *[789, 'yeah']) { 3 }.
47       should ==
48       ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'shit'}, [789, 'yeah'], 3]
50     foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', *[789, 'yeah']) do 3 end.should ==
51       ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes' }, [789, 'yeah'], 3]
53     l = lambda { 3 }
55     foo('abc', 'rbx' => 'cool', 'specs' => 'fail sometimes', *[789, 'yeah'], &l).should ==
56       ['abc', { 'rbx' => 'cool', 'specs' => 'fail sometimes' }, [789, 'yeah'], 3]
57   end
59   it "allows only a single * argument" do
60     lambda { eval 'def foo(a, *b, *c); end' }.should raise_error(SyntaxError)
61   end
63   it "requires the presence of any arguments that precede the *" do
64     def foo(a, b, *c); end
65     lambda { foo 1 }.should raise_error(ArgumentError)
66   end
67 end
69 describe "An instance method with a default argument" do
70   it "evaluates the default when no arguments are passed" do
71     def foo(a = 1)
72       a
73     end
74     foo.should == 1
75     foo(2).should == 2
76   end
78   it "assigns an empty Array to an unused splat argument" do
79     def foo(a = 1, *b)
80       [a,b]
81     end
82     foo.should == [1, []]
83     foo(2).should == [2, []]
84   end
86   it "evaluates the default when required arguments precede it" do
87     def foo(a, b = 2)
88       [a,b]
89     end
90     lambda { foo }.should raise_error(ArgumentError)
91     foo(1).should == [1, 2]
92   end
94   it "prefers to assign to a default argument before a splat argument" do
95     def foo(a, b = 2, *c)
96       [a,b,c]
97     end
98     lambda { foo }.should raise_error(ArgumentError)
99     foo(1).should == [1,2,[]]
100   end
102   it "prefers to assign to a default argument when there are no required arguments" do
103     def foo(a = 1, *args)
104       [a,args]
105     end
106     foo(2,2).should == [2,[2]]
107   end
109   it "does not evaluate the default when passed a value and a * argument" do
110     def foo(a, b = 2, *args)
111       [a,b,args]
112     end
113     foo(2,3,3).should == [2,3,[3]]
114   end
117 describe "A singleton method definition" do
118   it "can be declared for a local variable" do
119     a = "hi"
120     def a.foo
121       5
122     end
123     a.foo.should == 5
124   end
126   it "can be declared for an instance variable" do
127     @a = "hi"
128     def @a.foo
129       6
130     end
131     @a.foo.should == 6
132   end
134   it "can be declared for a global variable" do
135     $__a__ = "hi"
136     def $__a__.foo
137       7
138     end
139     $__a__.foo.should == 7
140   end
142   it "can be declared for a class variable" do
143     @@a = "hi"
144     def @@a.foo
145       8
146     end
147     @@a.foo.should == 8
148   end
150   it "can be declared with an empty method body" do
151     class DefSpec
152       def self.foo;end
153     end
154     DefSpec.foo.should == nil
155   end
158 describe "A method defined with extreme default arguments" do
159   it "can redefine itself when the default is evaluated" do
160     class DefSpecs
161       def foo(x = (def foo; "hello"; end;1));x;end
162     end
164     d = DefSpecs.new
165     d.foo(42).should == 42
166     d.foo.should == 1
167     d.foo.should == 'hello'
168   end
170   it "may use an fcall as a default" do
171     def foo(x = caller())
172       x
173     end
174     foo.shift.class.should == String
175   end
177   it "evaluates the defaults in the method's scope" do
178     def foo(x = ($foo_self = self; nil)); end
179     foo
180     $foo_self.should == self
181   end
183   it "may use preceding arguments as defaults" do
184     def foo(obj, width=obj.length)
185       width
186     end
187     foo('abcde').should == 5
188   end
190   it "may use a lambda as a default" do
191     def foo(output = 'a', prc = lambda {|n| output * n})
192       prc.call(5)
193     end
194     foo.should == 'aaaaa' 
195   end
198 describe "A singleton method defined with extreme default arguments" do
199   it "may use a method definition as a default" do
200     $__a = "hi"
201     def $__a.foo(x = (def $__a.foo; "hello"; end;1));x;end
203     $__a.foo(42).should == 42
204     $__a.foo.should == 1
205     $__a.foo.should == 'hello'
206   end
208   it "may use an fcall as a default" do
209     a = "hi"
210     def a.foo(x = caller())
211       x
212     end
213     a.foo.shift.class.should == String
214   end
216   it "evaluates the defaults in the singleton scope" do
217     a = "hi"
218     def a.foo(x = ($foo_self = self; nil)); 5 ;end
219     a.foo
220     $foo_self.should == a
221   end
223   it "may use preceding arguments as defaults" do
224     a = 'hi'
225     def a.foo(obj, width=obj.length)
226       width
227     end
228     a.foo('abcde').should == 5
229   end
230   
231   it "may use a lambda as a default" do
232     a = 'hi'
233     def a.foo(output = 'a', prc = lambda {|n| output * n})
234       prc.call(5)
235     end
236     a.foo.should == 'aaaaa' 
237   end
240 describe "A method definition inside a metaclass scope" do
241   it "can create a class method" do
242     class DefSpecSingleton
243       class << self
244         def a_class_method;self;end
245       end
246     end
248     DefSpecSingleton.a_class_method.should == DefSpecSingleton
249     lambda { Object.a_class_method }.should raise_error(NoMethodError)
250   end
252   it "can create a singleton method" do
253     obj = Object.new
254     class << obj
255       def a_singleton_method;self;end
256     end
258     obj.a_singleton_method.should == obj
259     lambda { Object.new.a_singleton_method }.should raise_error(NoMethodError)
260   end
263 describe "A nested method definition" do
264   it "creates an instance method when evaluated in an instance method" do
265     class DefSpecNested
266       def create_instance_method
267         def an_instance_method;self;end
268         an_instance_method
269       end
270     end
272     obj = DefSpecNested.new
273     obj.create_instance_method.should == obj
274     obj.an_instance_method.should == obj
276     other = DefSpecNested.new
277     other.an_instance_method.should == other
279     DefSpecNested.instance_methods.should include("an_instance_method")
280   end
282   it "creates a class method when evaluated in a class method" do
283     class DefSpecNested
284       class << self
285         def create_class_method
286           def a_class_method;self;end
287           a_class_method
288         end
289       end
290     end
292     lambda { DefSpecNested.a_class_method }.should raise_error(NoMethodError)
293     DefSpecNested.create_class_method.should == DefSpecNested
294     DefSpecNested.a_class_method.should == DefSpecNested
295     lambda { Object.a_class_method }.should raise_error(NoMethodError)
296     lambda { DefSpecNested.new.a_class_method }.should raise_error(NoMethodError)
297   end
299   it "creates a singleton method when evaluated in the metaclass of an instance" do
300     class DefSpecNested
301       def create_singleton_method
302         class << self
303           def a_singleton_method;self;end
304         end
305         a_singleton_method
306       end
307     end
309     obj = DefSpecNested.new
310     obj.create_singleton_method.should == obj
311     obj.a_singleton_method.should == obj
313     other = DefSpecNested.new
314     lambda { other.a_singleton_method }.should raise_error(NoMethodError)
315   end
318 describe "A method definition inside an instance_eval" do
319   it "creates a singleton method" do
320     obj = Object.new
321     obj.instance_eval do
322       def an_instance_eval_method;self;end
323     end
324     obj.an_instance_eval_method.should == obj
326     other = Object.new
327     lambda { other.an_instance_eval_method }.should raise_error(NoMethodError)
328   end
330   it "creates a singleton method when evaluated inside a metaclass" do
331     obj = Object.new
332     obj.instance_eval do
333       class << self
334         def a_metaclass_eval_method;self;end
335       end
336     end
337     obj.a_metaclass_eval_method.should == obj
339     other = Object.new
340     lambda { other.a_metaclass_eval_method }.should raise_error(NoMethodError)
341   end
343   it "creates a class method when the receiver is a class" do
344     DefSpecNested.instance_eval do
345       def an_instance_eval_class_method;self;end
346     end
348     DefSpecNested.an_instance_eval_class_method.should == DefSpecNested
349     lambda { Object.an_instance_eval_class_method }.should raise_error(NoMethodError)
350   end
353 describe "A method definition in an eval" do
354   it "creates an instance method" do
355     class DefSpecNested
356       def eval_instance_method
357         eval "def an_eval_instance_method;self;end", binding
358         an_eval_instance_method
359       end
360     end
362     obj = DefSpecNested.new
363     obj.eval_instance_method.should == obj
364     obj.an_eval_instance_method.should == obj
366     other = DefSpecNested.new
367     other.an_eval_instance_method.should == other
369     lambda { Object.new.an_eval_instance_method }.should raise_error(NoMethodError)
370   end
372   it "creates a class method" do
373     class DefSpecNestedB
374       class << self
375         def eval_class_method
376           eval "def an_eval_class_method;self;end" #, binding
377           an_eval_class_method
378         end
379       end
380     end
382     DefSpecNestedB.eval_class_method.should == DefSpecNestedB
383     DefSpecNestedB.an_eval_class_method.should == DefSpecNestedB
385     lambda { Object.an_eval_class_method }.should raise_error(NoMethodError)
386     lambda { DefSpecNestedB.new.an_eval_class_method}.should raise_error(NoMethodError)
387   end
389   it "creates a singleton method" do
390     class DefSpecNested
391       def eval_singleton_method
392         class << self
393           eval "def an_eval_singleton_method;self;end", binding
394         end
395         an_eval_singleton_method
396       end
397     end
399     obj = DefSpecNested.new
400     obj.eval_singleton_method.should == obj
401     obj.an_eval_singleton_method.should == obj
403     other = DefSpecNested.new
404     lambda { other.an_eval_singleton_method }.should raise_error(NoMethodError)
405   end