summaryrefslogtreecommitdiff
path: root/spec/ruby/core
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2022-11-07 20:05:30 +0100
committerBenoit Daloze <eregontp@gmail.com>2022-11-07 20:05:30 +0100
commit83decbb62b8b3f1638927033f12b55f9b11f78c6 (patch)
tree8995f5b5cdb615f3d19edded66c6a9a9e82f159c /spec/ruby/core
parentc99e4c427897e82a3419abed894d28705f70fa13 (diff)
Update to ruby/spec@740ccc8
Diffstat (limited to 'spec/ruby/core')
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/each_cons_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/each_slice_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/lazy/compact_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/lazy/lazy_spec.rb10
-rw-r--r--spec/ruby/core/false/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/fiber/blocking_spec.rb4
-rw-r--r--spec/ruby/core/float/shared/to_i.rb4
-rw-r--r--spec/ruby/core/hash/hash_spec.rb9
-rw-r--r--spec/ruby/core/io/read_spec.rb7
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb10
-rw-r--r--spec/ruby/core/io/set_encoding_spec.rb32
-rw-r--r--spec/ruby/core/kernel/Complex_spec.rb89
-rw-r--r--spec/ruby/core/kernel/fixtures/Complex.rb5
-rw-r--r--spec/ruby/core/kernel/shared/load.rb16
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb15
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/method/private_spec.rb21
-rw-r--r--spec/ruby/core/method/protected_spec.rb21
-rw-r--r--spec/ruby/core/method/public_spec.rb21
-rw-r--r--spec/ruby/core/method/super_method_spec.rb10
-rw-r--r--spec/ruby/core/process/_fork_spec.rb24
-rw-r--r--spec/ruby/core/process/spawn_spec.rb18
-rw-r--r--spec/ruby/core/regexp/timeout_spec.rb35
-rw-r--r--spec/ruby/core/string/element_set_spec.rb4
-rw-r--r--spec/ruby/core/string/fixtures/to_c.rb5
-rw-r--r--spec/ruby/core/string/gsub_spec.rb35
-rw-r--r--spec/ruby/core/string/index_spec.rb8
-rw-r--r--spec/ruby/core/string/partition_spec.rb22
-rw-r--r--spec/ruby/core/string/rindex_spec.rb8
-rw-r--r--spec/ruby/core/string/rpartition_spec.rb22
-rw-r--r--spec/ruby/core/string/sub_spec.rb32
-rw-r--r--spec/ruby/core/string/to_c_spec.rb105
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb6
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb5
-rw-r--r--spec/ruby/core/struct/initialize_spec.rb8
-rw-r--r--spec/ruby/core/struct/keyword_init_spec.rb21
-rw-r--r--spec/ruby/core/thread/backtrace/limit_spec.rb15
-rw-r--r--spec/ruby/core/thread/native_thread_id_spec.rb15
-rw-r--r--spec/ruby/core/time/at_spec.rb5
-rw-r--r--spec/ruby/core/time/new_spec.rb51
-rw-r--r--spec/ruby/core/time/now_spec.rb45
-rw-r--r--spec/ruby/core/time/shared/local.rb11
-rw-r--r--spec/ruby/core/time/strftime_spec.rb9
-rw-r--r--spec/ruby/core/tracepoint/allow_reentry_spec.rb32
-rw-r--r--spec/ruby/core/unboundmethod/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/unboundmethod/private_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/protected_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/public_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb10
50 files changed, 820 insertions, 127 deletions
diff --git a/spec/ruby/core/array/pack/m_spec.rb b/spec/ruby/core/array/pack/m_spec.rb
index 2b1a84abca..c6364af12d 100644
--- a/spec/ruby/core/array/pack/m_spec.rb
+++ b/spec/ruby/core/array/pack/m_spec.rb
@@ -80,8 +80,16 @@ describe "Array#pack with format 'M'" do
].should be_computed_by(:pack, "M")
end
- it "encodes a tab followed by a newline with an encoded newline" do
+ it "encodes a tab at the end of a line with an encoded newline" do
+ ["\t"].pack("M").should == "\t=\n"
["\t\n"].pack("M").should == "\t=\n\n"
+ ["abc\t\nxyz"].pack("M").should == "abc\t=\n\nxyz=\n"
+ end
+
+ it "encodes a space at the end of a line with an encoded newline" do
+ [" "].pack("M").should == " =\n"
+ [" \n"].pack("M").should == " =\n\n"
+ ["abc \nxyz"].pack("M").should == "abc =\n\nxyz=\n"
end
it "encodes 127..255 in hex format" do
diff --git a/spec/ruby/core/enumerable/each_cons_spec.rb b/spec/ruby/core/enumerable/each_cons_spec.rb
index ba658203a2..8fb31fb925 100644
--- a/spec/ruby/core/enumerable/each_cons_spec.rb
+++ b/spec/ruby/core/enumerable/each_cons_spec.rb
@@ -56,6 +56,12 @@ describe "Enumerable#each_cons" do
multi.each_cons(2).to_a.should == [[[1, 2], [3, 4, 5]], [[3, 4, 5], [6, 7, 8, 9]]]
end
+ ruby_version_is "3.1" do
+ it "returns self when a block is given" do
+ @enum.each_cons(3){}.should == @enum
+ end
+ end
+
describe "when no block is given" do
it "returns an enumerator" do
e = @enum.each_cons(3)
diff --git a/spec/ruby/core/enumerable/each_slice_spec.rb b/spec/ruby/core/enumerable/each_slice_spec.rb
index 2ea89f5e72..a57a1dba81 100644
--- a/spec/ruby/core/enumerable/each_slice_spec.rb
+++ b/spec/ruby/core/enumerable/each_slice_spec.rb
@@ -57,6 +57,12 @@ describe "Enumerable#each_slice" do
e.to_a.should == @sliced
end
+ ruby_version_is "3.1" do
+ it "returns self when a block is given" do
+ @enum.each_slice(3){}.should == @enum
+ end
+ end
+
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMulti.new
multi.each_slice(2).to_a.should == [[[1, 2], [3, 4, 5]], [[6, 7, 8, 9]]]
diff --git a/spec/ruby/core/enumerator/lazy/compact_spec.rb b/spec/ruby/core/enumerator/lazy/compact_spec.rb
new file mode 100644
index 0000000000..80b6f9481d
--- /dev/null
+++ b/spec/ruby/core/enumerator/lazy/compact_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is '3.1' do
+ describe "Enumerator::Lazy#compact" do
+ it 'returns array without nil elements' do
+ arr = [1, nil, 3, false, 5].to_enum.lazy.compact
+ arr.should be_an_instance_of(Enumerator::Lazy)
+ arr.force.should == [1, 3, false, 5]
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/lazy/lazy_spec.rb b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
index 683dfb81d7..0fb104e25a 100644
--- a/spec/ruby/core/enumerator/lazy/lazy_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
@@ -30,13 +30,3 @@ describe "Enumerator::Lazy#lazy" do
lazy.lazy.should equal(lazy)
end
end
-
-ruby_version_is '3.1' do
- describe "Enumerator::Lazy#compact" do
- it 'returns array without nil elements' do
- arr = [1, nil, 3, false, 5].to_enum.lazy.compact
- arr.should be_an_instance_of(Enumerator::Lazy)
- arr.force.should == [1, 3, false, 5]
- end
- end
-end
diff --git a/spec/ruby/core/false/case_compare_spec.rb b/spec/ruby/core/false/case_compare_spec.rb
new file mode 100644
index 0000000000..0bd0ab44ae
--- /dev/null
+++ b/spec/ruby/core/false/case_compare_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "FalseClass#===" do
+ it "returns true for false" do
+ (false === false).should == true
+ end
+
+ it "returns false for non-false object" do
+ (false === 0).should == false
+ (false === "").should == false
+ (false === Object).should == false
+ (false === nil).should == false
+ end
+end
diff --git a/spec/ruby/core/fiber/blocking_spec.rb b/spec/ruby/core/fiber/blocking_spec.rb
index 852861d12f..eeee5a71c1 100644
--- a/spec/ruby/core/fiber/blocking_spec.rb
+++ b/spec/ruby/core/fiber/blocking_spec.rb
@@ -66,8 +66,8 @@ ruby_version_is "3.2" do
context "when fiber is non-blocking" do
it "can become blocking" do
fiber = Fiber.new(blocking: false) do
- Fiber.blocking do |fiber|
- fiber.blocking? ? :blocking : :non_blocking
+ Fiber.blocking do |f|
+ f.blocking? ? :blocking : :non_blocking
end
end
diff --git a/spec/ruby/core/float/shared/to_i.rb b/spec/ruby/core/float/shared/to_i.rb
index 960295f095..33b32ca533 100644
--- a/spec/ruby/core/float/shared/to_i.rb
+++ b/spec/ruby/core/float/shared/to_i.rb
@@ -7,4 +7,8 @@ describe :float_to_i, shared: true do
-9223372036854775808.1.send(@method).should eql(-9223372036854775808)
9223372036854775808.1.send(@method).should eql(9223372036854775808)
end
+
+ it "raises a FloatDomainError for NaN" do
+ -> { nan_value.send(@method) }.should raise_error(FloatDomainError)
+ end
end
diff --git a/spec/ruby/core/hash/hash_spec.rb b/spec/ruby/core/hash/hash_spec.rb
index 3649d4d8de..2ccb483120 100644
--- a/spec/ruby/core/hash/hash_spec.rb
+++ b/spec/ruby/core/hash/hash_spec.rb
@@ -41,4 +41,13 @@ describe "Hash#hash" do
h.hash.should == {x: [h]}.hash
# Like above, because h.eql?(x: [h])
end
+
+ ruby_version_is "3.1" do
+ it "allows ommiting values" do
+ a = 1
+ b = 2
+
+ eval('{a:, b:}.should == { a: 1, b: 2 }')
+ end
+ end
end
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index d34f7bd0eb..529afbf0ff 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -402,13 +402,6 @@ describe "IO#read in binary mode" do
xE2 = [226].pack('C*')
result.should == ("abc" + xE2 + "def").force_encoding(Encoding::BINARY)
end
-
- it "does not transcode file contents when an internal encoding is specified" do
- result = File.open(@name, "r:binary:utf-8") { |f| f.read }.chomp
- result.encoding.should == Encoding::BINARY
- xE2 = [226].pack('C*')
- result.should == ("abc" + xE2 + "def").force_encoding(Encoding::BINARY)
- end
end
describe "IO#read in text mode" do
diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb
index 324ae0b6e6..2901b429c2 100644
--- a/spec/ruby/core/io/readpartial_spec.rb
+++ b/spec/ruby/core/io/readpartial_spec.rb
@@ -93,10 +93,12 @@ describe "IO#readpartial" do
@rd.readpartial(0).should == ""
end
- it "clears and returns the given buffer if the length argument is 0" do
- buffer = "existing content"
- @rd.readpartial(0, buffer).should == buffer
- buffer.should == ""
+ ruby_bug "#18421", ""..."3.0.4" do
+ it "clears and returns the given buffer if the length argument is 0" do
+ buffer = "existing content"
+ @rd.readpartial(0, buffer).should == buffer
+ buffer.should == ""
+ end
end
it "preserves the encoding of the given buffer" do
diff --git a/spec/ruby/core/io/set_encoding_spec.rb b/spec/ruby/core/io/set_encoding_spec.rb
index bc448acfce..22d9017635 100644
--- a/spec/ruby/core/io/set_encoding_spec.rb
+++ b/spec/ruby/core/io/set_encoding_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe :io_set_encoding_write, shared: true do
- it "sets the encodings to nil" do
+ it "sets the encodings to nil when they were set previously" do
@io = new_io @name, "#{@object}:ibm437:ibm866"
@io.set_encoding nil, nil
@@ -9,6 +9,19 @@ describe :io_set_encoding_write, shared: true do
@io.internal_encoding.should be_nil
end
+ it "sets the encodings to nil when the IO is built with no explicit encoding" do
+ @io = new_io @name, @object
+
+ # Checking our assumptions first
+ @io.external_encoding.should be_nil
+ @io.internal_encoding.should be_nil
+
+ @io.set_encoding nil, nil
+
+ @io.external_encoding.should be_nil
+ @io.internal_encoding.should be_nil
+ end
+
it "prevents the encodings from changing when Encoding defaults are changed" do
@io = new_io @name, "#{@object}:utf-8:us-ascii"
@io.set_encoding nil, nil
@@ -38,6 +51,7 @@ describe "IO#set_encoding when passed nil, nil" do
@external = Encoding.default_external
@internal = Encoding.default_internal
+ # The defaults
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = nil
@@ -113,6 +127,22 @@ describe "IO#set_encoding when passed nil, nil" do
describe "with 'a+' mode" do
it_behaves_like :io_set_encoding_write, nil, "a+"
end
+
+ describe "with standard IOs" do
+ it "correctly resets them" do
+ STDOUT.external_encoding.should == nil
+ STDOUT.internal_encoding.should == nil
+
+ begin
+ STDOUT.set_encoding(Encoding::US_ASCII, Encoding::ISO_8859_1)
+ ensure
+ STDOUT.set_encoding(nil, nil)
+ end
+
+ STDOUT.external_encoding.should == nil
+ STDOUT.internal_encoding.should == nil
+ end
+ end
end
describe "IO#set_encoding" do
diff --git a/spec/ruby/core/kernel/Complex_spec.rb b/spec/ruby/core/kernel/Complex_spec.rb
index 4f043526b8..cc8177fa02 100644
--- a/spec/ruby/core/kernel/Complex_spec.rb
+++ b/spec/ruby/core/kernel/Complex_spec.rb
@@ -1,4 +1,6 @@
require_relative '../../spec_helper'
+require_relative '../../shared/kernel/complex'
+require_relative 'fixtures/Complex'
describe "Kernel.Complex()" do
describe "when passed [Complex, Complex]" do
@@ -58,7 +60,92 @@ describe "Kernel.Complex()" do
end
end
- describe "when passed a String" do
+ describe "when passed [String]" do
+ it_behaves_like :kernel_complex, :Complex_method, KernelSpecs
+
+ context "invalid argument" do
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ Complex("79+4i".encode("UTF-16"))
+ }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+
+ it "raises ArgumentError for unrecognised Strings" do
+ -> {
+ Complex("ruby")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "ruby"')
+ end
+
+ it "raises ArgumentError for trailing garbage" do
+ -> {
+ Complex("79+4iruby")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "79+4iruby"')
+ end
+
+ it "does not understand Float::INFINITY" do
+ -> {
+ Complex("Infinity")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "Infinity"')
+
+ -> {
+ Complex("-Infinity")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "-Infinity"')
+ end
+
+ it "does not understand Float::NAN" do
+ -> {
+ Complex("NaN")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "NaN"')
+ end
+
+ it "does not understand a sequence of _" do
+ -> {
+ Complex("7__9+4__0i")
+ }.should raise_error(ArgumentError, 'invalid value for convert(): "7__9+4__0i"')
+ end
+
+ it "does not allow null-byte" do
+ -> {
+ Complex("1-2i\0")
+ }.should raise_error(ArgumentError, "string contains null byte")
+ end
+ end
+
+ context "invalid argument and exception: false passed" do
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ Complex("79+4i".encode("UTF-16"), exception: false)
+ }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+
+ it "returns nil for unrecognised Strings" do
+ Complex("ruby", exception: false).should == nil
+ end
+
+ it "returns nil when trailing garbage" do
+ Complex("79+4iruby", exception: false).should == nil
+ end
+
+ it "returns nil for Float::INFINITY" do
+ Complex("Infinity", exception: false).should == nil
+ Complex("-Infinity", exception: false).should == nil
+ end
+
+ it "returns nil for Float::NAN" do
+ Complex("NaN", exception: false).should == nil
+ end
+
+ it "returns nil when there is a sequence of _" do
+ Complex("7__9+4__0i", exception: false).should == nil
+ end
+
+ it "returns nil when String contains null-byte" do
+ Complex("1-2i\0", exception: false).should == nil
+ end
+ end
+ end
+
+ describe "when passes [String, String]" do
it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/core/kernel/fixtures/Complex.rb b/spec/ruby/core/kernel/fixtures/Complex.rb
new file mode 100644
index 0000000000..bf14d55ad5
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/Complex.rb
@@ -0,0 +1,5 @@
+module KernelSpecs
+ def self.Complex_method(string)
+ Complex(string)
+ end
+end
diff --git a/spec/ruby/core/kernel/shared/load.rb b/spec/ruby/core/kernel/shared/load.rb
index 120619abef..cc84daeb88 100644
--- a/spec/ruby/core/kernel/shared/load.rb
+++ b/spec/ruby/core/kernel/shared/load.rb
@@ -154,6 +154,22 @@ describe :kernel_load, shared: true do
end
end
+ describe "when passed a module for 'wrap'" do
+ ruby_version_is "3.1" do
+ it "sets the enclosing scope to the supplied module" do
+ path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
+
+ Object.const_defined?(:LoadSpecWrap).should be_false
+ mod.const_defined?(:LoadSpecWrap).should be_true
+
+ wrap_module = ScratchPad.recorded[1]
+ wrap_module.should == mod
+ end
+ end
+ end
+
describe "(shell expansion)" do
before :each do
@env_home = ENV["HOME"]
diff --git a/spec/ruby/core/matchdata/element_reference_spec.rb b/spec/ruby/core/matchdata/element_reference_spec.rb
index 8965f902a0..7c0f089bb4 100644
--- a/spec/ruby/core/matchdata/element_reference_spec.rb
+++ b/spec/ruby/core/matchdata/element_reference_spec.rb
@@ -26,6 +26,21 @@ describe "MatchData#[]" do
it "supports ranges [start..end]" do
/(.)(.)(\d+)(\d)/.match("THX1138.")[1..3].should == %w|H X 113|
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..10].should == %w|113 8|
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[-30..2].should == nil
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..1].should == []
+ end
+
+ it "supports endless ranges [start..]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[3..].should == %w|113 8|
+ end
+
+ it "supports beginningless ranges [..end]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[..1].should == %w|HX1138 H|
+ end
+
+ it "supports beginningless endless ranges [nil..nil]" do
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[nil..nil].should == %w|HX1138 H X 113 8|
end
ruby_version_is "3.0" do
diff --git a/spec/ruby/core/method/fixtures/classes.rb b/spec/ruby/core/method/fixtures/classes.rb
index 50daa773e1..464a519aea 100644
--- a/spec/ruby/core/method/fixtures/classes.rb
+++ b/spec/ruby/core/method/fixtures/classes.rb
@@ -84,6 +84,12 @@ module MethodSpecs
def two_req_one_opt_with_splat_and_block(a, b, c=nil, *d, &blk); end
def one_req_two_opt_with_splat_and_block(a, b=nil, c=nil, *d, &blk); end
+ def my_public_method; end
+ def my_protected_method; end
+ def my_private_method; end
+ protected :my_protected_method
+ private :my_private_method
+
define_method(:zero_defined_method, Proc.new {||})
define_method(:zero_with_splat_defined_method, Proc.new {|*x|})
define_method(:one_req_defined_method, Proc.new {|x|})
diff --git a/spec/ruby/core/method/private_spec.rb b/spec/ruby/core/method/private_spec.rb
new file mode 100644
index 0000000000..230a4e9e81
--- /dev/null
+++ b/spec/ruby/core/method/private_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "Method#private?" do
+ it "returns false when the method is public" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).private?.should == false
+ end
+
+ it "returns false when the method is protected" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).private?.should == false
+ end
+
+ it "returns true when the method is private" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).private?.should == true
+ end
+ end
+end
diff --git a/spec/ruby/core/method/protected_spec.rb b/spec/ruby/core/method/protected_spec.rb
new file mode 100644
index 0000000000..6ee85f7738
--- /dev/null
+++ b/spec/ruby/core/method/protected_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "Method#protected?" do
+ it "returns false when the method is public" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).protected?.should == false
+ end
+
+ it "returns true when the method is protected" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).protected?.should == true
+ end
+
+ it "returns false when the method is private" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).protected?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/method/public_spec.rb b/spec/ruby/core/method/public_spec.rb
new file mode 100644
index 0000000000..3988468551
--- /dev/null
+++ b/spec/ruby/core/method/public_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "Method#public?" do
+ it "returns true when the method is public" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).public?.should == true
+ end
+
+ it "returns false when the method is protected" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).public?.should == false
+ end
+
+ it "returns false when the method is private" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).public?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/method/super_method_spec.rb b/spec/ruby/core/method/super_method_spec.rb
index c63a7aaa0f..f9a18f3878 100644
--- a/spec/ruby/core/method/super_method_spec.rb
+++ b/spec/ruby/core/method/super_method_spec.rb
@@ -55,10 +55,12 @@ describe "Method#super_method" do
end
end
- context "after aliasing an inherited method" do
- it "returns the expected super_method" do
- method = MethodSpecs::InheritedMethods::C.new.method(:meow)
- method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ ruby_version_is "2.7.3" do
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
end
end
end
diff --git a/spec/ruby/core/process/_fork_spec.rb b/spec/ruby/core/process/_fork_spec.rb
new file mode 100644
index 0000000000..6f711ad2dd
--- /dev/null
+++ b/spec/ruby/core/process/_fork_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "Process._fork" do
+ it "for #respond_to? returns the same as Process.respond_to?(:fork)" do
+ Process.respond_to?(:_fork).should == Process.respond_to?(:fork)
+ end
+
+ guard_not -> { Process.respond_to?(:fork) } do
+ it "raises a NotImplementedError when called" do
+ -> { Process._fork }.should raise_error(NotImplementedError)
+ end
+ end
+
+ guard -> { Process.respond_to?(:fork) } do
+ it "is called by Process#fork" do
+ Process.should_receive(:_fork).once.and_return(42)
+
+ pid = Process.fork {}
+ pid.should equal(42)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index 9aa8da8125..ad4800d4f8 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -567,6 +567,24 @@ describe "Process.spawn" do
end
end
+ platform_is_not :windows do
+ it "redirects non-default file descriptor to itself" do
+ File.open(@name, 'w') do |file|
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{file.fileno}, 'w'); f.print(:bang); f.flush"), file.fileno => file.fileno)
+ end.should output_to_fd("bang", file)
+ end
+ end
+ end
+
+ it "redirects default file descriptor to itself" do
+ -> do
+ Process.wait Process.spawn(
+ ruby_cmd("f = IO.new(#{STDOUT.fileno}, 'w'); f.print(:bang); f.flush"), STDOUT.fileno => STDOUT.fileno)
+ end.should output_to_fd("bang", STDOUT)
+ end
+
# :close_others
platform_is_not :windows do
diff --git a/spec/ruby/core/regexp/timeout_spec.rb b/spec/ruby/core/regexp/timeout_spec.rb
new file mode 100644
index 0000000000..6fce261814
--- /dev/null
+++ b/spec/ruby/core/regexp/timeout_spec.rb
@@ -0,0 +1,35 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.2" do
+ describe "Regexp.timeout" do
+ after :each do
+ Regexp.timeout = nil
+ end
+
+ it "returns global timeout" do
+ Regexp.timeout = 3
+ Regexp.timeout.should == 3
+ end
+
+ it "raises Regexp::TimeoutError after global timeout elapsed" do
+ Regexp.timeout = 0.001
+ Regexp.timeout.should == 0.001
+
+ -> {
+ # A typical ReDoS case
+ /^(a*)*$/ =~ "a" * 1000000 + "x"
+ }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
+ end
+
+ it "raises Regexp::TimeoutError after timeout keyword value elapsed" do
+ Regexp.timeout = 3 # This should be ignored
+ Regexp.timeout.should == 3
+
+ re = Regexp.new("^a*b?a*$", timeout: 0.001)
+
+ -> {
+ re =~ "a" * 1000000 + "x"
+ }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
+ end
+ end
+end
diff --git a/spec/ruby/core/string/element_set_spec.rb b/spec/ruby/core/string/element_set_spec.rb
index 881b4343d4..fa041fa31d 100644
--- a/spec/ruby/core/string/element_set_spec.rb
+++ b/spec/ruby/core/string/element_set_spec.rb
@@ -357,11 +357,11 @@ describe "String#[]= with a Range index" do
end
it "raises a RangeError if negative Range begin is out of range" do
- -> { "abc"[-4..-2] = "x" }.should raise_error(RangeError)
+ -> { "abc"[-4..-2] = "x" }.should raise_error(RangeError, "-4..-2 out of range")
end
it "raises a RangeError if positive Range begin is greater than String size" do
- -> { "abc"[4..2] = "x" }.should raise_error(RangeError)
+ -> { "abc"[4..2] = "x" }.should raise_error(RangeError, "4..2 out of range")
end
it "uses the Range end as an index rather than a count" do
diff --git a/spec/ruby/core/string/fixtures/to_c.rb b/spec/ruby/core/string/fixtures/to_c.rb
new file mode 100644
index 0000000000..7776933263
--- /dev/null
+++ b/spec/ruby/core/string/fixtures/to_c.rb
@@ -0,0 +1,5 @@
+module StringSpecs
+ def self.to_c_method(string)
+ string.to_c
+ end
+end
diff --git a/spec/ruby/core/string/gsub_spec.rb b/spec/ruby/core/string/gsub_spec.rb
index 3211ebbd0a..c87a566591 100644
--- a/spec/ruby/core/string/gsub_spec.rb
+++ b/spec/ruby/core/string/gsub_spec.rb
@@ -210,8 +210,6 @@ describe "String#gsub with pattern and replacement" do
end
end
- # Note: $~ cannot be tested because mspec messes with it
-
it "sets $~ to MatchData of last match and nil when there's none" do
'hello.'.gsub('hello', 'x')
$~[0].should == 'hello'
@@ -225,6 +223,18 @@ describe "String#gsub with pattern and replacement" do
'hello.'.gsub(/not/, 'x')
$~.should == nil
end
+
+ it "handles a pattern in a superset encoding" do
+ result = 'abc'.force_encoding(Encoding::US_ASCII).gsub('é', 'è')
+ result.should == 'abc'
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ result = 'été'.gsub('t'.force_encoding(Encoding::US_ASCII), 'u')
+ result.should == 'éué'
+ result.encoding.should == Encoding::UTF_8
+ end
end
describe "String#gsub with pattern and Hash" do
@@ -521,6 +531,27 @@ describe "String#gsub! with pattern and replacement" do
-> { s.gsub!(/e/, "e") }.should raise_error(FrozenError)
-> { s.gsub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
end
+
+ it "handles a pattern in a superset encoding" do
+ string = 'abc'.force_encoding(Encoding::US_ASCII)
+
+ result = string.gsub!('é', 'è')
+
+ result.should == nil
+ string.should == 'abc'
+ string.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ string = 'été'
+ pattern = 't'.force_encoding(Encoding::US_ASCII)
+
+ result = string.gsub!(pattern, 'u')
+
+ result.should == string
+ string.should == 'éué'
+ string.encoding.should == Encoding::UTF_8
+ end
end
describe "String#gsub! with pattern and block" do
diff --git a/spec/ruby/core/string/index_spec.rb b/spec/ruby/core/string/index_spec.rb
index 5d77a88e4e..2eeee9be87 100644
--- a/spec/ruby/core/string/index_spec.rb
+++ b/spec/ruby/core/string/index_spec.rb
@@ -159,6 +159,14 @@ describe "String#index with String" do
"あれ".index char
end.should raise_error(Encoding::CompatibilityError)
end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.force_encoding(Encoding::US_ASCII).index('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.index('t'.force_encoding(Encoding::US_ASCII)).should == 1
+ end
end
describe "String#index with Regexp" do
diff --git a/spec/ruby/core/string/partition_spec.rb b/spec/ruby/core/string/partition_spec.rb
index 98311f2be4..9cb3672881 100644
--- a/spec/ruby/core/string/partition_spec.rb
+++ b/spec/ruby/core/string/partition_spec.rb
@@ -38,4 +38,26 @@ describe "String#partition with String" do
it "takes precedence over a given block" do
"hello world".partition("o") { true }.should == ["hell", "o", " world"]
end
+
+ it "handles a pattern in a superset encoding" do
+ string = "hello".force_encoding(Encoding::US_ASCII)
+
+ result = string.partition("é")
+
+ result.should == ["hello", "", ""]
+ result[0].encoding.should == Encoding::US_ASCII
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ pattern = "o".force_encoding(Encoding::US_ASCII)
+
+ result = "héllo world".partition(pattern)
+
+ result.should == ["héll", "o", " world"]
+ result[0].encoding.should == Encoding::UTF_8
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::UTF_8
+ end
end
diff --git a/spec/ruby/core/string/rindex_spec.rb b/spec/ruby/core/string/rindex_spec.rb
index a3b437a1e4..e795105e1d 100644
--- a/spec/ruby/core/string/rindex_spec.rb
+++ b/spec/ruby/core/string/rindex_spec.rb
@@ -196,6 +196,14 @@ describe "String#rindex with String" do
it "raises a TypeError when given offset is nil" do
-> { "str".rindex("st", nil) }.should raise_error(TypeError)
end
+
+ it "handles a substring in a superset encoding" do
+ 'abc'.force_encoding(Encoding::US_ASCII).rindex('é').should == nil
+ end
+
+ it "handles a substring in a subset encoding" do
+ 'été'.rindex('t'.force_encoding(Encoding::US_ASCII)).should == 1
+ end
end
describe "String#rindex with Regexp" do
diff --git a/spec/ruby/core/string/rpartition_spec.rb b/spec/ruby/core/string/rpartition_spec.rb
index c8f9afaee9..21e87f530a 100644
--- a/spec/ruby/core/string/rpartition_spec.rb
+++ b/spec/ruby/core/string/rpartition_spec.rb
@@ -46,4 +46,26 @@ describe "String#rpartition with String" do
->{ "hello".rpartition(5) }.should raise_error(TypeError)
->{ "hello".rpartition(nil) }.should raise_error(TypeError)
end
+
+ it "handles a pattern in a superset encoding" do
+ string = "hello".force_encoding(Encoding::US_ASCII)
+
+ result = string.rpartition("é")
+
+ result.should == ["", "", "hello"]
+ result[0].encoding.should == Encoding::US_ASCII
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ pattern = "o".force_encoding(Encoding::US_ASCII)
+
+ result = "héllo world".rpartition(pattern)
+
+ result.should == ["héllo w", "o", "rld"]
+ result[0].encoding.should == Encoding::UTF_8
+ result[1].encoding.should == Encoding::US_ASCII
+ result[2].encoding.should == Encoding::UTF_8
+ end
end
diff --git a/spec/ruby/core/string/sub_spec.rb b/spec/ruby/core/string/sub_spec.rb
index 9effe88c27..99dd7b45a8 100644
--- a/spec/ruby/core/string/sub_spec.rb
+++ b/spec/ruby/core/string/sub_spec.rb
@@ -214,6 +214,17 @@ describe "String#sub with pattern, replacement" do
"ababa".sub(/(b)/, '\\\\\1').should == "a\\baba"
end
+ it "handles a pattern in a superset encoding" do
+ result = 'abc'.force_encoding(Encoding::US_ASCII).sub('é', 'è')
+ result.should == 'abc'
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ result = 'été'.sub('t'.force_encoding(Encoding::US_ASCII), 'u')
+ result.should == 'éué'
+ result.encoding.should == Encoding::UTF_8
+ end
end
describe "String#sub with pattern and block" do
@@ -299,6 +310,27 @@ describe "String#sub! with pattern, replacement" do
-> { s.sub!(/e/, "e") }.should raise_error(FrozenError)
-> { s.sub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
end
+
+ it "handles a pattern in a superset encoding" do
+ string = 'abc'.force_encoding(Encoding::US_ASCII)
+
+ result = string.sub!('é', 'è')
+
+ result.should == nil
+ string.should == 'abc'
+ string.encoding.should == Encoding::US_ASCII
+ end
+
+ it "handles a pattern in a subset encoding" do
+ string = 'été'
+ pattern = 't'.force_encoding(Encoding::US_ASCII)
+
+ result = string.sub!(pattern, 'u')
+
+ result.should == string
+ string.should == 'éué'
+ string.encoding.should == Encoding::UTF_8
+ end
end
describe "String#sub! with pattern and block" do
diff --git a/spec/ruby/core/string/to_c_spec.rb b/spec/ruby/core/string/to_c_spec.rb
index 9c84b14f4d..994bdf99f6 100644
--- a/spec/ruby/core/string/to_c_spec.rb
+++ b/spec/ruby/core/string/to_c_spec.rb
@@ -1,99 +1,42 @@
require_relative '../../spec_helper'
+require_relative '../../shared/kernel/complex'
+require_relative 'fixtures/to_c'
describe "String#to_c" do
- it "returns a Complex object" do
- '9'.to_c.should be_an_instance_of(Complex)
- end
-
- it "understands integers" do
- '20'.to_c.should == Complex(20)
- end
-
- it "understands negative integers" do
- '-3'.to_c.should == Complex(-3)
- end
-
- it "understands fractions (numerator/denominator) for the real part" do
- '2/3'.to_c.should == Complex(Rational(2, 3))
- end
-
- it "understands fractions (numerator/denominator) for the imaginary part" do
- '4+2/3i'.to_c.should == Complex(4, Rational(2, 3))
- end
-
- it "understands negative fractions (-numerator/denominator) for the real part" do
- '-2/3'.to_c.should == Complex(Rational(-2, 3))
- end
-
- it "understands negative fractions (-numerator/denominator) for the imaginary part" do
- '7-2/3i'.to_c.should == Complex(7, Rational(-2, 3))
- end
-
- it "understands floats (a.b) for the real part" do
- '2.3'.to_c.should == Complex(2.3)
- end
-
- it "understands floats (a.b) for the imaginary part" do
- '4+2.3i'.to_c.should == Complex(4, 2.3)
- end
-
- it "understands negative floats (-a.b) for the real part" do
- '-2.33'.to_c.should == Complex(-2.33)
- end
-
- it "understands negative floats (-a.b) for the imaginary part" do
- '7-28.771i'.to_c.should == Complex(7, -28.771)
- end
-
- it "understands an integer followed by 'i' to mean that integer is the imaginary part" do
- '35i'.to_c.should == Complex(0,35)
- end
-
- it "understands a negative integer followed by 'i' to mean that negative integer is the imaginary part" do
- '-29i'.to_c.should == Complex(0,-29)
- end
-
- it "understands an 'i' by itself as denoting a complex number with an imaginary part of 1" do
- 'i'.to_c.should == Complex(0,1)
- end
-
- it "understands a '-i' by itself as denoting a complex number with an imaginary part of -1" do
- '-i'.to_c.should == Complex(0,-1)
- end
-
- it "understands 'a+bi' to mean a complex number with 'a' as the real part, 'b' as the imaginary" do
- '79+4i'.to_c.should == Complex(79,4)
- end
-
- it "understands 'a-bi' to mean a complex number with 'a' as the real part, '-b' as the imaginary" do
- '79-4i'.to_c.should == Complex(79,-4)
- end
+ it_behaves_like :kernel_complex, :to_c_method, StringSpecs
+end
- it "understands scientific notation for the real part" do
- '2e3+4i'.to_c.should == Complex(2e3,4)
+describe "String#to_c" do
+ it "returns a complex number with 0 as the real part, 0 as the imaginary part for unrecognised Strings" do
+ 'ruby'.to_c.should == Complex(0, 0)
end
- it "understands negative scientific notation for the real part" do
- '-2e3+4i'.to_c.should == Complex(-2e3,4)
+ it "ignores trailing garbage" do
+ '79+4iruby'.to_c.should == Complex(79, 4)
end
- it "understands scientific notation for the imaginary part" do
- '4+2e3i'.to_c.should == Complex(4, 2e3)
+ it "understands Float::INFINITY" do
+ 'Infinity'.to_c.should == Complex(0, 1)
+ '-Infinity'.to_c.should == Complex(0, -1)
end
- it "understands negative scientific notation for the imaginary part" do
- '4-2e3i'.to_c.should == Complex(4, -2e3)
+ it "understands Float::NAN" do
+ 'NaN'.to_c.should == Complex(0, 0)
end
- it "understands scientific notation for the real and imaginary part in the same String" do
- '2e3+2e4i'.to_c.should == Complex(2e3,2e4)
+ it "understands a sequence of _" do
+ '7__9+4__0i'.to_c.should == Complex(79, 40)
end
- it "understands negative scientific notation for the real and imaginary part in the same String" do
- '-2e3-2e4i'.to_c.should == Complex(-2e3,-2e4)
+ it "allows null-byte" do
+ "1-2i\0".to_c.should == Complex(1, -2)
+ "1\0-2i".to_c.should == Complex(1, 0)
+ "\01-2i".to_c.should == Complex(0, 0)
end
- it "returns a complex number with 0 as the real part, 0 as the imaginary part for unrecognised Strings" do
- 'ruby'.to_c.should == Complex(0,0)
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ '79+4i'.encode("UTF-16").to_c
+ }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
end
end
diff --git a/spec/ruby/core/string/unpack/b_spec.rb b/spec/ruby/core/string/unpack/b_spec.rb
index 1a838d6c7c..fcabc99731 100644
--- a/spec/ruby/core/string/unpack/b_spec.rb
+++ b/spec/ruby/core/string/unpack/b_spec.rb
@@ -93,6 +93,11 @@ describe "String#unpack with format 'B'" do
it "ignores spaces between directives" do
"\x80\x00".unpack("B B").should == ["1", "0"]
end
+
+ it "decodes into US-ASCII string values" do
+ str = "s".force_encoding('UTF-8').unpack("B*")[0]
+ str.encoding.name.should == 'US-ASCII'
+ end
end
describe "String#unpack with format 'b'" do
@@ -189,5 +194,4 @@ describe "String#unpack with format 'b'" do
str = "s".force_encoding('UTF-8').unpack("b*")[0]
str.encoding.name.should == 'US-ASCII'
end
-
end
diff --git a/spec/ruby/core/string/unpack/m_spec.rb b/spec/ruby/core/string/unpack/m_spec.rb
index 21134514a1..c551c755d1 100644
--- a/spec/ruby/core/string/unpack/m_spec.rb
+++ b/spec/ruby/core/string/unpack/m_spec.rb
@@ -97,6 +97,11 @@ describe "String#unpack with format 'M'" do
["=FF=\n", ["\xff"]]
].should be_computed_by(:unpack, "M")
end
+
+ it "unpacks incomplete escape sequences as literal characters" do
+ "foo=".unpack("M").should == ["foo="]
+ "foo=4".unpack("M").should == ["foo=4"]
+ end
end
describe "String#unpack with format 'm'" do
diff --git a/spec/ruby/core/struct/initialize_spec.rb b/spec/ruby/core/struct/initialize_spec.rb
index e82289071a..cfb302209e 100644
--- a/spec/ruby/core/struct/initialize_spec.rb
+++ b/spec/ruby/core/struct/initialize_spec.rb
@@ -40,4 +40,12 @@ describe "Struct#initialize" do
it "can be overridden" do
StructClasses::SubclassX.new(:y).new.key.should == :value
end
+
+ ruby_version_is "3.1"..."3.2" do
+ it "warns about passing only keyword arguments" do
+ -> {
+ StructClasses::Ruby.new(version: "3.1", platform: "OS")
+ }.should complain(/warning: Passing only keyword arguments/)
+ end
+ end
end
diff --git a/spec/ruby/core/struct/keyword_init_spec.rb b/spec/ruby/core/struct/keyword_init_spec.rb
new file mode 100644
index 0000000000..061f4c56e0
--- /dev/null
+++ b/spec/ruby/core/struct/keyword_init_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ # See https://bugs.ruby-lang.org/issues/18008
+ describe "StructClass#keyword_init?" do
+ it "returns true for a struct that accepts keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: true)
+ struct.keyword_init?.should be_true
+ end
+
+ it "returns false for a struct that does not accept keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: false)
+ struct.keyword_init?.should be_false
+ end
+
+ it "returns nil for a struct that did not explicitly specify keyword_init" do
+ struct = Struct.new(:arg)
+ struct.keyword_init?.should be_nil
+ end
+ end
+end
diff --git a/spec/ruby/core/thread/backtrace/limit_spec.rb b/spec/ruby/core/thread/backtrace/limit_spec.rb
new file mode 100644
index 0000000000..26a87a806c
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/limit_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "Thread::Backtrace.limit" do
+ it "returns maximum backtrace length set by --backtrace-limit command-line option" do
+ out = ruby_exe("print Thread::Backtrace.limit", options: "--backtrace-limit=2")
+ out.should == "2"
+ end
+
+ it "returns -1 when --backtrace-limit command-line option is not set" do
+ out = ruby_exe("print Thread::Backtrace.limit")
+ out.should == "-1"
+ end
+ end
+end
diff --git a/spec/ruby/core/thread/native_thread_id_spec.rb b/spec/ruby/core/thread/native_thread_id_spec.rb
new file mode 100644
index 0000000000..5a6c0c8632
--- /dev/null
+++ b/spec/ruby/core/thread/native_thread_id_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.1" do
+ describe "Thread#native_thread_id" do
+ it "returns an integer when the thread is alive" do
+ Thread.current.native_thread_id.should be_kind_of(Integer)
+ end
+
+ it "returns nil when the thread is not running" do
+ t = Thread.new {}
+ t.join
+ t.native_thread_id.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/time/at_spec.rb b/spec/ruby/core/time/at_spec.rb
index 2cc46ab8c9..74b1962a95 100644
--- a/spec/ruby/core/time/at_spec.rb
+++ b/spec/ruby/core/time/at_spec.rb
@@ -266,5 +266,10 @@ describe "Time.at" do
time.zone.should == zone
time.to_i.should == @epoch_time
end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.at(@epoch_time, in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.at(@epoch_time, in: "ABC") }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/time/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index 09b4d03a44..aabf28e712 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -332,4 +332,55 @@ describe "Time.new with a timezone argument" do
end
end
end
+
+ ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/17485
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "+05:00")
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00")
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "ABC") }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if two offset arguments are given" do
+ -> { Time.new(2000, 1, 1, 12, 0, 0, "+05:00", in: "+05:00") }.should raise_error(ArgumentError)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/time/now_spec.rb b/spec/ruby/core/time/now_spec.rb
index 7dc7951996..2b2e53a17c 100644
--- a/spec/ruby/core/time/now_spec.rb
+++ b/spec/ruby/core/time/now_spec.rb
@@ -3,4 +3,49 @@ require_relative 'shared/now'
describe "Time.now" do
it_behaves_like :time_now, :now
+
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.now(in: "+05:00")
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: "-09:00")
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.now(in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.now(in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.now(in: "ABC") }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/time/shared/local.rb b/spec/ruby/core/time/shared/local.rb
index c4aa7a7ea9..068e314999 100644
--- a/spec/ruby/core/time/shared/local.rb
+++ b/spec/ruby/core/time/shared/local.rb
@@ -7,12 +7,10 @@ describe :time_local, shared: true do
end
platform_is_not :windows do
- describe "timezone changes" do
- it "correctly adjusts the timezone change to 'CET' on 'Europe/Amsterdam'" do
- with_timezone("Europe/Amsterdam") do
- Time.send(@method, 1970, 5, 16).to_a.should ==
- [0, 0, 0, 16, 5, 1970, 6, 136, false, "CET"]
- end
+ it "uses the 'CET' timezone with TZ=Europe/Amsterdam in 1970" do
+ with_timezone("Europe/Amsterdam") do
+ Time.send(@method, 1970, 5, 16).to_a.should ==
+ [0, 0, 0, 16, 5, 1970, 6, 136, false, "CET"]
end
end
end
@@ -41,5 +39,4 @@ describe :time_local_10_arg, shared: true do
end
end
end
-
end
diff --git a/spec/ruby/core/time/strftime_spec.rb b/spec/ruby/core/time/strftime_spec.rb
index 1bd24b0538..c133e22008 100644
--- a/spec/ruby/core/time/strftime_spec.rb
+++ b/spec/ruby/core/time/strftime_spec.rb
@@ -49,4 +49,13 @@ describe "Time#strftime" do
time = @new_time_with_offset[2012, 1, 1, 0, 0, 0, Rational(36645, 10)]
time.strftime("%::z").should == "+01:01:05"
end
+
+ ruby_version_is "3.1" do
+ it "supports RFC 3339 UTC for unknown offset local time, -0000, as %-z" do
+ @time.strftime("%z").should == "+0000"
+ @time.strftime("%-z").should == "-0000"
+ @time.strftime("%-:z").should == "-00:00"
+ @time.strftime("%-::z").should == "-00:00:00"
+ end
+ end
end
diff --git a/spec/ruby/core/tracepoint/allow_reentry_spec.rb b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
new file mode 100644
index 0000000000..6bff1bed76
--- /dev/null
+++ b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
@@ -0,0 +1,32 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1" do
+ describe 'TracePoint.allow_reentry' do
+ it 'allows the reentrance in a given block' do
+ event_lines = []
+ l1 = l2 = l3 = l4 = nil
+ TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
+
+ event_lines << tp.lineno
+ next if (__LINE__ + 2 .. __LINE__ + 4).cover?(tp.lineno)
+ TracePoint.allow_reentry do
+ a = 1; l3 = __LINE__
+ b = 2; l4 = __LINE__
+ end
+ end.enable do
+ c = 3; l1 = __LINE__
+ d = 4; l2 = __LINE__
+ end
+
+ event_lines.should == [l1, l3, l4, l2, l3, l4]
+ end
+
+ it 'raises RuntimeError when not called inside a TracePoint' do
+ -> {
+ TracePoint.allow_reentry{}
+ }.should raise_error(RuntimeError)
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/fixtures/classes.rb b/spec/ruby/core/unboundmethod/fixtures/classes.rb
index 1f466e39d8..6ab958d447 100644
--- a/spec/ruby/core/unboundmethod/fixtures/classes.rb
+++ b/spec/ruby/core/unboundmethod/fixtures/classes.rb
@@ -53,6 +53,12 @@ module UnboundMethodSpecs
def discard_1(); :discard; end
def discard_2(); :discard; end
+
+ def my_public_method; end
+ def my_protected_method; end
+ def my_private_method; end
+ protected :my_protected_method
+ private :my_private_method
end
class Parent
diff --git a/spec/ruby/core/unboundmethod/private_spec.rb b/spec/ruby/core/unboundmethod/private_spec.rb
new file mode 100644
index 0000000000..fa735846bb
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/private_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "UnboundMethod#private?" do
+ it "returns false when the method is public" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.private?.should == false
+ end
+
+ it "returns false when the method is protected" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.private?.should == false
+ end
+
+ it "returns true when the method is private" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.private?.should == true
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/protected_spec.rb b/spec/ruby/core/unboundmethod/protected_spec.rb
new file mode 100644
index 0000000000..db00e7ef43
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/protected_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "UnboundMethod#protected?" do
+ it "returns false when the method is public" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.protected?.should == false
+ end
+
+ it "returns true when the method is protected" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.protected?.should == true
+ end
+
+ it "returns false when the method is private" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.protected?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/public_spec.rb b/spec/ruby/core/unboundmethod/public_spec.rb
new file mode 100644
index 0000000000..7b87a03b15
--- /dev/null
+++ b/spec/ruby/core/unboundmethod/public_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "3.1"..."3.2" do
+ describe "UnboundMethod#public?" do
+ it "returns true when the method is public" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.public?.should == true
+ end
+
+ it "returns false when the method is protected" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.public?.should == false
+ end
+
+ it "returns false when the method is private" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.public?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/unboundmethod/super_method_spec.rb b/spec/ruby/core/unboundmethod/super_method_spec.rb
index aa7c129377..101c83b8b3 100644
--- a/spec/ruby/core/unboundmethod/super_method_spec.rb
+++ b/spec/ruby/core/unboundmethod/super_method_spec.rb
@@ -40,10 +40,12 @@ describe "UnboundMethod#super_method" do
end
end
- context "after aliasing an inherited method" do
- it "returns the expected super_method" do
- method = MethodSpecs::InheritedMethods::C.instance_method(:meow)
- method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ ruby_version_is "2.7.3" do
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
end
end
end