Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,23 +285,24 @@ def select # :nodoc:
end
end

if Primitive.rb_builtin_basic_definition_p(:find)
undef :find
# TODO: Temporarily disabled because it is not compatible and fails multiple spec/ruby/core/array specs
# if Primitive.rb_builtin_basic_definition_p(:find)
# undef :find

def find(if_none_proc = nil) # :nodoc:
Primitive.attr! :inline_block, :c_trace, :without_interrupts
# def find(if_none_proc = nil) # :nodoc:
# Primitive.attr! :inline_block, :c_trace, :without_interrupts

unless defined?(yield)
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
end
i = 0
until Primitive.rb_jit_ary_at_end(i)
value = Primitive.rb_jit_ary_at(i)
return value if yield(value)
i = Primitive.rb_jit_fixnum_inc(i)
end
if_none_proc&.call
end
end
# unless defined?(yield)
# return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
# end
# i = 0
# until Primitive.rb_jit_ary_at_end(i)
# value = Primitive.rb_jit_ary_at(i)
# return value if yield(value)
# i = Primitive.rb_jit_fixnum_inc(i)
# end
# if_none_proc&.call
# end
# end
end
end
5 changes: 5 additions & 0 deletions spec/ruby/command_line/dash_r_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@
out.should_not.include?("REQUIRED")
out.should.include?("No such file or directory")
end

it "requires in order when given multiple times" do
ruby_exe("", options: "-r#{fixture(__FILE__, "test_file.rb")} -r#{fixture(__FILE__, "verbose.rb")}").
should == "REQUIRED\nfalse\n"
end
end
7 changes: 6 additions & 1 deletion spec/ruby/command_line/dash_upper_e_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
ruby_exe("p 1",
options: '-Eascii:ascii -U',
args: '2>&1',
exit_status: 1).should =~ /RuntimeError/
exit_status: 1).should =~ /already set to ascii \(RuntimeError\)/
end

it "doesn't raise a RuntimeError if used with -U in RUBYOPT" do
ruby_exe("puts Encoding.default_external, Encoding.default_internal", options: '-E ascii:ascii', env: { 'RUBYOPT' => '-U' }).
should == "US-ASCII\nUS-ASCII\n"
end
end
6 changes: 6 additions & 0 deletions spec/ruby/command_line/dash_x_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
result.should == "success\n"
end

it "changes the working directory when given" do
dir = fixture __FILE__, "bin"
result = ruby_exe(nil, options: "-x#{dir} embedded_ruby_change_directory.txt")
result.should == "#{dir}\n"
end

