summaryrefslogtreecommitdiff
path: root/spec/ruby/core/array
diff options
context:
space:
mode:
authorBenoit Daloze <[email protected]>2022-03-03 14:43:14 +0100
committerBenoit Daloze <[email protected]>2022-03-03 14:43:14 +0100
commit3b21818db1fac0c22f16364eab2d8cc0067abd63 (patch)
tree6776a6bfe92db4e35da1ff01e09c40d4c4c20351 /spec/ruby/core/array
parent1dc6bed0ca6ca379f1c4b2e9fc0dee72dbf1e205 (diff)
Update to ruby/spec@82cd3a3
Diffstat (limited to 'spec/ruby/core/array')
-rw-r--r--spec/ruby/core/array/each_spec.rb35
1 files changed, 32 insertions, 3 deletions
diff --git a/spec/ruby/core/array/each_spec.rb b/spec/ruby/core/array/each_spec.rb
index 256647d61e..cf8e9da6d8 100644
--- a/spec/ruby/core/array/each_spec.rb
+++ b/spec/ruby/core/array/each_spec.rb
@@ -3,9 +3,10 @@ require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
require_relative '../enumerable/shared/enumeratorized'
-# Modifying a collection while the contents are being iterated
-# gives undefined behavior. See
-# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
+# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
+# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
+# CRuby simply reads the array storage and checks the size for every iteration;
+# like `i = 0; while i < size; yield self[i]; end`
describe "Array#each" do
it "yields each element to the block" do
@@ -15,6 +16,34 @@ describe "Array#each" do
a.should == [1, 2, 3]
end
+ it "yields each element to the block even if the array is changed during iteration" do
+ a = [1, 2, 3, 4, 5]
+ iterated = []
+ a.each { |x| iterated << x; a << x+5 if x.even? }
+ iterated.should == [1, 2, 3, 4, 5, 7, 9]
+ end
+
+ it "yields only elements that are still in the array" do
+ a = [0, 1, 2, 3, 4]
+ iterated = []
+ a.each { |x| iterated << x; a.pop if x.even? }
+ iterated.should == [0, 1, 2]
+ end
+
+ it "yields elements based on an internal index" do
+ a = [0, 1, 2, 3, 4]
+ iterated = []
+ a.each { |x| iterated << x; a.shift if x.even? }
+ iterated.should == [0, 2, 4]
+ end
+
+ it "yields the same element multiple times if inserting while iterating" do
+ a = [1, 2]
+ iterated = []
+ a.each { |x| iterated << x; a.unshift(0) if a.size == 2 }
+ iterated.should == [1, 1, 2]
+ end
+
it "yields each element to a block that takes multiple arguments" do
a = [[1, 2], :a, [3, 4]]
b = []