summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-15 17:44:37 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-15 17:44:37 +0000
commit30ed82e7724093bb3c2015a818c28c3592134bba (patch)
tree5445b9e26d9ee173fa3735007f3e2b42791d2ec5
parentf941bdf263dcc16ea4e6b4576341882b89567c0b (diff)
Update to ruby/spec@595645f
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61285 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--spec/ruby/.rubocop.yml3
-rw-r--r--spec/ruby/.rubocop_todo.yml39
-rw-r--r--spec/ruby/.travis.yml2
-rw-r--r--spec/ruby/README.md1
-rw-r--r--spec/ruby/core/dir/children_spec.rb72
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb53
-rw-r--r--spec/ruby/core/encoding/locale_charmap_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/all_spec.rb11
-rw-r--r--spec/ruby/core/enumerable/none_spec.rb11
-rw-r--r--spec/ruby/core/enumerable/one_spec.rb11
-rw-r--r--spec/ruby/core/file/chown_spec.rb16
-rw-r--r--spec/ruby/core/file/shared/read.rb4
-rw-r--r--spec/ruby/core/file/stat/inspect_spec.rb2
-rw-r--r--spec/ruby/core/hash/slice_spec.rb36
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb110
-rw-r--r--spec/ruby/core/hash/transform_values_spec.rb9
-rw-r--r--spec/ruby/core/kernel/autoload_spec.rb2
-rw-r--r--spec/ruby/core/module/included_modules_spec.rb4
-rw-r--r--spec/ruby/core/module/refine_spec.rb42
-rw-r--r--spec/ruby/core/process/setsid_spec.rb2
-rw-r--r--spec/ruby/core/process/spawn_spec.rb6
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb81
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb81
-rw-r--r--spec/ruby/core/string/start_with_spec.rb6
-rw-r--r--spec/ruby/core/struct/new_spec.rb13
-rw-r--r--spec/ruby/core/time/at_spec.rb56
-rw-r--r--spec/ruby/language/constants_spec.rb22
-rw-r--r--spec/ruby/language/ensure_spec.rb229
-rw-r--r--spec/ruby/language/fixtures/ensure.rb7
-rw-r--r--spec/ruby/language/rescue_spec.rb154
-rw-r--r--spec/ruby/library/date/shared/valid_jd.rb4
-rw-r--r--spec/ruby/library/matrix/build_spec.rb2
-rw-r--r--spec/ruby/library/set/case_compare_spec.rb15
-rw-r--r--spec/ruby/library/set/inspect_spec.rb15
-rw-r--r--spec/ruby/library/set/shared/include.rb22
-rw-r--r--spec/ruby/library/set/shared/inspect.rb15
-rw-r--r--spec/ruby/library/set/to_s_spec.rb13
-rw-r--r--spec/ruby/library/socket/udpsocket/new_spec.rb6
-rw-r--r--spec/ruby/library/stringio/pos_spec.rb2
39 files changed, 1078 insertions, 105 deletions
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 = "#<File::Stat dev=0x#{st.dev.to_s(16)}, ino=#{st.ino}, mode=#{sprintf("%07o", st.mode)}, nlink=#{st.nlink}"
expected << ", uid=#{st.uid}, gid=#{st.gid}, rdev=0x#{st.rdev.to_s(16)}, size=#{st.size}, blksize=#{st.blksize.inspect}"
expected << ", blocks=#{st.blocks.inspect}, atime=#{st.atime}, mtime=#{st.mtime}, ctime=#{st.ctime}"
- platform_is :bsd, :darwin do
+ platform_is :netbsd, :freebsd, :darwin do
# Windows has File.birthtime but it's not here since already shown by ctime.
expected << ", birthtime=#{st.birthtime}"
end
diff --git a/spec/ruby/core/hash/slice_spec.rb b/spec/ruby/core/hash/slice_spec.rb
new file mode 100644
index 0000000000..15c9c815ff
--- /dev/null
+++ b/spec/ruby/core/hash/slice_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.5" do
+ describe "Hash#slice" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3 }
+ end
+
+ it "returns new hash" do
+ ret = @hash.slice
+ ret.should_not equal(@hash)
+ ret.should be_an_instance_of(Hash)
+ end
+
+ it "returns the requested subset" do
+ @hash.slice(:c, :a).should == { c: 3, a: 1 }
+ end
+
+ it "returns a hash ordered in the order of the requested keys" do
+ @hash.slice(:c, :a).keys.should == [:c, :a]
+ end
+
+ it "returns only the keys of the original hash" do
+ @hash.slice(:a, :chunky_bacon).should == { a: 1 }
+ end
+
+ it "returns a Hash instance, even on subclasses" do
+ klass = Class.new(Hash)
+ h = klass.new
+ h[:foo] = 42
+ r = h.slice(:foo)
+ r.should == {foo: 42}
+ r.class.should == Hash
+ end
+ end
+end
diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb
new file mode 100644
index 0000000000..379638bd4b
--- /dev/null
+++ b/spec/ruby/core/hash/transform_keys_spec.rb
@@ -0,0 +1,110 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.5" do
+ describe "Hash#transform_keys" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3 }
+ end
+
+ it "returns new hash" do
+ ret = @hash.transform_keys(&:succ)
+ ret.should_not equal(@hash)
+ ret.should be_an_instance_of(Hash)
+ end
+
+ it "sets the result as transformed keys with the given block" do
+ @hash.transform_keys(&:succ).should == { b: 1, c: 2, d: 3 }
+ end
+
+ it "keeps last pair if new keys conflict" do
+ @hash.transform_keys { |_| :a }.should == { a: 3 }
+ end
+
+ it "makes both hashes to share values" do
+ value = [1, 2, 3]
+ new_hash = { a: value }.transform_keys(&:upcase)
+ new_hash[:A].should equal(value)
+ 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(&:succ).should == { b: 1, c: 2, d: 3 }
+ end
+ end
+
+ it "returns a Hash instance, even on subclasses" do
+ klass = Class.new(Hash)
+ h = klass.new
+ h[:foo] = 42
+ r = h.transform_keys{|v| :"x#{v}"}
+ r.keys.should == [:xfoo]
+ r.class.should == Hash
+ end
+ end
+
+ describe "Hash#transform_keys!" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3, d: 4 }
+ @initial_pairs = @hash.dup
+ end
+
+ it "returns self" do
+ @hash.transform_keys!(&:succ).should equal(@hash)
+ end
+
+ it "updates self as transformed values with the given block" do
+ @hash.transform_keys!(&:to_s)
+ @hash.should == { 'a' => 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
+
+ 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
- end.should raise_error(Exception)
+ 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("#<Set: {...}>")
- 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("#<Set: {...}>")
+ 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