diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml index fff542a222..762fe42bad 100644 --- a/spec/ruby/.rubocop.yml +++ b/spec/ruby/.rubocop.yml @@ -32,9 +32,6 @@ Lint/LiteralAsCondition: Lint/UnneededRequireStatement: Enabled: false -Lint/RescueWithoutErrorClass: - Enabled: false - Lint/UnifiedInteger: Enabled: false diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml index 05ce1e9af8..c227ca032d 100644 --- a/spec/ruby/.rubocop_todo.yml +++ b/spec/ruby/.rubocop_todo.yml @@ -1,18 +1,11 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2017-10-09 20:22:01 +0200 using RuboCop version 0.50.0. +# on 2017-12-15 22:14:22 +0900 using RuboCop version 0.52.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 3 -Lint/CircularArgumentReference: - Exclude: - - 'language/block_spec.rb' - - 'language/def_spec.rb' - - 'language/lambda_spec.rb' - # Offense count: 2 Lint/DuplicateCaseCondition: Exclude: @@ -44,15 +37,13 @@ Lint/FloatOutOfRange: Exclude: - 'core/string/modulo_spec.rb' -# Offense count: 43 +# Offense count: 107 Lint/FormatParameterMismatch: Exclude: - - 'core/kernel/sprintf_spec.rb' - - 'core/string/modulo_spec.rb' - 'core/kernel/shared/sprintf.rb' - - 'core/kernel/shared/sprintf_encoding.rb' + - 'core/string/modulo_spec.rb' -# Offense count: 25 +# Offense count: 28 Lint/HandleExceptions: Enabled: false @@ -70,7 +61,7 @@ Lint/IneffectiveAccessModifier: # Offense count: 5 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle. # SupportedStyles: runtime_error, standard_error Lint/InheritException: Exclude: @@ -84,6 +75,7 @@ Lint/LiteralInInterpolation: Exclude: - 'language/defined_spec.rb' - 'language/fixtures/squiggly_heredoc.rb' + - 'core/module/refine_spec.rb' # Offense count: 16 Lint/Loop: @@ -112,7 +104,13 @@ Lint/ParenthesesAsGroupedExpression: - 'language/method_spec.rb' - 'library/socket/socket/getaddrinfo_spec.rb' -# Offense count: 22 +# Offense count: 1 +# Cop supports --auto-correct. +Lint/RedundantWithIndex: + Exclude: + - 'core/enumerator/with_index_spec.rb' + +# Offense count: 24 Lint/RescueException: Exclude: - 'command_line/fixtures/debug_info.rb' @@ -136,6 +134,12 @@ Lint/ScriptPermission: Exclude: - 'command_line/fixtures/bin/launcher.rb' +# Offense count: 2 +# Configuration parameters: IgnoreImplicitReferences. +Lint/ShadowedArgument: + Exclude: + - 'language/fixtures/super.rb' + # Offense count: 10 Lint/ShadowingOuterLocalVariable: Exclude: @@ -156,12 +160,11 @@ Lint/UnderscorePrefixedVariableName: - 'core/io/popen_spec.rb' - 'language/block_spec.rb' -# Offense count: 91 +# Offense count: 90 # Cop supports --auto-correct. Lint/UnneededSplatExpansion: Exclude: - 'core/array/element_reference_spec.rb' - - 'core/array/unshift_spec.rb' - 'core/enumerable/fixtures/classes.rb' - 'core/enumerable/max_by_spec.rb' - 'core/enumerable/min_by_spec.rb' @@ -176,7 +179,7 @@ Lint/UnneededSplatExpansion: - 'language/send_spec.rb' - 'language/variables_spec.rb' -# Offense count: 55 +# Offense count: 54 Lint/UnreachableCode: Exclude: - 'core/enumerator/lazy/fixtures/classes.rb' diff --git a/spec/ruby/.travis.yml b/spec/ruby/.travis.yml index e8a9106ac1..767d437f67 100644 --- a/spec/ruby/.travis.yml +++ b/spec/ruby/.travis.yml @@ -3,7 +3,7 @@ language: ruby install: - git clone https://github.com/ruby/mspec.git ../mspec script: - - if [ -n "$RUBOCOP" ]; then gem install rubocop -v 0.51.0 && rubocop; fi + - if [ -n "$RUBOCOP" ]; then gem install rubocop -v 0.52.0 && rubocop; fi - ../mspec/bin/mspec $MSPEC_OPTS matrix: include: diff --git a/spec/ruby/README.md b/spec/ruby/README.md index 970688a623..9c13ede75c 100644 --- a/spec/ruby/README.md +++ b/spec/ruby/README.md @@ -2,6 +2,7 @@ [![Build Status](https://travis-ci.org/ruby/spec.svg)](https://travis-ci.org/ruby/spec) [![Build Status](https://ci.appveyor.com/api/projects/status/1gs6f399320o44b1?svg=true)](https://ci.appveyor.com/project/eregon/spec-x948i) +[![Gitter](https://badges.gitter.im/ruby/spec.svg)](https://gitter.im/ruby/spec) The Ruby Spec Suite is a test suite for the behavior of the Ruby programming language. diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb new file mode 100644 index 0000000000..a80e685996 --- /dev/null +++ b/spec/ruby/core/dir/children_spec.rb @@ -0,0 +1,72 @@ +# encoding: utf-8 + +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +ruby_version_is "2.5" do + describe "Dir.children" do + before :all do + DirSpecs.create_mock_dirs + end + + before :each do + @internal = Encoding.default_internal + end + + after :all do + DirSpecs.delete_mock_dirs + end + + after :each do + Encoding.default_internal = @internal + end + + it "returns an Array of filenames in an existing directory including dotfiles" do + a = Dir.children(DirSpecs.mock_dir).sort + + a.should == DirSpecs.expected_paths - %w[. ..] + + a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested").sort + a.should == %w|.dotfile.ext directory| + end + + it "calls #to_path on non-String arguments" do + p = mock('path') + p.should_receive(:to_path).and_return(DirSpecs.mock_dir) + Dir.children(p) + end + + it "accepts an options Hash" do + a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").sort + a.should == %w|.dotfile.ext directory| + end + + it "returns children encoded with the filesystem encoding by default" do + # This spec depends on the locale not being US-ASCII because if it is, the + # children that are not ascii_only? will be ASCII-8BIT encoded. + children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort + encoding = Encoding.find("filesystem") + encoding = Encoding::ASCII_8BIT if encoding == Encoding::US_ASCII + platform_is_not :windows do + children.should include("こんにちは.txt".force_encoding(encoding)) + end + children.first.encoding.should equal(Encoding.find("filesystem")) + end + + it "returns children encoded with the specified encoding" do + dir = File.join(DirSpecs.mock_dir, 'special') + children = Dir.children(dir, encoding: "euc-jp").sort + children.first.encoding.should equal(Encoding::EUC_JP) + end + + it "returns children transcoded to the default internal encoding" do + Encoding.default_internal = Encoding::EUC_KR + children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort + children.first.encoding.should equal(Encoding::EUC_KR) + end + + it "raises a SystemCallError if called with a nonexistent diretory" do + lambda { Dir.children DirSpecs.nonexistent }.should raise_error(SystemCallError) + end + end +end diff --git a/spec/ruby/core/dir/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb new file mode 100644 index 0000000000..70f6f63333 --- /dev/null +++ b/spec/ruby/core/dir/each_child_spec.rb @@ -0,0 +1,53 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +ruby_version_is "2.5" do + describe "Dir.each_child" do + before :all do + DirSpecs.create_mock_dirs + end + + after :all do + DirSpecs.delete_mock_dirs + end + + it "yields all names in an existing directory to the provided block" do + a, b = [], [] + + Dir.each_child(DirSpecs.mock_dir) {|f| a << f} + Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested") {|f| b << f} + + a.sort.should == DirSpecs.expected_paths - %w[. ..] + b.sort.should == %w|.dotfile.ext directory| + end + + it "returns nil when successful" do + Dir.each_child(DirSpecs.mock_dir) {|f| f}.should == nil + end + + it "calls #to_path on non-String arguments" do + p = mock('path') + p.should_receive(:to_path).and_return(DirSpecs.mock_dir) + Dir.each_child(p).to_a + end + + it "raises a SystemCallError if passed a nonexistent directory" do + lambda { Dir.each_child(DirSpecs.nonexistent) {} }.should raise_error(SystemCallError) + end + + describe "when no block is given" do + it "returns an Enumerator" do + Dir.each_child(DirSpecs.mock_dir).should be_an_instance_of(Enumerator) + Dir.each_child(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths - %w[. ..] + end + + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + Dir.each_child(DirSpecs.mock_dir).size.should == nil + end + end + end + end + end +end diff --git a/spec/ruby/core/encoding/locale_charmap_spec.rb b/spec/ruby/core/encoding/locale_charmap_spec.rb index 12b93c2562..a9f0cd5ee0 100644 --- a/spec/ruby/core/encoding/locale_charmap_spec.rb +++ b/spec/ruby/core/encoding/locale_charmap_spec.rb @@ -16,7 +16,7 @@ with_feature :encoding do end end - platform_is :freebsd, :darwin do + platform_is :freebsd, :openbsd, :darwin do it "returns a value based on the LC_ALL environment variable" do old_lc_all = ENV['LC_ALL'] ENV['LC_ALL'] = 'C' @@ -25,7 +25,7 @@ with_feature :encoding do end end - platform_is :netbsd, :openbsd do + platform_is :netbsd do it "returns a value based on the LC_ALL environment variable" do old_lc_all = ENV['LC_ALL'] ENV['LC_ALL'] = 'C' diff --git a/spec/ruby/core/enumerable/all_spec.rb b/spec/ruby/core/enumerable/all_spec.rb index bfde584260..9e40315baa 100644 --- a/spec/ruby/core/enumerable/all_spec.rb +++ b/spec/ruby/core/enumerable/all_spec.rb @@ -54,10 +54,20 @@ describe "Enumerable#all?" do end it "gathers whole arrays as elements when each yields multiple" do + # This spec doesn't spec what it says it does multi = EnumerableSpecs::YieldsMultiWithFalse.new multi.all?.should be_true end + ruby_version_is "2.5" do + describe "given a pattern argument" do + # This spec should be replaced by more extensive ones + it "returns true iff all match that pattern" do + @enum.all?(Integer).should == true + @enum2.all?(NilClass).should == false + end + end + end end describe "with block" do @@ -116,6 +126,5 @@ describe "Enumerable#all?" do multi.all? {|e, i| yielded << [e, i] } yielded.should == [[1, 2], [3, 4], [6, 7]] end - end end diff --git a/spec/ruby/core/enumerable/none_spec.rb b/spec/ruby/core/enumerable/none_spec.rb index 0646c13b34..89472d6ee1 100644 --- a/spec/ruby/core/enumerable/none_spec.rb +++ b/spec/ruby/core/enumerable/none_spec.rb @@ -13,9 +13,20 @@ describe "Enumerable#none?" do end it "gathers whole arrays as elements when each yields multiple" do + # This spec doesn't spec what it says it does multi = EnumerableSpecs::YieldsMultiWithFalse.new multi.none?.should be_false end + + ruby_version_is "2.5" do + describe "given a pattern argument" do + # This spec should be replaced by more extensive ones + it "returns true iff none match that pattern" do + EnumerableSpecs::Numerous.new.none?(Float).should == true + [nil, false, true].none?(NilClass).should == false + end + end + end end describe "Enumerable#none? with a block" do diff --git a/spec/ruby/core/enumerable/one_spec.rb b/spec/ruby/core/enumerable/one_spec.rb index 818d4663a4..5f118e3323 100644 --- a/spec/ruby/core/enumerable/one_spec.rb +++ b/spec/ruby/core/enumerable/one_spec.rb @@ -16,6 +16,7 @@ describe "Enumerable#one?" do end it "gathers initial args as elements when each yields multiple" do + # This spec doesn't spec what it says it does multi = EnumerableSpecs::YieldsMulti.new multi.one? {|e| e == 1 }.should be_true end @@ -26,6 +27,16 @@ describe "Enumerable#one?" do multi.one? {|e, i| yielded << [e, i] } yielded.should == [[1, 2], [3, 4]] end + + ruby_version_is "2.5" do + describe "given a pattern argument" do + # This spec should be replaced by more extensive ones + it "returns true iff none match that pattern" do + EnumerableSpecs::Numerous.new.one?(Integer).should == false + [nil, false, true].one?(NilClass).should == true + end + end + end end describe "when not passed a block" do diff --git a/spec/ruby/core/file/chown_spec.rb b/spec/ruby/core/file/chown_spec.rb index a0b46e9e39..6266e12bfd 100644 --- a/spec/ruby/core/file/chown_spec.rb +++ b/spec/ruby/core/file/chown_spec.rb @@ -91,17 +91,17 @@ describe "File#chown" do as_superuser do platform_is :windows do it "does not modify the owner id of the file" do - File.chown 0, nil, @fname - File.stat(@fname).uid.should == 0 - File.chown 501, nil, @fname - File.stat(@fname).uid.should == 0 + @file.chown 0, nil + @file.stat.uid.should == 0 + @file.chown 501, nil + @file.stat.uid.should == 0 end it "does not modify the group id of the file" do - File.chown nil, 0, @fname - File.stat(@fname).gid.should == 0 - File.chown nil, 501, @fname - File.stat(@fname).gid.should == 0 + @file.chown nil, 0 + @file.stat.gid.should == 0 + @file.chown nil, 501 + @file.stat.gid.should == 0 end end diff --git a/spec/ruby/core/file/shared/read.rb b/spec/ruby/core/file/shared/read.rb index 916a6222bf..e37523c244 100644 --- a/spec/ruby/core/file/shared/read.rb +++ b/spec/ruby/core/file/shared/read.rb @@ -1,13 +1,13 @@ require File.expand_path('../../../dir/fixtures/common', __FILE__) describe :file_read_directory, shared: true do - platform_is :darwin, :linux, :windows do + platform_is :darwin, :linux, :openbsd, :windows do it "raises an Errno::EISDIR when passed a path that is a directory" do lambda { @object.send(@method, ".") }.should raise_error(Errno::EISDIR) end end - platform_is :bsd do + platform_is :freebsd, :netbsd do it "does not raises any exception when passed a path that is a directory" do lambda { @object.send(@method, ".") }.should_not raise_error end diff --git a/spec/ruby/core/file/stat/inspect_spec.rb b/spec/ruby/core/file/stat/inspect_spec.rb index dd2ad21da3..ec99ab16a8 100644 --- a/spec/ruby/core/file/stat/inspect_spec.rb +++ b/spec/ruby/core/file/stat/inspect_spec.rb @@ -16,7 +16,7 @@ describe "File::Stat#inspect" do expected = "# 1, 'b' => 2, 'c' => 3, 'd' => 4 } + end + + it "does not prevent conflicts between new keys and old ones" do + @hash.transform_keys!(&:succ) + @hash.should == { e: 1 } + end + + it "partially modifies the contents if we broke from the block" do + @hash.transform_keys! do |v| + break if v == :c + v.succ + end + @hash.should == { c: 1, d: 4 } + end + + it "keeps later pair if new keys conflict" do + @hash.transform_keys! { |_| :a }.should == { a: 4 } + end + + context "when no block is given" do + it "returns a sized Enumerator" do + enumerator = @hash.transform_keys! + enumerator.should be_an_instance_of(Enumerator) + enumerator.size.should == @hash.size + enumerator.each(&:upcase).should == { A: 1, B: 2, C: 3, D: 4 } + end + end + + describe "on frozen instance" do + before :each do + @hash.freeze + end + + it "raises a RuntimeError on an empty hash" do + ->{ {}.freeze.transform_keys!(&:upcase) }.should raise_error(RuntimeError) + end + + it "keeps pairs and raises a RuntimeError" do + ->{ @hash.transform_keys!(&:upcase) }.should raise_error(RuntimeError) + @hash.should == @initial_pairs + end + + context "when no block is given" do + it "does not raise an exception" do + @hash.transform_keys!.should be_an_instance_of(Enumerator) + end + end + end + end +end diff --git a/spec/ruby/core/hash/transform_values_spec.rb b/spec/ruby/core/hash/transform_values_spec.rb index 0c9e43d621..a9098a9f2d 100644 --- a/spec/ruby/core/hash/transform_values_spec.rb +++ b/spec/ruby/core/hash/transform_values_spec.rb @@ -16,6 +16,13 @@ ruby_version_is "2.4" do @hash.transform_values(&:succ).should == { a: 2, b: 3, c: 4 } end + it "makes both hashes to share keys" do + key = [1, 2, 3] + new_hash = { key => 1 }.transform_values(&:succ) + new_hash[key].should == 2 + new_hash.keys[0].should equal(key) + end + context "when no block is given" do it "returns a sized Enumerator" do enumerator = @hash.transform_values @@ -47,7 +54,7 @@ ruby_version_is "2.4" do it "updates self as transformed values with the given block" do @hash.transform_values!(&:succ) - @hash.should == { a: 2, b: 3, c: 4 } + @hash.should == { a: 2, b: 3, c: 4 } end it "partially modifies the contents if we broke from the block" do diff --git a/spec/ruby/core/kernel/autoload_spec.rb b/spec/ruby/core/kernel/autoload_spec.rb index b9715eea66..b2aab5a895 100644 --- a/spec/ruby/core/kernel/autoload_spec.rb +++ b/spec/ruby/core/kernel/autoload_spec.rb @@ -57,7 +57,7 @@ describe "Kernel#autoload" do describe "when Object is frozen" do it "raises a FrozenError before defining the constant" do - ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "FrozenError - nil" + ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "#{frozen_error_class} - nil" end end end diff --git a/spec/ruby/core/module/included_modules_spec.rb b/spec/ruby/core/module/included_modules_spec.rb index 91e1298eef..ff2dc434dd 100644 --- a/spec/ruby/core/module/included_modules_spec.rb +++ b/spec/ruby/core/module/included_modules_spec.rb @@ -4,9 +4,9 @@ require File.expand_path('../fixtures/classes', __FILE__) describe "Module#included_modules" do it "returns a list of modules included in self" do ModuleSpecs.included_modules.should == [] - ModuleSpecs::Child.included_modules.should include(ModuleSpecs::Super, ModuleSpecs::Basic, Kernel) + ModuleSpecs::Child.included_modules.should include(ModuleSpecs::Super, ModuleSpecs::Basic, Kernel) ModuleSpecs::Parent.included_modules.should include(Kernel) ModuleSpecs::Basic.included_modules.should == [] - ModuleSpecs::Super.included_modules.should include(ModuleSpecs::Basic) + ModuleSpecs::Super.included_modules.should include(ModuleSpecs::Basic) end end diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb index b54d83075f..ca7db0c2b6 100644 --- a/spec/ruby/core/module/refine_spec.rb +++ b/spec/ruby/core/module/refine_spec.rb @@ -320,7 +320,7 @@ describe "Module#refine" do result.should == "foo from subclass" end - context "for methods accesses indirectly" do + context "for methods accessed indirectly" do ruby_version_is "" ... "2.4" do it "is not honored by Kernel#send" do refinement = Module.new do @@ -425,6 +425,46 @@ describe "Module#refine" do end end + ruby_version_is "" ... "2.5" do + it "is not honored by string interpolation" do + refinement = Module.new do + refine Integer do + def to_s + "foo" + end + end + end + + result = nil + Module.new do + using refinement + result = "#{1}" + end + + result.should == "1" + end + end + + ruby_version_is "2.5" do + it "is honored by string interpolation" do + refinement = Module.new do + refine Integer do + def to_s + "foo" + end + end + end + + result = nil + Module.new do + using refinement + result = "#{1}" + end + + result.should == "foo" + end + end + it "is honored by Kernel#binding" do refinement = Module.new do refine String do diff --git a/spec/ruby/core/process/setsid_spec.rb b/spec/ruby/core/process/setsid_spec.rb index abb75f8225..5f060ef218 100644 --- a/spec/ruby/core/process/setsid_spec.rb +++ b/spec/ruby/core/process/setsid_spec.rb @@ -22,7 +22,7 @@ describe "Process.setsid" do read2.close pgid_child = Integer(read.gets) read.close - platform_is_not :aix do + platform_is_not :aix, :openbsd do # AIX does not allow Process.getsid(pid) # if pid is in a different session. pgid = Process.getsid(pid) diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb index 330ec8fcd8..9e34713757 100644 --- a/spec/ruby/core/process/spawn_spec.rb +++ b/spec/ruby/core/process/spawn_spec.rb @@ -595,8 +595,10 @@ describe "Process.spawn" do end end - it "raises an Errno::EACCES when passed a directory" do - lambda { Process.spawn File.dirname(__FILE__) }.should raise_error(Errno::EACCES) + it "raises an Errno::EACCES or Errno::EISDIR when passed a directory" do + lambda { Process.spawn File.dirname(__FILE__) }.should raise_error(SystemCallError) { |e| + [Errno::EACCES, Errno::EISDIR].should include(e.class) + } end it "raises an ArgumentError when passed a string key in options" do diff --git a/spec/ruby/core/string/delete_prefix_spec.rb b/spec/ruby/core/string/delete_prefix_spec.rb new file mode 100644 index 0000000000..94d486eace --- /dev/null +++ b/spec/ruby/core/string/delete_prefix_spec.rb @@ -0,0 +1,81 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes.rb', __FILE__) + +ruby_version_is '2.5' do + describe "String#delete_prefix" do + it "returns a copy of the string, with the given prefix removed" do + 'hello'.delete_prefix('hell').should == 'o' + 'hello'.delete_prefix('hello').should == '' + end + + it "returns a copy of the string, when the prefix isn't found" do + s = 'hello' + r = s.delete_prefix('hello!') + r.should_not equal s + r.should == s + r = s.delete_prefix('ell') + r.should_not equal s + r.should == s + r = s.delete_prefix('') + r.should_not equal s + r.should == s + end + + it "taints resulting strings when other is tainted" do + 'hello'.taint.delete_prefix('hell').tainted?.should == true + 'hello'.taint.delete_prefix('').tainted?.should == true + end + + it "doesn't set $~" do + $~ = nil + + 'hello'.delete_prefix('hell') + $~.should == nil + end + + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'hell' + 'hello'.delete_prefix(o).should == 'o' + end + + it "returns a subclass instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_prefix('hell').should be_an_instance_of(StringSpecs::MyString) + end + end + + describe "String#delete_prefix!" do + it "removes the found prefix" do + s = 'hello' + s.delete_prefix!('hell').should equal(s) + s.should == 'o' + end + + it "returns nil if no change is made" do + s = 'hello' + s.delete_prefix!('ell').should == nil + s.delete_prefix!('').should == nil + end + + it "doesn't set $~" do + $~ = nil + + 'hello'.delete_prefix!('hell') + $~.should == nil + end + + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'hell' + 'hello'.delete_prefix!(o).should == 'o' + end + + it "raises a RuntimeError when self is frozen" do + lambda { 'hello'.freeze.delete_prefix!('hell') }.should raise_error(RuntimeError) + lambda { 'hello'.freeze.delete_prefix!('') }.should raise_error(RuntimeError) + lambda { ''.freeze.delete_prefix!('') }.should raise_error(RuntimeError) + end + end +end diff --git a/spec/ruby/core/string/delete_suffix_spec.rb b/spec/ruby/core/string/delete_suffix_spec.rb new file mode 100644 index 0000000000..49689a8da1 --- /dev/null +++ b/spec/ruby/core/string/delete_suffix_spec.rb @@ -0,0 +1,81 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes.rb', __FILE__) + +ruby_version_is '2.5' do + describe "String#delete_suffix" do + it "returns a copy of the string, with the given suffix removed" do + 'hello'.delete_suffix('ello').should == 'h' + 'hello'.delete_suffix('hello').should == '' + end + + it "returns a copy of the string, when the suffix isn't found" do + s = 'hello' + r = s.delete_suffix('!hello') + r.should_not equal s + r.should == s + r = s.delete_suffix('ell') + r.should_not equal s + r.should == s + r = s.delete_suffix('') + r.should_not equal s + r.should == s + end + + it "taints resulting strings when other is tainted" do + 'hello'.taint.delete_suffix('ello').tainted?.should == true + 'hello'.taint.delete_suffix('').tainted?.should == true + end + + it "doesn't set $~" do + $~ = nil + + 'hello'.delete_suffix('ello') + $~.should == nil + end + + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'ello' + 'hello'.delete_suffix(o).should == 'h' + end + + it "returns a subclass instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_suffix('ello').should be_an_instance_of(StringSpecs::MyString) + end + end + + describe "String#delete_suffix!" do + it "removes the found prefix" do + s = 'hello' + s.delete_suffix!('ello').should equal(s) + s.should == 'h' + end + + it "returns nil if no change is made" do + s = 'hello' + s.delete_suffix!('ell').should == nil + s.delete_suffix!('').should == nil + end + + it "doesn't set $~" do + $~ = nil + + 'hello'.delete_suffix!('ello') + $~.should == nil + end + + it "calls to_str on its argument" do + o = mock('x') + o.should_receive(:to_str).and_return 'ello' + 'hello'.delete_suffix!(o).should == 'h' + end + + it "raises a RuntimeError when self is frozen" do + lambda { 'hello'.freeze.delete_suffix!('ello') }.should raise_error(RuntimeError) + lambda { 'hello'.freeze.delete_suffix!('') }.should raise_error(RuntimeError) + lambda { ''.freeze.delete_suffix!('') }.should raise_error(RuntimeError) + end + end +end diff --git a/spec/ruby/core/string/start_with_spec.rb b/spec/ruby/core/string/start_with_spec.rb index b85081037d..1b27fdaed7 100644 --- a/spec/ruby/core/string/start_with_spec.rb +++ b/spec/ruby/core/string/start_with_spec.rb @@ -28,9 +28,9 @@ describe "String#start_with?" do it "ignores arguments not convertible to string" do "hello".start_with?().should be_false - lambda { "hello".start_with?(1) }.should raise_error(TypeError) - lambda { "hello".start_with?(["h"]) }.should raise_error(TypeError) - lambda { "hello".start_with?(1, nil, "h").should }.should raise_error(TypeError) + lambda { "hello".start_with?(1) }.should raise_error(TypeError) + lambda { "hello".start_with?(["h"]) }.should raise_error(TypeError) + lambda { "hello".start_with?(1, nil, "h") }.should raise_error(TypeError) end it "uses only the needed arguments" do diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb index db168ba279..f43e764cb8 100644 --- a/spec/ruby/core/struct/new_spec.rb +++ b/spec/ruby/core/struct/new_spec.rb @@ -60,7 +60,18 @@ describe "Struct.new" do lambda { Struct.new(:animal, nil) }.should raise_error(TypeError) lambda { Struct.new(:animal, true) }.should raise_error(TypeError) lambda { Struct.new(:animal, ['chris', 'evan']) }.should raise_error(TypeError) - lambda { Struct.new(:animal, { name: 'chris' }) }.should raise_error(ArgumentError) + end + + ruby_version_is ""..."2.5" do + it "raises a TypeError if an argument is a Hash" do + lambda { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError) + end + end + + ruby_version_is "2.5" do + it "raises a ArgumentError if passed a Hash with an unknown key" do + lambda { Struct.new(:animal, { name: 'chris' }) }.should raise_error(ArgumentError) + end end it "raises a TypeError if object is not a Symbol" do diff --git a/spec/ruby/core/time/at_spec.rb b/spec/ruby/core/time/at_spec.rb index 40c729316e..6883a8d074 100644 --- a/spec/ruby/core/time/at_spec.rb +++ b/spec/ruby/core/time/at_spec.rb @@ -142,4 +142,60 @@ describe "Time.at" do lambda { Time.at(Time.now, 500000) }.should raise_error(TypeError) end end + + ruby_version_is "2.5" do + describe "passed [Time, Numeric, format]" do + context ":nanosecond format" do + it "traits second argument as nanoseconds" do + Time.at(0, 123456789, :nanosecond).nsec.should == 123456789 + end + end + + context ":nsec format" do + it "traits second argument as nanoseconds" do + Time.at(0, 123456789, :nsec).nsec.should == 123456789 + end + end + + context ":microsecond format" do + it "traits second argument as microseconds" do + Time.at(0, 123456, :microsecond).nsec.should == 123456000 + end + end + + context ":usec format" do + it "traits second argument as microseconds" do + Time.at(0, 123456, :usec).nsec.should == 123456000 + end + end + + context ":millisecond format" do + it "traits second argument as milliseconds" do + Time.at(0, 123, :millisecond).nsec.should == 123000000 + end + end + + context "not supported format" do + it "raises ArgumentError" do + ->() { Time.at(0, 123456, 2) }.should raise_error(ArgumentError) + ->() { Time.at(0, 123456, nil) }.should raise_error(ArgumentError) + ->() { Time.at(0, 123456, :invalid) }.should raise_error(ArgumentError) + end + + it "does not try to convert format to Symbol with #to_sym" do + format = "usec" + format.should_not_receive(:to_sym) + -> () { Time.at(0, 123456, format) }.should raise_error(ArgumentError) + end + end + + it "supports Float second argument" do + Time.at(0, 123456789.500, :nanosecond).nsec.should == 123456789 + Time.at(0, 123456789.500, :nsec).nsec.should == 123456789 + Time.at(0, 123456.500, :microsecond).nsec.should == 123456500 + Time.at(0, 123456.500, :usec).nsec.should == 123456500 + Time.at(0, 123.500, :millisecond).nsec.should == 123500000 + end + end + end end diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb index 45d87ce52f..1f1e254fb8 100644 --- a/spec/ruby/language/constants_spec.rb +++ b/spec/ruby/language/constants_spec.rb @@ -425,6 +425,28 @@ describe "Constant resolution within a singleton class (class << obj)" do end end +describe "top-level constant lookup" do + context "on a class" do + ruby_version_is "" ... "2.5" do + it "searches Object successfully after searching other scopes" do + ->() { + String::Hash.should == Hash + }.should complain(/toplevel constant Hash referenced by/) + end + end + + ruby_version_is "2.5" do + it "does not search Object after searching other scopes" do + ->() { String::Hash }.should raise_error(NameError) + end + end + end + + it "searches Object unsuccessfully when searches on a module" do + ->() { Enumerable::Hash }.should raise_error(NameError) + end +end + describe "Module#private_constant marked constants" do it "remain private even when updated" do diff --git a/spec/ruby/language/ensure_spec.rb b/spec/ruby/language/ensure_spec.rb index ae04feb739..1d99dcf5f2 100644 --- a/spec/ruby/language/ensure_spec.rb +++ b/spec/ruby/language/ensure_spec.rb @@ -7,50 +7,44 @@ describe "An ensure block inside a begin block" do end it "is executed when an exception is raised in it's corresponding begin block" do - begin - lambda { - begin - ScratchPad << :begin - raise "An exception occurred!" - ensure - ScratchPad << :ensure - end - }.should raise_error(RuntimeError) + lambda { + begin + ScratchPad << :begin + raise EnsureSpec::Error + ensure + ScratchPad << :ensure + end + }.should raise_error(EnsureSpec::Error) - ScratchPad.recorded.should == [:begin, :ensure] - end + ScratchPad.recorded.should == [:begin, :ensure] end it "is executed when an exception is raised and rescued in it's corresponding begin block" do begin + ScratchPad << :begin + raise "An exception occurred!" + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + + ScratchPad.recorded.should == [:begin, :rescue, :ensure] + end + + it "is executed even when a symbol is thrown in it's corresponding begin block" do + catch(:symbol) do begin ScratchPad << :begin - raise "An exception occurred!" + throw(:symbol) rescue ScratchPad << :rescue ensure ScratchPad << :ensure end - - ScratchPad.recorded.should == [:begin, :rescue, :ensure] end - end - it "is executed even when a symbol is thrown in it's corresponding begin block" do - begin - catch(:symbol) do - begin - ScratchPad << :begin - throw(:symbol) - rescue - ScratchPad << :rescue - ensure - ScratchPad << :ensure - end - end - - ScratchPad.recorded.should == [:begin, :ensure] - end + ScratchPad.recorded.should == [:begin, :ensure] end it "is executed when nothing is raised or thrown in it's corresponding begin block" do @@ -102,7 +96,7 @@ describe "An ensure block inside a method" do end it "is executed when an exception is raised in the method" do - lambda { @obj.raise_in_method_with_ensure }.should raise_error(RuntimeError) + lambda { @obj.raise_in_method_with_ensure }.should raise_error(EnsureSpec::Error) @obj.executed.should == [:method, :ensure] end @@ -124,3 +118,176 @@ describe "An ensure block inside a method" do @obj.explicit_return_in_method_with_ensure.should == :ensure end end + +describe "An ensure block inside a class" do + before :each do + ScratchPad.record [] + end + + it "is executed when an exception is raised" do + lambda { + eval <<-ruby + class EnsureInClassExample + ScratchPad << :class + raise EnsureSpec::Error + ensure + ScratchPad << :ensure + end + ruby + }.should raise_error(EnsureSpec::Error) + + ScratchPad.recorded.should == [:class, :ensure] + end + + it "is executed when an exception is raised and rescued" do + eval <<-ruby + class EnsureInClassExample + ScratchPad << :class + raise + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + ruby + + ScratchPad.recorded.should == [:class, :rescue, :ensure] + end + + it "is executed even when a symbol is thrown" do + catch(:symbol) do + eval <<-ruby + class EnsureInClassExample + ScratchPad << :class + throw(:symbol) + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + ruby + end + + ScratchPad.recorded.should == [:class, :ensure] + end + + it "is executed when nothing is raised or thrown" do + eval <<-ruby + class EnsureInClassExample + ScratchPad << :class + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + ruby + + ScratchPad.recorded.should == [:class, :ensure] + end + + it "has no return value" do + result = eval <<-ruby + class EnsureInClassExample + :class + ensure + :ensure + end + ruby + + result.should == :class + end +end + +describe "An ensure block inside {} block" do + it "is not allowed" do + lambda { + eval <<-ruby + lambda { + raise + ensure + } + ruby + }.should raise_error(SyntaxError) + end +end + +ruby_version_is "2.5" do + describe "An ensure block inside 'do end' block" do + before :each do + ScratchPad.record [] + end + + it "is executed when an exception is raised in it's corresponding begin block" do + lambda { + eval(<<-ruby).call + lambda do + ScratchPad << :begin + raise EnsureSpec::Error + ensure + ScratchPad << :ensure + end + ruby + }.should raise_error(EnsureSpec::Error) + + ScratchPad.recorded.should == [:begin, :ensure] + end + + it "is executed when an exception is raised and rescued in it's corresponding begin block" do + eval(<<-ruby).call + lambda do + ScratchPad << :begin + raise "An exception occurred!" + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + ruby + + ScratchPad.recorded.should == [:begin, :rescue, :ensure] + end + + it "is executed even when a symbol is thrown in it's corresponding begin block" do + catch(:symbol) do + eval(<<-ruby).call + lambda do + ScratchPad << :begin + throw(:symbol) + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + ruby + end + + ScratchPad.recorded.should == [:begin, :ensure] + end + + it "is executed when nothing is raised or thrown in it's corresponding begin block" do + eval(<<-ruby).call + lambda do + ScratchPad << :begin + rescue + ScratchPad << :rescue + ensure + ScratchPad << :ensure + end + ruby + + ScratchPad.recorded.should == [:begin, :ensure] + end + + it "has no return value" do + result = eval(<<-ruby).call + lambda do + :begin + ensure + :ensure + end + ruby + + result.should == :begin + end + end +end diff --git a/spec/ruby/language/fixtures/ensure.rb b/spec/ruby/language/fixtures/ensure.rb index 0dad7d8401..d1a9da37b8 100644 --- a/spec/ruby/language/fixtures/ensure.rb +++ b/spec/ruby/language/fixtures/ensure.rb @@ -8,7 +8,7 @@ module EnsureSpec def raise_in_method_with_ensure @executed << :method - raise "An Exception" + raise EnsureSpec::Error ensure @executed << :ensure end @@ -70,3 +70,8 @@ module EnsureSpec end end end + +module EnsureSpec + class Error < RuntimeError + end +end diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb index d7042b7973..0dc8894740 100644 --- a/spec/ruby/language/rescue_spec.rb +++ b/spec/ruby/language/rescue_spec.rb @@ -31,6 +31,28 @@ describe "The rescue keyword" do end end + it "returns value from `rescue` if an exception was raised" do + begin + raise + rescue + :caught + end.should == :caught + end + + it "returns value from `else` section if no exceptions were raised" do + result = begin + :begin + rescue + :rescue + else + :else + ensure + :ensure + end + + result.should == :else + end + it "can rescue multiple raised exceptions with a single rescue block" do [lambda{raise ArbitraryException}, lambda{raise SpecificExampleException}].map do |block| begin @@ -94,6 +116,32 @@ describe "The rescue keyword" do end.should raise_error(OtherCustomException) end + it "can rescue different types of exceptions in different ways" do + begin + raise Exception + rescue RuntimeError + rescue StandardError + rescue Exception + ScratchPad << :exception + end + + ScratchPad.recorded.should == [:exception] + end + + it "rescues exception within the first suitable section in order of declaration" do + begin + raise StandardError + rescue RuntimeError + ScratchPad << :runtime_error + rescue StandardError + ScratchPad << :standard_error + rescue Exception + ScratchPad << :exception + end + + ScratchPad.recorded.should == [:standard_error] + end + it "will execute an else block only if no exceptions were raised" do result = begin ScratchPad << :one @@ -147,6 +195,20 @@ describe "The rescue keyword" do ScratchPad.recorded.should == [:one, :else_ran, :ensure_ran, :outside_begin] end + it "will execute an else block even without rescue and ensure" do + lambda { + eval <<-ruby + begin + ScratchPad << :begin + else + ScratchPad << :else + end + ruby + }.should complain(/else without rescue is useless/) + + ScratchPad.recorded.should == [:begin, :else] + end + it "will not execute an else block if an exception was raised" do result = begin ScratchPad << :one @@ -223,14 +285,31 @@ describe "The rescue keyword" do a.should == 'ac' end - it "without classes will not rescue Exception" do - lambda do + context "without rescue expression" do + it "will rescue only StandardError and its subclasses" do begin - raise Exception + raise StandardError rescue - 'Exception wrongly rescued' + ScratchPad << :caught end - end.should raise_error(Exception) + + ScratchPad.recorded.should == [:caught] + end + + it "will not rescue exceptions except StandardError" do + [ Exception.new, NoMemoryError.new, ScriptError.new, SecurityError.new, + SignalException.new('INT'), SystemExit.new, SystemStackError.new + ].each do |exception| + lambda { + begin + raise exception + rescue + ScratchPad << :caught + end + }.should raise_error(exception.class) + end + ScratchPad.recorded.should == [] + end end it "uses === to compare against rescued classes" do @@ -279,7 +358,7 @@ describe "The rescue keyword" do invalid_rescuer = Object.new begin :foo - rescue rescuer + rescue invalid_rescuer end.should == :foo end @@ -291,6 +370,44 @@ describe "The rescue keyword" do end.should == :expected end + it "allows rescue in class" do + eval <<-ruby + class RescueInClassExample + raise SpecificExampleException + rescue SpecificExampleException + ScratchPad << :caught + end + ruby + + ScratchPad.recorded.should == [:caught] + end + + it "does not allow rescue in {} block" do + lambda { + eval <<-ruby + lambda { + raise SpecificExampleException + rescue SpecificExampleException + :caught + } + ruby + }.should raise_error(SyntaxError) + end + + ruby_version_is "2.5" do + it "allows rescue in 'do end' block" do + lambda = eval <<-ruby + lambda do + raise SpecificExampleException + rescue SpecificExampleException + ScratchPad << :caught + end.call + ruby + + ScratchPad.recorded.should == [:caught] + end + end + ruby_version_is ""..."2.4" do it "fails when using 'rescue' in method arguments" do lambda { eval '1.+ (1 rescue 1)' }.should raise_error(SyntaxError) @@ -305,6 +422,31 @@ describe "The rescue keyword" do it "requires the 'rescue' in method arguments to be wrapped in parens" do lambda { eval '1.+(1 rescue 1)' }.should raise_error(SyntaxError) + eval('1.+((1 rescue 1))').should == 2 + end + end + + describe "inline form" do + it "can be inlined" do + a = 1/0 rescue 1 + a.should == 1 + end + + it "doesn't except rescue expression" do + lambda { + eval <<-ruby + a = 1 rescue RuntimeError 2 + ruby + }.should raise_error(SyntaxError) + end + + it "rescues only StandardError and its subclasses" do + a = raise(StandardError) rescue 1 + a.should == 1 + + lambda { + a = raise(Exception) rescue 1 + }.should raise_error(Exception) end end end diff --git a/spec/ruby/library/date/shared/valid_jd.rb b/spec/ruby/library/date/shared/valid_jd.rb index d8a35992b3..bd71f5abba 100644 --- a/spec/ruby/library/date/shared/valid_jd.rb +++ b/spec/ruby/library/date/shared/valid_jd.rb @@ -1,8 +1,8 @@ describe :date_valid_jd?, shared: true do it "returns true if passed any value other than nil" do Date.send(@method, -100).should be_true - Date.send(@method, :number).should be_true - Date.send(@method, Rational(1,2)).should be_true + Date.send(@method, :number).should be_true + Date.send(@method, Rational(1,2)).should be_true end it "returns false if passed nil" do diff --git a/spec/ruby/library/matrix/build_spec.rb b/spec/ruby/library/matrix/build_spec.rb index 29fd72206f..4f80ed2b99 100644 --- a/spec/ruby/library/matrix/build_spec.rb +++ b/spec/ruby/library/matrix/build_spec.rb @@ -24,7 +24,7 @@ describe "Matrix.build" do it "returns an Enumerator is no block is given" do enum = Matrix.build(2, 1) - enum.should be_an_instance_of(Enumerator) + enum.should be_an_instance_of(Enumerator) enum.each{1}.should == Matrix[[1], [1]] end diff --git a/spec/ruby/library/set/case_compare_spec.rb b/spec/ruby/library/set/case_compare_spec.rb new file mode 100644 index 0000000000..f47e4e20c2 --- /dev/null +++ b/spec/ruby/library/set/case_compare_spec.rb @@ -0,0 +1,15 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/include', __FILE__) +require 'set' + +ruby_version_is "2.5" do + describe "Set#===" do + it_behaves_like :set_include, :=== + + it "is an alias for include?" do + set = Set.new + set.method(:===).should == set.method(:include?) + end + end +end + diff --git a/spec/ruby/library/set/inspect_spec.rb b/spec/ruby/library/set/inspect_spec.rb index 8a6c565c2e..ef91b11645 100644 --- a/spec/ruby/library/set/inspect_spec.rb +++ b/spec/ruby/library/set/inspect_spec.rb @@ -1,18 +1,7 @@ require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/inspect', __FILE__) require 'set' describe "Set#inspect" do - it "returns a String representation of self" do - Set[].inspect.should be_kind_of(String) - Set[nil, false, true].inspect.should be_kind_of(String) - Set[1, 2, 3].inspect.should be_kind_of(String) - Set["1", "2", "3"].inspect.should be_kind_of(String) - Set[:a, "b", Set[?c]].inspect.should be_kind_of(String) - end - - it "correctly handles self-references" do - (set = Set[]) << set - set.inspect.should be_kind_of(String) - set.inspect.should include("#") - end + it_behaves_like :set_inspect, :inspect end diff --git a/spec/ruby/library/set/shared/include.rb b/spec/ruby/library/set/shared/include.rb index d41f8f4102..b4d95cde24 100644 --- a/spec/ruby/library/set/shared/include.rb +++ b/spec/ruby/library/set/shared/include.rb @@ -4,4 +4,26 @@ describe :set_include, shared: true do set.send(@method, :a).should be_true set.send(@method, :e).should be_false end + + describe "member equality" do + it "is checked using both #hash and #eql?" do + obj = Object.new + obj_another = Object.new + + def obj.hash; 42 end + def obj_another.hash; 42 end + def obj_another.eql?(o) hash == o.hash end + + set = Set["a", "b", "c", obj] + set.send(@method, obj_another).should == true + end + + it "is not checked using #==" do + obj = Object.new + set = Set["a", "b", "c"] + + obj.should_not_receive(:==) + set.send(@method, obj) + end + end end diff --git a/spec/ruby/library/set/shared/inspect.rb b/spec/ruby/library/set/shared/inspect.rb new file mode 100644 index 0000000000..69fbdd12f6 --- /dev/null +++ b/spec/ruby/library/set/shared/inspect.rb @@ -0,0 +1,15 @@ +describe "set_inspect", shared: true do + it "returns a String representation of self" do + Set[].send(@method).should be_kind_of(String) + Set[nil, false, true].send(@method).should be_kind_of(String) + Set[1, 2, 3].send(@method).should be_kind_of(String) + Set["1", "2", "3"].send(@method).should be_kind_of(String) + Set[:a, "b", Set[?c]].send(@method).should be_kind_of(String) + end + + it "correctly handles self-references" do + (set = Set[]) << set + set.send(@method).should be_kind_of(String) + set.send(@method).should include("#") + end +end diff --git a/spec/ruby/library/set/to_s_spec.rb b/spec/ruby/library/set/to_s_spec.rb new file mode 100644 index 0000000000..f4c361f74f --- /dev/null +++ b/spec/ruby/library/set/to_s_spec.rb @@ -0,0 +1,13 @@ +require File.expand_path('../shared/inspect', __FILE__) +require 'set' + +ruby_version_is "2.5" do + describe "Set#to_s" do + it_behaves_like :set_inspect, :to_s + + it "is an alias of inspect" do + set = Set.new + set.method(:to_s).should == set.method(:inspect) + end + end +end diff --git a/spec/ruby/library/socket/udpsocket/new_spec.rb b/spec/ruby/library/socket/udpsocket/new_spec.rb index 5a2e4e1f31..f13e605959 100644 --- a/spec/ruby/library/socket/udpsocket/new_spec.rb +++ b/spec/ruby/library/socket/udpsocket/new_spec.rb @@ -26,7 +26,9 @@ describe 'UDPSocket.new' do @socket.should be_an_instance_of(UDPSocket) end - it 'raises Errno::EAFNOSUPPORT if unsupported family passed' do - lambda { UDPSocket.new(-1) }.should raise_error(Errno::EAFNOSUPPORT) + it 'raises Errno::EAFNOSUPPORT or Errno::EPROTONOSUPPORT if unsupported family passed' do + lambda { UDPSocket.new(-1) }.should raise_error(SystemCallError) { |e| + [Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT].should include(e.class) + } end end diff --git a/spec/ruby/library/stringio/pos_spec.rb b/spec/ruby/library/stringio/pos_spec.rb index 59d0a43f12..d5f3c3ab95 100644 --- a/spec/ruby/library/stringio/pos_spec.rb +++ b/spec/ruby/library/stringio/pos_spec.rb @@ -17,7 +17,7 @@ describe "StringIO#pos=" do end it "raises an EINVAL if given a negative argument" do - lambda { @io.pos = -10 }.should raise_error(Errno::EINVAL) + lambda { @io.pos = -10 }.should raise_error(Errno::EINVAL) end it "updates the current byte offset after reaching EOF" do