From e9117b4506ba1c26c1185490ab3122a8d527bfd5 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Fri, 31 Jan 2025 14:00:02 +0200 Subject: [PATCH 1/4] Update to ruby/mspec@0aabb3e --- spec/mspec/lib/mspec/commands/mkspec.rb | 2 -- spec/mspec/lib/mspec/commands/mspec-ci.rb | 4 ---- spec/mspec/lib/mspec/commands/mspec-run.rb | 4 ---- spec/mspec/lib/mspec/commands/mspec-tag.rb | 2 -- spec/mspec/lib/mspec/commands/mspec.rb | 2 -- 5 files changed, 14 deletions(-) mode change 100755 => 100644 spec/mspec/lib/mspec/commands/mkspec.rb mode change 100755 => 100644 spec/mspec/lib/mspec/commands/mspec.rb diff --git a/spec/mspec/lib/mspec/commands/mkspec.rb b/spec/mspec/lib/mspec/commands/mkspec.rb old mode 100755 new mode 100644 index a31cb2191c49..f75e683b1984 --- a/spec/mspec/lib/mspec/commands/mkspec.rb +++ b/spec/mspec/lib/mspec/commands/mkspec.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - require 'rbconfig' require 'mspec/version' require 'mspec/utils/options' diff --git a/spec/mspec/lib/mspec/commands/mspec-ci.rb b/spec/mspec/lib/mspec/commands/mspec-ci.rb index a31db1d7dcbb..9959059ca1c7 100644 --- a/spec/mspec/lib/mspec/commands/mspec-ci.rb +++ b/spec/mspec/lib/mspec/commands/mspec-ci.rb @@ -1,7 +1,3 @@ -#!/usr/bin/env ruby - -$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' diff --git a/spec/mspec/lib/mspec/commands/mspec-run.rb b/spec/mspec/lib/mspec/commands/mspec-run.rb index 36463d8c6f5f..0fb338fa23db 100644 --- a/spec/mspec/lib/mspec/commands/mspec-run.rb +++ b/spec/mspec/lib/mspec/commands/mspec-run.rb @@ -1,7 +1,3 @@ -#!/usr/bin/env ruby - -$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' diff --git a/spec/mspec/lib/mspec/commands/mspec-tag.rb b/spec/mspec/lib/mspec/commands/mspec-tag.rb index e1d04d14465e..8b1cb8380949 100644 --- a/spec/mspec/lib/mspec/commands/mspec-tag.rb +++ b/spec/mspec/lib/mspec/commands/mspec-tag.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' diff --git a/spec/mspec/lib/mspec/commands/mspec.rb b/spec/mspec/lib/mspec/commands/mspec.rb old mode 100755 new mode 100644 index f5341c699df4..a9d94ca35463 --- a/spec/mspec/lib/mspec/commands/mspec.rb +++ b/spec/mspec/lib/mspec/commands/mspec.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - require 'mspec/version' require 'mspec/utils/options' require 'mspec/utils/script' From db3d6ce733196b736f310ed4be942ae2044131cb Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Fri, 31 Jan 2025 14:00:07 +0200 Subject: [PATCH 2/4] Update to ruby/spec@affef93 --- spec/ruby/core/binding/fixtures/irb.rb | 3 -- spec/ruby/core/binding/shared/clone.rb | 2 +- spec/ruby/core/dir/chdir_spec.rb | 38 ++++++------- spec/ruby/core/dir/for_fd_spec.rb | 2 + .../core/enumerable/collect_concat_spec.rb | 2 +- spec/ruby/core/enumerable/collect_spec.rb | 2 +- spec/ruby/core/enumerable/detect_spec.rb | 2 +- spec/ruby/core/enumerable/entries_spec.rb | 2 +- spec/ruby/core/enumerable/filter_spec.rb | 2 +- spec/ruby/core/enumerable/find_all_spec.rb | 2 +- spec/ruby/core/enumerable/find_spec.rb | 2 +- spec/ruby/core/enumerable/flat_map_spec.rb | 2 +- spec/ruby/core/enumerable/map_spec.rb | 2 +- spec/ruby/core/enumerable/select_spec.rb | 2 +- spec/ruby/core/enumerable/to_a_spec.rb | 2 +- spec/ruby/core/fiber/storage_spec.rb | 27 +++++++++- spec/ruby/core/kernel/is_a_spec.rb | 2 +- spec/ruby/core/kernel/kind_of_spec.rb | 2 +- spec/ruby/core/method/shared/dup.rb | 2 +- spec/ruby/core/method/source_location_spec.rb | 16 ++++-- .../core/objectspace/define_finalizer_spec.rb | 2 +- spec/ruby/core/proc/shared/dup.rb | 2 +- spec/ruby/core/proc/source_location_spec.rb | 51 +++++++++++------- spec/ruby/core/range/overlap_spec.rb | 2 +- spec/ruby/core/string/append_as_bytes_spec.rb | 12 +++++ spec/ruby/core/unboundmethod/shared/dup.rb | 2 +- .../unboundmethod/source_location_spec.rb | 20 ++++--- spec/ruby/library/irb/fixtures/irb.rb | 3 ++ .../{core/binding => library/irb}/irb_spec.rb | 0 spec/ruby/library/net-ftp/fixtures/server.rb | 2 +- .../library/rubygems/gem/bin_path_spec.rb | 1 + .../socket/basicsocket/recv_nonblock_spec.rb | 2 + .../basicsocket/recvmsg_nonblock_spec.rb | 34 ++++++------ .../socket/basicsocket/recvmsg_spec.rb | 54 ++++++++++--------- .../library/socket/socket/gethostname_spec.rb | 10 +++- .../socket/socket/recvfrom_nonblock_spec.rb | 4 ++ spec/ruby/library/yaml/dump_spec.rb | 6 ++- spec/ruby/library/yaml/shared/load.rb | 6 ++- spec/ruby/optional/capi/ext/finalizer_spec.c | 31 +++++++++++ spec/ruby/optional/capi/ext/struct_spec.c | 4 ++ spec/ruby/optional/capi/finalizer_spec.rb | 40 ++++++++++++++ spec/ruby/optional/capi/struct_spec.rb | 2 +- 42 files changed, 288 insertions(+), 118 deletions(-) delete mode 100644 spec/ruby/core/binding/fixtures/irb.rb create mode 100644 spec/ruby/library/irb/fixtures/irb.rb rename spec/ruby/{core/binding => library/irb}/irb_spec.rb (100%) create mode 100644 spec/ruby/optional/capi/ext/finalizer_spec.c create mode 100644 spec/ruby/optional/capi/finalizer_spec.rb diff --git a/spec/ruby/core/binding/fixtures/irb.rb b/spec/ruby/core/binding/fixtures/irb.rb deleted file mode 100644 index 5f305f2d5d7f..000000000000 --- a/spec/ruby/core/binding/fixtures/irb.rb +++ /dev/null @@ -1,3 +0,0 @@ -a = 10 - -binding.irb diff --git a/spec/ruby/core/binding/shared/clone.rb b/spec/ruby/core/binding/shared/clone.rb index 1224b8ec7d0a..2d854fce965a 100644 --- a/spec/ruby/core/binding/shared/clone.rb +++ b/spec/ruby/core/binding/shared/clone.rb @@ -40,7 +40,7 @@ end it "copies the finalizer" do - code = <<-RUBY + code = <<-'RUBY' obj = binding ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" }) diff --git a/spec/ruby/core/dir/chdir_spec.rb b/spec/ruby/core/dir/chdir_spec.rb index b1fe06c2eb10..015386a9026c 100644 --- a/spec/ruby/core/dir/chdir_spec.rb +++ b/spec/ruby/core/dir/chdir_spec.rb @@ -177,27 +177,29 @@ def to_str; DirSpecs.mock_dir; end dir.close end - it "does not raise an Errno::ENOENT if the original directory no longer exists" do - dir_name1 = tmp('testdir1') - dir_name2 = tmp('testdir2') - Dir.should_not.exist?(dir_name1) - Dir.should_not.exist?(dir_name2) - Dir.mkdir dir_name1 - Dir.mkdir dir_name2 - - dir2 = Dir.new(dir_name2) - - begin - Dir.chdir(dir_name1) do - dir2.chdir { Dir.unlink dir_name1 } + platform_is_not :windows do + it "does not raise an Errno::ENOENT if the original directory no longer exists" do + dir_name1 = tmp('testdir1') + dir_name2 = tmp('testdir2') + Dir.should_not.exist?(dir_name1) + Dir.should_not.exist?(dir_name2) + Dir.mkdir dir_name1 + Dir.mkdir dir_name2 + + dir2 = Dir.new(dir_name2) + + begin + Dir.chdir(dir_name1) do + dir2.chdir { Dir.unlink dir_name1 } + end + Dir.pwd.should == @original + ensure + Dir.unlink dir_name1 if Dir.exist?(dir_name1) + Dir.unlink dir_name2 if Dir.exist?(dir_name2) end - Dir.pwd.should == @original ensure - Dir.unlink dir_name1 if Dir.exist?(dir_name1) - Dir.unlink dir_name2 if Dir.exist?(dir_name2) + dir2.close end - ensure - dir2.close end it "always returns to the original directory when given a block" do diff --git a/spec/ruby/core/dir/for_fd_spec.rb b/spec/ruby/core/dir/for_fd_spec.rb index d809f9211823..3afcc7e94901 100644 --- a/spec/ruby/core/dir/for_fd_spec.rb +++ b/spec/ruby/core/dir/for_fd_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' +quarantine! do # leads to "Errno::EBADF: Bad file descriptor - closedir" in DirSpecs.delete_mock_dirs ruby_version_is '3.3' do guard -> { Dir.respond_to? :for_fd } do describe "Dir.for_fd" do @@ -75,3 +76,4 @@ end end end +end diff --git a/spec/ruby/core/enumerable/collect_concat_spec.rb b/spec/ruby/core/enumerable/collect_concat_spec.rb index 6e34c9eb9390..59317cfe3411 100644 --- a/spec/ruby/core/enumerable/collect_concat_spec.rb +++ b/spec/ruby/core/enumerable/collect_concat_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/collect_concat' describe "Enumerable#collect_concat" do - it_behaves_like :enumerable_collect_concat , :collect_concat + it_behaves_like :enumerable_collect_concat, :collect_concat end diff --git a/spec/ruby/core/enumerable/collect_spec.rb b/spec/ruby/core/enumerable/collect_spec.rb index 1016b6779825..cfa2895cce21 100644 --- a/spec/ruby/core/enumerable/collect_spec.rb +++ b/spec/ruby/core/enumerable/collect_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/collect' describe "Enumerable#collect" do - it_behaves_like :enumerable_collect , :collect + it_behaves_like :enumerable_collect, :collect end diff --git a/spec/ruby/core/enumerable/detect_spec.rb b/spec/ruby/core/enumerable/detect_spec.rb index e912134fedad..6959aadc44b7 100644 --- a/spec/ruby/core/enumerable/detect_spec.rb +++ b/spec/ruby/core/enumerable/detect_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/find' describe "Enumerable#detect" do - it_behaves_like :enumerable_find , :detect + it_behaves_like :enumerable_find, :detect end diff --git a/spec/ruby/core/enumerable/entries_spec.rb b/spec/ruby/core/enumerable/entries_spec.rb index 83232cfa061b..2de4fc756a23 100644 --- a/spec/ruby/core/enumerable/entries_spec.rb +++ b/spec/ruby/core/enumerable/entries_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/entries' describe "Enumerable#entries" do - it_behaves_like :enumerable_entries , :entries + it_behaves_like :enumerable_entries, :entries end diff --git a/spec/ruby/core/enumerable/filter_spec.rb b/spec/ruby/core/enumerable/filter_spec.rb index 7e4f8c0b505d..c9ee23c54105 100644 --- a/spec/ruby/core/enumerable/filter_spec.rb +++ b/spec/ruby/core/enumerable/filter_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/find_all' describe "Enumerable#filter" do - it_behaves_like(:enumerable_find_all , :filter) + it_behaves_like(:enumerable_find_all, :filter) end diff --git a/spec/ruby/core/enumerable/find_all_spec.rb b/spec/ruby/core/enumerable/find_all_spec.rb index ce9058fe772e..9cd635f2470b 100644 --- a/spec/ruby/core/enumerable/find_all_spec.rb +++ b/spec/ruby/core/enumerable/find_all_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/find_all' describe "Enumerable#find_all" do - it_behaves_like :enumerable_find_all , :find_all + it_behaves_like :enumerable_find_all, :find_all end diff --git a/spec/ruby/core/enumerable/find_spec.rb b/spec/ruby/core/enumerable/find_spec.rb index 25aa3bf10326..5ddebc05f837 100644 --- a/spec/ruby/core/enumerable/find_spec.rb +++ b/spec/ruby/core/enumerable/find_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/find' describe "Enumerable#find" do - it_behaves_like :enumerable_find , :find + it_behaves_like :enumerable_find, :find end diff --git a/spec/ruby/core/enumerable/flat_map_spec.rb b/spec/ruby/core/enumerable/flat_map_spec.rb index a294b9ddad26..bd07eab6c5c1 100644 --- a/spec/ruby/core/enumerable/flat_map_spec.rb +++ b/spec/ruby/core/enumerable/flat_map_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/collect_concat' describe "Enumerable#flat_map" do - it_behaves_like :enumerable_collect_concat , :flat_map + it_behaves_like :enumerable_collect_concat, :flat_map end diff --git a/spec/ruby/core/enumerable/map_spec.rb b/spec/ruby/core/enumerable/map_spec.rb index d65aec238c05..98a70781cfc7 100644 --- a/spec/ruby/core/enumerable/map_spec.rb +++ b/spec/ruby/core/enumerable/map_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/collect' describe "Enumerable#map" do - it_behaves_like :enumerable_collect , :map + it_behaves_like :enumerable_collect, :map end diff --git a/spec/ruby/core/enumerable/select_spec.rb b/spec/ruby/core/enumerable/select_spec.rb index 11168eb42e25..7fc61926f900 100644 --- a/spec/ruby/core/enumerable/select_spec.rb +++ b/spec/ruby/core/enumerable/select_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/find_all' describe "Enumerable#select" do - it_behaves_like :enumerable_find_all , :select + it_behaves_like :enumerable_find_all, :select end diff --git a/spec/ruby/core/enumerable/to_a_spec.rb b/spec/ruby/core/enumerable/to_a_spec.rb index 0f3060dc483d..723f9225740c 100644 --- a/spec/ruby/core/enumerable/to_a_spec.rb +++ b/spec/ruby/core/enumerable/to_a_spec.rb @@ -3,5 +3,5 @@ require_relative 'shared/entries' describe "Enumerable#to_a" do - it_behaves_like :enumerable_entries , :to_a + it_behaves_like :enumerable_entries, :to_a end diff --git a/spec/ruby/core/fiber/storage_spec.rb b/spec/ruby/core/fiber/storage_spec.rb index d5603f006c8d..03e9e3b822f9 100644 --- a/spec/ruby/core/fiber/storage_spec.rb +++ b/spec/ruby/core/fiber/storage_spec.rb @@ -90,15 +90,38 @@ key = :"#{self.class.name}#.#{self.object_id}" Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42 end + + it "can't use invalid keys" do + invalid_keys = [Object.new, 12] + invalid_keys.each do |key| + -> { Fiber[key] }.should raise_error(TypeError) + end + end end ruby_bug "#20978", "3.2"..."3.4" do it "can use keys as strings" do key = Object.new def key.to_str; "Foo"; end - Fiber[key] = 42 - Fiber["Foo"].should == 42 + Fiber.new { Fiber[key] = 42; Fiber["Foo"] }.resume.should == 42 end + + it "converts a String key into a Symbol" do + Fiber.new { Fiber["key"] = 42; Fiber[:key] }.resume.should == 42 + Fiber.new { Fiber[:key] = 42; Fiber["key"] }.resume.should == 42 + end + + it "can use any object that responds to #to_str as a key" do + key = mock("key") + key.should_receive(:to_str).twice.and_return("key") + Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42 + end + end + + it "does not call #to_sym on the key" do + key = mock("key") + key.should_not_receive(:to_sym) + -> { Fiber[key] }.should raise_error(TypeError) end it "can access the storage of the parent fiber" do diff --git a/spec/ruby/core/kernel/is_a_spec.rb b/spec/ruby/core/kernel/is_a_spec.rb index dc69766f835c..bd8c96529a84 100644 --- a/spec/ruby/core/kernel/is_a_spec.rb +++ b/spec/ruby/core/kernel/is_a_spec.rb @@ -2,5 +2,5 @@ require_relative 'shared/kind_of' describe "Kernel#is_a?" do - it_behaves_like :kernel_kind_of , :is_a? + it_behaves_like :kernel_kind_of, :is_a? end diff --git a/spec/ruby/core/kernel/kind_of_spec.rb b/spec/ruby/core/kernel/kind_of_spec.rb index 734035620c3a..c988edccb5bb 100644 --- a/spec/ruby/core/kernel/kind_of_spec.rb +++ b/spec/ruby/core/kernel/kind_of_spec.rb @@ -2,5 +2,5 @@ require_relative 'shared/kind_of' describe "Kernel#kind_of?" do - it_behaves_like :kernel_kind_of , :kind_of? + it_behaves_like :kernel_kind_of, :kind_of? end diff --git a/spec/ruby/core/method/shared/dup.rb b/spec/ruby/core/method/shared/dup.rb index 1a10b90689f7..c74847083f80 100644 --- a/spec/ruby/core/method/shared/dup.rb +++ b/spec/ruby/core/method/shared/dup.rb @@ -16,7 +16,7 @@ end it "copies the finalizer" do - code = <<-RUBY + code = <<-'RUBY' obj = Object.new.method(:method) ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" }) diff --git a/spec/ruby/core/method/source_location_spec.rb b/spec/ruby/core/method/source_location_spec.rb index c5b296f6e2a7..23d956ebec05 100644 --- a/spec/ruby/core/method/source_location_spec.rb +++ b/spec/ruby/core/method/source_location_spec.rb @@ -11,23 +11,23 @@ end it "sets the first value to the path of the file in which the method was defined" do - file = @method.source_location.first + file = @method.source_location[0] file.should be_an_instance_of(String) file.should == File.realpath('fixtures/classes.rb', __dir__) end it "sets the last value to an Integer representing the line on which the method was defined" do - line = @method.source_location.last + line = @method.source_location[1] line.should be_an_instance_of(Integer) line.should == 5 end it "returns the last place the method was defined" do - MethodSpecs::SourceLocation.method(:redefined).source_location.last.should == 13 + MethodSpecs::SourceLocation.method(:redefined).source_location[1].should == 13 end it "returns the location of the original method even if it was aliased" do - MethodSpecs::SourceLocation.new.method(:aka).source_location.last.should == 17 + MethodSpecs::SourceLocation.new.method(:aka).source_location[1].should == 17 end it "works for methods defined with a block" do @@ -108,7 +108,13 @@ def f c = Class.new do eval('def self.m; end', nil, "foo", 100) end - c.method(:m).source_location.should == ["foo", 100] + location = c.method(:m).source_location + ruby_version_is(""..."3.5") do + location.should == ["foo", 100] + end + ruby_version_is("3.5") do + location.should == ["foo", 100, 0, 100, 15] + end end describe "for a Method generated by respond_to_missing?" do diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb index 4d4cfa9270c3..329f8e1f3048 100644 --- a/spec/ruby/core/objectspace/define_finalizer_spec.rb +++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb @@ -156,7 +156,7 @@ def finalizer(zelf) end it "allows multiple finalizers with different 'callables' to be defined" do - code = <<-RUBY + code = <<-'RUBY' obj = Object.new ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized1\n" }) diff --git a/spec/ruby/core/proc/shared/dup.rb b/spec/ruby/core/proc/shared/dup.rb index c419a4078af7..818f5b858e27 100644 --- a/spec/ruby/core/proc/shared/dup.rb +++ b/spec/ruby/core/proc/shared/dup.rb @@ -25,7 +25,7 @@ end it "copies the finalizer" do - code = <<-RUBY + code = <<-'RUBY' obj = Proc.new { } ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" }) diff --git a/spec/ruby/core/proc/source_location_spec.rb b/spec/ruby/core/proc/source_location_spec.rb index a8b99287d5c3..484466f57747 100644 --- a/spec/ruby/core/proc/source_location_spec.rb +++ b/spec/ruby/core/proc/source_location_spec.rb @@ -17,57 +17,64 @@ end it "sets the first value to the path of the file in which the proc was defined" do - file = @proc.source_location.first + file = @proc.source_location[0] file.should be_an_instance_of(String) file.should == File.realpath('fixtures/source_location.rb', __dir__) - file = @proc_new.source_location.first + file = @proc_new.source_location[0] file.should be_an_instance_of(String) file.should == File.realpath('fixtures/source_location.rb', __dir__) - file = @lambda.source_location.first + file = @lambda.source_location[0] file.should be_an_instance_of(String) file.should == File.realpath('fixtures/source_location.rb', __dir__) - file = @method.source_location.first + file = @method.source_location[0] file.should be_an_instance_of(String) file.should == File.realpath('fixtures/source_location.rb', __dir__) end - it "sets the last value to an Integer representing the line on which the proc was defined" do - line = @proc.source_location.last + it "sets the second value to an Integer representing the line on which the proc was defined" do + line = @proc.source_location[1] line.should be_an_instance_of(Integer) line.should == 4 - line = @proc_new.source_location.last + line = @proc_new.source_location[1] line.should be_an_instance_of(Integer) line.should == 12 - line = @lambda.source_location.last + line = @lambda.source_location[1] line.should be_an_instance_of(Integer) line.should == 8 - line = @method.source_location.last + line = @method.source_location[1] line.should be_an_instance_of(Integer) line.should == 15 end it "works even if the proc was created on the same line" do - proc { true }.source_location.should == [__FILE__, __LINE__] - Proc.new { true }.source_location.should == [__FILE__, __LINE__] - -> { true }.source_location.should == [__FILE__, __LINE__] + ruby_version_is(""..."3.5") do + proc { true }.source_location.should == [__FILE__, __LINE__] + Proc.new { true }.source_location.should == [__FILE__, __LINE__] + -> { true }.source_location.should == [__FILE__, __LINE__] + end + ruby_version_is("3.5") do + proc { true }.source_location.should == [__FILE__, __LINE__, 11, __LINE__, 19] + Proc.new { true }.source_location.should == [__FILE__, __LINE__, 15, __LINE__, 23] + -> { true }.source_location.should == [__FILE__, __LINE__, 8, __LINE__, 17] + end end it "returns the first line of a multi-line proc (i.e. the line containing 'proc do')" do - ProcSpecs::SourceLocation.my_multiline_proc.source_location.last.should == 20 - ProcSpecs::SourceLocation.my_multiline_proc_new.source_location.last.should == 34 - ProcSpecs::SourceLocation.my_multiline_lambda.source_location.last.should == 27 + ProcSpecs::SourceLocation.my_multiline_proc.source_location[1].should == 20 + ProcSpecs::SourceLocation.my_multiline_proc_new.source_location[1].should == 34 + ProcSpecs::SourceLocation.my_multiline_lambda.source_location[1].should == 27 end it "returns the location of the proc's body; not necessarily the proc itself" do - ProcSpecs::SourceLocation.my_detached_proc.source_location.last.should == 41 - ProcSpecs::SourceLocation.my_detached_proc_new.source_location.last.should == 51 - ProcSpecs::SourceLocation.my_detached_lambda.source_location.last.should == 46 + ProcSpecs::SourceLocation.my_detached_proc.source_location[1].should == 41 + ProcSpecs::SourceLocation.my_detached_proc_new.source_location[1].should == 51 + ProcSpecs::SourceLocation.my_detached_lambda.source_location[1].should == 46 end it "returns the same value for a proc-ified method as the method reports" do @@ -86,6 +93,12 @@ it "works for eval with a given line" do proc = eval('-> {}', nil, "foo", 100) - proc.source_location.should == ["foo", 100] + location = proc.source_location + ruby_version_is(""..."3.5") do + location.should == ["foo", 100] + end + ruby_version_is("3.5") do + location.should == ["foo", 100, 2, 100, 5] + end end end diff --git a/spec/ruby/core/range/overlap_spec.rb b/spec/ruby/core/range/overlap_spec.rb index f0db0de20ea8..9b6fc1349342 100644 --- a/spec/ruby/core/range/overlap_spec.rb +++ b/spec/ruby/core/range/overlap_spec.rb @@ -86,4 +86,4 @@ ('c'..'e').overlap?('a'...'c').should == false end end -end \ No newline at end of file +end diff --git a/spec/ruby/core/string/append_as_bytes_spec.rb b/spec/ruby/core/string/append_as_bytes_spec.rb index 0e1d09558bd1..b1703e5f89ba 100644 --- a/spec/ruby/core/string/append_as_bytes_spec.rb +++ b/spec/ruby/core/string/append_as_bytes_spec.rb @@ -34,6 +34,18 @@ str.should == "hello\xE2\x82\f+\xAC".b end + it "truncates integers to the least significant byte" do + str = +"" + str.append_as_bytes(0x131, 0x232, 0x333, bignum_value, bignum_value(1)) + str.bytes.should == [0x31, 0x32, 0x33, 0, 1] + end + + it "wraps negative integers" do + str = "".b + str.append_as_bytes(-1, -bignum_value, -bignum_value(1)) + str.bytes.should == [0xFF, 0, 0xFF] + end + it "only accepts strings or integers, and doesn't attempt to cast with #to_str or #to_int" do to_str = mock("to_str") to_str.should_not_receive(:to_str) diff --git a/spec/ruby/core/unboundmethod/shared/dup.rb b/spec/ruby/core/unboundmethod/shared/dup.rb index 943a7faaa397..194e2cc1a184 100644 --- a/spec/ruby/core/unboundmethod/shared/dup.rb +++ b/spec/ruby/core/unboundmethod/shared/dup.rb @@ -16,7 +16,7 @@ end it "copies the finalizer" do - code = <<-RUBY + code = <<-'RUBY' obj = Class.instance_method(:instance_method) ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" }) diff --git a/spec/ruby/core/unboundmethod/source_location_spec.rb b/spec/ruby/core/unboundmethod/source_location_spec.rb index 5c2f14362c40..45bd69438c99 100644 --- a/spec/ruby/core/unboundmethod/source_location_spec.rb +++ b/spec/ruby/core/unboundmethod/source_location_spec.rb @@ -7,23 +7,23 @@ end it "sets the first value to the path of the file in which the method was defined" do - file = @method.source_location.first + file = @method.source_location[0] file.should be_an_instance_of(String) file.should == File.realpath('fixtures/classes.rb', __dir__) end - it "sets the last value to an Integer representing the line on which the method was defined" do - line = @method.source_location.last + it "sets the second value to an Integer representing the line on which the method was defined" do + line = @method.source_location[1] line.should be_an_instance_of(Integer) line.should == 5 end it "returns the last place the method was defined" do - UnboundMethodSpecs::SourceLocation.method(:redefined).unbind.source_location.last.should == 13 + UnboundMethodSpecs::SourceLocation.method(:redefined).unbind.source_location[1].should == 13 end it "returns the location of the original method even if it was aliased" do - UnboundMethodSpecs::SourceLocation.instance_method(:aka).source_location.last.should == 17 + UnboundMethodSpecs::SourceLocation.instance_method(:aka).source_location[1].should == 17 end it "works for define_method methods" do @@ -54,6 +54,12 @@ c = Class.new do eval('def m; end', nil, "foo", 100) end - c.instance_method(:m).source_location.should == ["foo", 100] - end + location = c.instance_method(:m).source_location + ruby_version_is(""..."3.5") do + location.should == ["foo", 100] + end + ruby_version_is("3.5") do + location.should == ["foo", 100, 0, 100, 10] + end + end end diff --git a/spec/ruby/library/irb/fixtures/irb.rb b/spec/ruby/library/irb/fixtures/irb.rb new file mode 100644 index 000000000000..8d386dfda194 --- /dev/null +++ b/spec/ruby/library/irb/fixtures/irb.rb @@ -0,0 +1,3 @@ +a = 10 + +binding.irb # rubocop:disable Lint/Debugger diff --git a/spec/ruby/core/binding/irb_spec.rb b/spec/ruby/library/irb/irb_spec.rb similarity index 100% rename from spec/ruby/core/binding/irb_spec.rb rename to spec/ruby/library/irb/irb_spec.rb diff --git a/spec/ruby/library/net-ftp/fixtures/server.rb b/spec/ruby/library/net-ftp/fixtures/server.rb index ecbed591d589..8b34d3f8bd38 100644 --- a/spec/ruby/library/net-ftp/fixtures/server.rb +++ b/spec/ruby/library/net-ftp/fixtures/server.rb @@ -9,7 +9,7 @@ class DummyFTP attr_reader :server_port def initialize - @hostname = "localhost" + @hostname = "127.0.0.1" @server = TCPServer.new(@hostname, 0) @server_port = @server.addr[1] diff --git a/spec/ruby/library/rubygems/gem/bin_path_spec.rb b/spec/ruby/library/rubygems/gem/bin_path_spec.rb index 67b3e042c23d..0b8c4db08bb1 100644 --- a/spec/ruby/library/rubygems/gem/bin_path_spec.rb +++ b/spec/ruby/library/rubygems/gem/bin_path_spec.rb @@ -22,6 +22,7 @@ end skip "Could not find the default gemspecs" unless Dir.exist?(default_specifications_dir) + skip "default_specifications_dir mismatch with GEM_HOME" if ENV["GEM_HOME"] && !default_specifications_dir.start_with?(ENV['GEM_HOME']) Gem::Specification.each_spec([default_specifications_dir]) do |spec| spec.executables.each do |exe| diff --git a/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb index 001d2d74a3fe..5bdbbfe68831 100644 --- a/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb +++ b/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb @@ -113,6 +113,7 @@ end ruby_version_is ""..."3.3" do + quarantine! do # May fail with "IO::EAGAINWaitReadable: Resource temporarily unavailable - recvfrom(2) would block" error it "returns an empty String on a closed stream socket" do ready = false @@ -134,6 +135,7 @@ t.value.should == "" end + end end ruby_version_is "3.3" do diff --git a/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb index badafae81c41..8d5f541a8e75 100644 --- a/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb +++ b/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb @@ -236,6 +236,7 @@ end ruby_version_is ""..."3.3" do + quarantine! do # May fail with "IO::EAGAINWaitReadable: Resource temporarily unavailable - recvfrom(2) would block" error it "returns an empty String as received data on a closed stream socket" do ready = false @@ -258,29 +259,32 @@ t.value.should.is_a? Array t.value[0].should == "" end + end end ruby_version_is "3.3" do - it "returns nil on a closed stream socket" do - ready = false + platform_is_not :windows do + it "returns nil on a closed stream socket" do + ready = false - t = Thread.new do - client = @server.accept + t = Thread.new do + client = @server.accept - Thread.pass while !ready - client.recvmsg_nonblock(10) - ensure - client.close if client - end + Thread.pass while !ready + client.recvmsg_nonblock(10) + ensure + client.close if client + end - Thread.pass while t.status and t.status != "sleep" - t.status.should_not be_nil + Thread.pass while t.status and t.status != "sleep" + t.status.should_not be_nil - socket = TCPSocket.new('127.0.0.1', @port) - socket.close - ready = true + socket = TCPSocket.new('127.0.0.1', @port) + socket.close + ready = true - t.value.should be_nil + t.value.should be_nil + end end end end diff --git a/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb b/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb index bac5cad47af2..04ba1d74c768 100644 --- a/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb +++ b/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb @@ -209,41 +209,45 @@ end ruby_version_is ""..."3.3" do - it "returns an empty String as received data on a closed stream socket" do - t = Thread.new do - client = @server.accept - client.recvmsg(10) - ensure - client.close if client - end + platform_is_not :windows do + it "returns an empty String as received data on a closed stream socket" do + t = Thread.new do + client = @server.accept + client.recvmsg(10) + ensure + client.close if client + end - Thread.pass while t.status and t.status != "sleep" - t.status.should_not be_nil + Thread.pass while t.status and t.status != "sleep" + t.status.should_not be_nil - socket = TCPSocket.new('127.0.0.1', @port) - socket.close + socket = TCPSocket.new('127.0.0.1', @port) + socket.close - t.value.should.is_a? Array - t.value[0].should == "" + t.value.should.is_a? Array + t.value[0].should == "" + end end end ruby_version_is "3.3" do - it "returns nil on a closed stream socket" do - t = Thread.new do - client = @server.accept - client.recvmsg(10) - ensure - client.close if client - end + platform_is_not :windows do + it "returns nil on a closed stream socket" do + t = Thread.new do + client = @server.accept + client.recvmsg(10) + ensure + client.close if client + end - Thread.pass while t.status and t.status != "sleep" - t.status.should_not be_nil + Thread.pass while t.status and t.status != "sleep" + t.status.should_not be_nil - socket = TCPSocket.new('127.0.0.1', @port) - socket.close + socket = TCPSocket.new('127.0.0.1', @port) + socket.close - t.value.should be_nil + t.value.should be_nil + end end end end diff --git a/spec/ruby/library/socket/socket/gethostname_spec.rb b/spec/ruby/library/socket/socket/gethostname_spec.rb index 4b79747b2721..89e1ed496f10 100644 --- a/spec/ruby/library/socket/socket/gethostname_spec.rb +++ b/spec/ruby/library/socket/socket/gethostname_spec.rb @@ -2,7 +2,15 @@ require_relative '../fixtures/classes' describe "Socket.gethostname" do + def system_hostname + # Most platforms implement this POSIX standard: + `uname -n`.strip + rescue + # Only really required for Windows without MSYS/MinGW/Cygwin etc: + `hostname`.strip + end + it "returns the host name" do - Socket.gethostname.should == `hostname`.strip + Socket.gethostname.should == system_hostname end end diff --git a/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb b/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb index 8535e3b4f1c0..ade655e44335 100644 --- a/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb +++ b/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb @@ -159,6 +159,7 @@ end ruby_version_is ""..."3.3" do + quarantine! do # May fail with "IO::EAGAINWaitReadable: Resource temporarily unavailable - recvfrom(2) would block" error it "returns an empty String as received data on a closed stream socket" do ready = false @@ -181,9 +182,11 @@ t.value.should.is_a? Array t.value[0].should == "" end + end end ruby_version_is "3.3" do + quarantine! do # May fail with "IO::EAGAINWaitReadable: Resource temporarily unavailable - recvfrom(2) would block" error it "returns nil on a closed stream socket" do ready = false @@ -205,6 +208,7 @@ t.value.should be_nil end + end end end end diff --git a/spec/ruby/library/yaml/dump_spec.rb b/spec/ruby/library/yaml/dump_spec.rb index ea94b2f8565b..97b665d6a596 100644 --- a/spec/ruby/library/yaml/dump_spec.rb +++ b/spec/ruby/library/yaml/dump_spec.rb @@ -39,7 +39,11 @@ end it "dumps an OpenStruct" do - require "ostruct" + begin + require "ostruct" + rescue LoadError + skip "OpenStruct is not available" + end os = OpenStruct.new("age" => 20, "name" => "John") yaml_dump = YAML.dump(os) diff --git a/spec/ruby/library/yaml/shared/load.rb b/spec/ruby/library/yaml/shared/load.rb index bd55332fe5e9..b8bb605b0a02 100644 --- a/spec/ruby/library/yaml/shared/load.rb +++ b/spec/ruby/library/yaml/shared/load.rb @@ -123,7 +123,11 @@ end it "loads an OpenStruct" do - require "ostruct" + begin + require "ostruct" + rescue LoadError + skip "OpenStruct is not available" + end os = OpenStruct.new("age" => 20, "name" => "John") loaded = YAML.send(@method, "--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n") loaded.should == os diff --git a/spec/ruby/optional/capi/ext/finalizer_spec.c b/spec/ruby/optional/capi/ext/finalizer_spec.c new file mode 100644 index 000000000000..ef546aa5b1d0 --- /dev/null +++ b/spec/ruby/optional/capi/ext/finalizer_spec.c @@ -0,0 +1,31 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static VALUE define_finalizer(VALUE self, VALUE obj, VALUE finalizer) { + return rb_define_finalizer(obj, finalizer); +} + +static VALUE undefine_finalizer(VALUE self, VALUE obj) { +// Ruby 3.4.0 and 3.4.1 have a bug where rb_undefine_finalizer is missing +// See: https://bugs.ruby-lang.org/issues/20981 +#if RUBY_API_VERSION_CODE == 30400 && (RUBY_VERSION_TEENY == 0 || RUBY_VERSION_TEENY == 1) + return Qnil; +#else + return rb_undefine_finalizer(obj); +#endif +} + +void Init_finalizer_spec(void) { + VALUE cls = rb_define_class("CApiFinalizerSpecs", rb_cObject); + + rb_define_method(cls, "rb_define_finalizer", define_finalizer, 2); + rb_define_method(cls, "rb_undefine_finalizer", undefine_finalizer, 1); +} + +#ifdef __cplusplus +} +#endif diff --git a/spec/ruby/optional/capi/ext/struct_spec.c b/spec/ruby/optional/capi/ext/struct_spec.c index 63f9ced472a5..413249e828f6 100644 --- a/spec/ruby/optional/capi/ext/struct_spec.c +++ b/spec/ruby/optional/capi/ext/struct_spec.c @@ -62,6 +62,7 @@ static VALUE struct_spec_rb_struct_size(VALUE self, VALUE st) { return rb_struct_size(st); } +#if defined(RUBY_VERSION_IS_3_3) /* Only allow setting three attributes, should be sufficient for testing. */ static VALUE struct_spec_rb_data_define(VALUE self, VALUE superclass, VALUE attr1, VALUE attr2, VALUE attr3) { @@ -76,6 +77,7 @@ static VALUE struct_spec_rb_data_define(VALUE self, VALUE superclass, return rb_data_define(superclass, a1, a2, a3, NULL); } +#endif void Init_struct_spec(void) { VALUE cls = rb_define_class("CApiStructSpecs", rb_cObject); @@ -88,7 +90,9 @@ void Init_struct_spec(void) { rb_define_method(cls, "rb_struct_define_under", struct_spec_rb_struct_define_under, 5); rb_define_method(cls, "rb_struct_new", struct_spec_rb_struct_new, 4); rb_define_method(cls, "rb_struct_size", struct_spec_rb_struct_size, 1); +#if defined(RUBY_VERSION_IS_3_3) rb_define_method(cls, "rb_data_define", struct_spec_rb_data_define, 4); +#endif } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/finalizer_spec.rb b/spec/ruby/optional/capi/finalizer_spec.rb new file mode 100644 index 000000000000..162e8ea693bc --- /dev/null +++ b/spec/ruby/optional/capi/finalizer_spec.rb @@ -0,0 +1,40 @@ +require_relative "spec_helper" + +extension_path = load_extension("finalizer") + +describe "CApiFinalizerSpecs" do + before :each do + @s = CApiFinalizerSpecs.new + end + + describe "rb_define_finalizer" do + it "defines a finalizer on the object" do + code = <<~RUBY + require #{extension_path.dump} + + obj = Object.new + finalizer = Proc.new { puts "finalizer run" } + CApiFinalizerSpecs.new.rb_define_finalizer(obj, finalizer) + RUBY + + ruby_exe(code).should == "finalizer run\n" + end + end + + describe "rb_undefine_finalizer" do + ruby_bug "#20981", "3.4.0"..."3.4.2" do + it "removes finalizers from the object" do + code = <<~RUBY + require #{extension_path.dump} + + obj = Object.new + finalizer = Proc.new { puts "finalizer run" } + ObjectSpace.define_finalizer(obj, finalizer) + CApiFinalizerSpecs.new.rb_undefine_finalizer(obj) + RUBY + + ruby_exe(code).should.empty? + end + end + end +end diff --git a/spec/ruby/optional/capi/struct_spec.rb b/spec/ruby/optional/capi/struct_spec.rb index 04a2c9a31f12..474c39795690 100644 --- a/spec/ruby/optional/capi/struct_spec.rb +++ b/spec/ruby/optional/capi/struct_spec.rb @@ -257,4 +257,4 @@ end end end -end \ No newline at end of file +end From bce7f49ad066d8f1a4a098c7008b0f6d8e8d4cd7 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Fri, 31 Jan 2025 14:10:27 +0200 Subject: [PATCH 3/4] Tag slow specs --- spec/tags/library/irb/irb_tags.txt | 1 + spec/tags/optional/capi/finalizer_tags.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 spec/tags/library/irb/irb_tags.txt create mode 100644 spec/tags/optional/capi/finalizer_tags.txt diff --git a/spec/tags/library/irb/irb_tags.txt b/spec/tags/library/irb/irb_tags.txt new file mode 100644 index 000000000000..4483b6942d23 --- /dev/null +++ b/spec/tags/library/irb/irb_tags.txt @@ -0,0 +1 @@ +slow:Binding#irb creates an IRB session with the binding in scope diff --git a/spec/tags/optional/capi/finalizer_tags.txt b/spec/tags/optional/capi/finalizer_tags.txt new file mode 100644 index 000000000000..b856d8b3306c --- /dev/null +++ b/spec/tags/optional/capi/finalizer_tags.txt @@ -0,0 +1 @@ +slow:CApiFinalizerSpecs rb_define_finalizer defines a finalizer on the object From 51bf81d4276595b7da767b48bd746fc1dbc7ea79 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Fri, 31 Jan 2025 14:10:35 +0200 Subject: [PATCH 4/4] Tag failing specs --- spec/tags/core/fiber/storage_tags.txt | 3 +++ spec/tags/optional/capi/finalizer_tags.txt | 2 ++ 2 files changed, 5 insertions(+) diff --git a/spec/tags/core/fiber/storage_tags.txt b/spec/tags/core/fiber/storage_tags.txt index 21299f8096ca..a8b5e24de32f 100644 --- a/spec/tags/core/fiber/storage_tags.txt +++ b/spec/tags/core/fiber/storage_tags.txt @@ -23,3 +23,6 @@ fails:Fiber.[] can use dynamically defined keys fails:Fiber.[] can't use invalid keys fails:Fiber.[]= deletes the fiber storage key when assigning nil fails:Fiber.[] can use keys as strings +fails:Fiber.[] converts a String key into a Symbol +fails:Fiber.[] can use any object that responds to #to_str as a key +fails:Fiber.[] does not call #to_sym on the key diff --git a/spec/tags/optional/capi/finalizer_tags.txt b/spec/tags/optional/capi/finalizer_tags.txt index b856d8b3306c..8784ebaef65a 100644 --- a/spec/tags/optional/capi/finalizer_tags.txt +++ b/spec/tags/optional/capi/finalizer_tags.txt @@ -1 +1,3 @@ +fails:CApiFinalizerSpecs rb_define_finalizer defines a finalizer on the object +fails:CApiFinalizerSpecs rb_undefine_finalizer removes finalizers from the object slow:CApiFinalizerSpecs rb_define_finalizer defines a finalizer on the object