require File.expand_path('../fixtures/send', __FILE__) # Why so many fixed arg tests? JRuby and I assume other Ruby impls have # separate call paths for simple fixed arity methods. Testing up to five # will verify special and generic arity code paths for all impls. # # Method naming conventions: # M - Manditory Args # O - Optional Arg # R - Rest Arg # Q - Post Manditory Args (1.9) specs = LangSendSpecs describe "Invoking a method" do describe "with zero arguments" do it "requires no arguments passed" do specs.fooM0.should == 100 end it "raises ArgumentError if the method has a positive arity" do lambda { specs.fooM1 }.should raise_error(ArgumentError) end end describe "with only manditory arguments" do it "requires exactly the same number of passed values" do specs.fooM1(1).should == [1] specs.fooM2(1,2).should == [1,2] specs.fooM3(1,2,3).should == [1,2,3] specs.fooM4(1,2,3,4).should == [1,2,3,4] specs.fooM5(1,2,3,4,5).should == [1,2,3,4,5] end it "raises ArgumentError if the methods arity doesn't match" do lambda { specs.fooM1(1,2) }.should raise_error(ArgumentError) end end describe "with optional arguments" do it "uses the optional argument if none is is passed" do specs.fooM0O1.should == [1] end it "uses the passed argument if available" do specs.fooM0O1(2).should == [2] end it "raises ArgumentError if extra arguments are passed" do lambda { specs.fooM0O1(2,3) }.should raise_error(ArgumentError) end end describe "with manditory and optional arguments" do it "uses the passed values in left to right order" do specs.fooM1O1(2).should == [2,1] end it "raises an ArgumentError if there are no values for the manditory args" do lambda { specs.fooM1O1 }.should raise_error(ArgumentError) end it "raises an ArgumentError if too many values are passed" do lambda { specs.fooM1O1(1,2,3) }.should raise_error(ArgumentError) end end describe "with a rest argument" do it "is an empty array if there are no additional arguments" do specs.fooM0R().should == [] specs.fooM1R(1).should == [1, []] end it "gathers unused arguments" do specs.fooM0R(1).should == [1] specs.fooM1R(1,2).should == [1, [2]] end end it "with a block makes it available to yield" do specs.oneb(10) { 200 }.should == [10,200] end it "with a block converts the block to a Proc" do prc = specs.makeproc { "hello" } prc.should be_kind_of(Proc) prc.call.should == "hello" end it "with an object as a block uses 'to_proc' for coercion" do o = LangSendSpecs::ToProc.new(:from_to_proc) specs.makeproc(&o).call.should == :from_to_proc specs.yield_now(&o).should == :from_to_proc end it "raises a SyntaxError with both a literal block and an object as block" do lambda { eval "specs.oneb(10, &l){ 42 }" }.should raise_error(SyntaxError) end it "with same names as existing variables is ok" do foobar = 100 def foobar; 200; end foobar.should == 100 foobar().should == 200 end it "with splat operator makes the object the direct arguments" do a = [1,2,3] specs.fooM3(*a).should == [1,2,3] end it "without parentheses works" do (specs.fooM3 1,2,3).should == [1,2,3] end it "with a space separating method name and parenthesis treats expression in parenthesis as first argument" do specs.weird_parens().should == "55" end ruby_version_is "" ... "1.9" do describe "allows []=" do before :each do @obj = LangSendSpecs::AttrSet.new end it "with *args in the [] expanded to individual arguments" do ary = [2,3] (@obj[1, *ary] = 4).should == 4 @obj.result.should == [1,2,3,4] end it "with multiple *args" do ary = [2,3] post = [4,5] (@obj[1, *ary] = *post).should == [4,5] @obj.result.should == [1,2,3,[4,5]] end it "with multiple *args and unwraps the last splat" do ary = [2,3] post = [4] (@obj[1, *ary] = *post).should == 4 @obj.result.should == [1,2,3,4] end it "with a *args and multiple rhs args" do ary = [2,3] (@obj[1, *ary] = 4, 5).should == [4,5] @obj.result.should == [1,2,3,[4,5]] end end end it "passes literal hashes without curly braces as the last parameter" do specs.fooM3('abc', 456, 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'weh').should == \ ['abc', 456, {'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'weh'}] end it "passes a literal hash without curly braces or parens" do (specs.fooM3 'abc', 456, 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'weh').should == \ ['abc', 456, { 'rbx' => 'cool', 'specs' => 'fail sometimes', 'oh' => 'weh'}] end it "allows to literal hashes without curly braces as the only parameter" do specs.fooM1(:rbx => :cool, :specs => :fail_sometimes).should == [{ :rbx => :cool, :specs => :fail_sometimes }] (specs.fooM1 :rbx => :cool, :specs => :fail_sometimes).should == [{ :rbx => :cool, :specs => :fail_sometimes }] end describe "when the method is not available" do it "invokes method_missing" do o = LangSendSpecs::MethodMissing.new o.not_there(1,2) o.message.should == :not_there o.args.should == [1,2] end end end describe "Invoking a private setter method" do describe "permits self as a receiver" do it "for normal assignment" do receiver = LangSendSpecs::PrivateSetter.new receiver.call_self_foo_equals(42) receiver.foo.should == 42 end it "for multiple assignment" do receiver = LangSendSpecs::PrivateSetter.new receiver.call_self_foo_equals_masgn(42) receiver.foo.should == 42 end end end describe "Invoking a private getter method" do it "does not permit self as a receiver" do receiver = LangSendSpecs::PrivateGetter.new lambda { receiver.call_self_foo }.should raise_error(NoMethodError) lambda { receiver.call_self_foo_or_equals(6) }.should raise_error(NoMethodError) end end # language_version __FILE__, "send"