diff options
| author | Benoit Daloze <eregontp@gmail.com> | 2025-10-08 17:59:52 +0200 |
|---|---|---|
| committer | Benoit Daloze <eregontp@gmail.com> | 2025-10-08 17:59:52 +0200 |
| commit | 50593d51997eab4aa5a148c5e131d10ea535f955 (patch) | |
| tree | d284c028a5679843878f63eeb4fbb3f6525fdb4e /spec/ruby | |
| parent | 5e7e6040938a37d1c320d69d2266f1b39e1b9f2a (diff) | |
Update to ruby/spec@3d7e563
Diffstat (limited to 'spec/ruby')
24 files changed, 456 insertions, 22 deletions
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml index 6b43db9b9a..bd30f3f14a 100644 --- a/spec/ruby/.rubocop_todo.yml +++ b/spec/ruby/.rubocop_todo.yml @@ -44,6 +44,7 @@ Lint/FloatOutOfRange: Lint/ImplicitStringConcatenation: Exclude: - 'language/string_spec.rb' + - 'core/string/chilled_string_spec.rb' # Offense count: 4 Lint/IneffectiveAccessModifier: diff --git a/spec/ruby/README.md b/spec/ruby/README.md index 56d6c3c542..674ada4c9e 100644 --- a/spec/ruby/README.md +++ b/spec/ruby/README.md @@ -26,7 +26,7 @@ ruby/spec is known to be tested in these implementations for every commit: * [MRI](https://rubyci.org/) on 30 platforms and 4 versions * [JRuby](https://github.com/jruby/jruby/tree/master/spec/ruby) for both 1.7 and 9.x -* [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby) +* [TruffleRuby](https://github.com/truffleruby/truffleruby/tree/master/spec/ruby) * [Opal](https://github.com/opal/opal/tree/master/spec) * [Artichoke](https://github.com/artichoke/spec/tree/artichoke-vendor) diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb index 4941e098f6..9e0fe7556a 100644 --- a/spec/ruby/core/array/shared/unshift.rb +++ b/spec/ruby/core/array/shared/unshift.rb @@ -49,7 +49,7 @@ describe :array_unshift, shared: true do -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError) end - # https://github.com/oracle/truffleruby/issues/2772 + # https://github.com/truffleruby/truffleruby/issues/2772 it "doesn't rely on Array#[]= so it can be overridden" do subclass = Class.new(Array) do def []=(*) diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb index 2fcfaf5203..176c33cf9e 100644 --- a/spec/ruby/core/io/readpartial_spec.rb +++ b/spec/ruby/core/io/readpartial_spec.rb @@ -93,6 +93,11 @@ describe "IO#readpartial" do @rd.readpartial(0).should == "" end + it "raises IOError if the stream is closed and the length argument is 0" do + @rd.close + -> { @rd.readpartial(0) }.should raise_error(IOError, "closed stream") + end + it "clears and returns the given buffer if the length argument is 0" do buffer = +"existing content" @rd.readpartial(0, buffer).should == buffer diff --git a/spec/ruby/core/kernel/Float_spec.rb b/spec/ruby/core/kernel/Float_spec.rb index 1705205996..e00fe81572 100644 --- a/spec/ruby/core/kernel/Float_spec.rb +++ b/spec/ruby/core/kernel/Float_spec.rb @@ -163,6 +163,7 @@ describe :kernel_float, shared: true do -> { @object.send(:Float, "+1.") }.should raise_error(ArgumentError) -> { @object.send(:Float, "-1.") }.should raise_error(ArgumentError) -> { @object.send(:Float, "1.e+0") }.should raise_error(ArgumentError) + -> { @object.send(:Float, "1.e-2") }.should raise_error(ArgumentError) end end @@ -172,6 +173,7 @@ describe :kernel_float, shared: true do @object.send(:Float, "+1.").should == 1.0 @object.send(:Float, "-1.").should == -1.0 @object.send(:Float, "1.e+0").should == 1.0 + @object.send(:Float, "1.e-2").should be_close(0.01, TOLERANCE) end end diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb index a68389a7b4..2b2c6c9b63 100644 --- a/spec/ruby/core/kernel/shared/sprintf.rb +++ b/spec/ruby/core/kernel/shared/sprintf.rb @@ -449,7 +449,7 @@ describe :kernel_sprintf, shared: true do it "is escaped by %" do @method.call("%%").should == "%" - @method.call("%%d", 10).should == "%d" + @method.call("%%d").should == "%d" end end end diff --git a/spec/ruby/core/kernel/singleton_method_spec.rb b/spec/ruby/core/kernel/singleton_method_spec.rb index 0bdf125ad8..7d63fa7cc6 100644 --- a/spec/ruby/core/kernel/singleton_method_spec.rb +++ b/spec/ruby/core/kernel/singleton_method_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' describe "Kernel#singleton_method" do - it "find a method defined on the singleton class" do + it "finds a method defined on the singleton class" do obj = Object.new def obj.foo; end obj.singleton_method(:foo).should be_an_instance_of(Method) @@ -38,4 +38,48 @@ describe "Kernel#singleton_method" do e.class.should == NameError } end + + ruby_bug "#20620", ""..."3.4" do + it "finds a method defined in a module included in the singleton class" do + m = Module.new do + def foo + :foo + end + end + + obj = Object.new + obj.singleton_class.include(m) + + obj.singleton_method(:foo).should be_an_instance_of(Method) + obj.singleton_method(:foo).call.should == :foo + end + + it "finds a method defined in a module prepended in the singleton class" do + m = Module.new do + def foo + :foo + end + end + + obj = Object.new + obj.singleton_class.prepend(m) + + obj.singleton_method(:foo).should be_an_instance_of(Method) + obj.singleton_method(:foo).call.should == :foo + end + + it "finds a method defined in a module that an object is extended with" do + m = Module.new do + def foo + :foo + end + end + + obj = Object.new + obj.extend(m) + + obj.singleton_method(:foo).should be_an_instance_of(Method) + obj.singleton_method(:foo).call.should == :foo + end + end end diff --git a/spec/ruby/core/kernel/sprintf_spec.rb b/spec/ruby/core/kernel/sprintf_spec.rb index 9ef7f86f16..5a4a90ff7a 100644 --- a/spec/ruby/core/kernel/sprintf_spec.rb +++ b/spec/ruby/core/kernel/sprintf_spec.rb @@ -13,28 +13,52 @@ end describe "Kernel#sprintf" do it_behaves_like :kernel_sprintf, -> format, *args { - sprintf(format, *args) + r = nil + -> { + r = sprintf(format, *args) + }.should_not complain(verbose: true) + r } it_behaves_like :kernel_sprintf_encoding, -> format, *args { - sprintf(format, *args) + r = nil + -> { + r = sprintf(format, *args) + }.should_not complain(verbose: true) + r } it_behaves_like :kernel_sprintf_to_str, -> format, *args { - sprintf(format, *args) + r = nil + -> { + r = sprintf(format, *args) + }.should_not complain(verbose: true) + r } end describe "Kernel.sprintf" do it_behaves_like :kernel_sprintf, -> format, *args { - Kernel.sprintf(format, *args) + r = nil + -> { + r = Kernel.sprintf(format, *args) + }.should_not complain(verbose: true) + r } it_behaves_like :kernel_sprintf_encoding, -> format, *args { - Kernel.sprintf(format, *args) + r = nil + -> { + r = Kernel.sprintf(format, *args) + }.should_not complain(verbose: true) + r } it_behaves_like :kernel_sprintf_to_str, -> format, *args { - Kernel.sprintf(format, *args) + r = nil + -> { + r = Kernel.sprintf(format, *args) + }.should_not complain(verbose: true) + r } end diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb index 00164ad90b..e03498c6dc 100644 --- a/spec/ruby/core/kernel/warn_spec.rb +++ b/spec/ruby/core/kernel/warn_spec.rb @@ -112,6 +112,12 @@ describe "Kernel#warn" do ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n" end + it "doesn't show the caller when the uplevel is `nil`" do + w = KernelSpecs::WarnInNestedCall.new + + -> { w.f4("foo", nil) }.should output(nil, "foo\n") + end + guard -> { Kernel.instance_method(:tap).source_location } do it "skips <internal: core library methods defined in Ruby" do file, line = Kernel.instance_method(:tap).source_location diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb index bba911e752..625d945686 100644 --- a/spec/ruby/core/module/autoload_spec.rb +++ b/spec/ruby/core/module/autoload_spec.rb @@ -718,6 +718,21 @@ describe "Module#autoload" do end end + it "should trigger the autoload when using `private_constant`" do + @remove << :DynClass + module ModuleSpecs::Autoload + autoload :DynClass, fixture(__FILE__, "autoload_c.rb") + private_constant :DynClass + + ScratchPad.recorded.should be_nil + + DynClass::C.new.loaded.should == :dynclass_c + ScratchPad.recorded.should == :loaded + end + + -> { ModuleSpecs::Autoload::DynClass }.should raise_error(NameError, /private constant/) + end + # [ruby-core:19127] [ruby-core:29941] it "does NOT raise a NameError when the autoload file did not define the constant and a module is opened with the same name" do module ModuleSpecs::Autoload diff --git a/spec/ruby/core/regexp/compile_spec.rb b/spec/ruby/core/regexp/compile_spec.rb index c41399cfbb..887c8d77dc 100644 --- a/spec/ruby/core/regexp/compile_spec.rb +++ b/spec/ruby/core/regexp/compile_spec.rb @@ -14,6 +14,6 @@ describe "Regexp.compile given a Regexp" do it_behaves_like :regexp_new_regexp, :compile end -describe "Regexp.new given a non-String/Regexp" do +describe "Regexp.compile given a non-String/Regexp" do it_behaves_like :regexp_new_non_string_or_regexp, :compile end diff --git a/spec/ruby/core/regexp/new_spec.rb b/spec/ruby/core/regexp/new_spec.rb index 65f612df55..79210e9a23 100644 --- a/spec/ruby/core/regexp/new_spec.rb +++ b/spec/ruby/core/regexp/new_spec.rb @@ -7,11 +7,11 @@ end describe "Regexp.new given a String" do it_behaves_like :regexp_new_string, :new + it_behaves_like :regexp_new_string_binary, :new end describe "Regexp.new given a Regexp" do it_behaves_like :regexp_new_regexp, :new - it_behaves_like :regexp_new_string_binary, :new end describe "Regexp.new given a non-String/Regexp" do diff --git a/spec/ruby/core/string/to_f_spec.rb b/spec/ruby/core/string/to_f_spec.rb index a91ccc168e..abfd2517b6 100644 --- a/spec/ruby/core/string/to_f_spec.rb +++ b/spec/ruby/core/string/to_f_spec.rb @@ -127,4 +127,16 @@ describe "String#to_f" do }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16") end end + + it "allows String representation without a fractional part" do + "1.".to_f.should == 1.0 + "+1.".to_f.should == 1.0 + "-1.".to_f.should == -1.0 + "1.e+0".to_f.should == 1.0 + "1.e+0".to_f.should == 1.0 + + ruby_bug "#20705", ""..."3.4" do + "1.e-2".to_f.should be_close(0.01, TOLERANCE) + end + end end diff --git a/spec/ruby/core/string/unpack1_spec.rb b/spec/ruby/core/string/unpack1_spec.rb index 3b3b879f75..cfb47fe695 100644 --- a/spec/ruby/core/string/unpack1_spec.rb +++ b/spec/ruby/core/string/unpack1_spec.rb @@ -31,4 +31,17 @@ describe "String#unpack1" do it "raises an ArgumentError when the offset is larger than the string bytesize" do -> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string") end + + context "with format 'm0'" do + # unpack1("m0") takes a special code path that calls Pack.unpackBase46Strict instead of Pack.unpack_m, + # which is why we repeat the tests for unpack("m0") here. + + it "decodes base64" do + "dGVzdA==".unpack1("m0").should == "test" + end + + it "raises an ArgumentError for an invalid base64 character" do + -> { "dGV%zdA==".unpack1("m0") }.should raise_error(ArgumentError) + end + end end diff --git a/spec/ruby/core/thread/fixtures/classes.rb b/spec/ruby/core/thread/fixtures/classes.rb index 54bd85fae3..7c485660a8 100644 --- a/spec/ruby/core/thread/fixtures/classes.rb +++ b/spec/ruby/core/thread/fixtures/classes.rb @@ -27,6 +27,7 @@ module ThreadSpecs thread.join ensure thread.kill if thread.alive? + Thread.pass while thread.alive? # Thread#kill may not terminate a thread immediately so it may be detected as a leaked one end end diff --git a/spec/ruby/core/time/utc_spec.rb b/spec/ruby/core/time/utc_spec.rb index 3d36e13ccf..ab3c0df657 100644 --- a/spec/ruby/core/time/utc_spec.rb +++ b/spec/ruby/core/time/utc_spec.rb @@ -43,10 +43,14 @@ describe "Time#utc?" do it "does not treat time with +00:00 offset as UTC" do Time.new(2022, 1, 1, 0, 0, 0, "+00:00").utc?.should == false + Time.now.localtime("+00:00").utc?.should == false + Time.at(Time.now, in: "+00:00").utc?.should == false end it "does not treat time with 0 offset as UTC" do Time.new(2022, 1, 1, 0, 0, 0, 0).utc?.should == false + Time.now.localtime(0).utc?.should == false + Time.at(Time.now, in: 0).utc?.should == false end end diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb index 572885c2b4..1267734987 100644 --- a/spec/ruby/core/warning/warn_spec.rb +++ b/spec/ruby/core/warning/warn_spec.rb @@ -97,6 +97,20 @@ describe "Warning.warn" do end end + ruby_version_is "3.4" do + it "warns when category is :strict_unused_block but Warning[:strict_unused_block] is false" do + warn_experimental = Warning[:strict_unused_block] + Warning[:strict_unused_block] = true + begin + -> { + Warning.warn("foo", category: :strict_unused_block) + }.should complain("foo") + ensure + Warning[:strict_unused_block] = warn_experimental + end + end + end + it "doesn't print message when category is :deprecated but Warning[:deprecated] is false" do warn_deprecated = Warning[:deprecated] Warning[:deprecated] = false @@ -121,6 +135,20 @@ describe "Warning.warn" do end end + ruby_version_is "3.4" do + it "doesn't print message when category is :strict_unused_block but Warning[:strict_unused_block] is false" do + warn_experimental = Warning[:strict_unused_block] + Warning[:strict_unused_block] = false + begin + -> { + Warning.warn("foo", category: :strict_unused_block) + }.should_not complain + ensure + Warning[:strict_unused_block] = warn_experimental + end + end + end + ruby_bug '#20573', ''...'3.4' do it "isn't called by Kernel.warn when category is :deprecated but Warning[:deprecated] is false" do warn_deprecated = Warning[:deprecated] diff --git a/spec/ruby/language/assignments_spec.rb b/spec/ruby/language/assignments_spec.rb index 4ad9f4167b..d469459c43 100644 --- a/spec/ruby/language/assignments_spec.rb +++ b/spec/ruby/language/assignments_spec.rb @@ -72,6 +72,34 @@ describe 'Assignments' do end end end + + context "given keyword arguments" do + before do + @klass = Class.new do + attr_reader :x + + def []=(*args, **kw) + @x = [args, kw] + end + end + end + + ruby_version_is ""..."3.4" do + it "supports keyword arguments in index assignments" do + a = @klass.new + eval "a[1, 2, 3, b: 4] = 5" + a.x.should == [[1, 2, 3, {b: 4}, 5], {}] + end + end + + ruby_version_is "3.4" do + it "raies SyntaxError when given keyword arguments in index assignments" do + a = @klass.new + -> { eval "a[1, 2, 3, b: 4] = 5" }.should raise_error(SyntaxError, + /keywords are not allowed in index assignment expressions|keyword arg given in index assignment/) # prism|parse.y + end + end + end end describe 'using +=' do @@ -176,6 +204,46 @@ describe 'Assignments' do end end + context "given keyword arguments" do + before do + @klass = Class.new do + attr_reader :x + + def [](*args) + 100 + end + + def []=(*args, **kw) + @x = [args, kw] + end + end + end + + ruby_version_is ""..."3.3" do + it "supports keyword arguments in index assignments" do + a = @klass.new + eval "a[1, 2, 3, b: 4] += 5" + a.x.should == [[1, 2, 3, {b: 4}, 105], {}] + end + end + + ruby_version_is "3.3"..."3.4" do + it "supports keyword arguments in index assignments" do + a = @klass.new + eval "a[1, 2, 3, b: 4] += 5" + a.x.should == [[1, 2, 3, 105], {b: 4}] + end + end + + ruby_version_is "3.4" do + it "raies SyntaxError when given keyword arguments in index assignments" do + a = @klass.new + -> { eval "a[1, 2, 3, b: 4] += 5" }.should raise_error(SyntaxError, + /keywords are not allowed in index assignment expressions|keyword arg given in index assignment/) # prism|parse.y + end + end + end + context 'splatted argument' do it 'correctly handles it' do @b[:m] = 10 diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb index 1d412a133e..39b245fe2a 100644 --- a/spec/ruby/language/method_spec.rb +++ b/spec/ruby/language/method_spec.rb @@ -1487,3 +1487,163 @@ describe "Inside 'endless' method definitions" do greet("Homer").should == "Hi, Homer" end end + +describe "warning about not used block argument" do + ruby_version_is "3.4" do + it "warns when passing a block argument to a method that never uses it" do + def m_that_does_not_use_block + 42 + end + + -> { + m_that_does_not_use_block { } + }.should complain( + /#{__FILE__}:#{__LINE__ - 2}: warning: the block passed to 'm_that_does_not_use_block' defined at #{__FILE__}:#{__LINE__ - 7} may be ignored/, + verbose: true) + end + + it "does not warn when passing a block argument to a method that declares a block parameter" do + def m_with_block_parameter(&block) + 42 + end + + -> { m_with_block_parameter { } }.should_not complain(verbose: true) + end + + it "does not warn when passing a block argument to a method that declares an anonymous block parameter" do + def m_with_anonymous_block_parameter(&) + 42 + end + + -> { m_with_anonymous_block_parameter { } }.should_not complain(verbose: true) + end + + it "does not warn when passing a block argument to a method that yields an implicit block parameter" do + def m_with_yield + yield 42 + end + + -> { m_with_yield { } }.should_not complain(verbose: true) + end + + it "warns when passing a block argument to a method that calls #block_given?" do + def m_with_block_given + block_given? + end + + -> { + m_with_block_given { } + }.should complain( + /#{__FILE__}:#{__LINE__ - 2}: warning: the block passed to 'm_with_block_given' defined at #{__FILE__}:#{__LINE__ - 7} may be ignored/, + verbose: true) + end + + it "does not warn when passing a block argument to a method that calls super" do + parent = Class.new do + def m + end + end + + child = Class.new(parent) do + def m + super + end + end + + obj = child.new + -> { obj.m { } }.should_not complain(verbose: true) + end + + it "does not warn when passing a block argument to a method that calls super(...)" do + parent = Class.new do + def m(a) + end + end + + child = Class.new(parent) do + def m(...) + super(...) + end + end + + obj = child.new + -> { obj.m(42) { } }.should_not complain(verbose: true) + end + + it "does not warn when called #initialize()" do + klass = Class.new do + def initialize + end + end + + -> { klass.new {} }.should_not complain(verbose: true) + end + + it "does not warn when passing a block argument to a method that calls super()" do + parent = Class.new do + def m + end + end + + child = Class.new(parent) do + def m + super() + end + end + + obj = child.new + -> { obj.m { } }.should_not complain(verbose: true) + end + + it "warns only once per call site" do + def m_that_does_not_use_block + 42 + end + + def call_m_that_does_not_use_block + m_that_does_not_use_block {} + end + + -> { + m_that_does_not_use_block { } + }.should complain(/the block passed to 'm_that_does_not_use_block' defined at .+ may be ignored/, verbose: true) + + -> { + m_that_does_not_use_block { } + }.should_not complain(verbose: true) + end + + it "can be disabled with :strict_unused_block warning category" do + def m_that_does_not_use_block + 42 + end + + # ensure that warning is emitted + -> { m_that_does_not_use_block { } }.should complain(verbose: true) + + warn_experimental = Warning[:strict_unused_block] + Warning[:strict_unused_block] = false + begin + -> { m_that_does_not_use_block { } }.should_not complain(verbose: true) + ensure + Warning[:strict_unused_block] = warn_experimental + end + end + + it "can be enabled with :strict_unused_block = true warning category in not verbose mode" do + def m_that_does_not_use_block + 42 + end + + warn_experimental = Warning[:strict_unused_block] + Warning[:strict_unused_block] = true + begin + -> { + m_that_does_not_use_block { } + }.should complain(/the block passed to 'm_that_does_not_use_block' defined at .+ may be ignored/) + ensure + Warning[:strict_unused_block] = warn_experimental + end + end + end +end diff --git a/spec/ruby/library/socket/socket/getaddrinfo_spec.rb b/spec/ruby/library/socket/socket/getaddrinfo_spec.rb index 9f049597d0..a2330715ad 100644 --- a/spec/ruby/library/socket/socket/getaddrinfo_spec.rb +++ b/spec/ruby/library/socket/socket/getaddrinfo_spec.rb @@ -106,6 +106,24 @@ describe "Socket.getaddrinfo" do ] res.each { |a| expected.should include(a) } end + + ruby_version_is ""..."3.3" do + it "raises SocketError when fails to resolve address" do + -> { + Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX") + }.should raise_error(SocketError) + end + end + + ruby_version_is "3.3" do + it "raises ResolutionError when fails to resolve address" do + -> { + Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX") + }.should raise_error(Socket::ResolutionError) { |e| + e.error_code.should == Socket::EAI_FAMILY + } + end + end end end diff --git a/spec/ruby/library/socket/socket/getnameinfo_spec.rb b/spec/ruby/library/socket/socket/getnameinfo_spec.rb index 4f13bf484d..b3105244a2 100644 --- a/spec/ruby/library/socket/socket/getnameinfo_spec.rb +++ b/spec/ruby/library/socket/socket/getnameinfo_spec.rb @@ -60,6 +60,24 @@ describe "Socket.getnameinfo" do name_info = Socket.getnameinfo ["AF_INET", 9, 'foo', '127.0.0.1'] name_info[1].should == 'discard' end + + ruby_version_is ""..."3.3" do + it "raises SocketError when fails to resolve address" do + -> { + Socket.getnameinfo(["AF_UNIX", 80, "0.0.0.0"]) + }.should raise_error(SocketError) + end + end + + ruby_version_is "3.3" do + it "raises ResolutionError when fails to resolve address" do + -> { + Socket.getnameinfo(["AF_UNIX", 80, "0.0.0.0"]) + }.should raise_error(Socket::ResolutionError) { |e| + e.error_code.should == Socket::EAI_FAMILY + } + end + end end describe 'Socket.getnameinfo' do diff --git a/spec/ruby/library/stringio/readpartial_spec.rb b/spec/ruby/library/stringio/readpartial_spec.rb index f25cef4014..988c552235 100644 --- a/spec/ruby/library/stringio/readpartial_spec.rb +++ b/spec/ruby/library/stringio/readpartial_spec.rb @@ -10,13 +10,7 @@ describe "StringIO#readpartial" do @string.close unless @string.closed? end - it "raises IOError on closed stream" do - @string.close - -> { @string.readpartial(10) }.should raise_error(IOError) - end - it "reads at most the specified number of bytes" do - # buffered read @string.read(1).should == 'S' # return only specified number, not the whole buffer @@ -67,14 +61,34 @@ describe "StringIO#readpartial" do it "raises IOError if the stream is closed" do @string.close - -> { @string.readpartial(1) }.should raise_error(IOError) + -> { @string.readpartial(1) }.should raise_error(IOError, "not opened for reading") end it "raises ArgumentError if the negative argument is provided" do - -> { @string.readpartial(-1) }.should raise_error(ArgumentError) + -> { @string.readpartial(-1) }.should raise_error(ArgumentError, "negative length -1 given") end it "immediately returns an empty string if the length argument is 0" do @string.readpartial(0).should == "" end + + it "raises IOError if the stream is closed and the length argument is 0" do + @string.close + -> { @string.readpartial(0) }.should raise_error(IOError, "not opened for reading") + end + + it "clears and returns the given buffer if the length argument is 0" do + buffer = +"existing content" + @string.readpartial(0, buffer).should == buffer + buffer.should == "" + end + + version_is StringIO::VERSION, "3.1.2" do # ruby_version_is "3.4" + it "preserves the encoding of the given buffer" do + buffer = ''.encode(Encoding::ISO_8859_1) + @string.readpartial(10, buffer) + + buffer.encoding.should == Encoding::ISO_8859_1 + end + end end diff --git a/spec/ruby/optional/capi/ext/set_spec.c b/spec/ruby/optional/capi/ext/set_spec.c index 72938be1d8..7af922fd49 100644 --- a/spec/ruby/optional/capi/ext/set_spec.c +++ b/spec/ruby/optional/capi/ext/set_spec.c @@ -47,6 +47,7 @@ VALUE set_spec_rb_set_size(VALUE self, VALUE set) { void Init_set_spec(void) { VALUE cls = rb_define_class("CApiSetSpecs", rb_cObject); + rb_define_method(cls, "rb_set_foreach", set_spec_rb_set_foreach, 2); rb_define_method(cls, "rb_set_new", set_spec_rb_set_new, 0); rb_define_method(cls, "rb_set_new_capa", set_spec_rb_set_new_capa, 1); diff --git a/spec/ruby/shared/kernel/raise.rb b/spec/ruby/shared/kernel/raise.rb index d46c4b7b15..8432c83594 100644 --- a/spec/ruby/shared/kernel/raise.rb +++ b/spec/ruby/shared/kernel/raise.rb @@ -191,8 +191,8 @@ describe :kernel_raise, shared: true do -> do @object.raise(error, cause: error) - end.should raise_error(RuntimeError, "message") do |error| - error.cause.should == nil + end.should raise_error(RuntimeError, "message") do |e| + e.cause.should == nil end end |
