diff options
Diffstat (limited to 'spec/ruby/core/enumerator/product')
-rw-r--r-- | spec/ruby/core/enumerator/product/each_spec.rb | 73 | ||||
-rw-r--r-- | spec/ruby/core/enumerator/product/initialize_copy_spec.rb | 54 | ||||
-rw-r--r-- | spec/ruby/core/enumerator/product/initialize_spec.rb | 33 | ||||
-rw-r--r-- | spec/ruby/core/enumerator/product/inspect_spec.rb | 22 | ||||
-rw-r--r-- | spec/ruby/core/enumerator/product/rewind_spec.rb | 64 | ||||
-rw-r--r-- | spec/ruby/core/enumerator/product/size_spec.rb | 56 |
6 files changed, 302 insertions, 0 deletions
diff --git a/spec/ruby/core/enumerator/product/each_spec.rb b/spec/ruby/core/enumerator/product/each_spec.rb new file mode 100644 index 0000000000..cabeb9d93a --- /dev/null +++ b/spec/ruby/core/enumerator/product/each_spec.rb @@ -0,0 +1,73 @@ +require_relative '../../../spec_helper' +require_relative '../../enumerable/shared/enumeratorized' + +ruby_version_is "3.2" do + describe "Enumerator::Product#each" do + it_behaves_like :enumeratorized_with_origin_size, :each, Enumerator::Product.new([1, 2], [:a, :b]) + + it "yields each element of Cartesian product of enumerators" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + acc = [] + enum.each { |e| acc << e } + acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "calls #each_entry method on enumerators" do + object1 = Object.new + def object1.each_entry + yield 1 + yield 2 + end + + object2 = Object.new + def object2.each_entry + yield :a + yield :b + end + + enum = Enumerator::Product.new(object1, object2) + acc = [] + enum.each { |e| acc << e } + acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "raises a NoMethodError if the object doesn't respond to #each_entry" do + -> { + Enumerator::Product.new(Object.new).each {} + }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/) + end + + it "returns enumerator if not given a block" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.each.should.kind_of?(Enumerator) + + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "returns self if given a block" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.each {}.should.equal?(enum) + end + + it "doesn't accept arguments" do + Enumerator::Product.instance_method(:each).arity.should == 0 + end + + it "yields each element to a block that takes multiple arguments" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + + acc = [] + enum.each { |x, y| acc << x } + acc.should == [1, 1, 2, 2] + + acc = [] + enum.each { |x, y| acc << y } + acc.should == [:a, :b, :a, :b] + + acc = [] + enum.each { |x, y, z| acc << z } + acc.should == [nil, nil, nil, nil] + end + end +end diff --git a/spec/ruby/core/enumerator/product/initialize_copy_spec.rb b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb new file mode 100644 index 0000000000..46e8421322 --- /dev/null +++ b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb @@ -0,0 +1,54 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#initialize_copy" do + it "replaces content of the receiver with content of the other object" do + enum = Enumerator::Product.new([true, false]) + enum2 = Enumerator::Product.new([1, 2], [:a, :b]) + + enum.send(:initialize_copy, enum2) + enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "returns self" do + enum = Enumerator::Product.new([true, false]) + enum2 = Enumerator::Product.new([1, 2], [:a, :b]) + + enum.send(:initialize_copy, enum2).should.equal?(enum) + end + + it "is a private method" do + Enumerator::Product.should have_private_instance_method(:initialize_copy, false) + end + + it "does nothing if the argument is the same as the receiver" do + enum = Enumerator::Product.new(1..2) + enum.send(:initialize_copy, enum).should.equal?(enum) + + enum.freeze + enum.send(:initialize_copy, enum).should.equal?(enum) + end + + it "raises FrozenError if the receiver is frozen" do + enum = Enumerator::Product.new(1..2) + enum2 = Enumerator::Product.new(3..4) + + -> { enum.freeze.send(:initialize_copy, enum2) }.should raise_error(FrozenError) + end + + it "raises TypeError if the objects are of different class" do + enum = Enumerator::Product.new(1..2) + enum2 = Class.new(Enumerator::Product).new(3..4) + + -> { enum.send(:initialize_copy, enum2) }.should raise_error(TypeError, 'initialize_copy should take same class object') + -> { enum2.send(:initialize_copy, enum) }.should raise_error(TypeError, 'initialize_copy should take same class object') + end + + it "raises ArgumentError if the argument is not initialized yet" do + enum = Enumerator::Product.new(1..2) + enum2 = Enumerator::Product.allocate + + -> { enum.send(:initialize_copy, enum2) }.should raise_error(ArgumentError, 'uninitialized product') + end + end +end diff --git a/spec/ruby/core/enumerator/product/initialize_spec.rb b/spec/ruby/core/enumerator/product/initialize_spec.rb new file mode 100644 index 0000000000..4b60564240 --- /dev/null +++ b/spec/ruby/core/enumerator/product/initialize_spec.rb @@ -0,0 +1,33 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#initialize" do + before :each do + @uninitialized = Enumerator::Product.allocate + end + + it "is a private method" do + Enumerator::Product.should have_private_instance_method(:initialize, false) + end + + it "returns self" do + @uninitialized.send(:initialize).should equal(@uninitialized) + end + + it "accepts many arguments" do + @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should equal(@uninitialized) + end + + it "accepts arguments that are not Enumerable nor responding to :each_entry" do + @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) + end + + describe "on frozen instance" do + it "raises a FrozenError" do + -> { + @uninitialized.freeze.send(:initialize, 0..1) + }.should raise_error(FrozenError) + end + end + end +end diff --git a/spec/ruby/core/enumerator/product/inspect_spec.rb b/spec/ruby/core/enumerator/product/inspect_spec.rb new file mode 100644 index 0000000000..1ea8e9c49b --- /dev/null +++ b/spec/ruby/core/enumerator/product/inspect_spec.rb @@ -0,0 +1,22 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#inspect" do + it "returns a String including enumerators" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.inspect.should == "#<Enumerator::Product: [[1, 2], [:a, :b]]>" + end + + it "represents a recursive element with '[...]'" do + enum = [1, 2] + enum_recursive = Enumerator::Product.new(enum) + + enum << enum_recursive + enum_recursive.inspect.should == "#<Enumerator::Product: [[1, 2, #<Enumerator::Product: ...>]]>" + end + + it "returns a not initialized representation if #initialized is not called yet" do + Enumerator::Product.allocate.inspect.should == "#<Enumerator::Product: uninitialized>" + end + end +end diff --git a/spec/ruby/core/enumerator/product/rewind_spec.rb b/spec/ruby/core/enumerator/product/rewind_spec.rb new file mode 100644 index 0000000000..e8ee730239 --- /dev/null +++ b/spec/ruby/core/enumerator/product/rewind_spec.rb @@ -0,0 +1,64 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#rewind" do + before :each do + @enum = Enumerator::Product.new([1, 2].each.to_enum, [:a, :b].each.to_enum) + end + + it "resets the enumerator to its initial state" do + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + @enum.rewind + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "returns self" do + @enum.rewind.should.equal? @enum + end + + it "has no effect on a new enumerator" do + @enum.rewind + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "has no effect if called multiple, consecutive times" do + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + @enum.rewind + @enum.rewind + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "calls the enclosed object's rewind method if one exists" do + obj = mock('rewinder') + enum = Enumerator::Product.new(obj.to_enum) + + obj.should_receive(:rewind) + enum.rewind + end + + it "does nothing if the object doesn't have a #rewind method" do + obj = mock('rewinder') + enum = Enumerator::Product.new(obj.to_enum) + + enum.rewind.should == enum + end + + it "calls a rewind method on each enumerable in direct order" do + ScratchPad.record [] + + object1 = Object.new + def object1.rewind; ScratchPad << :object1; end + + object2 = Object.new + def object2.rewind; ScratchPad << :object2; end + + object3 = Object.new + def object3.rewind; ScratchPad << :object3; end + + enum = Enumerator::Product.new(object1, object2, object3) + enum.rewind + + ScratchPad.recorded.should == [:object1, :object2, :object3] + end + end +end diff --git a/spec/ruby/core/enumerator/product/size_spec.rb b/spec/ruby/core/enumerator/product/size_spec.rb new file mode 100644 index 0000000000..46958b1a22 --- /dev/null +++ b/spec/ruby/core/enumerator/product/size_spec.rb @@ -0,0 +1,56 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#size" do + it "returns the total size of the enumerator product calculated by multiplying the sizes of enumerables in the product" do + product = Enumerator::Product.new(1..2, 1..3, 1..4) + product.size.should == 24 # 2 * 3 * 4 + end + + it "returns nil if any enumerable reports its size as nil" do + enum = Object.new + def enum.size; nil; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns Float::INFINITY if any enumerable reports its size as Float::INFINITY" do + enum = Object.new + def enum.size; Float::INFINITY; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == Float::INFINITY + end + + it "returns nil if any enumerable reports its size as Float::NAN" do + enum = Object.new + def enum.size; Float::NAN; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns nil if any enumerable doesn't respond to #size" do + enum = Object.new + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns nil if any enumerable reports a not-convertible to Integer" do + enum = Object.new + def enum.size; :symbol; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns nil if any enumerable reports a non-Integer but convertible to Integer size" do + enum = Object.new + def enum.size; 1.0; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + end +end |