diff options
author | Benoit Daloze <eregontp@gmail.com> | 2020-06-27 15:51:37 +0200 |
---|---|---|
committer | Benoit Daloze <eregontp@gmail.com> | 2020-06-27 15:51:37 +0200 |
commit | b3fa158d1c4d8e03b8dc04f1e4f9940a8a4ef44c (patch) | |
tree | fa8a62d6192c24a21e70aa02589507adfe4e4e6a /spec | |
parent | 64d8c0815e6ab042e8a67a670bda9f34404fa662 (diff) | |
download | ruby-b3fa158d1c4d8e03b8dc04f1e4f9940a8a4ef44c.tar.gz |
Update to ruby/spec@b6b7752
Diffstat (limited to 'spec')
35 files changed, 651 insertions, 55 deletions
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml index 54780ed435..5370d996b8 100644 --- a/spec/ruby/.rubocop.yml +++ b/spec/ruby/.rubocop.yml @@ -15,6 +15,10 @@ Layout/TrailingEmptyLines: Exclude: - library/coverage/fixtures/some_class.rb +Layout/SpaceInLambdaLiteral: + Enabled: true + EnforcedStyle: require_space + Lint: Enabled: true diff --git a/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh b/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh index 0eede2a99f..fd3249f0e5 100644 --- a/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh +++ b/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash -exec somehow this file +echo 'error' && exit 1 #!ruby puts 'success' diff --git a/spec/ruby/core/array/element_set_spec.rb b/spec/ruby/core/array/element_set_spec.rb index 09066d6b54..2e01e838e9 100644 --- a/spec/ruby/core/array/element_set_spec.rb +++ b/spec/ruby/core/array/element_set_spec.rb @@ -323,6 +323,10 @@ describe "Array#[]= with [index, count]" do b = [1, 2, 3, 4, 5] b[10, 0] = [1] a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 1] + + c = [1, 2, 3, 4, 5] + c[10, 0] = [] + c.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil] end it "inserts other section in place defined by idx" do diff --git a/spec/ruby/core/exception/top_level_spec.rb b/spec/ruby/core/exception/top_level_spec.rb new file mode 100644 index 0000000000..96f957411e --- /dev/null +++ b/spec/ruby/core/exception/top_level_spec.rb @@ -0,0 +1,22 @@ +require_relative '../../spec_helper' + +describe "An Exception reaching the top level" do + it "is printed on STDERR" do + ruby_exe('raise "foo"', args: "2>&1").should.include?("in `<main>': foo (RuntimeError)") + end + + describe "with a custom backtrace" do + it "is printed on STDERR" do + code = <<-RUBY + raise RuntimeError, "foo", [ + "/dir/foo.rb:10:in `raising'", + "/dir/bar.rb:20:in `caller'", + ] + RUBY + ruby_exe(code, args: "2>&1").should == <<-EOS +/dir/foo.rb:10:in `raising': foo (RuntimeError) +\tfrom /dir/bar.rb:20:in `caller' + EOS + end + end +end diff --git a/spec/ruby/core/integer/pow_spec.rb b/spec/ruby/core/integer/pow_spec.rb index d7561baf96..4712911095 100644 --- a/spec/ruby/core/integer/pow_spec.rb +++ b/spec/ruby/core/integer/pow_spec.rb @@ -43,5 +43,9 @@ describe "Integer#pow" do it "raises a ZeroDivisionError when the given argument is 0" do -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError) end + + it "raises a RangeError when the first argument is negative and the second argument is present" do + -> { 2.pow(-5, 1) }.should raise_error(RangeError) + end end end diff --git a/spec/ruby/core/io/ungetbyte_spec.rb b/spec/ruby/core/io/ungetbyte_spec.rb index 1971dee534..9d189f8abb 100644 --- a/spec/ruby/core/io/ungetbyte_spec.rb +++ b/spec/ruby/core/io/ungetbyte_spec.rb @@ -66,6 +66,10 @@ describe "IO#ungetbyte" do end end + it "raises IOError on stream not opened for reading" do + -> { STDOUT.ungetbyte(42) }.should raise_error(IOError, "not opened for reading") + end + it "raises an IOError if the IO is closed" do @io.close -> { @io.ungetbyte(42) }.should raise_error(IOError) diff --git a/spec/ruby/core/io/ungetc_spec.rb b/spec/ruby/core/io/ungetc_spec.rb index 85c15b5a71..dc31c3743a 100644 --- a/spec/ruby/core/io/ungetc_spec.rb +++ b/spec/ruby/core/io/ungetc_spec.rb @@ -136,6 +136,10 @@ describe "IO#ungetc" do @io.ungetc(100).should be_nil end + it "raises IOError on stream not opened for reading" do + -> { STDOUT.ungetc(100) }.should raise_error(IOError, "not opened for reading") + end + it "raises IOError on closed stream" do @io.getc @io.close diff --git a/spec/ruby/core/kernel/initialize_copy_spec.rb b/spec/ruby/core/kernel/initialize_copy_spec.rb new file mode 100644 index 0000000000..fe08d184ad --- /dev/null +++ b/spec/ruby/core/kernel/initialize_copy_spec.rb @@ -0,0 +1,29 @@ +require_relative '../../spec_helper' + +describe "Kernel#initialize_copy" do + it "does nothing if the argument is the same as the receiver" do + obj = Object.new + obj.send(:initialize_copy, obj).should.equal?(obj) + obj.freeze + obj.send(:initialize_copy, obj).should.equal?(obj) + 1.send(:initialize_copy, 1).should.equal?(1) + end + + it "raises FrozenError if the receiver is frozen" do + -> { Object.new.freeze.send(:initialize_copy, Object.new) }.should raise_error(FrozenError) + -> { 1.send(:initialize_copy, Object.new) }.should raise_error(FrozenError) + end + + it "raises TypeError if the objects are of different class" do + klass = Class.new + sub = Class.new(klass) + a = klass.new + b = sub.new + message = 'initialize_copy should take same class object' + -> { a.send(:initialize_copy, b) }.should raise_error(TypeError, message) + -> { b.send(:initialize_copy, a) }.should raise_error(TypeError, message) + + -> { a.send(:initialize_copy, 1) }.should raise_error(TypeError, message) + -> { a.send(:initialize_copy, 1.0) }.should raise_error(TypeError, message) + end +end diff --git a/spec/ruby/core/kernel/proc_spec.rb b/spec/ruby/core/kernel/proc_spec.rb index 3930715ebd..7b4493dcc4 100644 --- a/spec/ruby/core/kernel/proc_spec.rb +++ b/spec/ruby/core/kernel/proc_spec.rb @@ -36,27 +36,31 @@ describe "Kernel.proc" do end describe "Kernel#proc" do + def some_method + proc + end + ruby_version_is ""..."2.7" do it "uses the implicit block from an enclosing method" do - def some_method - proc - end - prc = some_method { "hello" } prc.call.should == "hello" end end - ruby_version_is "2.7" ... "2.8" do + ruby_version_is "2.7"..."2.8" do it "can be created when called with no block" do - def some_method - proc - end - -> { some_method { "hello" } }.should complain(/Capturing the given block using Kernel#proc is deprecated/) end end + + ruby_version_is "2.8" do + it "raises an ArgumentError when passed no block" do + -> { + some_method { "hello" } + }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + end + end end diff --git a/spec/ruby/core/kernel/srand_spec.rb b/spec/ruby/core/kernel/srand_spec.rb index 5454aae8cf..0985c76cb0 100644 --- a/spec/ruby/core/kernel/srand_spec.rb +++ b/spec/ruby/core/kernel/srand_spec.rb @@ -11,6 +11,10 @@ describe "Kernel.srand" do srand(20).should == 10 end + it "returns the previous seed value on the first call" do + ruby_exe('p srand(10)', options: '--disable-gems').chomp.should =~ /\A\d+\z/ + end + it "seeds the RNG correctly and repeatably" do srand(10) x = rand diff --git a/spec/ruby/core/module/fixtures/refine.rb b/spec/ruby/core/module/fixtures/refine.rb index 46975361dd..79e2e80197 100644 --- a/spec/ruby/core/module/fixtures/refine.rb +++ b/spec/ruby/core/module/fixtures/refine.rb @@ -10,4 +10,8 @@ module ModuleSpecs module IncludedModule def foo; "foo from included module"; end end + + def self.build_refined_class + Class.new(ClassWithFoo) + end end diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb index 6df4fa4719..ca12d5d13b 100644 --- a/spec/ruby/core/module/refine_spec.rb +++ b/spec/ruby/core/module/refine_spec.rb @@ -87,6 +87,31 @@ describe "Module#refine" do inner_self.public_instance_methods.should include(:blah) end + it "applies refinements to the module" do + refinement = Module.new do + refine(Enumerable) do + def foo? + self.any? ? "yes" : "no" + end + end + end + + foo = Class.new do + using refinement + + def initialize(items) + @items = items + end + + def result + @items.foo? + end + end + + foo.new([]).result.should == "no" + foo.new([1]).result.should == "yes" + end + it "raises ArgumentError if not given a block" do -> do Module.new do @@ -196,8 +221,10 @@ describe "Module#refine" do # * The included modules of C describe "method lookup" do it "looks in the object singleton class first" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -206,7 +233,7 @@ describe "Module#refine" do Module.new do using refinement - obj = ModuleSpecs::ClassWithFoo.new + obj = refined_class.new class << obj def foo; "foo from singleton class"; end end @@ -216,9 +243,66 @@ describe "Module#refine" do result.should == "foo from singleton class" end + it "looks in the included modules for builtin methods" do + result = ruby_exe(<<-RUBY) + a = Module.new do + def /(other) quo(other) end + end + + refinement = Module.new do + refine Integer do + include a + end + end + + result = nil + Module.new do + using refinement + result = 1 / 2 + end + + print result.class + RUBY + + result.should == 'Rational' + end + + it "looks in later included modules of the refined module first" do + a = Module.new do + def foo + "foo from A" + end + end + + include_me_later = Module.new do + def foo + "foo from IncludeMeLater" + end + end + + c = Class.new do + include a + end + + refinement = Module.new do + refine c do; end + end + + result = nil + Module.new do + using refinement + c.include include_me_later + result = c.new.foo + end + + result.should == "foo from IncludeMeLater" + end + it "looks in prepended modules from the refinement first" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do include ModuleSpecs::IncludedModule prepend ModuleSpecs::PrependedModule @@ -229,15 +313,17 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo from prepended module" end it "looks in refinement then" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine(ModuleSpecs::ClassWithFoo) do + refine(refined_class) do include ModuleSpecs::IncludedModule def foo; "foo from refinement"; end @@ -247,15 +333,17 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo from refinement" end it "looks in included modules from the refinement then" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do include ModuleSpecs::IncludedModule end end @@ -263,21 +351,23 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo from included module" end it "looks in the class then" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine(ModuleSpecs::ClassWithFoo) { } + refine(refined_class) { } end result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo" @@ -287,12 +377,14 @@ describe "Module#refine" do # methods in a subclass have priority over refinements in a superclass it "does not override methods in subclasses" do - subclass = Class.new(ModuleSpecs::ClassWithFoo) do + refined_class = ModuleSpecs.build_refined_class + + subclass = Class.new(refined_class) do def foo; "foo from subclass"; end end refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -308,8 +400,10 @@ describe "Module#refine" do context "for methods accessed indirectly" do it "is honored by Kernel#send" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -317,15 +411,17 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.send :foo + result = refined_class.new.send :foo end result.should == "foo from refinement" end it "is honored by BasicObject#__send__" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -333,7 +429,7 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.__send__ :foo + result = refined_class.new.__send__ :foo end result.should == "foo from refinement" @@ -359,8 +455,10 @@ describe "Module#refine" do ruby_version_is "" ... "2.6" do it "is not honored by Kernel#public_send" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -368,7 +466,7 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.public_send :foo + result = refined_class.new.public_send :foo end result.should == "foo" @@ -377,8 +475,10 @@ describe "Module#refine" do ruby_version_is "2.6" do it "is honored by Kernel#public_send" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo; "foo from refinement"; end end end @@ -386,7 +486,7 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.public_send :foo + result = refined_class.new.public_send :foo end result.should == "foo from refinement" @@ -590,8 +690,10 @@ describe "Module#refine" do context "when super is called in a refinement" do it "looks in the included to refinery module" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do include ModuleSpecs::IncludedModule def foo @@ -603,15 +705,17 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo from included module" end it "looks in the refined class" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo super end @@ -621,7 +725,7 @@ describe "Module#refine" do result = nil Module.new do using refinement - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo" @@ -631,8 +735,10 @@ describe "Module#refine" do # class even if there is another refinement which has been activated # in the same context. it "looks in the refined class even if there is another active refinement" do + refined_class = ModuleSpecs.build_refined_class + refinement = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo "foo from refinement" end @@ -640,7 +746,7 @@ describe "Module#refine" do end refinement_with_super = Module.new do - refine ModuleSpecs::ClassWithFoo do + refine refined_class do def foo super end @@ -651,7 +757,7 @@ describe "Module#refine" do Module.new do using refinement using refinement_with_super - result = ModuleSpecs::ClassWithFoo.new.foo + result = refined_class.new.foo end result.should == "foo" diff --git a/spec/ruby/core/proc/new_spec.rb b/spec/ruby/core/proc/new_spec.rb index faaf85fea5..0a6247239f 100644 --- a/spec/ruby/core/proc/new_spec.rb +++ b/spec/ruby/core/proc/new_spec.rb @@ -203,7 +203,7 @@ describe "Proc.new without a block" do end end - ruby_version_is "2.7" ... "2.8" do + ruby_version_is "2.7"..."2.8" do it "can be created if invoked from within a method with a block" do -> { ProcSpecs.new_proc_in_method { "hello" } }.should complain(/Capturing the given block using Proc.new is deprecated/) end @@ -223,4 +223,16 @@ describe "Proc.new without a block" do }.should complain(/Capturing the given block using Proc.new is deprecated/) end end + + ruby_version_is "2.8" do + it "raises an ArgumentError when passed no block" do + def some_method + Proc.new + end + + -> { ProcSpecs.new_proc_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + -> { some_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block') + end + end end diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb index 2bc5f1325c..5fb5cf418d 100644 --- a/spec/ruby/core/proc/parameters_spec.rb +++ b/spec/ruby/core/proc/parameters_spec.rb @@ -57,7 +57,7 @@ describe "Proc#parameters" do end it "sets the first element of each sub-Array to :block for parameters prefixed with ampersands" do - ->&x { }.parameters.first.first.should == :block + -> &x { }.parameters.first.first.should == :block -> x, &y { }.parameters.last.first.should == :block proc {|&x| }.parameters.first.first.should == :block proc {|x,&y| }.parameters.last.first.should == :block @@ -68,7 +68,7 @@ describe "Proc#parameters" do -> x=Math::PI { }.parameters.first.last.should == :x -> an_argument, glark, &foo { }.parameters[1].last.should == :glark -> *rest { }.parameters.first.last.should == :rest - ->&block { }.parameters.first.last.should == :block + -> &block { }.parameters.first.last.should == :block proc {|x| }.parameters.first.last.should == :x proc {|x=Math::PI| }.parameters.first.last.should == :x proc {|an_argument, glark, &foo| }.parameters[1].last.should == :glark diff --git a/spec/ruby/core/proc/shared/call_arguments.rb b/spec/ruby/core/proc/shared/call_arguments.rb index ef6ec04620..91ada3439e 100644 --- a/spec/ruby/core/proc/shared/call_arguments.rb +++ b/spec/ruby/core/proc/shared/call_arguments.rb @@ -1,7 +1,7 @@ describe :proc_call_block_args, shared: true do it "can receive block arguments" do Proc.new {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 - ->&b { b.send(@method)}.send(@method) {1 + 1}.should == 2 + -> &b { b.send(@method)}.send(@method) {1 + 1}.should == 2 proc {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 end diff --git a/spec/ruby/core/symbol/all_symbols_spec.rb b/spec/ruby/core/symbol/all_symbols_spec.rb index ef2b4f85e6..1e21809093 100644 --- a/spec/ruby/core/symbol/all_symbols_spec.rb +++ b/spec/ruby/core/symbol/all_symbols_spec.rb @@ -1,14 +1,19 @@ require_relative '../../spec_helper' describe "Symbol.all_symbols" do - it "returns an array containing all the Symbols in the symbol table" do + it "returns an array of Symbols" do all_symbols = Symbol.all_symbols all_symbols.should be_an_instance_of(Array) - all_symbols.all? { |s| s.is_a?(Symbol) ? true : (p s; false) }.should == true + all_symbols.each { |s| s.should be_an_instance_of(Symbol) } end - it "returns an Array containing Symbols that have been created" do + it "includes symbols that are strongly referenced" do symbol = "symbol_specs_#{rand(5_000_000)}".to_sym Symbol.all_symbols.should include(symbol) end + + it "includes symbols that are referenced in source code but not yet executed" do + Symbol.all_symbols.any? { |s| s.to_s == 'symbol_specs_referenced_in_source_code' }.should be_true + :symbol_specs_referenced_in_source_code + end end diff --git a/spec/ruby/language/fixtures/rescue_captures.rb b/spec/ruby/language/fixtures/rescue_captures.rb new file mode 100644 index 0000000000..69f9b83904 --- /dev/null +++ b/spec/ruby/language/fixtures/rescue_captures.rb @@ -0,0 +1,107 @@ +module RescueSpecs + class Captor + attr_accessor :captured_error + + def self.should_capture_exception + captor = new + captor.capture('some text').should == :caught # Ensure rescue body still runs + captor.captured_error.message.should == 'some text' + end + end + + class ClassVariableCaptor < Captor + def capture(msg) + raise msg + rescue => @@captured_error + :caught + end + + def captured_error + self.class.remove_class_variable(:@@captured_error) + end + end + + class ConstantCaptor < Captor + # Using lambda gets around the dynamic constant assignment warning + CAPTURE = -> msg { + begin + raise msg + rescue => CapturedError + :caught + end + } + + def capture(msg) + CAPTURE.call(msg) + end + + def captured_error + self.class.send(:remove_const, :CapturedError) + end + end + + class GlobalVariableCaptor < Captor + def capture(msg) + raise msg + rescue => $captured_error + :caught + end + + def captured_error + $captured_error.tap do + $captured_error = nil # Can't remove globals, only nil them out + end + end + end + + class InstanceVariableCaptor < Captor + def capture(msg) + raise msg + rescue => @captured_error + :caught + end + end + + class LocalVariableCaptor < Captor + def capture(msg) + raise msg + rescue => captured_error + @captured_error = captured_error + :caught + end + end + + class SafeNavigationSetterCaptor < Captor + def capture(msg) + raise msg + rescue => self&.captured_error + :caught + end + end + + class SetterCaptor < Captor + def capture(msg) + raise msg + rescue => self.captured_error + :caught + end + end + + class SquareBracketsCaptor < Captor + def capture(msg) + @hash = {} + + raise msg + rescue => self[:error] + :caught + end + + def []=(key, value) + @hash[key] = value + end + + def captured_error + @hash[:error] + end + end +end diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb index bc7b8b6606..e31f3032b0 100644 --- a/spec/ruby/language/method_spec.rb +++ b/spec/ruby/language/method_spec.rb @@ -156,6 +156,26 @@ describe "A method send" do -> { m(1, 2, *x) }.should raise_error(TypeError) end end + + context "with a block argument" do + before :all do + def m(x) + if block_given? + [true, yield(x + 'b')] + else + [false] + end + end + end + + it "that refers to a proc passes the proc as the block" do + m('a', &-> y { y + 'c'}).should == [true, 'abc'] + end + + it "that is nil passes no block" do + m('a', &nil).should == [false] + end + end end describe "An element assignment method send" do diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb index 7fa674d009..54cbae1440 100644 --- a/spec/ruby/language/rescue_spec.rb +++ b/spec/ruby/language/rescue_spec.rb @@ -23,11 +23,41 @@ describe "The rescue keyword" do end.should == :caught end - it "can capture the raised exception in a local variable" do - begin - raise SpecificExampleException, "some text" - rescue SpecificExampleException => e - e.message.should == "some text" + describe 'can capture the raised exception' do + before :all do + require_relative 'fixtures/rescue_captures' + end + + it 'in a local variable' do + RescueSpecs::LocalVariableCaptor.should_capture_exception + end + + it 'in a class variable' do + RescueSpecs::ClassVariableCaptor.should_capture_exception + end + + it 'in a constant' do + RescueSpecs::ConstantCaptor.should_capture_exception + end + + it 'in a global variable' do + RescueSpecs::GlobalVariableCaptor.should_capture_exception + end + + it 'in an instance variable' do + RescueSpecs::InstanceVariableCaptor.should_capture_exception + end + + it 'using a safely navigated setter method' do + RescueSpecs::SafeNavigationSetterCaptor.should_capture_exception + end + + it 'using a setter method' do + RescueSpecs::SetterCaptor.should_capture_exception + end + + it 'using a square brackets setter' do + RescueSpecs::SquareBracketsCaptor.should_capture_exception end end diff --git a/spec/ruby/language/super_spec.rb b/spec/ruby/language/super_spec.rb index 66a1ec7592..3e94155bf3 100644 --- a/spec/ruby/language/super_spec.rb +++ b/spec/ruby/language/super_spec.rb @@ -102,6 +102,37 @@ describe "The super keyword" do c2.new.m(:dump) { :value }.should == :value end + it "can pass an explicit block" do + c1 = Class.new do + def m(v) + yield(v) + end + end + c2 = Class.new(c1) do + def m(v) + block = -> w { yield(w + 'b') } + super(v, &block) + end + end + + c2.new.m('a') { |x| x + 'c' }.should == 'abc' + end + + it "can pass no block using &nil" do + c1 = Class.new do + def m(v) + block_given? + end + end + c2 = Class.new(c1) do + def m(v) + super(v, &nil) + end + end + + c2.new.m('a') { raise }.should be_false + end + it "uses block argument given to method when used in a block" do c1 = Class.new do def m diff --git a/spec/ruby/library/rbconfig/rbconfig_spec.rb b/spec/ruby/library/rbconfig/rbconfig_spec.rb index 1aa12df741..c204d5326f 100644 --- a/spec/ruby/library/rbconfig/rbconfig_spec.rb +++ b/spec/ruby/library/rbconfig/rbconfig_spec.rb @@ -28,8 +28,7 @@ describe 'RbConfig::CONFIG' do ruby_exe(<<-RUBY, options: '--enable-frozen-string-literal').should == "Done\n" require 'rbconfig' RbConfig::CONFIG.each do |k, v| - # SDKROOT excluded here to workaround the issue: https://bugs.ruby-lang.org/issues/16738 - if v.frozen? && k != 'SDKROOT' + if v.frozen? puts "\#{k} Failure" end end diff --git a/spec/ruby/library/stringio/getpass_spec.rb b/spec/ruby/library/stringio/getpass_spec.rb new file mode 100644 index 0000000000..60fc64f0c5 --- /dev/null +++ b/spec/ruby/library/stringio/getpass_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require 'stringio' + +# This method is added by io/console on require. +describe "StringIO#getpass" do + require 'io/console' + + it "is defined by io/console" do + StringIO.new("example").should.respond_to?(:getpass) + end +end diff --git a/spec/ruby/library/timeout/timeout_spec.rb b/spec/ruby/library/timeout/timeout_spec.rb index a9a60fdeb9..584b38d8ec 100644 --- a/spec/ruby/library/timeout/timeout_spec.rb +++ b/spec/ruby/library/timeout/timeout_spec.rb @@ -18,6 +18,22 @@ describe "Timeout.timeout" do end.should raise_error(StandardError) end + it "raises specified error type with specified message when it times out" do + -> do + Timeout.timeout(1, StandardError, "foobar") do + sleep + end + end.should raise_error(StandardError, "foobar") + end + + it "raises specified error type with a default message when it times out if message is nil" do + -> do + Timeout.timeout(1, StandardError, nil) do + sleep + end + end.should raise_error(StandardError, "execution expired") + end + it "returns back the last value in the block" do Timeout.timeout(1) do 42 diff --git a/spec/ruby/optional/capi/array_spec.rb b/spec/ruby/optional/capi/array_spec.rb index 1a26c6c585..8d003fb2b1 100644 --- a/spec/ruby/optional/capi/array_spec.rb +++ b/spec/ruby/optional/capi/array_spec.rb @@ -190,6 +190,22 @@ describe "C-API Array function" do end end + describe "rb_ary_sort" do + it "returns a new sorted array" do + a = [2, 1, 3] + @s.rb_ary_sort(a).should == [1, 2, 3] + a.should == [2, 1, 3] + end + end + + describe "rb_ary_sort_bang" do + it "sorts the given array" do + a = [2, 1, 3] + @s.rb_ary_sort_bang(a).should == [1, 2, 3] + a.should == [1, 2, 3] + end + end + describe "rb_ary_store" do it "overwrites the element at the given position" do a = [1, 2, 3] diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb index f550390c22..8e59ee8b1b 100644 --- a/spec/ruby/optional/capi/encoding_spec.rb +++ b/spec/ruby/optional/capi/encoding_spec.rb @@ -82,12 +82,54 @@ describe "C-API Encoding function" do end end + describe "rb_enc_isalnum" do + it "returns non-zero for alpha-numeric characters" do + @s.rb_enc_isalnum("a".ord, Encoding::US_ASCII).should == true + @s.rb_enc_isalnum("2".ord, Encoding::US_ASCII).should == true + @s.rb_enc_isalnum("a".ord, Encoding::UTF_8).should == true + @s.rb_enc_isalnum("2".ord, Encoding::UTF_8).should == true + @s.rb_enc_isalnum("é".encode(Encoding::ISO_8859_1).ord, Encoding::ISO_8859_1).should == true + end + + it "returns zero for non alpha-numeric characters" do + @s.rb_enc_isalnum("-".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isalnum(" ".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isalnum("-".ord, Encoding::UTF_8).should == false + @s.rb_enc_isalnum(" ".ord, Encoding::UTF_8).should == false + end + end + + describe "rb_enc_isspace" do + it "returns non-zero for space characters" do + @s.rb_enc_isspace(" ".ord, Encoding::US_ASCII).should == true + @s.rb_enc_isspace(" ".ord, Encoding::UTF_8).should == true + end + + it "returns zero for non space characters" do + @s.rb_enc_isspace("-".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isspace("A".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isspace("3".ord, Encoding::US_ASCII).should == false + @s.rb_enc_isspace("-".ord, Encoding::UTF_8).should == false + @s.rb_enc_isspace("A".ord, Encoding::UTF_8).should == false + @s.rb_enc_isspace("3".ord, Encoding::UTF_8).should == false + end + end + describe "rb_enc_from_index" do it "returns an Encoding" do @s.rb_enc_from_index(0).should be_an_instance_of(String) end end + describe "rb_enc_mbc_to_codepoint" do + it "returns the correct codepoint for the given character and size" do + @s.rb_enc_mbc_to_codepoint("é", 2).should == 0x00E9 + @s.rb_enc_mbc_to_codepoint("éa", 2).should == 0x00E9 + @s.rb_enc_mbc_to_codepoint("éa", 1).should == 0xC3 + @s.rb_enc_mbc_to_codepoint("éa", 3).should == 0x00E9 + end + end + describe "rb_usascii_encoding" do it "returns the encoding for Encoding::US_ASCII" do @s.rb_usascii_encoding.should == "US-ASCII" diff --git a/spec/ruby/optional/capi/ext/array_spec.c b/spec/ruby/optional/capi/ext/array_spec.c index afd6aeef15..39ed1ed18b 100644 --- a/spec/ruby/optional/capi/ext/array_spec.c +++ b/spec/ruby/optional/capi/ext/array_spec.c @@ -162,6 +162,14 @@ static VALUE array_spec_rb_ary_shift(VALUE self, VALUE array) { return rb_ary_shift(array); } +static VALUE array_spec_rb_ary_sort(VALUE self, VALUE array) { + return rb_ary_sort(array); +} + +static VALUE array_spec_rb_ary_sort_bang(VALUE self, VALUE array) { + return rb_ary_sort_bang(array); +} + static VALUE array_spec_rb_ary_store(VALUE self, VALUE array, VALUE offset, VALUE value) { rb_ary_store(array, FIX2INT(offset), value); @@ -272,6 +280,8 @@ void Init_array_spec(void) { rb_define_method(cls, "rb_ary_reverse", array_spec_rb_ary_reverse, 1); rb_define_method(cls, "rb_ary_rotate", array_spec_rb_ary_rotate, 2); rb_define_method(cls, "rb_ary_shift", array_spec_rb_ary_shift, 1); + rb_define_method(cls, "rb_ary_sort", array_spec_rb_ary_sort, 1); + rb_define_method(cls, "rb_ary_sort_bang", array_spec_rb_ary_sort_bang, 1); rb_define_method(cls, "rb_ary_store", array_spec_rb_ary_store, 3); rb_define_method(cls, "rb_ary_concat", array_spec_rb_ary_concat, 2); rb_define_method(cls, "rb_ary_plus", array_spec_rb_ary_plus, 2); diff --git a/spec/ruby/optional/capi/ext/encoding_spec.c b/spec/ruby/optional/capi/ext/encoding_spec.c index 2ee5c9c824..8935db966e 100644 --- a/spec/ruby/optional/capi/ext/encoding_spec.c +++ b/spec/ruby/optional/capi/ext/encoding_spec.c @@ -106,10 +106,27 @@ static VALUE encoding_spec_rb_enc_find_index(VALUE self, VALUE name) { return INT2NUM(rb_enc_find_index(RSTRING_PTR(name))); } +static VALUE encoding_spec_rb_enc_isalnum(VALUE self, VALUE chr, VALUE encoding) { + rb_encoding *e = rb_to_encoding(encoding); + return rb_enc_isalnum(FIX2INT(chr), e) ? Qtrue : Qfalse; +} + +static VALUE encoding_spec_rb_enc_isspace(VALUE self, VALUE chr, VALUE encoding) { + rb_encoding *e = rb_to_encoding(encoding); + return rb_enc_isspace(FIX2INT(chr), e) ? Qtrue : Qfalse; +} + static VALUE encoding_spec_rb_enc_from_index(VALUE self, VALUE index) { return rb_str_new2(rb_enc_from_index(NUM2INT(index))->name); } +static VALUE encoding_spec_rb_enc_mbc_to_codepoint(VALUE self, VALUE str, VALUE offset) { + int o = FIX2INT(offset); + char *p = RSTRING_PTR(str); + char *e = p + o; + return INT2FIX(rb_enc_mbc_to_codepoint(p, e, rb_enc_get(str))); +} + static VALUE encoding_spec_rb_enc_from_encoding(VALUE self, VALUE name) { return rb_enc_from_encoding(rb_enc_find(RSTRING_PTR(name))); } @@ -284,7 +301,10 @@ void Init_encoding_spec(void) { rb_define_method(cls, "rb_enc_copy", encoding_spec_rb_enc_copy, 2); rb_define_method(cls, "rb_enc_find", encoding_spec_rb_enc_find, 1); rb_define_method(cls, "rb_enc_find_index", encoding_spec_rb_enc_find_index, 1); + rb_define_method(cls, "rb_enc_isalnum", encoding_spec_rb_enc_isalnum, 2); + rb_define_method(cls, "rb_enc_isspace", encoding_spec_rb_enc_isspace, 2); rb_define_method(cls, "rb_enc_from_index", encoding_spec_rb_enc_from_index, 1); + rb_define_method(cls, "rb_enc_mbc_to_codepoint", encoding_spec_rb_enc_mbc_to_codepoint, 2); rb_define_method(cls, "rb_enc_from_encoding", encoding_spec_rb_enc_from_encoding, 1); rb_define_method(cls, "rb_enc_get", encoding_spec_rb_enc_get, 1); rb_define_method(cls, "rb_enc_precise_mbclen", encoding_spec_rb_enc_precise_mbclen, 2); diff --git a/spec/ruby/optional/capi/ext/hash_spec.c b/spec/ruby/optional/capi/ext/hash_spec.c index 36a07d74f6..7f38708915 100644 --- a/spec/ruby/optional/capi/ext/hash_spec.c +++ b/spec/ruby/optional/capi/ext/hash_spec.c @@ -105,6 +105,12 @@ VALUE hash_spec_rb_hash_new(VALUE self) { return rb_hash_new(); } +VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */ + +VALUE hash_spec_rb_ident_hash_new(VALUE self) { + return rb_ident_hash_new(); +} + VALUE hash_spec_rb_hash_size(VALUE self, VALUE hash) { return rb_hash_size(hash); } @@ -143,6 +149,7 @@ void Init_hash_spec(void) { rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3); rb_define_method(cls, "rb_hash_lookup2_default_undef", hash_spec_rb_hash_lookup2_default_undef, 2); rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0); + rb_define_method(cls, "rb_ident_hash_new", hash_spec_rb_ident_hash_new, 0); rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1); rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2); rb_define_method(cls, "compute_a_hash_code", hash_spec_compute_a_hash_code, 1); diff --git a/spec/ruby/optional/capi/ext/integer_spec.c b/spec/ruby/optional/capi/ext/integer_spec.c index 124591e231..5ed1d3fd73 100644 --- a/spec/ruby/optional/capi/ext/integer_spec.c +++ b/spec/ruby/optional/capi/ext/integer_spec.c @@ -13,6 +13,12 @@ static VALUE integer_spec_rb_integer_pack(VALUE self, VALUE value, return INT2FIX(result); } +VALUE rb_int_positive_pow(long x, unsigned long y); /* internal.h, used in ripper */ + +static VALUE integer_spec_rb_int_positive_pow(VALUE self, VALUE a, VALUE b){ + return rb_int_positive_pow(FIX2INT(a), FIX2INT(b)); +} + void Init_integer_spec(void) { VALUE cls = rb_define_class("CApiIntegerSpecs", rb_cObject); rb_define_const(cls, "MSWORD", INT2NUM(INTEGER_PACK_MSWORD_FIRST)); @@ -27,6 +33,7 @@ void Init_integer_spec(void) { rb_define_const(cls, "NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE)); rb_define_method(cls, "rb_integer_pack", integer_spec_rb_integer_pack, 6); + rb_define_method(cls, "rb_int_positive_pow", integer_spec_rb_int_positive_pow, 2); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/regexp_spec.c b/spec/ruby/optional/capi/ext/regexp_spec.c index fc1c8b1e63..58ab079eff 100644 --- a/spec/ruby/optional/capi/ext/regexp_spec.c +++ b/spec/ruby/optional/capi/ext/regexp_spec.c @@ -9,8 +9,10 @@ extern "C" { #endif -VALUE regexp_spec_re(VALUE self) { - return rb_reg_new("a", 1, 0); +VALUE regexp_spec_re(VALUE self, VALUE str, VALUE options) { + char *cstr = StringValueCStr(str); + int opts = FIX2INT(options); + return rb_reg_new(cstr, strlen(cstr), opts); } VALUE regexp_spec_reg_1st_match(VALUE self, VALUE md) { @@ -40,7 +42,7 @@ VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) { void Init_regexp_spec(void) { VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject); rb_define_method(cls, "match", regexp_spec_match, 2); - rb_define_method(cls, "a_re", regexp_spec_re, 0); + rb_define_method(cls, "a_re", regexp_spec_re, 2); rb_define_method(cls, "a_re_1st_match", regexp_spec_reg_1st_match, 1); rb_define_method(cls, "rb_reg_match", regexp_spec_reg_match, 2); rb_define_method(cls, "rb_backref_get", regexp_spec_backref_get, 0); diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c index b6e03f29a5..fb428e5e0f 100644 --- a/spec/ruby/optional/capi/ext/string_spec.c +++ b/spec/ruby/optional/capi/ext/string_spec.c @@ -91,6 +91,12 @@ VALUE string_spec_rb_str_buf_cat(VALUE self, VALUE str) { return str; } +VALUE string_spec_rb_enc_str_buf_cat(VALUE self, VALUE str, VALUE other, VALUE encoding) { + char *cstr = StringValueCStr(other); + rb_encoding* enc = rb_to_encoding(encoding); + return rb_enc_str_buf_cat(str, cstr, strlen(cstr), enc); +} + VALUE string_spec_rb_str_cat(VALUE self, VALUE str) { return rb_str_cat(str, "?", 1); } @@ -432,6 +438,14 @@ static VALUE string_spec_rb_usascii_str_new(VALUE self, VALUE str, VALUE len) { return rb_usascii_str_new(RSTRING_PTR(str), NUM2INT(len)); } +static VALUE string_spec_rb_usascii_str_new_lit(VALUE self) { + return rb_usascii_str_new_lit("nokogiri"); +} + +static VALUE string_spec_rb_usascii_str_new_lit_non_ascii(VALUE self) { + return rb_usascii_str_new_lit("r\u00E9sum\u00E9"); +} + static VALUE string_spec_rb_usascii_str_new_cstr(VALUE self, VALUE str) { return rb_usascii_str_new_cstr(RSTRING_PTR(str)); } @@ -475,6 +489,7 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_str_tmp_new", string_spec_rb_str_tmp_new, 1); rb_define_method(cls, "rb_str_tmp_new_klass", string_spec_rb_str_tmp_new_klass, 1); rb_define_method(cls, "rb_str_buf_cat", string_spec_rb_str_buf_cat, 1); + rb_define_method(cls, "rb_enc_str_buf_cat", string_spec_rb_enc_str_buf_cat, 3); rb_define_method(cls, "rb_str_cat", string_spec_rb_str_cat, 1); rb_define_method(cls, "rb_str_cat2", string_spec_rb_str_cat2, 1); rb_define_method(cls, "rb_str_cat_cstr", string_spec_rb_str_cat_cstr, 2); @@ -539,6 +554,8 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4); rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2); rb_define_method(cls, "rb_usascii_str_new", string_spec_rb_usascii_str_new, 2); + rb_define_method(cls, "rb_usascii_str_new_lit", string_spec_rb_usascii_str_new_lit, 0); + rb_define_method(cls, "rb_usascii_str_new_lit_non_ascii", string_spec_rb_usascii_str_new_lit_non_ascii, 0); rb_define_method(cls, "rb_usascii_str_new_cstr", string_spec_rb_usascii_str_new_cstr, 1); rb_define_method(cls, "rb_String", string_spec_rb_String, 1); rb_define_method(cls, "rb_string_value_cstr", string_spec_rb_string_value_cstr, 1); diff --git a/spec/ruby/optional/capi/hash_spec.rb b/spec/ruby/optional/capi/hash_spec.rb index df2becb2b4..75f1978585 100644 --- a/spec/ruby/optional/capi/hash_spec.rb +++ b/spec/ruby/optional/capi/hash_spec.rb @@ -50,6 +50,14 @@ describe "C-API Hash function" do end end + describe "rb_ident_hash_new" do + it "returns a new compare by identity hash" do + result = @s.rb_ident_hash_new + result.should == {} + result.compare_by_identity?.should == true + end + end + describe "rb_hash_dup" do it "returns a copy of the hash" do hsh = {} diff --git a/spec/ruby/optional/capi/integer_spec.rb b/spec/ruby/optional/capi/integer_spec.rb index 56f7ca3034..e26735824e 100644 --- a/spec/ruby/optional/capi/integer_spec.rb +++ b/spec/ruby/optional/capi/integer_spec.rb @@ -272,4 +272,19 @@ describe "CApiIntegerSpecs" do end end end + + describe "rb_int_positive_pow" do + it "raises an integer to given power" do + @s.rb_int_positive_pow(2, 3).should == 8 + end + + it "raises a negative integer to given power" do + @s.rb_int_positive_pow(-2, 3).should == -8 + @s.rb_int_positive_pow(-2, 4).should == 16 + end + + it "overflows for large inputs" do + @s.rb_int_positive_pow(8, 23).should == 590295810358705651712 + end + end end diff --git a/spec/ruby/optional/capi/regexp_spec.rb b/spec/ruby/optional/capi/regexp_spec.rb index 52aae6bb01..d99935da57 100644 --- a/spec/ruby/optional/capi/regexp_spec.rb +++ b/spec/ruby/optional/capi/regexp_spec.rb @@ -9,12 +9,20 @@ describe "C-API Regexp function" do describe "rb_reg_new" do it "returns a new valid Regexp" do - my_re = @p.a_re + my_re = @p.a_re("a", 0) my_re.kind_of?(Regexp).should == true ('1a' =~ my_re).should == 1 ('1b' =~ my_re).should == nil my_re.source.should == 'a' end + + it "returns a Regexp with the given options" do + @p.a_re("a", 0).options == 0 + @p.a_re("a", Regexp::IGNORECASE).options.should == Regexp::IGNORECASE + @p.a_re("a", Regexp::EXTENDED).options.should == Regexp::EXTENDED + @p.a_re("a", Regexp::EXTENDED | Regexp::IGNORECASE).options.should == Regexp::EXTENDED | Regexp::IGNORECASE + @p.a_re("a", Regexp::MULTILINE).options.should == Regexp::MULTILINE + end end describe "rb_reg_nth_match" do diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb index 35a6fd1c92..7c33b79348 100644 --- a/spec/ruby/optional/capi/string_spec.rb +++ b/spec/ruby/optional/capi/string_spec.rb @@ -218,6 +218,20 @@ describe "C-API String function" do end end + describe "rb_usascii_str_new_lit" do + it "returns a US-ASCII string of the correct characters" do + str = @s.rb_usascii_str_new_lit + str.should == "nokogiri" + str.encoding.should == Encoding::US_ASCII + end + + it "returns US-ASCII string for non-US-ASCII string literal" do + str = @s.rb_usascii_str_new_lit_non_ascii + str.should == "r\xC3\xA9sum\xC3\xA9".force_encoding(Encoding::US_ASCII) + str.encoding.should == Encoding::US_ASCII + end + end + describe "rb_usascii_str_new_cstr" do it "creates a new String with US-ASCII Encoding" do str = "abc".force_encoding("us-ascii") @@ -392,6 +406,16 @@ describe "C-API String function" do end end + describe "rb_enc_str_buf_cat" do + it "concatenates a C string literal to a ruby string with the given encoding" do + input = "hello ".force_encoding(Encoding::US_ASCII) + result = @s.rb_enc_str_buf_cat(input, "résumé", Encoding::UTF_8) + result.should == "hello résumé" + result.encoding.should == Encoding::UTF_8 + result.object_id.should == input.object_id + end + end + describe "rb_str_cmp" do it "returns 0 if two strings are identical" do @s.rb_str_cmp("ppp", "ppp").should == 0 |