it "fails when /\#!.*ruby.*/-ish line in target file is not found" do
bad_embedded_ruby = fixture __FILE__, "bin/bad_embedded_ruby.txt"
result = ruby_exe(bad_embedded_ruby, options: '-x', args: '2>&1', exit_status: 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@@@This line is not valid Ruby
#!ruby
puts Dir.pwd
4 changes: 2 additions & 2 deletions spec/ruby/command_line/fixtures/freeze_flag_one_literal.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ids = Array.new(2) { "abc".object_id }
p ids.first == ids.last
ids = Array.new(2) { "abc" }
p ids.first.equal? ids.last
11 changes: 11 additions & 0 deletions spec/ruby/command_line/rubyopt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
ruby_exe("p $VERBOSE").chomp.should == "true"
end

it "is overwritten by a cli switch" do
ENV["RUBYOPT"] = "-W2"
ruby_exe("p $VERBOSE", options: "-W0").chomp.should == "nil"
end

it "suppresses deprecation warnings for '-W:no-deprecated'" do
ENV["RUBYOPT"] = '-W:no-deprecated'
result = ruby_exe('$; = ""', args: '2>&1')
Expand All @@ -83,6 +88,12 @@
ruby_exe("0", args: '2>&1').should =~ /^rubyopt.rb required/
end

it "requires from CLI -r first and then from RUBYOPT -r" do
ENV["RUBYOPT"] = "-r#{fixture(__FILE__, "rubyopt.rb")}"
ruby_exe("", options: "-r#{fixture(__FILE__, "test_file.rb")}").
should == "REQUIRED\nrubyopt.rb required\n"
end

it "raises a RuntimeError for '-a'" do
ENV["RUBYOPT"] = '-a'
ruby_exe("", args: '2>&1', exit_status: 1).should =~ /RuntimeError/
Expand Down
9 changes: 9 additions & 0 deletions spec/ruby/core/array/detect_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require_relative '../../spec_helper'

ruby_version_is "4.0" do
describe "Array#detect" do
it "is an alias of Array#find" do
Array.instance_method(:detect).should == Array.instance_method(:find)
end
end
end
90 changes: 90 additions & 0 deletions spec/ruby/core/array/find_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative '../enumerable/shared/enumeratorized'

# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
# https://blade.ruby-lang.org/ruby-core/23633

ruby_version_is "4.0" do
describe "Array#find" do
it "returns the first element for which the block is not false" do
[1, 2, 3, 4, 5].find { |x| x % 2 == 0 }.should == 2
end

it "returns nil when the block is false and there is no ifnone proc given" do
[1, 2, 3].find { |x| false }.should == nil
end

it "returns the value of the ifnone proc if the block is false" do
fail_proc = -> { "cheeseburgers" }
[1, 2, 3].find(fail_proc) { |x| false }.should == "cheeseburgers"
end

it "doesn't call the ifnone proc if an element is found" do
fail_proc = -> { raise "This shouldn't have been called" }
[1, 2, 3].find(fail_proc) { |x| x == 1 }.should == 1
end

it "calls the ifnone proc only once when the block is false" do
times = 0
fail_proc = -> { times += 1; raise if times > 1; "cheeseburgers" }
[1, 2, 3].find(fail_proc) { |x| false }.should == "cheeseburgers"
end

it "calls the ifnone proc when there are no elements" do
fail_proc = -> { "yay" }
[].find(fail_proc) { |x| true }.should == "yay"
end

it "ignores the ifnone argument when nil" do
[1, 2, 3].find(nil) { |x| false }.should == nil
end

it "raises a NoMethodError if the ifnone argument does not respond to #call and no element is found" do
-> { [1, 2, 3].find(42) { |x| false } }.should.raise(NoMethodError)
end

it "iterates elements in forward order" do
visited = []
[1, 2, 3].find { |element| visited << element; false }
visited.should == [1, 2, 3]
end

it "passes through the values yielded by #each_with_index" do
ScratchPad.record []
[:a, :b].each_with_index.to_a.find { |x, i| ScratchPad << [x, i]; nil }
ScratchPad.recorded.should == [[:a, 0], [:b, 1]]
end

it "stops iterating as soon as an element is found" do
visited = []
[1, 2, 3, 4, 5].find { |x| visited << x; x == 3 }
visited.should == [1, 2, 3]
end

it "returns an enumerator when no block given" do
[1, 2, 3].find.should.instance_of?(Enumerator)
end

it "passes the ifnone proc to the enumerator" do
fail_proc = -> { "cheeseburgers" }
enum = [1, 2, 3].find(fail_proc)
enum.each { |x| false }.should == "cheeseburgers"
end

it "does not destructure elements" do
multi = [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
multi.find { |e| e == [1, 2] }.should == [1, 2]
end

it "rechecks the array size during iteration" do
ary = [4, 2, 1, 5, 1, 3]
seen = []
ary.find { |x| seen << x; ary.clear; false }
seen.should == [4]
end

it_behaves_like :enumeratorized_with_unknown_size, :find, [1, 2, 3]
end
end
2 changes: 1 addition & 1 deletion spec/ruby/core/array/fixtures/classes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def pack_format(count=nil, repeat=nil)
format = instance_variable_get(:@method)
format += count.to_s unless format == 'P' || format == 'p'
format *= repeat if repeat
format.dup # because it may then become tainted
format
end
end

Expand Down
3 changes: 0 additions & 3 deletions spec/ruby/core/array/pack/a_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
require_relative 'shared/taint'

describe "Array#pack with format 'A'" do
it_behaves_like :array_pack_basic, 'A'
it_behaves_like :array_pack_basic_non_float, 'A'
it_behaves_like :array_pack_no_platform, 'A'
it_behaves_like :array_pack_string, 'A'
it_behaves_like :array_pack_taint, 'A'

it "calls #to_str to convert an Object to a String" do
obj = mock("pack A string")
Expand Down Expand Up @@ -49,7 +47,6 @@
it_behaves_like :array_pack_basic_non_float, 'a'
it_behaves_like :array_pack_no_platform, 'a'
it_behaves_like :array_pack_string, 'a'
it_behaves_like :array_pack_taint, 'a'

it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("a*").should == "abc"
Expand Down
3 changes: 0 additions & 3 deletions spec/ruby/core/array/pack/b_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/encodings'
require_relative 'shared/taint'

describe "Array#pack with format 'B'" do
it_behaves_like :array_pack_basic, 'B'
it_behaves_like :array_pack_basic_non_float, 'B'
it_behaves_like :array_pack_arguments, 'B'
it_behaves_like :array_pack_hex, 'B'
it_behaves_like :array_pack_taint, 'B'

it "calls #to_str to convert an Object to a String" do
obj = mock("pack B string")
Expand Down Expand Up @@ -66,7 +64,6 @@
it_behaves_like :array_pack_basic_non_float, 'b'
it_behaves_like :array_pack_arguments, 'b'
it_behaves_like :array_pack_hex, 'b'
it_behaves_like :array_pack_taint, 'b'

it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
Expand Down
3 changes: 0 additions & 3 deletions spec/ruby/core/array/pack/h_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/encodings'
require_relative 'shared/taint'

describe "Array#pack with format 'H'" do
it_behaves_like :array_pack_basic, 'H'
it_behaves_like :array_pack_basic_non_float, 'H'
it_behaves_like :array_pack_arguments, 'H'
it_behaves_like :array_pack_hex, 'H'
it_behaves_like :array_pack_taint, 'H'

it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
Expand Down Expand Up @@ -112,7 +110,6 @@
it_behaves_like :array_pack_basic_non_float, 'h'
it_behaves_like :array_pack_arguments, 'h'
it_behaves_like :array_pack_hex, 'h'
it_behaves_like :array_pack_taint, 'h'

it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
Expand Down
3 changes: 0 additions & 3 deletions spec/ruby/core/array/pack/m_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'

describe "Array#pack with format 'M'" do
it_behaves_like :array_pack_basic, 'M'
it_behaves_like :array_pack_basic_non_float, 'M'
it_behaves_like :array_pack_arguments, 'M'
it_behaves_like :array_pack_taint, 'M'

it "encodes an empty string as an empty string" do
[""].pack("M").should == ""
Expand Down Expand Up @@ -202,7 +200,6 @@
it_behaves_like :array_pack_basic, 'm'
it_behaves_like :array_pack_basic_non_float, 'm'
it_behaves_like :array_pack_arguments, 'm'
it_behaves_like :array_pack_taint, 'm'

it "encodes an empty string as an empty string" do
[""].pack("m").should == ""
Expand Down
3 changes: 0 additions & 3 deletions spec/ruby/core/array/pack/p_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/taint'

describe "Array#pack with format 'P'" do
it_behaves_like :array_pack_basic_non_float, 'P'
it_behaves_like :array_pack_taint, 'P'

it "produces as many bytes as there are in a pointer" do
["hello"].pack("P").size.should == [0].pack("J").size
Expand All @@ -22,7 +20,6 @@

describe "Array#pack with format 'p'" do
it_behaves_like :array_pack_basic_non_float, 'p'
it_behaves_like :array_pack_taint, 'p'

it "produces as many bytes as there are in a pointer" do
["hello"].pack("p").size.should == [0].pack("J").size
Expand Down
2 changes: 0 additions & 2 deletions spec/ruby/core/array/pack/shared/taint.rb

This file was deleted.

2 changes: 0 additions & 2 deletions spec/ruby/core/array/pack/u_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/unicode'
require_relative 'shared/taint'

describe "Array#pack with format 'U'" do
it_behaves_like :array_pack_basic, 'U'
Expand All @@ -16,7 +15,6 @@
it_behaves_like :array_pack_basic, 'u'
it_behaves_like :array_pack_basic_non_float, 'u'
it_behaves_like :array_pack_arguments, 'u'
it_behaves_like :array_pack_taint, 'u'

it "calls #to_str to convert an Object to a String" do
obj = mock("pack u string")
Expand Down
2 changes: 0 additions & 2 deletions spec/ruby/core/array/pack/z_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
require_relative '../fixtures/classes'
require_relative 'shared/basic'
require_relative 'shared/string'
require_relative 'shared/taint'

describe "Array#pack with format 'Z'" do
it_behaves_like :array_pack_basic, 'Z'
it_behaves_like :array_pack_basic_non_float, 'Z'
it_behaves_like :array_pack_no_platform, 'Z'
it_behaves_like :array_pack_string, 'Z'
it_behaves_like :array_pack_taint, 'Z'

it "calls #to_str to convert an Object to a String" do
obj = mock("pack Z string")
Expand Down
Loading