diff options
Diffstat (limited to 'spec/ruby/language')
21 files changed, 586 insertions, 79 deletions
diff --git a/spec/ruby/language/README b/spec/ruby/language/README index b9d969ba1e..74eaf58709 100644 --- a/spec/ruby/language/README +++ b/spec/ruby/language/README @@ -6,7 +6,7 @@ execution like 'if' and 'unless', exceptional execution control like 'rescue', etc. There are also literals for the basic "types" like String, Regexp, Array and Fixnum. -Behavorial specifications describe the behavior of concrete entities. Rather +Behavioral specifications describe the behavior of concrete entities. Rather than using concepts of computation to organize these spec files, we use entities of the Ruby language. Consider looking at any syntactic element of a Ruby program. With (almost) no ambiguity, one can identify it as a literal, diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb index 219d61e2bf..733e90211c 100644 --- a/spec/ruby/language/block_spec.rb +++ b/spec/ruby/language/block_spec.rb @@ -687,7 +687,7 @@ describe "Block-local variables" do end.should raise_error(SyntaxError) end - it "need not be preceeded by standard parameters" do + it "need not be preceded by standard parameters" do [1].map {|; foo| foo }.should == [nil] [1].map {|; glark, bar| [glark, bar] }.should == [[nil, nil]] end diff --git a/spec/ruby/language/break_spec.rb b/spec/ruby/language/break_spec.rb index 794eed2dd9..da3c3bd272 100644 --- a/spec/ruby/language/break_spec.rb +++ b/spec/ruby/language/break_spec.rb @@ -63,15 +63,14 @@ describe "The break statement in a captured block" do describe "from another thread" do it "raises a LocalJumpError when getting the value from another thread" do - ScratchPad << :a thread_with_break = Thread.new do - ScratchPad << :b - break :break - ScratchPad << :c + begin + break :break + rescue LocalJumpError => e + e + end end - - lambda { thread_with_break.value }.should raise_error(LocalJumpError) - ScratchPad.recorded.should == [:a, :b] + thread_with_break.value.should be_an_instance_of(LocalJumpError) end end end diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb index cb0e8150bf..25f5d0efc4 100644 --- a/spec/ruby/language/case_spec.rb +++ b/spec/ruby/language/case_spec.rb @@ -379,4 +379,11 @@ describe "The 'case'-construct with no target expression" do :called end.should == :called end + + it "accepts complex expressions within ()" do + case 'a' + when (raise if 2+2 == 3; /a/) + :called + end.should == :called + end end diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb index 354570e5e9..ba4af3d880 100644 --- a/spec/ruby/language/class_spec.rb +++ b/spec/ruby/language/class_spec.rb @@ -88,19 +88,17 @@ describe "A class definition" do end # [Bug #12367] [ruby-core:75446] - ruby_version_is "2.4" do # Until backported - it "raises an error when reopening a class with Object as superclass" do - module ClassSpecs - class SuperclassReopenedObject < A - end - SuperclassReopenedObject.superclass.should == A - - lambda { - class SuperclassReopenedObject < Object - end - }.should raise_error(TypeError, /superclass mismatch/) - SuperclassReopenedObject.superclass.should == A + it "raises an error when reopening a class with Object as superclass" do + module ClassSpecs + class SuperclassReopenedObject < A end + SuperclassReopenedObject.superclass.should == A + + lambda { + class SuperclassReopenedObject < Object + end + }.should raise_error(TypeError, /superclass mismatch/) + SuperclassReopenedObject.superclass.should == A end end diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb index e68ba495be..1d3cecd9c6 100644 --- a/spec/ruby/language/constants_spec.rb +++ b/spec/ruby/language/constants_spec.rb @@ -353,16 +353,27 @@ describe "Constant resolution within methods" do end describe "with ||=" do - it "assignes constant if previously undefined" do + it "assigns a scoped constant if previously undefined" do ConstantSpecs.should_not have_constant(:OpAssignUndefined) - # Literally opening the module is required to avoid content - # re-assignment error module ConstantSpecs OpAssignUndefined ||= 42 end ConstantSpecs::OpAssignUndefined.should == 42 + ConstantSpecs::OpAssignUndefinedOutside ||= 42 + ConstantSpecs::OpAssignUndefinedOutside.should == 42 ConstantSpecs.send(:remove_const, :OpAssignUndefined) + ConstantSpecs.send(:remove_const, :OpAssignUndefinedOutside) end + + it "assigns a global constant if previously undefined" do + OpAssignGlobalUndefined ||= 42 + ::OpAssignGlobalUndefinedExplicitScope ||= 42 + OpAssignGlobalUndefined.should == 42 + ::OpAssignGlobalUndefinedExplicitScope.should == 42 + Object.send :remove_const, :OpAssignGlobalUndefined + Object.send :remove_const, :OpAssignGlobalUndefinedExplicitScope + end + end end diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb index 458c74258f..1247658381 100644 --- a/spec/ruby/language/defined_spec.rb +++ b/spec/ruby/language/defined_spec.rb @@ -725,7 +725,7 @@ describe "The defined? keyword for a top-level constant" do defined?(::DefinedSpecs).should == "constant" end - it "retuns nil if the constant is not defined" do + it "returns nil if the constant is not defined" do defined?(::DefinedSpecsUndefined).should be_nil end diff --git a/spec/ruby/language/ensure_spec.rb b/spec/ruby/language/ensure_spec.rb index 13575fccc5..ae04feb739 100644 --- a/spec/ruby/language/ensure_spec.rb +++ b/spec/ruby/language/ensure_spec.rb @@ -11,7 +11,7 @@ describe "An ensure block inside a begin block" do lambda { begin ScratchPad << :begin - raise "An exception occured!" + raise "An exception occurred!" ensure ScratchPad << :ensure end @@ -25,7 +25,7 @@ describe "An ensure block inside a begin block" do begin begin ScratchPad << :begin - raise "An exception occured!" + raise "An exception occurred!" rescue ScratchPad << :rescue ensure diff --git a/spec/ruby/language/fixtures/binary_symbol.rb b/spec/ruby/language/fixtures/binary_symbol.rb new file mode 100644 index 0000000000..2ddf565820 --- /dev/null +++ b/spec/ruby/language/fixtures/binary_symbol.rb @@ -0,0 +1,4 @@ +# encoding: binary + +p :il_était.to_s.bytes +puts :il_était.encoding.name diff --git a/spec/ruby/language/fixtures/super.rb b/spec/ruby/language/fixtures/super.rb index 4e89d59bed..09a454bdf4 100644 --- a/spec/ruby/language/fixtures/super.rb +++ b/spec/ruby/language/fixtures/super.rb @@ -478,20 +478,129 @@ module Super end end - module KeywordArguments - class A + module Keywords + class Arguments def foo(**args) args end end - class B < A - def foo(**) + # ---- + + class RequiredArguments < Arguments + def foo(a:) super end end - class C < A + class OptionalArguments < Arguments + def foo(b: 'b') + super + end + end + + class PlaceholderArguments < Arguments + def foo(**args) + super + end + end + + # ---- + + class RequiredAndOptionalArguments < Arguments + def foo(a:, b: 'b') + super + end + end + + class RequiredAndPlaceholderArguments < Arguments + def foo(a:, **args) + super + end + end + + class OptionalAndPlaceholderArguments < Arguments + def foo(b: 'b', **args) + super + end + end + + # ---- + + class RequiredAndOptionalAndPlaceholderArguments < Arguments + def foo(a:, b: 'b', **args) + super + end + end + end + + module RegularAndKeywords + class Arguments + def foo(a, **options) + [a, options] + end + end + + # ----- + + class RequiredArguments < Arguments + def foo(a, b:) + super + end + end + + class OptionalArguments < Arguments + def foo(a, c: 'c') + super + end + end + + class PlaceholderArguments < Arguments + def foo(a, **options) + super + end + end + + # ----- + + class RequiredAndOptionalArguments < Arguments + def foo(a, b:, c: 'c') + super + end + end + + class RequiredAndPlaceholderArguments < Arguments + def foo(a, b:, **options) + super + end + end + + class OptionalAndPlaceholderArguments < Arguments + def foo(a, c: 'c', **options) + super + end + end + + # ----- + + class RequiredAndOptionalAndPlaceholderArguments < Arguments + def foo(a, b:, c: 'c', **options) + super + end + end + end + + module SplatAndKeywords + class Arguments + def foo(*args, **options) + [args, options] + end + end + + class AllArguments < Arguments + def foo(*args, **options) + super + end end end @@ -552,18 +661,4 @@ module Super end end end - - module SplatAndKeyword - class A - def foo(*args, **options) - [args, options] - end - end - - class B < A - def foo(*args, **options) - super - end - end - end end diff --git a/spec/ruby/language/if_spec.rb b/spec/ruby/language/if_spec.rb index bd4fdcae81..284d852462 100644 --- a/spec/ruby/language/if_spec.rb +++ b/spec/ruby/language/if_spec.rb @@ -1,6 +1,25 @@ require File.expand_path('../../spec_helper', __FILE__) describe "The if expression" do + ruby_version_is '2.4' do + describe "accepts multiple assignments in conditional expression" do + before(:each) { ScratchPad.record([]) } + after(:each) { ScratchPad.clear } + + it 'with non-nil values' do + ary = [1, 2] + eval "if (a, b = ary); ScratchPad.record [a, b]; end" + ScratchPad.recorded.should == [1, 2] + end + + it 'with nil values' do + ary = nil + eval "if (a, b = ary); else; ScratchPad.record [a, b]; end" + ScratchPad.recorded.should == [nil, nil] + end + end + end + it "evaluates body if expression is true" do a = [] if true diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb index c92a8ee51b..ca939dbab6 100644 --- a/spec/ruby/language/method_spec.rb +++ b/spec/ruby/language/method_spec.rb @@ -1178,7 +1178,7 @@ describe "A method" do end evaluate <<-ruby do - def m a, b=1, *c, d, e:, f: 2, g:, **k, &l + def m(a, b=1, *c, d, e:, f: 2, g:, **k, &l) [a, b, c, d, e, f, g, k, l] end ruby @@ -1188,13 +1188,19 @@ describe "A method" do end evaluate <<-ruby do - def m (a, b = nil, c = nil, d, e: nil, **f) + def m(a, b = nil, c = nil, d, e: nil, **f) [a, b, c, d, e, f] end ruby result = m(1, 2) result.should == [1, nil, nil, 2, nil, {}] + + result = m(1, 2, {foo: :bar}) + result.should == [1, nil, nil, 2, nil, {foo: :bar}] + + result = m(1, {foo: :bar}) + result.should == [1, nil, nil, {foo: :bar}, nil, {}] end end end diff --git a/spec/ruby/language/optional_assignments_spec.rb b/spec/ruby/language/optional_assignments_spec.rb index c104d08253..0ab28985ed 100644 --- a/spec/ruby/language/optional_assignments_spec.rb +++ b/spec/ruby/language/optional_assignments_spec.rb @@ -207,7 +207,7 @@ describe 'Optional variable assignments' do Object::A.should == 10 end - it 'with &&= assignments will fail with non-existant constants' do + it 'with &&= assignments will fail with non-existent constants' do lambda { Object::A &&= 10 }.should raise_error(NameError) end @@ -219,7 +219,7 @@ describe 'Optional variable assignments' do Object::A.should == 30 end - it 'with operator assignments will fail with non-existant constants' do + it 'with operator assignments will fail with non-existent constants' do lambda { Object::A += 10 }.should raise_error(NameError) end end diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb index a0930eb214..f827fb2eb5 100644 --- a/spec/ruby/language/predefined_spec.rb +++ b/spec/ruby/language/predefined_spec.rb @@ -879,6 +879,25 @@ describe "Global variable $-d" do end end +describe "Global variable $VERBOSE" do + it "converts truthy values to true" do + [true, 1, 0, [], ""].each do |true_value| + $VERBOSE = true_value + $VERBOSE.should be_true + end + end + + it "allows false" do + $VERBOSE = false + $VERBOSE.should be_false + end + + it "allows nil without coercing to false" do + $VERBOSE = nil + $VERBOSE.should be_nil + end +end + describe :verbose_global_alias, shared: true do before :each do @verbose = $VERBOSE diff --git a/spec/ruby/language/regexp/character_classes_spec.rb b/spec/ruby/language/regexp/character_classes_spec.rb index 74568a0beb..ce66d8e65f 100644 --- a/spec/ruby/language/regexp/character_classes_spec.rb +++ b/spec/ruby/language/regexp/character_classes_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../fixtures/classes', __FILE__) @@ -607,4 +608,26 @@ describe "Regexp with character classes" do it "matches unicode Hangul properties" do "루비(Ruby)".match(/\p{Hangul}+/u).to_a.should == ["루비"] end + + ruby_version_is "2.4" do + it "supports \\X (unicode 9.0 with UTR #51 workarounds)" do + # simple emoji without any fancy modifier or ZWJ + /\X/.match("\u{1F98A}").to_a.should == ["🦊"] + + # skin tone modifier + /\X/.match("\u{1F918}\u{1F3FD}").to_a.should == ["🤘🏽"] + + # emoji joined with ZWJ + /\X/.match("\u{1F3F3}\u{FE0F}\u{200D}\u{1F308}").to_a.should == ["🏳️🌈"] + /\X/.match("\u{1F469}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}").to_a.should == ["👩👩👧👦"] + + # without the ZWJ + /\X+/.match("\u{1F3F3}\u{FE0F}\u{1F308}").to_a.should == ["🏳️🌈"] + /\X+/.match("\u{1F469}\u{1F469}\u{1F467}\u{1F466}").to_a.should == ["👩👩👧👦"] + + # both of the ZWJ combined + /\X+/.match("\u{1F3F3}\u{FE0F}\u{200D}\u{1F308}\u{1F469}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}") + .to_a.should == ["🏳️🌈👩👩👧👦"] + end + end end diff --git a/spec/ruby/language/regexp/modifiers_spec.rb b/spec/ruby/language/regexp/modifiers_spec.rb index 03dec26f3f..a7052a941c 100644 --- a/spec/ruby/language/regexp/modifiers_spec.rb +++ b/spec/ruby/language/regexp/modifiers_spec.rb @@ -39,6 +39,13 @@ describe "Regexps with modifers" do lambda { eval('/foo/a') }.should raise_error(SyntaxError) end + ruby_version_is "2.4" do + it "supports (?~) (absent operator)" do + Regexp.new("(?~foo)").match("hello").to_a.should == ["hello"] + "foo".scan(Regexp.new("(?~foo)")).should == ["fo","o",""] + end + end + it "supports (?imx-imx) (inline modifiers)" do /(?i)foo/.match("FOO").to_a.should == ["FOO"] /foo(?i)/.match("FOO").should be_nil diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb index 66366cd1a0..281bb8fde8 100644 --- a/spec/ruby/language/rescue_spec.rb +++ b/spec/ruby/language/rescue_spec.rb @@ -290,4 +290,11 @@ describe "The rescue keyword" do :expected end.should == :expected end + + ruby_version_is "2.4" do + it "allows 'rescue' in method arguments" do + two = eval '1.+ (raise("Error") rescue 1)' + two.should == 2 + end + end end diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb index 323f74aad3..6a98fa6d12 100644 --- a/spec/ruby/language/return_spec.rb +++ b/spec/ruby/language/return_spec.rb @@ -24,7 +24,14 @@ describe "The return keyword" do describe "in a Thread" do it "raises a LocalJumpError if used to exit a thread" do - lambda { Thread.new { return }.join }.should raise_error(LocalJumpError) + t = Thread.new { + begin + return + rescue LocalJumpError => e + e + end + } + t.value.should be_an_instance_of(LocalJumpError) end end @@ -242,4 +249,218 @@ describe "The return keyword" do ReturnSpecs::MethodWithBlock.new.method2.should == [0, 1, 2] end end + + ruby_version_is '2.4.2' do + describe "at top level" do + before :each do + @filename = tmp("top_return.rb") + ScratchPad.record [] + end + + after do + rm_r @filename + end + + it "stops file execution" do + ruby_exe(<<-END_OF_CODE).should == "before return\n" + puts "before return" + return + + puts "after return" + END_OF_CODE + + $?.exitstatus.should == 0 + end + + describe "within if" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before if" + if true + return + end + + ScratchPad << "after if" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before if"] + end + end + + describe "within while loop" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before while" + while true + return + end + + ScratchPad << "after while" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before while"] + end + end + + describe "within a begin" do + it "is allowed in begin block" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + return + end + + ScratchPad << "after begin" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before begin"] + end + + it "is allowed in ensure block" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + ensure + return + end + + ScratchPad << "after begin" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before begin"] + end + + it "is allowed in rescue block" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + raise + rescue RuntimeError + return + end + + ScratchPad << "after begin" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before begin"] + end + + it "fires ensure block before returning" do + ruby_exe(<<-END_OF_CODE).should == "within ensure\n" + begin + return + ensure + puts "within ensure" + end + + puts "after begin" + END_OF_CODE + end + + ruby_bug "#14061", "2.4"..."2.6" do + it "fires ensure block before returning while loads file" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before begin" + begin + return + ensure + ScratchPad << "within ensure" + end + + ScratchPad << "after begin" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before begin", "within ensure"] + end + end + + it "swallows exception if returns in ensure block" do + File.write(@filename, <<-END_OF_CODE) + begin + raise + ensure + ScratchPad << "before return" + return + end + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before return"] + end + end + + describe "within a block" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before call" + proc { return }.call + + ScratchPad << "after call" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before call"] + end + end + + describe "within a class" do + it "is allowed" do + File.write(@filename, <<-END_OF_CODE) + class A + ScratchPad << "before return" + return + + ScratchPad << "after return" + end + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before return"] + end + end + + describe "file loading" do + it "stops file loading and execution" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before return" + return + ScratchPad << "after return" + END_OF_CODE + + load @filename + ScratchPad.recorded.should == ["before return"] + end + end + + describe "file requiring" do + it "stops file loading and execution" do + File.write(@filename, <<-END_OF_CODE) + ScratchPad << "before return" + return + ScratchPad << "after return" + END_OF_CODE + + require @filename + ScratchPad.recorded.should == ["before return"] + end + end + + describe "return with argument" do + # https://bugs.ruby-lang.org/issues/14062 + it "does not affect exit status" do + ruby_exe(<<-END_OF_CODE).should == "" + return 10 + END_OF_CODE + + $?.exitstatus.should == 0 + end + end + end + end end diff --git a/spec/ruby/language/super_spec.rb b/spec/ruby/language/super_spec.rb index fb7e089fb4..3d3f5d6f74 100644 --- a/spec/ruby/language/super_spec.rb +++ b/spec/ruby/language/super_spec.rb @@ -9,7 +9,7 @@ describe "The super keyword" do Super::S1::B.new.bar([]).should == ["B#bar","A#bar"] end - it "searches the full inheritence chain" do + it "searches the full inheritance chain" do Super::S2::B.new.foo([]).should == ["B#foo","A#baz"] Super::S2::B.new.baz([]).should == ["A#baz"] Super::S2::C.new.foo([]).should == ["B#foo","C#baz","A#baz"] @@ -32,7 +32,7 @@ describe "The super keyword" do Super::MS1::B.new.bar([]).should == ["ModB#bar","ModA#bar"] end - it "searches the full inheritence chain including modules" do + it "searches the full inheritance chain including modules" do Super::MS2::B.new.foo([]).should == ["ModB#foo","A#baz"] Super::MS2::B.new.baz([]).should == ["A#baz"] Super::MS2::C.new.baz([]).should == ["C#baz","A#baz"] @@ -248,35 +248,112 @@ describe "The super keyword" do end describe 'when using keyword arguments' do - it 'passes any given keyword arguments to the parent' do - b = Super::KeywordArguments::B.new - b.foo(:number => 10).should == {:number => 10} + before :each do + @req = Super::Keywords::RequiredArguments.new + @opts = Super::Keywords::OptionalArguments.new + @etc = Super::Keywords::PlaceholderArguments.new + + @req_and_opts = Super::Keywords::RequiredAndOptionalArguments.new + @req_and_etc = Super::Keywords::RequiredAndPlaceholderArguments.new + @opts_and_etc = Super::Keywords::OptionalAndPlaceholderArguments.new + + @req_and_opts_and_etc = Super::Keywords::RequiredAndOptionalAndPlaceholderArguments.new end - it "passes any given keyword arguments including optional and required ones to the parent" do - class Super::KeywordArguments::C - eval <<-RUBY - def foo(a:, b: 'b', **) - super - end - RUBY + it 'does not pass any arguments to the parent when none are given' do + @etc.foo.should == {} + end + + it 'passes only required arguments to the parent when no optional arguments are given' do + [@req, @req_and_etc].each do |obj| + obj.foo(a: 'a').should == {a: 'a'} + end + end + + it 'passes default argument values to the parent' do + [@opts, @opts_and_etc].each do |obj| + obj.foo.should == {b: 'b'} + end + + [@req_and_opts, @opts_and_etc, @req_and_opts_and_etc].each do |obj| + obj.foo(a: 'a').should == {a: 'a', b: 'b'} + end + end + + it 'passes any given arguments including optional keyword arguments to the parent' do + [@etc, @req_and_opts, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj| + obj.foo(a: 'a', b: 'b').should == {a: 'a', b: 'b'} end - c = Super::KeywordArguments::C.new - c.foo(a: 'a', c: 'c').should == {a: 'a', b: 'b', c: 'c'} + [@etc, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj| + obj.foo(a: 'a', b: 'b', c: 'c').should == {a: 'a', b: 'b', c: 'c'} + end end + end - it 'does not pass any keyword arguments to the parent when none are given' do - b = Super::KeywordArguments::B.new - b.foo.should == {} + describe 'when using regular and keyword arguments' do + before :each do + @req = Super::RegularAndKeywords::RequiredArguments.new + @opts = Super::RegularAndKeywords::OptionalArguments.new + @etc = Super::RegularAndKeywords::PlaceholderArguments.new + + @req_and_opts = Super::RegularAndKeywords::RequiredAndOptionalArguments.new + @req_and_etc = Super::RegularAndKeywords::RequiredAndPlaceholderArguments.new + @opts_and_etc = Super::RegularAndKeywords::OptionalAndPlaceholderArguments.new + + @req_and_opts_and_etc = Super::RegularAndKeywords::RequiredAndOptionalAndPlaceholderArguments.new end - describe 'when using splat arguments' do - it 'passes splat arguments and keyword arguments to the parent' do - b = Super::SplatAndKeyword::B.new + it 'passes only required regular arguments to the parent when no optional keyword arguments are given' do + @etc.foo('a').should == ['a', {}] + end - b.foo('bar', baz: true).should == [['bar'], {baz: true}] + it 'passes only required regular and keyword arguments to the parent when no optional keyword arguments are given' do + [@req, @req_and_etc].each do |obj| + obj.foo('a', b: 'b').should == ['a', {b: 'b'}] end end + + it 'passes default argument values to the parent' do + [@opts, @opts_and_etc].each do |obj| + obj.foo('a').should == ['a', {c: 'c'}] + end + + [@req_and_opts, @opts_and_etc, @req_and_opts_and_etc].each do |obj| + obj.foo('a', b: 'b').should == ['a', {b: 'b', c: 'c'}] + end + end + + it 'passes any given regular and keyword arguments including optional keyword arguments to the parent' do + [@etc, @req_and_opts, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj| + obj.foo('a', b: 'b', c: 'c').should == ['a', {b: 'b', c: 'c'}] + end + + [@etc, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj| + obj.foo('a', b: 'b', c: 'c', d: 'd').should == ['a', {b: 'b', c: 'c', d: 'd'}] + end + end + end + + describe 'when using splat and keyword arguments' do + before :each do + @all = Super::SplatAndKeywords::AllArguments.new + end + + it 'does not pass any arguments to the parent when none are given' do + @all.foo.should == [[], {}] + end + + it 'passes only splat arguments to the parent when no keyword arguments are given' do + @all.foo('a').should == [['a'], {}] + end + + it 'passes only keyword arguments to the parent when no splat arguments are given' do + @all.foo(b: 'b').should == [[], {b: 'b'}] + end + + it 'passes any given splat and keyword arguments to the parent' do + @all.foo('a', b: 'b').should == [['a'], {b: 'b'}] + end end end diff --git a/spec/ruby/language/symbol_spec.rb b/spec/ruby/language/symbol_spec.rb index 41be5b2236..90540f7d1d 100644 --- a/spec/ruby/language/symbol_spec.rb +++ b/spec/ruby/language/symbol_spec.rb @@ -36,6 +36,11 @@ describe "A Symbol literal" do } end + it 'inherits the encoding of the magic comment and can have a binary encoding' do + ruby_exe(fixture(__FILE__, "binary_symbol.rb")) + .should == "[105, 108, 95, 195, 169, 116, 97, 105, 116]\nASCII-8BIT\n" + end + it "may contain '::' in the string" do :'Some::Class'.should be_kind_of(Symbol) end @@ -90,4 +95,12 @@ describe "A Symbol literal" do it "can be created from list syntax %I{a b c} with interpolation" do %I{a b #{"c"}}.should == [:a, :b, :c] end + + it "with invalid bytes raises an EncodingError at parse time" do + ScratchPad.record [] + -> { + eval 'ScratchPad << 1; :"\xC3"' + }.should raise_error(EncodingError, /invalid/) + ScratchPad.recorded.should == [] + end end diff --git a/spec/ruby/language/throw_spec.rb b/spec/ruby/language/throw_spec.rb index d78c137708..92f699350c 100644 --- a/spec/ruby/language/throw_spec.rb +++ b/spec/ruby/language/throw_spec.rb @@ -68,13 +68,14 @@ describe "The throw keyword" do lambda { catch(:different) { throw :test, 5 } }.should raise_error(ArgumentError) end - it "raises an ArgumentError if used to exit a thread" do - lambda { - catch(:what) do - Thread.new { + it "raises an UncaughtThrowError if used to exit a thread" do + catch(:what) do + t = Thread.new { + -> { throw :what - }.join - end - }.should raise_error(ArgumentError) + }.should raise_error(UncaughtThrowError) + } + t.join + end end end |