diff --git a/core/argf/each_byte_spec.rb b/core/argf/each_byte_spec.rb index c5cce9f250..d9e4e7fe5b 100644 --- a/core/argf/each_byte_spec.rb +++ b/core/argf/each_byte_spec.rb @@ -1,6 +1,60 @@ require_relative '../../spec_helper' -require_relative 'shared/each_byte' describe "ARGF.each_byte" do - it_behaves_like :argf_each_byte, :each_byte + before :each do + @file1_name = fixture __FILE__, "file1.txt" + @file2_name = fixture __FILE__, "file2.txt" + + @bytes = [] + File.read(@file1_name).each_byte { |b| @bytes << b } + File.read(@file2_name).each_byte { |b| @bytes << b } + end + + it "yields each byte of all streams to the passed block" do + argf [@file1_name, @file2_name] do + bytes = [] + @argf.each_byte { |b| bytes << b } + bytes.should == @bytes + end + end + + it "returns self when passed a block" do + argf [@file1_name, @file2_name] do + @argf.each_byte {}.should.equal?(@argf) + end + end + + it "returns an Enumerator when passed no block" do + argf [@file1_name, @file2_name] do + enum = @argf.each_byte + enum.should.instance_of?(Enumerator) + + bytes = [] + enum.each { |b| bytes << b } + bytes.should == @bytes + end + end + + describe "when no block is given" do + it "returns an Enumerator" do + argf [@file1_name, @file2_name] do + enum = @argf.each_byte + enum.should.instance_of?(Enumerator) + + bytes = [] + enum.each { |b| bytes << b } + bytes.should == @bytes + end + end + + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + argf [@file1_name, @file2_name] do + @argf.each_byte.size.should == nil + end + end + end + end + end end diff --git a/core/argf/each_char_spec.rb b/core/argf/each_char_spec.rb index 724e5e6e3e..62d19b6574 100644 --- a/core/argf/each_char_spec.rb +++ b/core/argf/each_char_spec.rb @@ -1,6 +1,60 @@ require_relative '../../spec_helper' -require_relative 'shared/each_char' describe "ARGF.each_char" do - it_behaves_like :argf_each_char, :each_char + before :each do + @file1_name = fixture __FILE__, "file1.txt" + @file2_name = fixture __FILE__, "file2.txt" + + @chars = [] + File.read(@file1_name).each_char { |c| @chars << c } + File.read(@file2_name).each_char { |c| @chars << c } + end + + it "yields each char of all streams to the passed block" do + argf [@file1_name, @file2_name] do + chars = [] + @argf.each_char { |c| chars << c } + chars.should == @chars + end + end + + it "returns self when passed a block" do + argf [@file1_name, @file2_name] do + @argf.each_char {}.should.equal?(@argf) + end + end + + it "returns an Enumerator when passed no block" do + argf [@file1_name, @file2_name] do + enum = @argf.each_char + enum.should.instance_of?(Enumerator) + + chars = [] + enum.each { |c| chars << c } + chars.should == @chars + end + end + + describe "when no block is given" do + it "returns an Enumerator" do + argf [@file1_name, @file2_name] do + enum = @argf.each_char + enum.should.instance_of?(Enumerator) + + chars = [] + enum.each { |c| chars << c } + chars.should == @chars + end + end + + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + argf [@file1_name, @file2_name] do + @argf.each_char.size.should == nil + end + end + end + end + end end diff --git a/core/argf/each_codepoint_spec.rb b/core/argf/each_codepoint_spec.rb index 0bf8bf9764..ad55785cba 100644 --- a/core/argf/each_codepoint_spec.rb +++ b/core/argf/each_codepoint_spec.rb @@ -1,6 +1,60 @@ require_relative '../../spec_helper' -require_relative 'shared/each_codepoint' describe "ARGF.each_codepoint" do - it_behaves_like :argf_each_codepoint, :each_codepoint + before :each do + file1_name = fixture __FILE__, "file1.txt" + file2_name = fixture __FILE__, "file2.txt" + @filenames = [file1_name, file2_name] + + @codepoints = File.read(file1_name).codepoints + @codepoints.concat File.read(file2_name).codepoints + end + + it "is a public method" do + argf @filenames do + @argf.public_methods(false).should.include?(:each_codepoint) + end + end + + it "does not require arguments" do + argf @filenames do + @argf.method(:each_codepoint).arity.should == 0 + end + end + + it "returns self when passed a block" do + argf @filenames do + @argf.each_codepoint {}.should.equal?(@argf) + end + end + + it "returns an Enumerator when passed no block" do + argf @filenames do + @argf.each_codepoint.should.instance_of?(Enumerator) + end + end + + it "yields each codepoint of all streams" do + argf @filenames do + @argf.each_codepoint.to_a.should == @codepoints + end + end + + describe "when no block is given" do + it "returns an Enumerator" do + argf @filenames do + @argf.each_codepoint.should.instance_of?(Enumerator) + end + end + + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + argf @filenames do + @argf.each_codepoint.size.should == nil + end + end + end + end + end end diff --git a/core/argf/each_line_spec.rb b/core/argf/each_line_spec.rb index 52a7e5c411..fc4d6433b8 100644 --- a/core/argf/each_line_spec.rb +++ b/core/argf/each_line_spec.rb @@ -1,6 +1,64 @@ require_relative '../../spec_helper' -require_relative 'shared/each_line' describe "ARGF.each_line" do - it_behaves_like :argf_each_line, :each_line + before :each do + @file1_name = fixture __FILE__, "file1.txt" + @file2_name = fixture __FILE__, "file2.txt" + + @lines = File.readlines @file1_name + @lines += File.readlines @file2_name + end + + it "is a public method" do + argf [@file1_name, @file2_name] do + @argf.public_methods(false).should.include?(:each_line) + end + end + + it "requires multiple arguments" do + argf [@file1_name, @file2_name] do + @argf.method(:each_line).arity.should < 0 + end + end + + it "reads each line of files" do + argf [@file1_name, @file2_name] do + lines = [] + @argf.each_line { |b| lines << b } + lines.should == @lines + end + end + + it "returns self when passed a block" do + argf [@file1_name, @file2_name] do + @argf.each_line {}.should.equal?(@argf) + end + end + + describe "with a separator" do + it "yields each separated section of all streams" do + argf [@file1_name, @file2_name] do + @argf.send(:each_line, '.').to_a.should == + (File.readlines(@file1_name, '.') + File.readlines(@file2_name, '.')) + end + end + end + + describe "when no block is given" do + it "returns an Enumerator" do + argf [@file1_name, @file2_name] do + @argf.each_line.should.instance_of?(Enumerator) + end + end + + describe "returned Enumerator" do + describe "size" do + it "should return nil" do + argf [@file1_name, @file2_name] do + @argf.each_line.size.should == nil + end + end + end + end + end end diff --git a/core/argf/each_spec.rb b/core/argf/each_spec.rb index 5742ba43bd..25f60b31d2 100644 --- a/core/argf/each_spec.rb +++ b/core/argf/each_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/each_line' describe "ARGF.each" do - it_behaves_like :argf_each_line, :each + it "is an alias of ARGF.each_line" do + ARGF.method(:each).should == ARGF.method(:each_line) + end end diff --git a/core/argf/eof_spec.rb b/core/argf/eof_spec.rb index 518f6e566e..940d104d69 100644 --- a/core/argf/eof_spec.rb +++ b/core/argf/eof_spec.rb @@ -1,10 +1,32 @@ require_relative '../../spec_helper' -require_relative 'shared/eof' describe "ARGF.eof" do - it_behaves_like :argf_eof, :eof + it "is an alias of ARGF.eof?" do + ARGF.method(:eof).should == ARGF.method(:eof?) + end end describe "ARGF.eof?" do - it_behaves_like :argf_eof, :eof? + before :each do + @file1 = fixture __FILE__, "file1.txt" + @file2 = fixture __FILE__, "file2.txt" + end + + # NOTE: this test assumes that fixtures files have two lines each + it "returns true when reaching the end of a file" do + argf [@file1, @file2] do + result = [] + while @argf.gets + result << @argf.eof? + end + result.should == [false, true, false, true] + end + end + + it "raises IOError when called on a closed stream" do + argf [@file1] do + @argf.read + -> { @argf.eof? }.should.raise(IOError) + end + end end diff --git a/core/argf/filename_spec.rb b/core/argf/filename_spec.rb index 7c0446269d..f4b6e922c6 100644 --- a/core/argf/filename_spec.rb +++ b/core/argf/filename_spec.rb @@ -1,6 +1,30 @@ require_relative '../../spec_helper' -require_relative 'shared/filename' describe "ARGF.filename" do - it_behaves_like :argf_filename, :filename + before :each do + @file1 = fixture __FILE__, "file1.txt" + @file2 = fixture __FILE__, "file2.txt" + end + + # NOTE: this test assumes that fixtures files have two lines each + it "returns the current file name on each file" do + argf [@file1, @file2] do + result = [] + # returns first current file even when not yet open + result << @argf.filename + result << @argf.filename while @argf.gets + # returns last current file even when closed + result << @argf.filename + + result.map! { |f| File.expand_path(f) } + result.should == [@file1, @file1, @file1, @file2, @file2, @file2] + end + end + + # NOTE: this test assumes that fixtures files have two lines each + it "sets the $FILENAME global variable with the current file name on each file" do + script = fixture __FILE__, "filename.rb" + out = ruby_exe(script, args: [@file1, @file2]) + out.should == "#{@file1}\n#{@file1}\n#{@file2}\n#{@file2}\n#{@file2}\n" + end end diff --git a/core/argf/fileno_spec.rb b/core/argf/fileno_spec.rb index 29d50c3582..99245f043c 100644 --- a/core/argf/fileno_spec.rb +++ b/core/argf/fileno_spec.rb @@ -1,6 +1,26 @@ require_relative '../../spec_helper' -require_relative 'shared/fileno' describe "ARGF.fileno" do - it_behaves_like :argf_fileno, :fileno + before :each do + @file1 = fixture __FILE__, "file1.txt" + @file2 = fixture __FILE__, "file2.txt" + end + + # NOTE: this test assumes that fixtures files have two lines each + it "returns the current file number on each file" do + argf [@file1, @file2] do + result = [] + # returns first current file even when not yet open + result << @argf.fileno while @argf.gets + # returns last current file even when closed + result.map { |d| d.class }.should == [Integer, Integer, Integer, Integer] + end + end + + it "raises an ArgumentError when called on a closed stream" do + argf [@file1] do + @argf.read + -> { @argf.fileno }.should.raise(ArgumentError) + end + end end diff --git a/core/argf/inspect_spec.rb b/core/argf/inspect_spec.rb new file mode 100644 index 0000000000..df0e3ba8dc --- /dev/null +++ b/core/argf/inspect_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' + +describe "ARGF.inspect" do + it "is an alias of ARGF.to_s" do + ARGF.method(:inspect).should == ARGF.method(:to_s) + end +end diff --git a/core/argf/path_spec.rb b/core/argf/path_spec.rb index 7120f7d0e3..2f7b91999f 100644 --- a/core/argf/path_spec.rb +++ b/core/argf/path_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/filename' describe "ARGF.path" do - it_behaves_like :argf_filename, :path + it "is an alias of ARGF.filename" do + ARGF.method(:path).should == ARGF.method(:filename) + end end diff --git a/core/argf/pos_spec.rb b/core/argf/pos_spec.rb index fb3f25b945..1ff16e4f17 100644 --- a/core/argf/pos_spec.rb +++ b/core/argf/pos_spec.rb @@ -1,8 +1,35 @@ require_relative '../../spec_helper' -require_relative 'shared/pos' describe "ARGF.pos" do - it_behaves_like :argf_pos, :pos + before :each do + @file1 = fixture __FILE__, "file1.txt" + @file2 = fixture __FILE__, "file2.txt" + end + + it "gives the correct position for each read operation" do + argf [@file1, @file2] do + size1 = File.size(@file1) + size2 = File.size(@file2) + + @argf.read(2) + @argf.pos.should == 2 + @argf.read(size1-2) + @argf.pos.should == size1 + @argf.read(6) + @argf.pos.should == 6 + @argf.rewind + @argf.pos.should == 0 + @argf.read(size2) + @argf.pos.should == size2 + end + end + + it "raises an ArgumentError when called on a closed stream" do + argf [@file1] do + @argf.read + -> { @argf.pos }.should.raise(ArgumentError) + end + end end describe "ARGF.pos=" do diff --git a/core/argf/readlines_spec.rb b/core/argf/readlines_spec.rb index 30be936dab..156bb6a33f 100644 --- a/core/argf/readlines_spec.rb +++ b/core/argf/readlines_spec.rb @@ -1,6 +1,24 @@ require_relative '../../spec_helper' -require_relative 'shared/readlines' describe "ARGF.readlines" do - it_behaves_like :argf_readlines, :readlines + before :each do + @file1 = fixture __FILE__, "file1.txt" + @file2 = fixture __FILE__, "file2.txt" + + @lines = File.readlines(@file1) + @lines += File.readlines(@file2) + end + + it "reads all lines of all files" do + argf [@file1, @file2] do + @argf.readlines.should == @lines + end + end + + it "returns an empty Array when end of stream reached" do + argf [@file1, @file2] do + @argf.read + @argf.readlines.should == [] + end + end end diff --git a/core/argf/shared/each_byte.rb b/core/argf/shared/each_byte.rb deleted file mode 100644 index 48c9ae04f8..0000000000 --- a/core/argf/shared/each_byte.rb +++ /dev/null @@ -1,58 +0,0 @@ -describe :argf_each_byte, shared: true do - before :each do - @file1_name = fixture __FILE__, "file1.txt" - @file2_name = fixture __FILE__, "file2.txt" - - @bytes = [] - File.read(@file1_name).each_byte { |b| @bytes << b } - File.read(@file2_name).each_byte { |b| @bytes << b } - end - - it "yields each byte of all streams to the passed block" do - argf [@file1_name, @file2_name] do - bytes = [] - @argf.send(@method) { |b| bytes << b } - bytes.should == @bytes - end - end - - it "returns self when passed a block" do - argf [@file1_name, @file2_name] do - @argf.send(@method) {}.should.equal?(@argf) - end - end - - it "returns an Enumerator when passed no block" do - argf [@file1_name, @file2_name] do - enum = @argf.send(@method) - enum.should.instance_of?(Enumerator) - - bytes = [] - enum.each { |b| bytes << b } - bytes.should == @bytes - end - end - - describe "when no block is given" do - it "returns an Enumerator" do - argf [@file1_name, @file2_name] do - enum = @argf.send(@method) - enum.should.instance_of?(Enumerator) - - bytes = [] - enum.each { |b| bytes << b } - bytes.should == @bytes - end - end - - describe "returned Enumerator" do - describe "size" do - it "should return nil" do - argf [@file1_name, @file2_name] do - @argf.send(@method).size.should == nil - end - end - end - end - end -end diff --git a/core/argf/shared/each_char.rb b/core/argf/shared/each_char.rb deleted file mode 100644 index 4b5e8452ab..0000000000 --- a/core/argf/shared/each_char.rb +++ /dev/null @@ -1,58 +0,0 @@ -describe :argf_each_char, shared: true do - before :each do - @file1_name = fixture __FILE__, "file1.txt" - @file2_name = fixture __FILE__, "file2.txt" - - @chars = [] - File.read(@file1_name).each_char { |c| @chars << c } - File.read(@file2_name).each_char { |c| @chars << c } - end - - it "yields each char of all streams to the passed block" do - argf [@file1_name, @file2_name] do - chars = [] - @argf.send(@method) { |c| chars << c } - chars.should == @chars - end - end - - it "returns self when passed a block" do - argf [@file1_name, @file2_name] do - @argf.send(@method) {}.should.equal?(@argf) - end - end - - it "returns an Enumerator when passed no block" do - argf [@file1_name, @file2_name] do - enum = @argf.send(@method) - enum.should.instance_of?(Enumerator) - - chars = [] - enum.each { |c| chars << c } - chars.should == @chars - end - end - - describe "when no block is given" do - it "returns an Enumerator" do - argf [@file1_name, @file2_name] do - enum = @argf.send(@method) - enum.should.instance_of?(Enumerator) - - chars = [] - enum.each { |c| chars << c } - chars.should == @chars - end - end - - describe "returned Enumerator" do - describe "size" do - it "should return nil" do - argf [@file1_name, @file2_name] do - @argf.send(@method).size.should == nil - end - end - end - end - end -end diff --git a/core/argf/shared/each_codepoint.rb b/core/argf/shared/each_codepoint.rb deleted file mode 100644 index 3137306ad5..0000000000 --- a/core/argf/shared/each_codepoint.rb +++ /dev/null @@ -1,58 +0,0 @@ -describe :argf_each_codepoint, shared: true do - before :each do - file1_name = fixture __FILE__, "file1.txt" - file2_name = fixture __FILE__, "file2.txt" - @filenames = [file1_name, file2_name] - - @codepoints = File.read(file1_name).codepoints - @codepoints.concat File.read(file2_name).codepoints - end - - it "is a public method" do - argf @filenames do - @argf.public_methods(false).should.include?(@method) - end - end - - it "does not require arguments" do - argf @filenames do - @argf.method(@method).arity.should == 0 - end - end - - it "returns self when passed a block" do - argf @filenames do - @argf.send(@method) {}.should.equal?(@argf) - end - end - - it "returns an Enumerator when passed no block" do - argf @filenames do - @argf.send(@method).should.instance_of?(Enumerator) - end - end - - it "yields each codepoint of all streams" do - argf @filenames do - @argf.send(@method).to_a.should == @codepoints - end - end - - describe "when no block is given" do - it "returns an Enumerator" do - argf @filenames do - @argf.send(@method).should.instance_of?(Enumerator) - end - end - - describe "returned Enumerator" do - describe "size" do - it "should return nil" do - argf @filenames do - @argf.send(@method).size.should == nil - end - end - end - end - end -end diff --git a/core/argf/shared/each_line.rb b/core/argf/shared/each_line.rb deleted file mode 100644 index 7e66e38803..0000000000 --- a/core/argf/shared/each_line.rb +++ /dev/null @@ -1,62 +0,0 @@ -describe :argf_each_line, shared: true do - before :each do - @file1_name = fixture __FILE__, "file1.txt" - @file2_name = fixture __FILE__, "file2.txt" - - @lines = File.readlines @file1_name - @lines += File.readlines @file2_name - end - - it "is a public method" do - argf [@file1_name, @file2_name] do - @argf.public_methods(false).should.include?(@method) - end - end - - it "requires multiple arguments" do - argf [@file1_name, @file2_name] do - @argf.method(@method).arity.should < 0 - end - end - - it "reads each line of files" do - argf [@file1_name, @file2_name] do - lines = [] - @argf.send(@method) { |b| lines << b } - lines.should == @lines - end - end - - it "returns self when passed a block" do - argf [@file1_name, @file2_name] do - @argf.send(@method) {}.should.equal?(@argf) - end - end - - describe "with a separator" do - it "yields each separated section of all streams" do - argf [@file1_name, @file2_name] do - @argf.send(@method, '.').to_a.should == - (File.readlines(@file1_name, '.') + File.readlines(@file2_name, '.')) - end - end - end - - describe "when no block is given" do - it "returns an Enumerator" do - argf [@file1_name, @file2_name] do - @argf.send(@method).should.instance_of?(Enumerator) - end - end - - describe "returned Enumerator" do - describe "size" do - it "should return nil" do - argf [@file1_name, @file2_name] do - @argf.send(@method).size.should == nil - end - end - end - end - end -end diff --git a/core/argf/shared/eof.rb b/core/argf/shared/eof.rb deleted file mode 100644 index 8b3897b952..0000000000 --- a/core/argf/shared/eof.rb +++ /dev/null @@ -1,24 +0,0 @@ -describe :argf_eof, shared: true do - before :each do - @file1 = fixture __FILE__, "file1.txt" - @file2 = fixture __FILE__, "file2.txt" - end - - # NOTE: this test assumes that fixtures files have two lines each - it "returns true when reaching the end of a file" do - argf [@file1, @file2] do - result = [] - while @argf.gets - result << @argf.send(@method) - end - result.should == [false, true, false, true] - end - end - - it "raises IOError when called on a closed stream" do - argf [@file1] do - @argf.read - -> { @argf.send(@method) }.should.raise(IOError) - end - end -end diff --git a/core/argf/shared/filename.rb b/core/argf/shared/filename.rb deleted file mode 100644 index f47c673dc0..0000000000 --- a/core/argf/shared/filename.rb +++ /dev/null @@ -1,28 +0,0 @@ -describe :argf_filename, shared: true do - before :each do - @file1 = fixture __FILE__, "file1.txt" - @file2 = fixture __FILE__, "file2.txt" - end - - # NOTE: this test assumes that fixtures files have two lines each - it "returns the current file name on each file" do - argf [@file1, @file2] do - result = [] - # returns first current file even when not yet open - result << @argf.send(@method) - result << @argf.send(@method) while @argf.gets - # returns last current file even when closed - result << @argf.send(@method) - - result.map! { |f| File.expand_path(f) } - result.should == [@file1, @file1, @file1, @file2, @file2, @file2] - end - end - - # NOTE: this test assumes that fixtures files have two lines each - it "sets the $FILENAME global variable with the current file name on each file" do - script = fixture __FILE__, "filename.rb" - out = ruby_exe(script, args: [@file1, @file2]) - out.should == "#{@file1}\n#{@file1}\n#{@file2}\n#{@file2}\n#{@file2}\n" - end -end diff --git a/core/argf/shared/fileno.rb b/core/argf/shared/fileno.rb deleted file mode 100644 index e605be46e3..0000000000 --- a/core/argf/shared/fileno.rb +++ /dev/null @@ -1,24 +0,0 @@ -describe :argf_fileno, shared: true do - before :each do - @file1 = fixture __FILE__, "file1.txt" - @file2 = fixture __FILE__, "file2.txt" - end - - # NOTE: this test assumes that fixtures files have two lines each - it "returns the current file number on each file" do - argf [@file1, @file2] do - result = [] - # returns first current file even when not yet open - result << @argf.send(@method) while @argf.gets - # returns last current file even when closed - result.map { |d| d.class }.should == [Integer, Integer, Integer, Integer] - end - end - - it "raises an ArgumentError when called on a closed stream" do - argf [@file1] do - @argf.read - -> { @argf.send(@method) }.should.raise(ArgumentError) - end - end -end diff --git a/core/argf/shared/pos.rb b/core/argf/shared/pos.rb deleted file mode 100644 index f859d3a29d..0000000000 --- a/core/argf/shared/pos.rb +++ /dev/null @@ -1,31 +0,0 @@ -describe :argf_pos, shared: true do - before :each do - @file1 = fixture __FILE__, "file1.txt" - @file2 = fixture __FILE__, "file2.txt" - end - - it "gives the correct position for each read operation" do - argf [@file1, @file2] do - size1 = File.size(@file1) - size2 = File.size(@file2) - - @argf.read(2) - @argf.send(@method).should == 2 - @argf.read(size1-2) - @argf.send(@method).should == size1 - @argf.read(6) - @argf.send(@method).should == 6 - @argf.rewind - @argf.send(@method).should == 0 - @argf.read(size2) - @argf.send(@method).should == size2 - end - end - - it "raises an ArgumentError when called on a closed stream" do - argf [@file1] do - @argf.read - -> { @argf.send(@method) }.should.raise(ArgumentError) - end - end -end diff --git a/core/argf/shared/readlines.rb b/core/argf/shared/readlines.rb deleted file mode 100644 index 505fa94acb..0000000000 --- a/core/argf/shared/readlines.rb +++ /dev/null @@ -1,22 +0,0 @@ -describe :argf_readlines, shared: true do - before :each do - @file1 = fixture __FILE__, "file1.txt" - @file2 = fixture __FILE__, "file2.txt" - - @lines = File.readlines(@file1) - @lines += File.readlines(@file2) - end - - it "reads all lines of all files" do - argf [@file1, @file2] do - @argf.send(@method).should == @lines - end - end - - it "returns an empty Array when end of stream reached" do - argf [@file1, @file2] do - @argf.read - @argf.send(@method).should == [] - end - end -end diff --git a/core/argf/tell_spec.rb b/core/argf/tell_spec.rb index 16d9f29920..bb28df74a2 100644 --- a/core/argf/tell_spec.rb +++ b/core/argf/tell_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/pos' describe "ARGF.tell" do - it_behaves_like :argf_pos, :tell + it "is an alias of ARGF.pos" do + ARGF.method(:tell).should == ARGF.method(:pos) + end end diff --git a/core/argf/to_a_spec.rb b/core/argf/to_a_spec.rb index b17a93db33..d95dc732ec 100644 --- a/core/argf/to_a_spec.rb +++ b/core/argf/to_a_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/readlines' describe "ARGF.to_a" do - it_behaves_like :argf_readlines, :to_a + it "is an alias of ARGF.readlines" do + ARGF.method(:to_a).should == ARGF.method(:readlines) + end end diff --git a/core/argf/to_i_spec.rb b/core/argf/to_i_spec.rb index 2183de6cd4..e8df378f4e 100644 --- a/core/argf/to_i_spec.rb +++ b/core/argf/to_i_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/fileno' describe "ARGF.to_i" do - it_behaves_like :argf_fileno, :to_i + it "is an alias of ARGF.fileno" do + ARGF.method(:to_i).should == ARGF.method(:fileno) + end end diff --git a/core/array/append_spec.rb b/core/array/append_spec.rb index de0e56b513..5480d9f65e 100644 --- a/core/array/append_spec.rb +++ b/core/array/append_spec.rb @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/push' describe "Array#<<" do it "pushes the object onto the end of the array" do @@ -36,5 +35,7 @@ end describe "Array#append" do - it_behaves_like :array_push, :append + it "is an alias of Array#push" do + Array.instance_method(:append).should == Array.instance_method(:push) + end end diff --git a/core/array/collect_spec.rb b/core/array/collect_spec.rb index 0ad4c283b1..43a539f805 100644 --- a/core/array/collect_spec.rb +++ b/core/array/collect_spec.rb @@ -1,11 +1,143 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/collect' +require_relative '../enumerable/shared/enumeratorized' +require_relative 'shared/iterable_and_tolerating_size_increasing' describe "Array#collect" do - it_behaves_like :array_collect, :collect + it "returns a copy of array with each element replaced by the value returned by block" do + a = ['a', 'b', 'c', 'd'] + b = a.collect { |i| i + '!' } + b.should == ["a!", "b!", "c!", "d!"] + b.should_not.equal? a + end + + it "does not return subclass instance" do + ArraySpecs::MyArray[1, 2, 3].collect { |x| x + 1 }.should.instance_of?(Array) + end + + it "does not change self" do + a = ['a', 'b', 'c', 'd'] + a.collect { |i| i + '!' } + a.should == ['a', 'b', 'c', 'd'] + end + + it "returns the evaluated value of block if it broke in the block" do + a = ['a', 'b', 'c', 'd'] + b = a.collect {|i| + if i == 'c' + break 0 + else + i + '!' + end + } + b.should == 0 + end + + it "returns an Enumerator when no block given" do + a = [1, 2, 3] + a.collect.should.instance_of?(Enumerator) + end + + it "raises an ArgumentError when no block and with arguments" do + a = [1, 2, 3] + -> { + a.collect(:foo) + }.should.raise(ArgumentError) + end + + before :each do + @object = [1, 2, 3, 4] + end + it_behaves_like :enumeratorized_with_origin_size, :collect + + it_behaves_like :array_iterable_and_tolerating_size_increasing, :collect end describe "Array#collect!" do - it_behaves_like :array_collect_b, :collect! + it "replaces each element with the value returned by block" do + a = [7, 9, 3, 5] + a.collect! { |i| i - 1 }.should.equal?(a) + a.should == [6, 8, 2, 4] + end + + it "returns self" do + a = [1, 2, 3, 4, 5] + b = a.collect! {|i| i+1 } + a.should.equal? b + end + + it "returns the evaluated value of block but its contents is partially modified, if it broke in the block" do + a = ['a', 'b', 'c', 'd'] + b = a.collect! {|i| + if i == 'c' + break 0 + else + i + '!' + end + } + b.should == 0 + a.should == ['a!', 'b!', 'c', 'd'] + end + + it "returns an Enumerator when no block given, and the enumerator can modify the original array" do + a = [1, 2, 3] + enum = a.collect! + enum.should.instance_of?(Enumerator) + enum.each{|i| "#{i}!" } + a.should == ["1!", "2!", "3!"] + end + + describe "when frozen" do + it "raises a FrozenError" do + -> { ArraySpecs.frozen_array.collect! {} }.should.raise(FrozenError) + end + + it "raises a FrozenError when empty" do + -> { ArraySpecs.empty_frozen_array.collect! {} }.should.raise(FrozenError) + end + + it "raises a FrozenError when calling #each on the returned Enumerator" do + enumerator = ArraySpecs.frozen_array.collect! + -> { enumerator.each {|x| x } }.should.raise(FrozenError) + end + + it "raises a FrozenError when calling #each on the returned Enumerator when empty" do + enumerator = ArraySpecs.empty_frozen_array.collect! + -> { enumerator.each {|x| x } }.should.raise(FrozenError) + end + end + + it "does not truncate the array is the block raises an exception" do + a = [1, 2, 3] + begin + a.collect! { raise StandardError, 'Oops' } + rescue + end + + a.should == [1, 2, 3] + end + + it "only changes elements before error is raised, keeping the element which raised an error." do + a = [1, 2, 3, 4] + begin + a.collect! do |e| + case e + when 1 then -1 + when 2 then -2 + when 3 then raise StandardError, 'Oops' + else 0 + end + end + rescue StandardError + end + + a.should == [-1, -2, 3, 4] + end + + before :each do + @object = [1, 2, 3, 4] + end + it_behaves_like :enumeratorized_with_origin_size, :collect! + + it_behaves_like :array_iterable_and_tolerating_size_increasing, :collect! end diff --git a/core/array/element_reference_spec.rb b/core/array/element_reference_spec.rb index eb41a9e199..d5f4b54961 100644 --- a/core/array/element_reference_spec.rb +++ b/core/array/element_reference_spec.rb @@ -1,9 +1,862 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/slice' describe "Array#[]" do - it_behaves_like :array_slice, :[] + it "returns the element at index with [index]" do + [ "a", "b", "c", "d", "e" ][1].should == "b" + + a = [1, 2, 3, 4] + + a[0].should == 1 + a[1].should == 2 + a[2].should == 3 + a[3].should == 4 + a[4].should == nil + a[10].should == nil + + a.should == [1, 2, 3, 4] + end + + it "returns the element at index from the end of the array with [-index]" do + [ "a", "b", "c", "d", "e" ][-2].should == "d" + + a = [1, 2, 3, 4] + + a[-1].should == 4 + a[-2].should == 3 + a[-3].should == 2 + a[-4].should == 1 + a[-5].should == nil + a[-10].should == nil + + a.should == [1, 2, 3, 4] + end + + it "returns count elements starting from index with [index, count]" do + [ "a", "b", "c", "d", "e" ][2, 3].should == ["c", "d", "e"] + + a = [1, 2, 3, 4] + + a[0, 0].should == [] + a[0, 1].should == [1] + a[0, 2].should == [1, 2] + a[0, 4].should == [1, 2, 3, 4] + a[0, 6].should == [1, 2, 3, 4] + a[0, -1].should == nil + a[0, -2].should == nil + a[0, -4].should == nil + + a[2, 0].should == [] + a[2, 1].should == [3] + a[2, 2].should == [3, 4] + a[2, 4].should == [3, 4] + a[2, -1].should == nil + + a[4, 0].should == [] + a[4, 2].should == [] + a[4, -1].should == nil + + a[5, 0].should == nil + a[5, 2].should == nil + a[5, -1].should == nil + + a[6, 0].should == nil + a[6, 2].should == nil + a[6, -1].should == nil + + a.should == [1, 2, 3, 4] + end + + it "returns count elements starting at index from the end of array with [-index, count]" do + [ "a", "b", "c", "d", "e" ][-2, 2].should == ["d", "e"] + + a = [1, 2, 3, 4] + + a[-1, 0].should == [] + a[-1, 1].should == [4] + a[-1, 2].should == [4] + a[-1, -1].should == nil + + a[-2, 0].should == [] + a[-2, 1].should == [3] + a[-2, 2].should == [3, 4] + a[-2, 4].should == [3, 4] + a[-2, -1].should == nil + + a[-4, 0].should == [] + a[-4, 1].should == [1] + a[-4, 2].should == [1, 2] + a[-4, 4].should == [1, 2, 3, 4] + a[-4, 6].should == [1, 2, 3, 4] + a[-4, -1].should == nil + + a[-5, 0].should == nil + a[-5, 1].should == nil + a[-5, 10].should == nil + a[-5, -1].should == nil + + a.should == [1, 2, 3, 4] + end + + it "returns the first count elements with [0, count]" do + [ "a", "b", "c", "d", "e" ][0, 3].should == ["a", "b", "c"] + end + + it "returns the subarray which is independent to self with [index,count]" do + a = [1, 2, 3] + sub = a[1, 2] + sub.replace([:a, :b]) + a.should == [1, 2, 3] + end + + it "tries to convert the passed argument to an Integer using #to_int" do + obj = mock('to_int') + obj.stub!(:to_int).and_return(2) + + a = [1, 2, 3, 4] + a[obj].should == 3 + a[obj, 1].should == [3] + a[obj, obj].should == [3, 4] + a[0, obj].should == [1, 2] + end + + it "raises TypeError if to_int returns non-integer" do + from = mock('from') + to = mock('to') + + # So we can construct a range out of them... + def from.<=>(o) 0 end + def to.<=>(o) 0 end + + a = [1, 2, 3, 4, 5] + + def from.to_int() 'cat' end + def to.to_int() -2 end + + -> { a[from..to] }.should.raise(TypeError) + + def from.to_int() 1 end + def to.to_int() 'cat' end + + -> { a[from..to] }.should.raise(TypeError) + end + + it "returns the elements specified by Range indexes with [m..n]" do + [ "a", "b", "c", "d", "e" ][1..3].should == ["b", "c", "d"] + [ "a", "b", "c", "d", "e" ][4..-1].should == ['e'] + [ "a", "b", "c", "d", "e" ][3..3].should == ['d'] + [ "a", "b", "c", "d", "e" ][3..-2].should == ['d'] + ['a'][0..-1].should == ['a'] + + a = [1, 2, 3, 4] + + a[0..-10].should == [] + a[0..0].should == [1] + a[0..1].should == [1, 2] + a[0..2].should == [1, 2, 3] + a[0..3].should == [1, 2, 3, 4] + a[0..4].should == [1, 2, 3, 4] + a[0..10].should == [1, 2, 3, 4] + + a[2..-10].should == [] + a[2..0].should == [] + a[2..2].should == [3] + a[2..3].should == [3, 4] + a[2..4].should == [3, 4] + + a[3..0].should == [] + a[3..3].should == [4] + a[3..4].should == [4] + + a[4..0].should == [] + a[4..4].should == [] + a[4..5].should == [] + + a[5..0].should == nil + a[5..5].should == nil + a[5..6].should == nil + + a.should == [1, 2, 3, 4] + end + + it "returns elements specified by Range indexes except the element at index n with [m...n]" do + [ "a", "b", "c", "d", "e" ][1...3].should == ["b", "c"] + + a = [1, 2, 3, 4] + + a[0...-10].should == [] + a[0...0].should == [] + a[0...1].should == [1] + a[0...2].should == [1, 2] + a[0...3].should == [1, 2, 3] + a[0...4].should == [1, 2, 3, 4] + a[0...10].should == [1, 2, 3, 4] + + a[2...-10].should == [] + a[2...0].should == [] + a[2...2].should == [] + a[2...3].should == [3] + a[2...4].should == [3, 4] + + a[3...0].should == [] + a[3...3].should == [] + a[3...4].should == [4] + + a[4...0].should == [] + a[4...4].should == [] + a[4...5].should == [] + + a[5...0].should == nil + a[5...5].should == nil + a[5...6].should == nil + + a.should == [1, 2, 3, 4] + end + + it "returns elements that exist if range start is in the array but range end is not with [m..n]" do + [ "a", "b", "c", "d", "e" ][4..7].should == ["e"] + end + + it "accepts Range instances having a negative m and both signs for n with [m..n] and [m...n]" do + a = [1, 2, 3, 4] + + a[-1..-1].should == [4] + a[-1...-1].should == [] + a[-1..3].should == [4] + a[-1...3].should == [] + a[-1..4].should == [4] + a[-1...4].should == [4] + a[-1..10].should == [4] + a[-1...10].should == [4] + a[-1..0].should == [] + a[-1..-4].should == [] + a[-1...-4].should == [] + a[-1..-6].should == [] + a[-1...-6].should == [] + + a[-2..-2].should == [3] + a[-2...-2].should == [] + a[-2..-1].should == [3, 4] + a[-2...-1].should == [3] + a[-2..10].should == [3, 4] + a[-2...10].should == [3, 4] + + a[-4..-4].should == [1] + a[-4..-2].should == [1, 2, 3] + a[-4...-2].should == [1, 2] + a[-4..-1].should == [1, 2, 3, 4] + a[-4...-1].should == [1, 2, 3] + a[-4..3].should == [1, 2, 3, 4] + a[-4...3].should == [1, 2, 3] + a[-4..4].should == [1, 2, 3, 4] + a[-4...4].should == [1, 2, 3, 4] + a[-4...4].should == [1, 2, 3, 4] + a[-4..0].should == [1] + a[-4...0].should == [] + a[-4..1].should == [1, 2] + a[-4...1].should == [1] + + a[-5..-5].should == nil + a[-5...-5].should == nil + a[-5..-4].should == nil + a[-5..-1].should == nil + a[-5..10].should == nil + + a.should == [1, 2, 3, 4] + end + + it "returns the subarray which is independent to self with [m..n]" do + a = [1, 2, 3] + sub = a[1..2] + sub.replace([:a, :b]) + a.should == [1, 2, 3] + end + + it "tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]" do + from = mock('from') + to = mock('to') + + # So we can construct a range out of them... + def from.<=>(o) 0 end + def to.<=>(o) 0 end + + def from.to_int() 1 end + def to.to_int() -2 end + + a = [1, 2, 3, 4] + + a[from..to].should == [2, 3] + a[from...to].should == [2] + a[1..0].should == [] + a[1...0].should == [] + + -> { a["a" .. "b"] }.should.raise(TypeError) + -> { a["a" ... "b"] }.should.raise(TypeError) + -> { a[from .. "b"] }.should.raise(TypeError) + -> { a[from ... "b"] }.should.raise(TypeError) + end + + it "returns the same elements as [m..n] and [m...n] with Range subclasses" do + a = [1, 2, 3, 4] + range_incl = ArraySpecs::MyRange.new(1, 2) + range_excl = ArraySpecs::MyRange.new(-3, -1, true) + + a[range_incl].should == [2, 3] + a[range_excl].should == [2, 3] + end + + it "returns nil for a requested index not in the array with [index]" do + [ "a", "b", "c", "d", "e" ][5].should == nil + end + + it "returns [] if the index is valid but length is zero with [index, length]" do + [ "a", "b", "c", "d", "e" ][0, 0].should == [] + [ "a", "b", "c", "d", "e" ][2, 0].should == [] + end + + it "returns nil if length is zero but index is invalid with [index, length]" do + [ "a", "b", "c", "d", "e" ][100, 0].should == nil + [ "a", "b", "c", "d", "e" ][-50, 0].should == nil + end + + # This is by design. It is in the official documentation. + it "returns [] if index == array.size with [index, length]" do + %w|a b c d e|[5, 2].should == [] + end + + it "returns nil if index > array.size with [index, length]" do + %w|a b c d e|[6, 2].should == nil + end + + it "returns nil if length is negative with [index, length]" do + %w|a b c d e|[3, -1].should == nil + %w|a b c d e|[2, -2].should == nil + %w|a b c d e|[1, -100].should == nil + end + + it "returns nil if no requested index is in the array with [m..n]" do + [ "a", "b", "c", "d", "e" ][6..10].should == nil + end + + it "returns nil if range start is not in the array with [m..n]" do + [ "a", "b", "c", "d", "e" ][-10..2].should == nil + [ "a", "b", "c", "d", "e" ][10..12].should == nil + end + + it "returns an empty array when m == n with [m...n]" do + [1, 2, 3, 4, 5][1...1].should == [] + end + + it "returns an empty array with [0...0]" do + [1, 2, 3, 4, 5][0...0].should == [] + end + + it "returns a subarray where m, n negatives and m < n with [m..n]" do + [ "a", "b", "c", "d", "e" ][-3..-2].should == ["c", "d"] + end + + it "returns an array containing the first element with [0..0]" do + [1, 2, 3, 4, 5][0..0].should == [1] + end + + it "returns the entire array with [0..-1]" do + [1, 2, 3, 4, 5][0..-1].should == [1, 2, 3, 4, 5] + end + + it "returns all but the last element with [0...-1]" do + [1, 2, 3, 4, 5][0...-1].should == [1, 2, 3, 4] + end + + it "returns [3] for [2..-1] out of [1, 2, 3]" do + [1,2,3][2..-1].should == [3] + end + + it "returns an empty array when m > n and m, n are positive with [m..n]" do + [1, 2, 3, 4, 5][3..2].should == [] + end + + it "returns an empty array when m > n and m, n are negative with [m..n]" do + [1, 2, 3, 4, 5][-2..-3].should == [] + end + + it "does not expand array when the indices are outside of the array bounds" do + a = [1, 2] + a[4].should == nil + a.should == [1, 2] + a[4, 0].should == nil + a.should == [1, 2] + a[6, 1].should == nil + a.should == [1, 2] + a[8...8].should == nil + a.should == [1, 2] + a[10..10].should == nil + a.should == [1, 2] + end + + describe "with a subclass of Array" do + before :each do + ScratchPad.clear + + @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] + end + + it "returns a Array instance with [n, m]" do + @array[0, 2].should.instance_of?(Array) + end + + it "returns a Array instance with [-n, m]" do + @array[-3, 2].should.instance_of?(Array) + end + + it "returns a Array instance with [n..m]" do + @array[1..3].should.instance_of?(Array) + end + + it "returns a Array instance with [n...m]" do + @array[1...3].should.instance_of?(Array) + end + + it "returns a Array instance with [-n..-m]" do + @array[-3..-1].should.instance_of?(Array) + end + + it "returns a Array instance with [-n...-m]" do + @array[-3...-1].should.instance_of?(Array) + end + + it "returns an empty array when m == n with [m...n]" do + @array[1...1].should == [] + ScratchPad.recorded.should == nil + end + + it "returns an empty array with [0...0]" do + @array[0...0].should == [] + ScratchPad.recorded.should == nil + end + + it "returns an empty array when m > n and m, n are positive with [m..n]" do + @array[3..2].should == [] + ScratchPad.recorded.should == nil + end + + it "returns an empty array when m > n and m, n are negative with [m..n]" do + @array[-2..-3].should == [] + ScratchPad.recorded.should == nil + end + + it "returns [] if index == array.size with [index, length]" do + @array[5, 2].should == [] + ScratchPad.recorded.should == nil + end + + it "returns [] if the index is valid but length is zero with [index, length]" do + @array[0, 0].should == [] + @array[2, 0].should == [] + ScratchPad.recorded.should == nil + end + + it "does not call #initialize on the subclass instance" do + @array[0, 3].should == [1, 2, 3] + ScratchPad.recorded.should == nil + end + end + + it "raises a RangeError when the start index is out of range of Fixnum" do + array = [1, 2, 3, 4, 5, 6] + obj = mock('large value') + obj.should_receive(:to_int).and_return(bignum_value) + -> { array[obj] }.should.raise(RangeError) + + obj = 8e19 + -> { array[obj] }.should.raise(RangeError) + + # boundary value when longs are 64 bits + -> { array[2.0**63] }.should.raise(RangeError) + + # just under the boundary value when longs are 64 bits + array[max_long.to_f.prev_float].should == nil + end + + it "raises a RangeError when the length is out of range of Fixnum" do + array = [1, 2, 3, 4, 5, 6] + obj = mock('large value') + obj.should_receive(:to_int).and_return(bignum_value) + -> { array[1, obj] }.should.raise(RangeError) + + obj = 8e19 + -> { array[1, obj] }.should.raise(RangeError) + end + + it "raises a type error if a range is passed with a length" do + ->{ [1, 2, 3][1..2, 1] }.should.raise(TypeError) + end + + it "raises a RangeError if passed a range with a bound that is too large" do + array = [1, 2, 3, 4, 5, 6] + -> { array[bignum_value..(bignum_value + 1)] }.should.raise(RangeError) + -> { array[0..bignum_value] }.should.raise(RangeError) + end + + it "can accept endless ranges" do + a = [0, 1, 2, 3, 4, 5] + a[eval("(2..)")].should == [2, 3, 4, 5] + a[eval("(2...)")].should == [2, 3, 4, 5] + a[eval("(-2..)")].should == [4, 5] + a[eval("(-2...)")].should == [4, 5] + a[eval("(9..)")].should == nil + a[eval("(9...)")].should == nil + a[eval("(-9..)")].should == nil + a[eval("(-9...)")].should == nil + end + + describe "can be sliced with Enumerator::ArithmeticSequence" do + before :each do + @array = [0, 1, 2, 3, 4, 5] + end + + it "has endless range and positive steps" do + @array[eval("(0..).step(1)")].should == [0, 1, 2, 3, 4, 5] + @array[eval("(0..).step(2)")].should == [0, 2, 4] + @array[eval("(0..).step(10)")].should == [0] + + @array[eval("(2..).step(1)")].should == [2, 3, 4, 5] + @array[eval("(2..).step(2)")].should == [2, 4] + @array[eval("(2..).step(10)")].should == [2] + + @array[eval("(-3..).step(1)")].should == [3, 4, 5] + @array[eval("(-3..).step(2)")].should == [3, 5] + @array[eval("(-3..).step(10)")].should == [3] + end + + it "has beginless range and positive steps" do + # end with zero index + @array[(..0).step(1)].should == [0] + @array[(...0).step(1)].should == [] + + @array[(..0).step(2)].should == [0] + @array[(...0).step(2)].should == [] + + @array[(..0).step(10)].should == [0] + @array[(...0).step(10)].should == [] + + # end with positive index + @array[(..3).step(1)].should == [0, 1, 2, 3] + @array[(...3).step(1)].should == [0, 1, 2] + + @array[(..3).step(2)].should == [0, 2] + @array[(...3).step(2)].should == [0, 2] + + @array[(..3).step(10)].should == [0] + @array[(...3).step(10)].should == [0] + + # end with negative index + @array[(..-2).step(1)].should == [0, 1, 2, 3, 4,] + @array[(...-2).step(1)].should == [0, 1, 2, 3] + + @array[(..-2).step(2)].should == [0, 2, 4] + @array[(...-2).step(2)].should == [0, 2] + + @array[(..-2).step(10)].should == [0] + @array[(...-2).step(10)].should == [0] + end + + it "has endless range and negative steps" do + @array[eval("(0..).step(-1)")].should == [0] + @array[eval("(0..).step(-2)")].should == [0] + @array[eval("(0..).step(-10)")].should == [0] + + @array[eval("(2..).step(-1)")].should == [2, 1, 0] + @array[eval("(2..).step(-2)")].should == [2, 0] + + @array[eval("(-3..).step(-1)")].should == [3, 2, 1, 0] + @array[eval("(-3..).step(-2)")].should == [3, 1] + end + + it "has closed range and positive steps" do + # start and end with 0 + @array[eval("(0..0).step(1)")].should == [0] + @array[eval("(0...0).step(1)")].should == [] + + @array[eval("(0..0).step(2)")].should == [0] + @array[eval("(0...0).step(2)")].should == [] + + @array[eval("(0..0).step(10)")].should == [0] + @array[eval("(0...0).step(10)")].should == [] + + # start and end with positive index + @array[eval("(1..3).step(1)")].should == [1, 2, 3] + @array[eval("(1...3).step(1)")].should == [1, 2] + + @array[eval("(1..3).step(2)")].should == [1, 3] + @array[eval("(1...3).step(2)")].should == [1] + + @array[eval("(1..3).step(10)")].should == [1] + @array[eval("(1...3).step(10)")].should == [1] + + # start with positive index, end with negative index + @array[eval("(1..-2).step(1)")].should == [1, 2, 3, 4] + @array[eval("(1...-2).step(1)")].should == [1, 2, 3] + + @array[eval("(1..-2).step(2)")].should == [1, 3] + @array[eval("(1...-2).step(2)")].should == [1, 3] + + @array[eval("(1..-2).step(10)")].should == [1] + @array[eval("(1...-2).step(10)")].should == [1] + + # start with negative index, end with positive index + @array[eval("(-4..4).step(1)")].should == [2, 3, 4] + @array[eval("(-4...4).step(1)")].should == [2, 3] + + @array[eval("(-4..4).step(2)")].should == [2, 4] + @array[eval("(-4...4).step(2)")].should == [2] + + @array[eval("(-4..4).step(10)")].should == [2] + @array[eval("(-4...4).step(10)")].should == [2] + + # start with negative index, end with negative index + @array[eval("(-4..-2).step(1)")].should == [2, 3, 4] + @array[eval("(-4...-2).step(1)")].should == [2, 3] + + @array[eval("(-4..-2).step(2)")].should == [2, 4] + @array[eval("(-4...-2).step(2)")].should == [2] + + @array[eval("(-4..-2).step(10)")].should == [2] + @array[eval("(-4...-2).step(10)")].should == [2] + end + + it "has closed range and negative steps" do + # start and end with 0 + @array[eval("(0..0).step(-1)")].should == [0] + @array[eval("(0...0).step(-1)")].should == [] + + @array[eval("(0..0).step(-2)")].should == [0] + @array[eval("(0...0).step(-2)")].should == [] + + @array[eval("(0..0).step(-10)")].should == [0] + @array[eval("(0...0).step(-10)")].should == [] + + # start and end with positive index + @array[eval("(1..3).step(-1)")].should == [] + @array[eval("(1...3).step(-1)")].should == [] + + @array[eval("(1..3).step(-2)")].should == [] + @array[eval("(1...3).step(-2)")].should == [] + + @array[eval("(1..3).step(-10)")].should == [] + @array[eval("(1...3).step(-10)")].should == [] + + # start with positive index, end with negative index + @array[eval("(1..-2).step(-1)")].should == [] + @array[eval("(1...-2).step(-1)")].should == [] + + @array[eval("(1..-2).step(-2)")].should == [] + @array[eval("(1...-2).step(-2)")].should == [] + + @array[eval("(1..-2).step(-10)")].should == [] + @array[eval("(1...-2).step(-10)")].should == [] + + # start with negative index, end with positive index + @array[eval("(-4..4).step(-1)")].should == [] + @array[eval("(-4...4).step(-1)")].should == [] + + @array[eval("(-4..4).step(-2)")].should == [] + @array[eval("(-4...4).step(-2)")].should == [] + + @array[eval("(-4..4).step(-10)")].should == [] + @array[eval("(-4...4).step(-10)")].should == [] + + # start with negative index, end with negative index + @array[eval("(-4..-2).step(-1)")].should == [] + @array[eval("(-4...-2).step(-1)")].should == [] + + @array[eval("(-4..-2).step(-2)")].should == [] + @array[eval("(-4...-2).step(-2)")].should == [] + + @array[eval("(-4..-2).step(-10)")].should == [] + @array[eval("(-4...-2).step(-10)")].should == [] + end + + it "has inverted closed range and positive steps" do + # start and end with positive index + @array[eval("(3..1).step(1)")].should == [] + @array[eval("(3...1).step(1)")].should == [] + + @array[eval("(3..1).step(2)")].should == [] + @array[eval("(3...1).step(2)")].should == [] + + @array[eval("(3..1).step(10)")].should == [] + @array[eval("(3...1).step(10)")].should == [] + + # start with negative index, end with positive index + @array[eval("(-2..1).step(1)")].should == [] + @array[eval("(-2...1).step(1)")].should == [] + + @array[eval("(-2..1).step(2)")].should == [] + @array[eval("(-2...1).step(2)")].should == [] + + @array[eval("(-2..1).step(10)")].should == [] + @array[eval("(-2...1).step(10)")].should == [] + + # start with positive index, end with negative index + @array[eval("(4..-4).step(1)")].should == [] + @array[eval("(4...-4).step(1)")].should == [] + + @array[eval("(4..-4).step(2)")].should == [] + @array[eval("(4...-4).step(2)")].should == [] + + @array[eval("(4..-4).step(10)")].should == [] + @array[eval("(4...-4).step(10)")].should == [] + + # start with negative index, end with negative index + @array[eval("(-2..-4).step(1)")].should == [] + @array[eval("(-2...-4).step(1)")].should == [] + + @array[eval("(-2..-4).step(2)")].should == [] + @array[eval("(-2...-4).step(2)")].should == [] + + @array[eval("(-2..-4).step(10)")].should == [] + @array[eval("(-2...-4).step(10)")].should == [] + end + + it "has range with bounds outside of array" do + # end is equal to array's length + @array[(0..6).step(1)].should == [0, 1, 2, 3, 4, 5] + -> { @array[(0..6).step(2)] }.should.raise(RangeError) + + # end is greater than length with positive steps + @array[(1..6).step(2)].should == [1, 3, 5] + @array[(2..7).step(2)].should == [2, 4] + -> { @array[(2..8).step(2)] }.should.raise(RangeError) + + # begin is greater than length with negative steps + @array[(6..1).step(-2)].should == [5, 3, 1] + @array[(7..2).step(-2)].should == [5, 3] + -> { @array[(8..2).step(-2)] }.should.raise(RangeError) + end + + it "has endless range with start outside of array's bounds" do + @array[eval("(6..).step(1)")].should == [] + @array[eval("(7..).step(1)")].should == nil + + @array[eval("(6..).step(2)")].should == [] + -> { @array[eval("(7..).step(2)")] }.should.raise(RangeError) + end + end + + it "can accept beginless ranges" do + a = [0, 1, 2, 3, 4, 5] + a[(..3)].should == [0, 1, 2, 3] + a[(...3)].should == [0, 1, 2] + a[(..-3)].should == [0, 1, 2, 3] + a[(...-3)].should == [0, 1, 2] + a[(..0)].should == [0] + a[(...0)].should == [] + a[(..9)].should == [0, 1, 2, 3, 4, 5] + a[(...9)].should == [0, 1, 2, 3, 4, 5] + a[(..-9)].should == [] + a[(...-9)].should == [] + end + + describe "can be sliced with Enumerator::ArithmeticSequence" do + it "with infinite/inverted ranges and negative steps" do + array = [0, 1, 2, 3, 4, 5] + array[(2..).step(-1)].should == [2, 1, 0] + array[(2..).step(-2)].should == [2, 0] + array[(2..).step(-3)].should == [2] + array[(2..).step(-4)].should == [2] + + array[(-3..).step(-1)].should == [3, 2, 1, 0] + array[(-3..).step(-2)].should == [3, 1] + array[(-3..).step(-3)].should == [3, 0] + array[(-3..).step(-4)].should == [3] + array[(-3..).step(-5)].should == [3] + + array[(..0).step(-1)].should == [5, 4, 3, 2, 1, 0] + array[(..0).step(-2)].should == [5, 3, 1] + array[(..0).step(-3)].should == [5, 2] + array[(..0).step(-4)].should == [5, 1] + array[(..0).step(-5)].should == [5, 0] + array[(..0).step(-6)].should == [5] + array[(..0).step(-7)].should == [5] + + array[(...0).step(-1)].should == [5, 4, 3, 2, 1] + array[(...0).step(-2)].should == [5, 3, 1] + array[(...0).step(-3)].should == [5, 2] + array[(...0).step(-4)].should == [5, 1] + array[(...0).step(-5)].should == [5] + array[(...0).step(-6)].should == [5] + + array[(...1).step(-1)].should == [5, 4, 3, 2] + array[(...1).step(-2)].should == [5, 3] + array[(...1).step(-3)].should == [5, 2] + array[(...1).step(-4)].should == [5] + array[(...1).step(-5)].should == [5] + + array[(..-5).step(-1)].should == [5, 4, 3, 2, 1] + array[(..-5).step(-2)].should == [5, 3, 1] + array[(..-5).step(-3)].should == [5, 2] + array[(..-5).step(-4)].should == [5, 1] + array[(..-5).step(-5)].should == [5] + array[(..-5).step(-6)].should == [5] + + array[(...-5).step(-1)].should == [5, 4, 3, 2] + array[(...-5).step(-2)].should == [5, 3] + array[(...-5).step(-3)].should == [5, 2] + array[(...-5).step(-4)].should == [5] + array[(...-5).step(-5)].should == [5] + + array[(4..1).step(-1)].should == [4, 3, 2, 1] + array[(4..1).step(-2)].should == [4, 2] + array[(4..1).step(-3)].should == [4, 1] + array[(4..1).step(-4)].should == [4] + array[(4..1).step(-5)].should == [4] + + array[(4...1).step(-1)].should == [4, 3, 2] + array[(4...1).step(-2)].should == [4, 2] + array[(4...1).step(-3)].should == [4] + array[(4...1).step(-4)].should == [4] + + array[(-2..1).step(-1)].should == [4, 3, 2, 1] + array[(-2..1).step(-2)].should == [4, 2] + array[(-2..1).step(-3)].should == [4, 1] + array[(-2..1).step(-4)].should == [4] + array[(-2..1).step(-5)].should == [4] + + array[(-2...1).step(-1)].should == [4, 3, 2] + array[(-2...1).step(-2)].should == [4, 2] + array[(-2...1).step(-3)].should == [4] + array[(-2...1).step(-4)].should == [4] + + array[(4..-5).step(-1)].should == [4, 3, 2, 1] + array[(4..-5).step(-2)].should == [4, 2] + array[(4..-5).step(-3)].should == [4, 1] + array[(4..-5).step(-4)].should == [4] + array[(4..-5).step(-5)].should == [4] + + array[(4...-5).step(-1)].should == [4, 3, 2] + array[(4...-5).step(-2)].should == [4, 2] + array[(4...-5).step(-3)].should == [4] + array[(4...-5).step(-4)].should == [4] + + array[(-2..-5).step(-1)].should == [4, 3, 2, 1] + array[(-2..-5).step(-2)].should == [4, 2] + array[(-2..-5).step(-3)].should == [4, 1] + array[(-2..-5).step(-4)].should == [4] + array[(-2..-5).step(-5)].should == [4] + + array[(-2...-5).step(-1)].should == [4, 3, 2] + array[(-2...-5).step(-2)].should == [4, 2] + array[(-2...-5).step(-3)].should == [4] + array[(-2...-5).step(-4)].should == [4] + end + end + + it "can accept nil...nil ranges" do + a = [0, 1, 2, 3, 4, 5] + a[eval("(nil...nil)")].should == a + a[(...nil)].should == a + a[eval("(nil..)")].should == a + end end describe "Array.[]" do diff --git a/core/array/filter_spec.rb b/core/array/filter_spec.rb index 7807c3886d..6ebda61069 100644 --- a/core/array/filter_spec.rb +++ b/core/array/filter_spec.rb @@ -1,14 +1,13 @@ require_relative '../../spec_helper' -require_relative 'shared/select' describe "Array#filter" do - it_behaves_like :array_select, :filter + it "is an alias of Array#select" do + Array.instance_method(:filter).should == Array.instance_method(:select) + end end describe "Array#filter!" do - it "returns nil if no changes were made in the array" do - [1, 2, 3].filter! { true }.should == nil + it "is an alias of Array#select!" do + Array.instance_method(:filter!).should == Array.instance_method(:select!) end - - it_behaves_like :keep_if, :filter! end diff --git a/core/array/find_index_spec.rb b/core/array/find_index_spec.rb index 759472024a..17ff6c04a7 100644 --- a/core/array/find_index_spec.rb +++ b/core/array/find_index_spec.rb @@ -1,6 +1,42 @@ require_relative '../../spec_helper' -require_relative 'shared/index' +require_relative 'shared/iterable_and_tolerating_size_increasing' describe "Array#find_index" do - it_behaves_like :array_index, :find_index + it "returns the index of the first element == to object" do + x = mock('3') + def x.==(obj) 3 == obj; end + + [2, x, 3, 1, 3, 1].find_index(3).should == 1 + [2, 3.0, 3, x, 1, 3, 1].find_index(x).should == 1 + end + + it "returns 0 if first element == to object" do + [2, 1, 3, 2, 5].find_index(2).should == 0 + end + + it "returns size-1 if only last element == to object" do + [2, 1, 3, 1, 5].find_index(5).should == 4 + end + + it "returns nil if no element == to object" do + [2, 1, 1, 1, 1].find_index(3).should == nil + end + + it "accepts a block instead of an argument" do + [4, 2, 1, 5, 1, 3].find_index {|x| x < 2}.should == 2 + end + + it "ignores the block if there is an argument" do + -> { + [4, 2, 1, 5, 1, 3].find_index(5) {|x| x < 2}.should == 3 + }.should complain(/given block not used/) + end + + describe "given no argument and no block" do + it "produces an Enumerator" do + [].find_index.should.instance_of?(Enumerator) + end + end + + it_behaves_like :array_iterable_and_tolerating_size_increasing, :find_index end diff --git a/core/array/index_spec.rb b/core/array/index_spec.rb index 3acb7d0ef3..b66cb6eb53 100644 --- a/core/array/index_spec.rb +++ b/core/array/index_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/index' describe "Array#index" do - it_behaves_like :array_index, :index + it "is an alias of Array#find_index" do + Array.instance_method(:index).should == Array.instance_method(:find_index) + end end diff --git a/core/array/inspect_spec.rb b/core/array/inspect_spec.rb index 0832224f5a..e5dca82889 100644 --- a/core/array/inspect_spec.rb +++ b/core/array/inspect_spec.rb @@ -1,7 +1,108 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/inspect' describe "Array#inspect" do - it_behaves_like :array_inspect, :inspect + it "returns a string" do + [1, 2, 3].inspect.should.instance_of?(String) + end + + it "returns '[]' for an empty Array" do + [].inspect.should == "[]" + end + + it "calls inspect on its elements and joins the results with commas" do + items = Array.new(3) do |i| + obj = mock(i.to_s) + obj.should_receive(:inspect).and_return(i.to_s) + obj + end + items.inspect.should == "[0, 1, 2]" + end + + it "does not call #to_s on a String returned from #inspect" do + str = +"abc" + str.should_not_receive(:to_s) + + [str].inspect.should == '["abc"]' + end + + it "calls #to_s on the object returned from #inspect if the Object isn't a String" do + obj = mock("Array#inspect/to_s calls #to_s") + obj.should_receive(:inspect).and_return(obj) + obj.should_receive(:to_s).and_return("abc") + + [obj].inspect.should == "[abc]" + end + + it "does not call #to_str on the object returned from #inspect when it is not a String" do + obj = mock("Array#inspect/to_s does not call #to_str") + obj.should_receive(:inspect).and_return(obj) + obj.should_not_receive(:to_str) + + [obj].inspect.should =~ /^\[#\]$/ + end + + it "does not call #to_str on the object returned from #to_s when it is not a String" do + obj = mock("Array#inspect/to_s does not call #to_str on #to_s result") + obj.should_receive(:inspect).and_return(obj) + obj.should_receive(:to_s).and_return(obj) + obj.should_not_receive(:to_str) + + [obj].inspect.should =~ /^\[#\]$/ + end + + it "does not swallow exceptions raised by #to_s" do + obj = mock("Array#inspect/to_s does not swallow #to_s exceptions") + obj.should_receive(:inspect).and_return(obj) + obj.should_receive(:to_s).and_raise(Exception) + + -> { [obj].inspect }.should.raise(Exception) + end + + it "represents a recursive element with '[...]'" do + ArraySpecs.recursive_array.inspect.should == "[1, \"two\", 3.0, [...], [...], [...], [...], [...]]" + ArraySpecs.head_recursive_array.inspect.should == "[[...], [...], [...], [...], [...], 1, \"two\", 3.0]" + ArraySpecs.empty_recursive_array.inspect.should == "[[...]]" + end + + describe "with encoding" do + before :each do + @default_external_encoding = Encoding.default_external + end + + after :each do + Encoding.default_external = @default_external_encoding + end + + it "returns a US-ASCII string for an empty Array" do + [].inspect.encoding.should == Encoding::US_ASCII + end + + it "use the default external encoding if it is ascii compatible" do + Encoding.default_external = Encoding.find('UTF-8') + + utf8 = "utf8".encode("UTF-8") + jp = "jp".encode("EUC-JP") + array = [jp, utf8] + + array.inspect.encoding.name.should == "UTF-8" + end + + it "use US-ASCII encoding if the default external encoding is not ascii compatible" do + Encoding.default_external = Encoding.find('UTF-32') + + utf8 = "utf8".encode("UTF-8") + jp = "jp".encode("EUC-JP") + array = [jp, utf8] + + array.inspect.encoding.name.should == "US-ASCII" + end + + it "does not raise if inspected result is not default external encoding" do + utf_16be = mock(+"utf_16be") + utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE)) + + [utf_16be].inspect.should == '["utf_16be \u3042"]' + end + end end diff --git a/core/array/join_spec.rb b/core/array/join_spec.rb index 811db036a8..3b4946a99f 100644 --- a/core/array/join_spec.rb +++ b/core/array/join_spec.rb @@ -4,7 +4,6 @@ describe "Array#join" do it_behaves_like :array_join_with_string_separator, :join - it_behaves_like :array_join_with_default_separator, :join it "does not separate elements when the passed separator is nil" do [1, 2, 3].join(nil).should == '123' @@ -32,6 +31,103 @@ end end +describe "Array#join with default separator" do + before :each do + @separator = $, + end + + after :each do + $, = @separator + end + + it "returns an empty string if the Array is empty" do + [].join.should == '' + end + + it "returns a US-ASCII string for an empty Array" do + [].join.encoding.should == Encoding::US_ASCII + end + + it "returns a string formed by concatenating each String element separated by $," do + suppress_warning { + $, = " | " + ["1", "2", "3"].join.should == "1 | 2 | 3" + } + end + + it "attempts coercion via #to_str first" do + obj = mock('foo') + obj.should_receive(:to_str).any_number_of_times.and_return("foo") + [obj].join.should == "foo" + end + + it "attempts coercion via #to_ary second" do + obj = mock('foo') + obj.should_receive(:to_str).any_number_of_times.and_return(nil) + obj.should_receive(:to_ary).any_number_of_times.and_return(["foo"]) + [obj].join.should == "foo" + end + + it "attempts coercion via #to_s third" do + obj = mock('foo') + obj.should_receive(:to_str).any_number_of_times.and_return(nil) + obj.should_receive(:to_ary).any_number_of_times.and_return(nil) + obj.should_receive(:to_s).any_number_of_times.and_return("foo") + [obj].join.should == "foo" + end + + it "raises a NoMethodError if an element does not respond to #to_str, #to_ary, or #to_s" do + obj = mock('o') + class << obj; undef :to_s; end + -> { [1, obj].join }.should.raise(NoMethodError) + end + + it "raises an ArgumentError when the Array is recursive" do + -> { ArraySpecs.recursive_array.join }.should.raise(ArgumentError) + -> { ArraySpecs.head_recursive_array.join }.should.raise(ArgumentError) + -> { ArraySpecs.empty_recursive_array.join }.should.raise(ArgumentError) + end + + it "uses the first encoding when other strings are compatible" do + ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings + ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings + ary3 = ArraySpecs.array_with_utf8_and_7bit_binary_strings + ary4 = ArraySpecs.array_with_usascii_and_7bit_binary_strings + + ary1.join.encoding.should == Encoding::UTF_8 + ary2.join.encoding.should == Encoding::US_ASCII + ary3.join.encoding.should == Encoding::UTF_8 + ary4.join.encoding.should == Encoding::US_ASCII + end + + it "uses the widest common encoding when other strings are incompatible" do + ary1 = ArraySpecs.array_with_utf8_and_usascii_strings + ary2 = ArraySpecs.array_with_usascii_and_utf8_strings + + ary1.join.encoding.should == Encoding::UTF_8 + ary2.join.encoding.should == Encoding::UTF_8 + end + + it "fails for arrays with incompatibly-encoded strings" do + ary_utf8_bad_binary = ArraySpecs.array_with_utf8_and_binary_strings + + -> { ary_utf8_bad_binary.join }.should.raise(EncodingError) + end + + context "when $, is not nil" do + before do + suppress_warning do + $, = '*' + end + end + + it "warns" do + -> { [].join }.should complain(/warning: \$, is set to non-nil value/) + -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/) + end + end +end + describe "Array#join with $," do before :each do @before_separator = $, diff --git a/core/array/length_spec.rb b/core/array/length_spec.rb index a90c001300..74b2eb3a08 100644 --- a/core/array/length_spec.rb +++ b/core/array/length_spec.rb @@ -1,7 +1,14 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/length' describe "Array#length" do - it_behaves_like :array_length, :length + it "returns the number of elements" do + [].length.should == 0 + [1, 2, 3].length.should == 3 + end + + it "properly handles recursive arrays" do + ArraySpecs.empty_recursive_array.length.should == 1 + ArraySpecs.recursive_array.length.should == 8 + end end diff --git a/core/array/map_spec.rb b/core/array/map_spec.rb index 0c7f3afa8c..f5e88c8624 100644 --- a/core/array/map_spec.rb +++ b/core/array/map_spec.rb @@ -1,11 +1,13 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/collect' describe "Array#map" do - it_behaves_like :array_collect, :map + it "is an alias of Array#collect" do + Array.instance_method(:map).should == Array.instance_method(:collect) + end end describe "Array#map!" do - it_behaves_like :array_collect_b, :map! + it "is an alias of Array#collect!" do + Array.instance_method(:map!).should == Array.instance_method(:collect!) + end end diff --git a/core/array/prepend_spec.rb b/core/array/prepend_spec.rb index 368b8dcfcd..2d0ce31c71 100644 --- a/core/array/prepend_spec.rb +++ b/core/array/prepend_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/unshift' describe "Array#prepend" do - it_behaves_like :array_unshift, :prepend + it "is an alias of Array#unshift" do + Array.instance_method(:prepend).should == Array.instance_method(:unshift) + end end diff --git a/core/array/push_spec.rb b/core/array/push_spec.rb index 607cbc7b4d..6255a84371 100644 --- a/core/array/push_spec.rb +++ b/core/array/push_spec.rb @@ -1,7 +1,36 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/push' describe "Array#push" do - it_behaves_like :array_push, :push + it "appends the arguments to the array" do + a = [ "a", "b", "c" ] + a.push("d", "e", "f").should.equal?(a) + a.push.should == ["a", "b", "c", "d", "e", "f"] + a.push(5) + a.should == ["a", "b", "c", "d", "e", "f", 5] + + a = [0, 1] + a.push(2) + a.should == [0, 1, 2] + end + + it "isn't confused by previous shift" do + a = [ "a", "b", "c" ] + a.shift + a.push("foo") + a.should == ["b", "c", "foo"] + end + + it "properly handles recursive arrays" do + empty = ArraySpecs.empty_recursive_array + empty.push(:last).should == [empty, :last] + + array = ArraySpecs.recursive_array + array.push(:last).should == [1, 'two', 3.0, array, array, array, array, array, :last] + end + + it "raises a FrozenError on a frozen array" do + -> { ArraySpecs.frozen_array.push(1) }.should.raise(FrozenError) + -> { ArraySpecs.frozen_array.push }.should.raise(FrozenError) + end end diff --git a/core/array/replace_spec.rb b/core/array/replace_spec.rb index 2f53338f5e..ee6a98a646 100644 --- a/core/array/replace_spec.rb +++ b/core/array/replace_spec.rb @@ -1,7 +1,63 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/replace' describe "Array#replace" do - it_behaves_like :array_replace, :replace + it "replaces the elements with elements from other array" do + a = [1, 2, 3, 4, 5] + b = ['a', 'b', 'c'] + a.replace(b).should.equal?(a) + a.should == b + a.should_not.equal?(b) + + a.replace([4] * 10) + a.should == [4] * 10 + + a.replace([]) + a.should == [] + end + + it "properly handles recursive arrays" do + orig = [1, 2, 3] + empty = ArraySpecs.empty_recursive_array + orig.replace(empty) + orig.should == empty + + array = ArraySpecs.recursive_array + orig.replace(array) + orig.should == array + end + + it "returns self" do + ary = [1, 2, 3] + other = [:a, :b, :c] + ary.replace(other).should.equal?(ary) + end + + it "does not make self dependent to the original array" do + ary = [1, 2, 3] + other = [:a, :b, :c] + ary.replace(other) + ary.should == [:a, :b, :c] + ary << :d + ary.should == [:a, :b, :c, :d] + other.should == [:a, :b, :c] + end + + it "tries to convert the passed argument to an Array using #to_ary" do + obj = mock('to_ary') + obj.stub!(:to_ary).and_return([1, 2, 3]) + [].replace(obj).should == [1, 2, 3] + end + + it "does not call #to_ary on Array subclasses" do + obj = ArraySpecs::ToAryArray[5, 6, 7] + obj.should_not_receive(:to_ary) + [].replace(ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7] + end + + it "raises a FrozenError on a frozen array" do + -> { + ArraySpecs.frozen_array.replace(ArraySpecs.frozen_array) + }.should.raise(FrozenError) + end end diff --git a/core/array/select_spec.rb b/core/array/select_spec.rb index e8775ee5ac..57ec0b2540 100644 --- a/core/array/select_spec.rb +++ b/core/array/select_spec.rb @@ -1,8 +1,37 @@ require_relative '../../spec_helper' -require_relative 'shared/select' +require_relative '../enumerable/shared/enumeratorized' +require_relative 'fixtures/classes' +require_relative 'shared/enumeratorize' +require_relative 'shared/iterable_and_tolerating_size_increasing' +require_relative 'shared/keep_if' describe "Array#select" do - it_behaves_like :array_select, :select + it_behaves_like :enumeratorize, :select + + it_behaves_like :array_iterable_and_tolerating_size_increasing, :select + + before :each do + @object = [1,2,3] + end + it_behaves_like :enumeratorized_with_origin_size, :select + + it "returns a new array of elements for which block is true" do + [1, 3, 4, 5, 6, 9].select { |i| i % ((i + 1) / 2) == 0}.should == [1, 4, 6] + end + + it "does not return subclass instance on Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].select { true }.should.instance_of?(Array) + end + + it "properly handles recursive arrays" do + empty = ArraySpecs.empty_recursive_array + empty.select { true }.should == empty + empty.select { false }.should == [] + + array = ArraySpecs.recursive_array + array.select { true }.should == [1, 'two', 3.0, array, array, array, array, array] + array.select { false }.should == [] + end end describe "Array#select!" do diff --git a/core/array/shared/collect.rb b/core/array/shared/collect.rb deleted file mode 100644 index aec51c9dc9..0000000000 --- a/core/array/shared/collect.rb +++ /dev/null @@ -1,141 +0,0 @@ -require_relative '../../enumerable/shared/enumeratorized' -require_relative '../shared/iterable_and_tolerating_size_increasing' - -describe :array_collect, shared: true do - it "returns a copy of array with each element replaced by the value returned by block" do - a = ['a', 'b', 'c', 'd'] - b = a.send(@method) { |i| i + '!' } - b.should == ["a!", "b!", "c!", "d!"] - b.should_not.equal? a - end - - it "does not return subclass instance" do - ArraySpecs::MyArray[1, 2, 3].send(@method) { |x| x + 1 }.should.instance_of?(Array) - end - - it "does not change self" do - a = ['a', 'b', 'c', 'd'] - a.send(@method) { |i| i + '!' } - a.should == ['a', 'b', 'c', 'd'] - end - - it "returns the evaluated value of block if it broke in the block" do - a = ['a', 'b', 'c', 'd'] - b = a.send(@method) {|i| - if i == 'c' - break 0 - else - i + '!' - end - } - b.should == 0 - end - - it "returns an Enumerator when no block given" do - a = [1, 2, 3] - a.send(@method).should.instance_of?(Enumerator) - end - - it "raises an ArgumentError when no block and with arguments" do - a = [1, 2, 3] - -> { - a.send(@method, :foo) - }.should.raise(ArgumentError) - end - - before :all do - @object = [1, 2, 3, 4] - end - it_should_behave_like :enumeratorized_with_origin_size - - it_should_behave_like :array_iterable_and_tolerating_size_increasing -end - -describe :array_collect_b, shared: true do - it "replaces each element with the value returned by block" do - a = [7, 9, 3, 5] - a.send(@method) { |i| i - 1 }.should.equal?(a) - a.should == [6, 8, 2, 4] - end - - it "returns self" do - a = [1, 2, 3, 4, 5] - b = a.send(@method) {|i| i+1 } - a.should.equal? b - end - - it "returns the evaluated value of block but its contents is partially modified, if it broke in the block" do - a = ['a', 'b', 'c', 'd'] - b = a.send(@method) {|i| - if i == 'c' - break 0 - else - i + '!' - end - } - b.should == 0 - a.should == ['a!', 'b!', 'c', 'd'] - end - - it "returns an Enumerator when no block given, and the enumerator can modify the original array" do - a = [1, 2, 3] - enum = a.send(@method) - enum.should.instance_of?(Enumerator) - enum.each{|i| "#{i}!" } - a.should == ["1!", "2!", "3!"] - end - - describe "when frozen" do - it "raises a FrozenError" do - -> { ArraySpecs.frozen_array.send(@method) {} }.should.raise(FrozenError) - end - - it "raises a FrozenError when empty" do - -> { ArraySpecs.empty_frozen_array.send(@method) {} }.should.raise(FrozenError) - end - - it "raises a FrozenError when calling #each on the returned Enumerator" do - enumerator = ArraySpecs.frozen_array.send(@method) - -> { enumerator.each {|x| x } }.should.raise(FrozenError) - end - - it "raises a FrozenError when calling #each on the returned Enumerator when empty" do - enumerator = ArraySpecs.empty_frozen_array.send(@method) - -> { enumerator.each {|x| x } }.should.raise(FrozenError) - end - end - - it "does not truncate the array is the block raises an exception" do - a = [1, 2, 3] - begin - a.send(@method) { raise StandardError, 'Oops' } - rescue - end - - a.should == [1, 2, 3] - end - - it "only changes elements before error is raised, keeping the element which raised an error." do - a = [1, 2, 3, 4] - begin - a.send(@method) do |e| - case e - when 1 then -1 - when 2 then -2 - when 3 then raise StandardError, 'Oops' - else 0 - end - end - rescue StandardError - end - - a.should == [-1, -2, 3, 4] - end - - before :all do - @object = [1, 2, 3, 4] - end - it_should_behave_like :enumeratorized_with_origin_size - - it_should_behave_like :array_iterable_and_tolerating_size_increasing -end diff --git a/core/array/shared/index.rb b/core/array/shared/index.rb deleted file mode 100644 index cc6d6cfb5b..0000000000 --- a/core/array/shared/index.rb +++ /dev/null @@ -1,41 +0,0 @@ -require_relative '../shared/iterable_and_tolerating_size_increasing' - -describe :array_index, shared: true do - it "returns the index of the first element == to object" do - x = mock('3') - def x.==(obj) 3 == obj; end - - [2, x, 3, 1, 3, 1].send(@method, 3).should == 1 - [2, 3.0, 3, x, 1, 3, 1].send(@method, x).should == 1 - end - - it "returns 0 if first element == to object" do - [2, 1, 3, 2, 5].send(@method, 2).should == 0 - end - - it "returns size-1 if only last element == to object" do - [2, 1, 3, 1, 5].send(@method, 5).should == 4 - end - - it "returns nil if no element == to object" do - [2, 1, 1, 1, 1].send(@method, 3).should == nil - end - - it "accepts a block instead of an argument" do - [4, 2, 1, 5, 1, 3].send(@method) {|x| x < 2}.should == 2 - end - - it "ignores the block if there is an argument" do - -> { - [4, 2, 1, 5, 1, 3].send(@method, 5) {|x| x < 2}.should == 3 - }.should complain(/given block not used/) - end - - describe "given no argument and no block" do - it "produces an Enumerator" do - [].send(@method).should.instance_of?(Enumerator) - end - end - - it_should_behave_like :array_iterable_and_tolerating_size_increasing -end diff --git a/core/array/shared/inspect.rb b/core/array/shared/inspect.rb deleted file mode 100644 index 7197cd7f26..0000000000 --- a/core/array/shared/inspect.rb +++ /dev/null @@ -1,107 +0,0 @@ -require_relative '../fixtures/encoded_strings' - -describe :array_inspect, shared: true do - it "returns a string" do - [1, 2, 3].send(@method).should.instance_of?(String) - end - - it "returns '[]' for an empty Array" do - [].send(@method).should == "[]" - end - - it "calls inspect on its elements and joins the results with commas" do - items = Array.new(3) do |i| - obj = mock(i.to_s) - obj.should_receive(:inspect).and_return(i.to_s) - obj - end - items.send(@method).should == "[0, 1, 2]" - end - - it "does not call #to_s on a String returned from #inspect" do - str = +"abc" - str.should_not_receive(:to_s) - - [str].send(@method).should == '["abc"]' - end - - it "calls #to_s on the object returned from #inspect if the Object isn't a String" do - obj = mock("Array#inspect/to_s calls #to_s") - obj.should_receive(:inspect).and_return(obj) - obj.should_receive(:to_s).and_return("abc") - - [obj].send(@method).should == "[abc]" - end - - it "does not call #to_str on the object returned from #inspect when it is not a String" do - obj = mock("Array#inspect/to_s does not call #to_str") - obj.should_receive(:inspect).and_return(obj) - obj.should_not_receive(:to_str) - - [obj].send(@method).should =~ /^\[#\]$/ - end - - it "does not call #to_str on the object returned from #to_s when it is not a String" do - obj = mock("Array#inspect/to_s does not call #to_str on #to_s result") - obj.should_receive(:inspect).and_return(obj) - obj.should_receive(:to_s).and_return(obj) - obj.should_not_receive(:to_str) - - [obj].send(@method).should =~ /^\[#\]$/ - end - - it "does not swallow exceptions raised by #to_s" do - obj = mock("Array#inspect/to_s does not swallow #to_s exceptions") - obj.should_receive(:inspect).and_return(obj) - obj.should_receive(:to_s).and_raise(Exception) - - -> { [obj].send(@method) }.should.raise(Exception) - end - - it "represents a recursive element with '[...]'" do - ArraySpecs.recursive_array.send(@method).should == "[1, \"two\", 3.0, [...], [...], [...], [...], [...]]" - ArraySpecs.head_recursive_array.send(@method).should == "[[...], [...], [...], [...], [...], 1, \"two\", 3.0]" - ArraySpecs.empty_recursive_array.send(@method).should == "[[...]]" - end - - describe "with encoding" do - before :each do - @default_external_encoding = Encoding.default_external - end - - after :each do - Encoding.default_external = @default_external_encoding - end - - it "returns a US-ASCII string for an empty Array" do - [].send(@method).encoding.should == Encoding::US_ASCII - end - - it "use the default external encoding if it is ascii compatible" do - Encoding.default_external = Encoding.find('UTF-8') - - utf8 = "utf8".encode("UTF-8") - jp = "jp".encode("EUC-JP") - array = [jp, utf8] - - array.send(@method).encoding.name.should == "UTF-8" - end - - it "use US-ASCII encoding if the default external encoding is not ascii compatible" do - Encoding.default_external = Encoding.find('UTF-32') - - utf8 = "utf8".encode("UTF-8") - jp = "jp".encode("EUC-JP") - array = [jp, utf8] - - array.send(@method).encoding.name.should == "US-ASCII" - end - - it "does not raise if inspected result is not default external encoding" do - utf_16be = mock(+"utf_16be") - utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE)) - - [utf_16be].send(@method).should == '["utf_16be \u3042"]' - end - end -end diff --git a/core/array/shared/join.rb b/core/array/shared/join.rb index 2be60a4dbc..93d5329ee3 100644 --- a/core/array/shared/join.rb +++ b/core/array/shared/join.rb @@ -1,103 +1,6 @@ require_relative '../fixtures/classes' require_relative '../fixtures/encoded_strings' -describe :array_join_with_default_separator, shared: true do - before :each do - @separator = $, - end - - after :each do - $, = @separator - end - - it "returns an empty string if the Array is empty" do - [].send(@method).should == '' - end - - it "returns a US-ASCII string for an empty Array" do - [].send(@method).encoding.should == Encoding::US_ASCII - end - - it "returns a string formed by concatenating each String element separated by $," do - suppress_warning { - $, = " | " - ["1", "2", "3"].send(@method).should == "1 | 2 | 3" - } - end - - it "attempts coercion via #to_str first" do - obj = mock('foo') - obj.should_receive(:to_str).any_number_of_times.and_return("foo") - [obj].send(@method).should == "foo" - end - - it "attempts coercion via #to_ary second" do - obj = mock('foo') - obj.should_receive(:to_str).any_number_of_times.and_return(nil) - obj.should_receive(:to_ary).any_number_of_times.and_return(["foo"]) - [obj].send(@method).should == "foo" - end - - it "attempts coercion via #to_s third" do - obj = mock('foo') - obj.should_receive(:to_str).any_number_of_times.and_return(nil) - obj.should_receive(:to_ary).any_number_of_times.and_return(nil) - obj.should_receive(:to_s).any_number_of_times.and_return("foo") - [obj].send(@method).should == "foo" - end - - it "raises a NoMethodError if an element does not respond to #to_str, #to_ary, or #to_s" do - obj = mock('o') - class << obj; undef :to_s; end - -> { [1, obj].send(@method) }.should.raise(NoMethodError) - end - - it "raises an ArgumentError when the Array is recursive" do - -> { ArraySpecs.recursive_array.send(@method) }.should.raise(ArgumentError) - -> { ArraySpecs.head_recursive_array.send(@method) }.should.raise(ArgumentError) - -> { ArraySpecs.empty_recursive_array.send(@method) }.should.raise(ArgumentError) - end - - it "uses the first encoding when other strings are compatible" do - ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings - ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings - ary3 = ArraySpecs.array_with_utf8_and_7bit_binary_strings - ary4 = ArraySpecs.array_with_usascii_and_7bit_binary_strings - - ary1.send(@method).encoding.should == Encoding::UTF_8 - ary2.send(@method).encoding.should == Encoding::US_ASCII - ary3.send(@method).encoding.should == Encoding::UTF_8 - ary4.send(@method).encoding.should == Encoding::US_ASCII - end - - it "uses the widest common encoding when other strings are incompatible" do - ary1 = ArraySpecs.array_with_utf8_and_usascii_strings - ary2 = ArraySpecs.array_with_usascii_and_utf8_strings - - ary1.send(@method).encoding.should == Encoding::UTF_8 - ary2.send(@method).encoding.should == Encoding::UTF_8 - end - - it "fails for arrays with incompatibly-encoded strings" do - ary_utf8_bad_binary = ArraySpecs.array_with_utf8_and_binary_strings - - -> { ary_utf8_bad_binary.send(@method) }.should.raise(EncodingError) - end - - context "when $, is not nil" do - before do - suppress_warning do - $, = '*' - end - end - - it "warns" do - -> { [].join }.should complain(/warning: \$, is set to non-nil value/) - -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/) - end - end -end - describe :array_join_with_string_separator, shared: true do it "returns a string formed by concatenating each element.to_str separated by separator" do obj = mock('foo') diff --git a/core/array/shared/length.rb b/core/array/shared/length.rb deleted file mode 100644 index f84966d0ba..0000000000 --- a/core/array/shared/length.rb +++ /dev/null @@ -1,11 +0,0 @@ -describe :array_length, shared: true do - it "returns the number of elements" do - [].send(@method).should == 0 - [1, 2, 3].send(@method).should == 3 - end - - it "properly handles recursive arrays" do - ArraySpecs.empty_recursive_array.send(@method).should == 1 - ArraySpecs.recursive_array.send(@method).should == 8 - end -end diff --git a/core/array/shared/push.rb b/core/array/shared/push.rb deleted file mode 100644 index ec406e506e..0000000000 --- a/core/array/shared/push.rb +++ /dev/null @@ -1,33 +0,0 @@ -describe :array_push, shared: true do - it "appends the arguments to the array" do - a = [ "a", "b", "c" ] - a.send(@method, "d", "e", "f").should.equal?(a) - a.send(@method).should == ["a", "b", "c", "d", "e", "f"] - a.send(@method, 5) - a.should == ["a", "b", "c", "d", "e", "f", 5] - - a = [0, 1] - a.send(@method, 2) - a.should == [0, 1, 2] - end - - it "isn't confused by previous shift" do - a = [ "a", "b", "c" ] - a.shift - a.send(@method, "foo") - a.should == ["b", "c", "foo"] - end - - it "properly handles recursive arrays" do - empty = ArraySpecs.empty_recursive_array - empty.send(@method, :last).should == [empty, :last] - - array = ArraySpecs.recursive_array - array.send(@method, :last).should == [1, 'two', 3.0, array, array, array, array, array, :last] - end - - it "raises a FrozenError on a frozen array" do - -> { ArraySpecs.frozen_array.send(@method, 1) }.should.raise(FrozenError) - -> { ArraySpecs.frozen_array.send(@method) }.should.raise(FrozenError) - end -end diff --git a/core/array/shared/replace.rb b/core/array/shared/replace.rb deleted file mode 100644 index 06bfd00795..0000000000 --- a/core/array/shared/replace.rb +++ /dev/null @@ -1,60 +0,0 @@ -describe :array_replace, shared: true do - it "replaces the elements with elements from other array" do - a = [1, 2, 3, 4, 5] - b = ['a', 'b', 'c'] - a.send(@method, b).should.equal?(a) - a.should == b - a.should_not.equal?(b) - - a.send(@method, [4] * 10) - a.should == [4] * 10 - - a.send(@method, []) - a.should == [] - end - - it "properly handles recursive arrays" do - orig = [1, 2, 3] - empty = ArraySpecs.empty_recursive_array - orig.send(@method, empty) - orig.should == empty - - array = ArraySpecs.recursive_array - orig.send(@method, array) - orig.should == array - end - - it "returns self" do - ary = [1, 2, 3] - other = [:a, :b, :c] - ary.send(@method, other).should.equal?(ary) - end - - it "does not make self dependent to the original array" do - ary = [1, 2, 3] - other = [:a, :b, :c] - ary.send(@method, other) - ary.should == [:a, :b, :c] - ary << :d - ary.should == [:a, :b, :c, :d] - other.should == [:a, :b, :c] - end - - it "tries to convert the passed argument to an Array using #to_ary" do - obj = mock('to_ary') - obj.stub!(:to_ary).and_return([1, 2, 3]) - [].send(@method, obj).should == [1, 2, 3] - end - - it "does not call #to_ary on Array subclasses" do - obj = ArraySpecs::ToAryArray[5, 6, 7] - obj.should_not_receive(:to_ary) - [].send(@method, ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7] - end - - it "raises a FrozenError on a frozen array" do - -> { - ArraySpecs.frozen_array.send(@method, ArraySpecs.frozen_array) - }.should.raise(FrozenError) - end -end diff --git a/core/array/shared/select.rb b/core/array/shared/select.rb deleted file mode 100644 index cb4f9acbb7..0000000000 --- a/core/array/shared/select.rb +++ /dev/null @@ -1,35 +0,0 @@ -require_relative '../../../spec_helper' -require_relative '../fixtures/classes' -require_relative '../shared/enumeratorize' -require_relative '../shared/keep_if' -require_relative '../shared/iterable_and_tolerating_size_increasing' -require_relative '../../enumerable/shared/enumeratorized' - -describe :array_select, shared: true do - it_should_behave_like :enumeratorize - - it_should_behave_like :array_iterable_and_tolerating_size_increasing - - before :each do - @object = [1,2,3] - end - it_should_behave_like :enumeratorized_with_origin_size - - it "returns a new array of elements for which block is true" do - [1, 3, 4, 5, 6, 9].send(@method) { |i| i % ((i + 1) / 2) == 0}.should == [1, 4, 6] - end - - it "does not return subclass instance on Array subclasses" do - ArraySpecs::MyArray[1, 2, 3].send(@method) { true }.should.instance_of?(Array) - end - - it "properly handles recursive arrays" do - empty = ArraySpecs.empty_recursive_array - empty.send(@method) { true }.should == empty - empty.send(@method) { false }.should == [] - - array = ArraySpecs.recursive_array - array.send(@method) { true }.should == [1, 'two', 3.0, array, array, array, array, array] - array.send(@method) { false }.should == [] - end -end diff --git a/core/array/shared/slice.rb b/core/array/shared/slice.rb deleted file mode 100644 index b838d86118..0000000000 --- a/core/array/shared/slice.rb +++ /dev/null @@ -1,857 +0,0 @@ -describe :array_slice, shared: true do - it "returns the element at index with [index]" do - [ "a", "b", "c", "d", "e" ].send(@method, 1).should == "b" - - a = [1, 2, 3, 4] - - a.send(@method, 0).should == 1 - a.send(@method, 1).should == 2 - a.send(@method, 2).should == 3 - a.send(@method, 3).should == 4 - a.send(@method, 4).should == nil - a.send(@method, 10).should == nil - - a.should == [1, 2, 3, 4] - end - - it "returns the element at index from the end of the array with [-index]" do - [ "a", "b", "c", "d", "e" ].send(@method, -2).should == "d" - - a = [1, 2, 3, 4] - - a.send(@method, -1).should == 4 - a.send(@method, -2).should == 3 - a.send(@method, -3).should == 2 - a.send(@method, -4).should == 1 - a.send(@method, -5).should == nil - a.send(@method, -10).should == nil - - a.should == [1, 2, 3, 4] - end - - it "returns count elements starting from index with [index, count]" do - [ "a", "b", "c", "d", "e" ].send(@method, 2, 3).should == ["c", "d", "e"] - - a = [1, 2, 3, 4] - - a.send(@method, 0, 0).should == [] - a.send(@method, 0, 1).should == [1] - a.send(@method, 0, 2).should == [1, 2] - a.send(@method, 0, 4).should == [1, 2, 3, 4] - a.send(@method, 0, 6).should == [1, 2, 3, 4] - a.send(@method, 0, -1).should == nil - a.send(@method, 0, -2).should == nil - a.send(@method, 0, -4).should == nil - - a.send(@method, 2, 0).should == [] - a.send(@method, 2, 1).should == [3] - a.send(@method, 2, 2).should == [3, 4] - a.send(@method, 2, 4).should == [3, 4] - a.send(@method, 2, -1).should == nil - - a.send(@method, 4, 0).should == [] - a.send(@method, 4, 2).should == [] - a.send(@method, 4, -1).should == nil - - a.send(@method, 5, 0).should == nil - a.send(@method, 5, 2).should == nil - a.send(@method, 5, -1).should == nil - - a.send(@method, 6, 0).should == nil - a.send(@method, 6, 2).should == nil - a.send(@method, 6, -1).should == nil - - a.should == [1, 2, 3, 4] - end - - it "returns count elements starting at index from the end of array with [-index, count]" do - [ "a", "b", "c", "d", "e" ].send(@method, -2, 2).should == ["d", "e"] - - a = [1, 2, 3, 4] - - a.send(@method, -1, 0).should == [] - a.send(@method, -1, 1).should == [4] - a.send(@method, -1, 2).should == [4] - a.send(@method, -1, -1).should == nil - - a.send(@method, -2, 0).should == [] - a.send(@method, -2, 1).should == [3] - a.send(@method, -2, 2).should == [3, 4] - a.send(@method, -2, 4).should == [3, 4] - a.send(@method, -2, -1).should == nil - - a.send(@method, -4, 0).should == [] - a.send(@method, -4, 1).should == [1] - a.send(@method, -4, 2).should == [1, 2] - a.send(@method, -4, 4).should == [1, 2, 3, 4] - a.send(@method, -4, 6).should == [1, 2, 3, 4] - a.send(@method, -4, -1).should == nil - - a.send(@method, -5, 0).should == nil - a.send(@method, -5, 1).should == nil - a.send(@method, -5, 10).should == nil - a.send(@method, -5, -1).should == nil - - a.should == [1, 2, 3, 4] - end - - it "returns the first count elements with [0, count]" do - [ "a", "b", "c", "d", "e" ].send(@method, 0, 3).should == ["a", "b", "c"] - end - - it "returns the subarray which is independent to self with [index,count]" do - a = [1, 2, 3] - sub = a.send(@method, 1,2) - sub.replace([:a, :b]) - a.should == [1, 2, 3] - end - - it "tries to convert the passed argument to an Integer using #to_int" do - obj = mock('to_int') - obj.stub!(:to_int).and_return(2) - - a = [1, 2, 3, 4] - a.send(@method, obj).should == 3 - a.send(@method, obj, 1).should == [3] - a.send(@method, obj, obj).should == [3, 4] - a.send(@method, 0, obj).should == [1, 2] - end - - it "raises TypeError if to_int returns non-integer" do - from = mock('from') - to = mock('to') - - # So we can construct a range out of them... - def from.<=>(o) 0 end - def to.<=>(o) 0 end - - a = [1, 2, 3, 4, 5] - - def from.to_int() 'cat' end - def to.to_int() -2 end - - -> { a.send(@method, from..to) }.should.raise(TypeError) - - def from.to_int() 1 end - def to.to_int() 'cat' end - - -> { a.send(@method, from..to) }.should.raise(TypeError) - end - - it "returns the elements specified by Range indexes with [m..n]" do - [ "a", "b", "c", "d", "e" ].send(@method, 1..3).should == ["b", "c", "d"] - [ "a", "b", "c", "d", "e" ].send(@method, 4..-1).should == ['e'] - [ "a", "b", "c", "d", "e" ].send(@method, 3..3).should == ['d'] - [ "a", "b", "c", "d", "e" ].send(@method, 3..-2).should == ['d'] - ['a'].send(@method, 0..-1).should == ['a'] - - a = [1, 2, 3, 4] - - a.send(@method, 0..-10).should == [] - a.send(@method, 0..0).should == [1] - a.send(@method, 0..1).should == [1, 2] - a.send(@method, 0..2).should == [1, 2, 3] - a.send(@method, 0..3).should == [1, 2, 3, 4] - a.send(@method, 0..4).should == [1, 2, 3, 4] - a.send(@method, 0..10).should == [1, 2, 3, 4] - - a.send(@method, 2..-10).should == [] - a.send(@method, 2..0).should == [] - a.send(@method, 2..2).should == [3] - a.send(@method, 2..3).should == [3, 4] - a.send(@method, 2..4).should == [3, 4] - - a.send(@method, 3..0).should == [] - a.send(@method, 3..3).should == [4] - a.send(@method, 3..4).should == [4] - - a.send(@method, 4..0).should == [] - a.send(@method, 4..4).should == [] - a.send(@method, 4..5).should == [] - - a.send(@method, 5..0).should == nil - a.send(@method, 5..5).should == nil - a.send(@method, 5..6).should == nil - - a.should == [1, 2, 3, 4] - end - - it "returns elements specified by Range indexes except the element at index n with [m...n]" do - [ "a", "b", "c", "d", "e" ].send(@method, 1...3).should == ["b", "c"] - - a = [1, 2, 3, 4] - - a.send(@method, 0...-10).should == [] - a.send(@method, 0...0).should == [] - a.send(@method, 0...1).should == [1] - a.send(@method, 0...2).should == [1, 2] - a.send(@method, 0...3).should == [1, 2, 3] - a.send(@method, 0...4).should == [1, 2, 3, 4] - a.send(@method, 0...10).should == [1, 2, 3, 4] - - a.send(@method, 2...-10).should == [] - a.send(@method, 2...0).should == [] - a.send(@method, 2...2).should == [] - a.send(@method, 2...3).should == [3] - a.send(@method, 2...4).should == [3, 4] - - a.send(@method, 3...0).should == [] - a.send(@method, 3...3).should == [] - a.send(@method, 3...4).should == [4] - - a.send(@method, 4...0).should == [] - a.send(@method, 4...4).should == [] - a.send(@method, 4...5).should == [] - - a.send(@method, 5...0).should == nil - a.send(@method, 5...5).should == nil - a.send(@method, 5...6).should == nil - - a.should == [1, 2, 3, 4] - end - - it "returns elements that exist if range start is in the array but range end is not with [m..n]" do - [ "a", "b", "c", "d", "e" ].send(@method, 4..7).should == ["e"] - end - - it "accepts Range instances having a negative m and both signs for n with [m..n] and [m...n]" do - a = [1, 2, 3, 4] - - a.send(@method, -1..-1).should == [4] - a.send(@method, -1...-1).should == [] - a.send(@method, -1..3).should == [4] - a.send(@method, -1...3).should == [] - a.send(@method, -1..4).should == [4] - a.send(@method, -1...4).should == [4] - a.send(@method, -1..10).should == [4] - a.send(@method, -1...10).should == [4] - a.send(@method, -1..0).should == [] - a.send(@method, -1..-4).should == [] - a.send(@method, -1...-4).should == [] - a.send(@method, -1..-6).should == [] - a.send(@method, -1...-6).should == [] - - a.send(@method, -2..-2).should == [3] - a.send(@method, -2...-2).should == [] - a.send(@method, -2..-1).should == [3, 4] - a.send(@method, -2...-1).should == [3] - a.send(@method, -2..10).should == [3, 4] - a.send(@method, -2...10).should == [3, 4] - - a.send(@method, -4..-4).should == [1] - a.send(@method, -4..-2).should == [1, 2, 3] - a.send(@method, -4...-2).should == [1, 2] - a.send(@method, -4..-1).should == [1, 2, 3, 4] - a.send(@method, -4...-1).should == [1, 2, 3] - a.send(@method, -4..3).should == [1, 2, 3, 4] - a.send(@method, -4...3).should == [1, 2, 3] - a.send(@method, -4..4).should == [1, 2, 3, 4] - a.send(@method, -4...4).should == [1, 2, 3, 4] - a.send(@method, -4...4).should == [1, 2, 3, 4] - a.send(@method, -4..0).should == [1] - a.send(@method, -4...0).should == [] - a.send(@method, -4..1).should == [1, 2] - a.send(@method, -4...1).should == [1] - - a.send(@method, -5..-5).should == nil - a.send(@method, -5...-5).should == nil - a.send(@method, -5..-4).should == nil - a.send(@method, -5..-1).should == nil - a.send(@method, -5..10).should == nil - - a.should == [1, 2, 3, 4] - end - - it "returns the subarray which is independent to self with [m..n]" do - a = [1, 2, 3] - sub = a.send(@method, 1..2) - sub.replace([:a, :b]) - a.should == [1, 2, 3] - end - - it "tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]" do - from = mock('from') - to = mock('to') - - # So we can construct a range out of them... - def from.<=>(o) 0 end - def to.<=>(o) 0 end - - def from.to_int() 1 end - def to.to_int() -2 end - - a = [1, 2, 3, 4] - - a.send(@method, from..to).should == [2, 3] - a.send(@method, from...to).should == [2] - a.send(@method, 1..0).should == [] - a.send(@method, 1...0).should == [] - - -> { a.send(@method, "a" .. "b") }.should.raise(TypeError) - -> { a.send(@method, "a" ... "b") }.should.raise(TypeError) - -> { a.send(@method, from .. "b") }.should.raise(TypeError) - -> { a.send(@method, from ... "b") }.should.raise(TypeError) - end - - it "returns the same elements as [m..n] and [m...n] with Range subclasses" do - a = [1, 2, 3, 4] - range_incl = ArraySpecs::MyRange.new(1, 2) - range_excl = ArraySpecs::MyRange.new(-3, -1, true) - - a.send(@method, range_incl).should == [2, 3] - a.send(@method, range_excl).should == [2, 3] - end - - it "returns nil for a requested index not in the array with [index]" do - [ "a", "b", "c", "d", "e" ].send(@method, 5).should == nil - end - - it "returns [] if the index is valid but length is zero with [index, length]" do - [ "a", "b", "c", "d", "e" ].send(@method, 0, 0).should == [] - [ "a", "b", "c", "d", "e" ].send(@method, 2, 0).should == [] - end - - it "returns nil if length is zero but index is invalid with [index, length]" do - [ "a", "b", "c", "d", "e" ].send(@method, 100, 0).should == nil - [ "a", "b", "c", "d", "e" ].send(@method, -50, 0).should == nil - end - - # This is by design. It is in the official documentation. - it "returns [] if index == array.size with [index, length]" do - %w|a b c d e|.send(@method, 5, 2).should == [] - end - - it "returns nil if index > array.size with [index, length]" do - %w|a b c d e|.send(@method, 6, 2).should == nil - end - - it "returns nil if length is negative with [index, length]" do - %w|a b c d e|.send(@method, 3, -1).should == nil - %w|a b c d e|.send(@method, 2, -2).should == nil - %w|a b c d e|.send(@method, 1, -100).should == nil - end - - it "returns nil if no requested index is in the array with [m..n]" do - [ "a", "b", "c", "d", "e" ].send(@method, 6..10).should == nil - end - - it "returns nil if range start is not in the array with [m..n]" do - [ "a", "b", "c", "d", "e" ].send(@method, -10..2).should == nil - [ "a", "b", "c", "d", "e" ].send(@method, 10..12).should == nil - end - - it "returns an empty array when m == n with [m...n]" do - [1, 2, 3, 4, 5].send(@method, 1...1).should == [] - end - - it "returns an empty array with [0...0]" do - [1, 2, 3, 4, 5].send(@method, 0...0).should == [] - end - - it "returns a subarray where m, n negatives and m < n with [m..n]" do - [ "a", "b", "c", "d", "e" ].send(@method, -3..-2).should == ["c", "d"] - end - - it "returns an array containing the first element with [0..0]" do - [1, 2, 3, 4, 5].send(@method, 0..0).should == [1] - end - - it "returns the entire array with [0..-1]" do - [1, 2, 3, 4, 5].send(@method, 0..-1).should == [1, 2, 3, 4, 5] - end - - it "returns all but the last element with [0...-1]" do - [1, 2, 3, 4, 5].send(@method, 0...-1).should == [1, 2, 3, 4] - end - - it "returns [3] for [2..-1] out of [1, 2, 3]" do - [1,2,3].send(@method, 2..-1).should == [3] - end - - it "returns an empty array when m > n and m, n are positive with [m..n]" do - [1, 2, 3, 4, 5].send(@method, 3..2).should == [] - end - - it "returns an empty array when m > n and m, n are negative with [m..n]" do - [1, 2, 3, 4, 5].send(@method, -2..-3).should == [] - end - - it "does not expand array when the indices are outside of the array bounds" do - a = [1, 2] - a.send(@method, 4).should == nil - a.should == [1, 2] - a.send(@method, 4, 0).should == nil - a.should == [1, 2] - a.send(@method, 6, 1).should == nil - a.should == [1, 2] - a.send(@method, 8...8).should == nil - a.should == [1, 2] - a.send(@method, 10..10).should == nil - a.should == [1, 2] - end - - describe "with a subclass of Array" do - before :each do - ScratchPad.clear - - @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] - end - - it "returns a Array instance with [n, m]" do - @array.send(@method, 0, 2).should.instance_of?(Array) - end - - it "returns a Array instance with [-n, m]" do - @array.send(@method, -3, 2).should.instance_of?(Array) - end - - it "returns a Array instance with [n..m]" do - @array.send(@method, 1..3).should.instance_of?(Array) - end - - it "returns a Array instance with [n...m]" do - @array.send(@method, 1...3).should.instance_of?(Array) - end - - it "returns a Array instance with [-n..-m]" do - @array.send(@method, -3..-1).should.instance_of?(Array) - end - - it "returns a Array instance with [-n...-m]" do - @array.send(@method, -3...-1).should.instance_of?(Array) - end - - it "returns an empty array when m == n with [m...n]" do - @array.send(@method, 1...1).should == [] - ScratchPad.recorded.should == nil - end - - it "returns an empty array with [0...0]" do - @array.send(@method, 0...0).should == [] - ScratchPad.recorded.should == nil - end - - it "returns an empty array when m > n and m, n are positive with [m..n]" do - @array.send(@method, 3..2).should == [] - ScratchPad.recorded.should == nil - end - - it "returns an empty array when m > n and m, n are negative with [m..n]" do - @array.send(@method, -2..-3).should == [] - ScratchPad.recorded.should == nil - end - - it "returns [] if index == array.size with [index, length]" do - @array.send(@method, 5, 2).should == [] - ScratchPad.recorded.should == nil - end - - it "returns [] if the index is valid but length is zero with [index, length]" do - @array.send(@method, 0, 0).should == [] - @array.send(@method, 2, 0).should == [] - ScratchPad.recorded.should == nil - end - - it "does not call #initialize on the subclass instance" do - @array.send(@method, 0, 3).should == [1, 2, 3] - ScratchPad.recorded.should == nil - end - end - - it "raises a RangeError when the start index is out of range of Fixnum" do - array = [1, 2, 3, 4, 5, 6] - obj = mock('large value') - obj.should_receive(:to_int).and_return(bignum_value) - -> { array.send(@method, obj) }.should.raise(RangeError) - - obj = 8e19 - -> { array.send(@method, obj) }.should.raise(RangeError) - - # boundary value when longs are 64 bits - -> { array.send(@method, 2.0**63) }.should.raise(RangeError) - - # just under the boundary value when longs are 64 bits - array.send(@method, max_long.to_f.prev_float).should == nil - end - - it "raises a RangeError when the length is out of range of Fixnum" do - array = [1, 2, 3, 4, 5, 6] - obj = mock('large value') - obj.should_receive(:to_int).and_return(bignum_value) - -> { array.send(@method, 1, obj) }.should.raise(RangeError) - - obj = 8e19 - -> { array.send(@method, 1, obj) }.should.raise(RangeError) - end - - it "raises a type error if a range is passed with a length" do - ->{ [1, 2, 3].send(@method, 1..2, 1) }.should.raise(TypeError) - end - - it "raises a RangeError if passed a range with a bound that is too large" do - array = [1, 2, 3, 4, 5, 6] - -> { array.send(@method, bignum_value..(bignum_value + 1)) }.should.raise(RangeError) - -> { array.send(@method, 0..bignum_value) }.should.raise(RangeError) - end - - it "can accept endless ranges" do - a = [0, 1, 2, 3, 4, 5] - a.send(@method, eval("(2..)")).should == [2, 3, 4, 5] - a.send(@method, eval("(2...)")).should == [2, 3, 4, 5] - a.send(@method, eval("(-2..)")).should == [4, 5] - a.send(@method, eval("(-2...)")).should == [4, 5] - a.send(@method, eval("(9..)")).should == nil - a.send(@method, eval("(9...)")).should == nil - a.send(@method, eval("(-9..)")).should == nil - a.send(@method, eval("(-9...)")).should == nil - end - - describe "can be sliced with Enumerator::ArithmeticSequence" do - before :each do - @array = [0, 1, 2, 3, 4, 5] - end - - it "has endless range and positive steps" do - @array.send(@method, eval("(0..).step(1)")).should == [0, 1, 2, 3, 4, 5] - @array.send(@method, eval("(0..).step(2)")).should == [0, 2, 4] - @array.send(@method, eval("(0..).step(10)")).should == [0] - - @array.send(@method, eval("(2..).step(1)")).should == [2, 3, 4, 5] - @array.send(@method, eval("(2..).step(2)")).should == [2, 4] - @array.send(@method, eval("(2..).step(10)")).should == [2] - - @array.send(@method, eval("(-3..).step(1)")).should == [3, 4, 5] - @array.send(@method, eval("(-3..).step(2)")).should == [3, 5] - @array.send(@method, eval("(-3..).step(10)")).should == [3] - end - - it "has beginless range and positive steps" do - # end with zero index - @array.send(@method, (..0).step(1)).should == [0] - @array.send(@method, (...0).step(1)).should == [] - - @array.send(@method, (..0).step(2)).should == [0] - @array.send(@method, (...0).step(2)).should == [] - - @array.send(@method, (..0).step(10)).should == [0] - @array.send(@method, (...0).step(10)).should == [] - - # end with positive index - @array.send(@method, (..3).step(1)).should == [0, 1, 2, 3] - @array.send(@method, (...3).step(1)).should == [0, 1, 2] - - @array.send(@method, (..3).step(2)).should == [0, 2] - @array.send(@method, (...3).step(2)).should == [0, 2] - - @array.send(@method, (..3).step(10)).should == [0] - @array.send(@method, (...3).step(10)).should == [0] - - # end with negative index - @array.send(@method, (..-2).step(1)).should == [0, 1, 2, 3, 4,] - @array.send(@method, (...-2).step(1)).should == [0, 1, 2, 3] - - @array.send(@method, (..-2).step(2)).should == [0, 2, 4] - @array.send(@method, (...-2).step(2)).should == [0, 2] - - @array.send(@method, (..-2).step(10)).should == [0] - @array.send(@method, (...-2).step(10)).should == [0] - end - - it "has endless range and negative steps" do - @array.send(@method, eval("(0..).step(-1)")).should == [0] - @array.send(@method, eval("(0..).step(-2)")).should == [0] - @array.send(@method, eval("(0..).step(-10)")).should == [0] - - @array.send(@method, eval("(2..).step(-1)")).should == [2, 1, 0] - @array.send(@method, eval("(2..).step(-2)")).should == [2, 0] - - @array.send(@method, eval("(-3..).step(-1)")).should == [3, 2, 1, 0] - @array.send(@method, eval("(-3..).step(-2)")).should == [3, 1] - end - - it "has closed range and positive steps" do - # start and end with 0 - @array.send(@method, eval("(0..0).step(1)")).should == [0] - @array.send(@method, eval("(0...0).step(1)")).should == [] - - @array.send(@method, eval("(0..0).step(2)")).should == [0] - @array.send(@method, eval("(0...0).step(2)")).should == [] - - @array.send(@method, eval("(0..0).step(10)")).should == [0] - @array.send(@method, eval("(0...0).step(10)")).should == [] - - # start and end with positive index - @array.send(@method, eval("(1..3).step(1)")).should == [1, 2, 3] - @array.send(@method, eval("(1...3).step(1)")).should == [1, 2] - - @array.send(@method, eval("(1..3).step(2)")).should == [1, 3] - @array.send(@method, eval("(1...3).step(2)")).should == [1] - - @array.send(@method, eval("(1..3).step(10)")).should == [1] - @array.send(@method, eval("(1...3).step(10)")).should == [1] - - # start with positive index, end with negative index - @array.send(@method, eval("(1..-2).step(1)")).should == [1, 2, 3, 4] - @array.send(@method, eval("(1...-2).step(1)")).should == [1, 2, 3] - - @array.send(@method, eval("(1..-2).step(2)")).should == [1, 3] - @array.send(@method, eval("(1...-2).step(2)")).should == [1, 3] - - @array.send(@method, eval("(1..-2).step(10)")).should == [1] - @array.send(@method, eval("(1...-2).step(10)")).should == [1] - - # start with negative index, end with positive index - @array.send(@method, eval("(-4..4).step(1)")).should == [2, 3, 4] - @array.send(@method, eval("(-4...4).step(1)")).should == [2, 3] - - @array.send(@method, eval("(-4..4).step(2)")).should == [2, 4] - @array.send(@method, eval("(-4...4).step(2)")).should == [2] - - @array.send(@method, eval("(-4..4).step(10)")).should == [2] - @array.send(@method, eval("(-4...4).step(10)")).should == [2] - - # start with negative index, end with negative index - @array.send(@method, eval("(-4..-2).step(1)")).should == [2, 3, 4] - @array.send(@method, eval("(-4...-2).step(1)")).should == [2, 3] - - @array.send(@method, eval("(-4..-2).step(2)")).should == [2, 4] - @array.send(@method, eval("(-4...-2).step(2)")).should == [2] - - @array.send(@method, eval("(-4..-2).step(10)")).should == [2] - @array.send(@method, eval("(-4...-2).step(10)")).should == [2] - end - - it "has closed range and negative steps" do - # start and end with 0 - @array.send(@method, eval("(0..0).step(-1)")).should == [0] - @array.send(@method, eval("(0...0).step(-1)")).should == [] - - @array.send(@method, eval("(0..0).step(-2)")).should == [0] - @array.send(@method, eval("(0...0).step(-2)")).should == [] - - @array.send(@method, eval("(0..0).step(-10)")).should == [0] - @array.send(@method, eval("(0...0).step(-10)")).should == [] - - # start and end with positive index - @array.send(@method, eval("(1..3).step(-1)")).should == [] - @array.send(@method, eval("(1...3).step(-1)")).should == [] - - @array.send(@method, eval("(1..3).step(-2)")).should == [] - @array.send(@method, eval("(1...3).step(-2)")).should == [] - - @array.send(@method, eval("(1..3).step(-10)")).should == [] - @array.send(@method, eval("(1...3).step(-10)")).should == [] - - # start with positive index, end with negative index - @array.send(@method, eval("(1..-2).step(-1)")).should == [] - @array.send(@method, eval("(1...-2).step(-1)")).should == [] - - @array.send(@method, eval("(1..-2).step(-2)")).should == [] - @array.send(@method, eval("(1...-2).step(-2)")).should == [] - - @array.send(@method, eval("(1..-2).step(-10)")).should == [] - @array.send(@method, eval("(1...-2).step(-10)")).should == [] - - # start with negative index, end with positive index - @array.send(@method, eval("(-4..4).step(-1)")).should == [] - @array.send(@method, eval("(-4...4).step(-1)")).should == [] - - @array.send(@method, eval("(-4..4).step(-2)")).should == [] - @array.send(@method, eval("(-4...4).step(-2)")).should == [] - - @array.send(@method, eval("(-4..4).step(-10)")).should == [] - @array.send(@method, eval("(-4...4).step(-10)")).should == [] - - # start with negative index, end with negative index - @array.send(@method, eval("(-4..-2).step(-1)")).should == [] - @array.send(@method, eval("(-4...-2).step(-1)")).should == [] - - @array.send(@method, eval("(-4..-2).step(-2)")).should == [] - @array.send(@method, eval("(-4...-2).step(-2)")).should == [] - - @array.send(@method, eval("(-4..-2).step(-10)")).should == [] - @array.send(@method, eval("(-4...-2).step(-10)")).should == [] - end - - it "has inverted closed range and positive steps" do - # start and end with positive index - @array.send(@method, eval("(3..1).step(1)")).should == [] - @array.send(@method, eval("(3...1).step(1)")).should == [] - - @array.send(@method, eval("(3..1).step(2)")).should == [] - @array.send(@method, eval("(3...1).step(2)")).should == [] - - @array.send(@method, eval("(3..1).step(10)")).should == [] - @array.send(@method, eval("(3...1).step(10)")).should == [] - - # start with negative index, end with positive index - @array.send(@method, eval("(-2..1).step(1)")).should == [] - @array.send(@method, eval("(-2...1).step(1)")).should == [] - - @array.send(@method, eval("(-2..1).step(2)")).should == [] - @array.send(@method, eval("(-2...1).step(2)")).should == [] - - @array.send(@method, eval("(-2..1).step(10)")).should == [] - @array.send(@method, eval("(-2...1).step(10)")).should == [] - - # start with positive index, end with negative index - @array.send(@method, eval("(4..-4).step(1)")).should == [] - @array.send(@method, eval("(4...-4).step(1)")).should == [] - - @array.send(@method, eval("(4..-4).step(2)")).should == [] - @array.send(@method, eval("(4...-4).step(2)")).should == [] - - @array.send(@method, eval("(4..-4).step(10)")).should == [] - @array.send(@method, eval("(4...-4).step(10)")).should == [] - - # start with negative index, end with negative index - @array.send(@method, eval("(-2..-4).step(1)")).should == [] - @array.send(@method, eval("(-2...-4).step(1)")).should == [] - - @array.send(@method, eval("(-2..-4).step(2)")).should == [] - @array.send(@method, eval("(-2...-4).step(2)")).should == [] - - @array.send(@method, eval("(-2..-4).step(10)")).should == [] - @array.send(@method, eval("(-2...-4).step(10)")).should == [] - end - - it "has range with bounds outside of array" do - # end is equal to array's length - @array.send(@method, (0..6).step(1)).should == [0, 1, 2, 3, 4, 5] - -> { @array.send(@method, (0..6).step(2)) }.should.raise(RangeError) - - # end is greater than length with positive steps - @array.send(@method, (1..6).step(2)).should == [1, 3, 5] - @array.send(@method, (2..7).step(2)).should == [2, 4] - -> { @array.send(@method, (2..8).step(2)) }.should.raise(RangeError) - - # begin is greater than length with negative steps - @array.send(@method, (6..1).step(-2)).should == [5, 3, 1] - @array.send(@method, (7..2).step(-2)).should == [5, 3] - -> { @array.send(@method, (8..2).step(-2)) }.should.raise(RangeError) - end - - it "has endless range with start outside of array's bounds" do - @array.send(@method, eval("(6..).step(1)")).should == [] - @array.send(@method, eval("(7..).step(1)")).should == nil - - @array.send(@method, eval("(6..).step(2)")).should == [] - -> { @array.send(@method, eval("(7..).step(2)")) }.should.raise(RangeError) - end - end - - it "can accept beginless ranges" do - a = [0, 1, 2, 3, 4, 5] - a.send(@method, (..3)).should == [0, 1, 2, 3] - a.send(@method, (...3)).should == [0, 1, 2] - a.send(@method, (..-3)).should == [0, 1, 2, 3] - a.send(@method, (...-3)).should == [0, 1, 2] - a.send(@method, (..0)).should == [0] - a.send(@method, (...0)).should == [] - a.send(@method, (..9)).should == [0, 1, 2, 3, 4, 5] - a.send(@method, (...9)).should == [0, 1, 2, 3, 4, 5] - a.send(@method, (..-9)).should == [] - a.send(@method, (...-9)).should == [] - end - - describe "can be sliced with Enumerator::ArithmeticSequence" do - it "with infinite/inverted ranges and negative steps" do - @array = [0, 1, 2, 3, 4, 5] - @array.send(@method, (2..).step(-1)).should == [2, 1, 0] - @array.send(@method, (2..).step(-2)).should == [2, 0] - @array.send(@method, (2..).step(-3)).should == [2] - @array.send(@method, (2..).step(-4)).should == [2] - - @array.send(@method, (-3..).step(-1)).should == [3, 2, 1, 0] - @array.send(@method, (-3..).step(-2)).should == [3, 1] - @array.send(@method, (-3..).step(-3)).should == [3, 0] - @array.send(@method, (-3..).step(-4)).should == [3] - @array.send(@method, (-3..).step(-5)).should == [3] - - @array.send(@method, (..0).step(-1)).should == [5, 4, 3, 2, 1, 0] - @array.send(@method, (..0).step(-2)).should == [5, 3, 1] - @array.send(@method, (..0).step(-3)).should == [5, 2] - @array.send(@method, (..0).step(-4)).should == [5, 1] - @array.send(@method, (..0).step(-5)).should == [5, 0] - @array.send(@method, (..0).step(-6)).should == [5] - @array.send(@method, (..0).step(-7)).should == [5] - - @array.send(@method, (...0).step(-1)).should == [5, 4, 3, 2, 1] - @array.send(@method, (...0).step(-2)).should == [5, 3, 1] - @array.send(@method, (...0).step(-3)).should == [5, 2] - @array.send(@method, (...0).step(-4)).should == [5, 1] - @array.send(@method, (...0).step(-5)).should == [5] - @array.send(@method, (...0).step(-6)).should == [5] - - @array.send(@method, (...1).step(-1)).should == [5, 4, 3, 2] - @array.send(@method, (...1).step(-2)).should == [5, 3] - @array.send(@method, (...1).step(-3)).should == [5, 2] - @array.send(@method, (...1).step(-4)).should == [5] - @array.send(@method, (...1).step(-5)).should == [5] - - @array.send(@method, (..-5).step(-1)).should == [5, 4, 3, 2, 1] - @array.send(@method, (..-5).step(-2)).should == [5, 3, 1] - @array.send(@method, (..-5).step(-3)).should == [5, 2] - @array.send(@method, (..-5).step(-4)).should == [5, 1] - @array.send(@method, (..-5).step(-5)).should == [5] - @array.send(@method, (..-5).step(-6)).should == [5] - - @array.send(@method, (...-5).step(-1)).should == [5, 4, 3, 2] - @array.send(@method, (...-5).step(-2)).should == [5, 3] - @array.send(@method, (...-5).step(-3)).should == [5, 2] - @array.send(@method, (...-5).step(-4)).should == [5] - @array.send(@method, (...-5).step(-5)).should == [5] - - @array.send(@method, (4..1).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (4..1).step(-2)).should == [4, 2] - @array.send(@method, (4..1).step(-3)).should == [4, 1] - @array.send(@method, (4..1).step(-4)).should == [4] - @array.send(@method, (4..1).step(-5)).should == [4] - - @array.send(@method, (4...1).step(-1)).should == [4, 3, 2] - @array.send(@method, (4...1).step(-2)).should == [4, 2] - @array.send(@method, (4...1).step(-3)).should == [4] - @array.send(@method, (4...1).step(-4)).should == [4] - - @array.send(@method, (-2..1).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (-2..1).step(-2)).should == [4, 2] - @array.send(@method, (-2..1).step(-3)).should == [4, 1] - @array.send(@method, (-2..1).step(-4)).should == [4] - @array.send(@method, (-2..1).step(-5)).should == [4] - - @array.send(@method, (-2...1).step(-1)).should == [4, 3, 2] - @array.send(@method, (-2...1).step(-2)).should == [4, 2] - @array.send(@method, (-2...1).step(-3)).should == [4] - @array.send(@method, (-2...1).step(-4)).should == [4] - - @array.send(@method, (4..-5).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (4..-5).step(-2)).should == [4, 2] - @array.send(@method, (4..-5).step(-3)).should == [4, 1] - @array.send(@method, (4..-5).step(-4)).should == [4] - @array.send(@method, (4..-5).step(-5)).should == [4] - - @array.send(@method, (4...-5).step(-1)).should == [4, 3, 2] - @array.send(@method, (4...-5).step(-2)).should == [4, 2] - @array.send(@method, (4...-5).step(-3)).should == [4] - @array.send(@method, (4...-5).step(-4)).should == [4] - - @array.send(@method, (-2..-5).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (-2..-5).step(-2)).should == [4, 2] - @array.send(@method, (-2..-5).step(-3)).should == [4, 1] - @array.send(@method, (-2..-5).step(-4)).should == [4] - @array.send(@method, (-2..-5).step(-5)).should == [4] - - @array.send(@method, (-2...-5).step(-1)).should == [4, 3, 2] - @array.send(@method, (-2...-5).step(-2)).should == [4, 2] - @array.send(@method, (-2...-5).step(-3)).should == [4] - @array.send(@method, (-2...-5).step(-4)).should == [4] - end - end - - it "can accept nil...nil ranges" do - a = [0, 1, 2, 3, 4, 5] - a.send(@method, eval("(nil...nil)")).should == a - a.send(@method, (...nil)).should == a - a.send(@method, eval("(nil..)")).should == a - end -end diff --git a/core/array/shared/unshift.rb b/core/array/shared/unshift.rb deleted file mode 100644 index b636347cd3..0000000000 --- a/core/array/shared/unshift.rb +++ /dev/null @@ -1,64 +0,0 @@ -describe :array_unshift, shared: true do - it "prepends object to the original array" do - a = [1, 2, 3] - a.send(@method, "a").should.equal?(a) - a.should == ['a', 1, 2, 3] - a.send(@method).should.equal?(a) - a.should == ['a', 1, 2, 3] - a.send(@method, 5, 4, 3) - a.should == [5, 4, 3, 'a', 1, 2, 3] - - # shift all but one element - a = [1, 2] - a.shift - a.send(@method, 3, 4) - a.should == [3, 4, 2] - - # now shift all elements - a.shift - a.shift - a.shift - a.send(@method, 3, 4) - a.should == [3, 4] - end - - it "returns self" do - a = [1, 2, 3] - a.send(@method, "a").should.equal?(a) - end - - it "quietly ignores unshifting nothing" do - [].send(@method).should == [] - end - - it "properly handles recursive arrays" do - empty = ArraySpecs.empty_recursive_array - empty.send(@method, :new).should == [:new, empty] - - array = ArraySpecs.recursive_array - array.send(@method, :new) - array[0..5].should == [:new, 1, 'two', 3.0, array, array] - end - - it "raises a FrozenError on a frozen array when the array is modified" do - -> { ArraySpecs.frozen_array.send(@method, 1) }.should.raise(FrozenError) - end - - # see [ruby-core:23666] - it "raises a FrozenError on a frozen array when the array would not be modified" do - -> { ArraySpecs.frozen_array.send(@method) }.should.raise(FrozenError) - end - - # 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 []=(*) - raise "[]= is called" - end - end - - array = subclass.new - array.send(@method, 1) - array.should == [1] - end -end diff --git a/core/array/size_spec.rb b/core/array/size_spec.rb index d68f956a83..83e8969012 100644 --- a/core/array/size_spec.rb +++ b/core/array/size_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/length' describe "Array#size" do - it_behaves_like :array_length, :size + it "is an alias of Array#length" do + Array.instance_method(:size).should == Array.instance_method(:length) + end end diff --git a/core/array/slice_spec.rb b/core/array/slice_spec.rb index eb7e47d947..230d1dc5d1 100644 --- a/core/array/slice_spec.rb +++ b/core/array/slice_spec.rb @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/slice' describe "Array#slice!" do it "removes and return the element at index" do @@ -214,5 +213,7 @@ def to.to_int() -2 end end describe "Array#slice" do - it_behaves_like :array_slice, :slice + it "is an alias of Array#[]" do + Array.instance_method(:slice).should == Array.instance_method(:[]) + end end diff --git a/core/array/to_s_spec.rb b/core/array/to_s_spec.rb index e8476702ec..483e14f902 100644 --- a/core/array/to_s_spec.rb +++ b/core/array/to_s_spec.rb @@ -1,8 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/join' -require_relative 'shared/inspect' describe "Array#to_s" do - it_behaves_like :array_inspect, :to_s + it "is an alias of Array#inspect" do + Array.instance_method(:to_s).should == Array.instance_method(:inspect) + end end diff --git a/core/array/unshift_spec.rb b/core/array/unshift_spec.rb index b8b675e5f8..c190db4d02 100644 --- a/core/array/unshift_spec.rb +++ b/core/array/unshift_spec.rb @@ -1,7 +1,67 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/unshift' describe "Array#unshift" do - it_behaves_like :array_unshift, :unshift + it "prepends object to the original array" do + a = [1, 2, 3] + a.unshift("a").should.equal?(a) + a.should == ['a', 1, 2, 3] + a.unshift.should.equal?(a) + a.should == ['a', 1, 2, 3] + a.unshift(5, 4, 3) + a.should == [5, 4, 3, 'a', 1, 2, 3] + + # shift all but one element + a = [1, 2] + a.shift + a.unshift(3, 4) + a.should == [3, 4, 2] + + # now shift all elements + a.shift + a.shift + a.shift + a.unshift(3, 4) + a.should == [3, 4] + end + + it "returns self" do + a = [1, 2, 3] + a.unshift("a").should.equal?(a) + end + + it "quietly ignores unshifting nothing" do + [].unshift.should == [] + end + + it "properly handles recursive arrays" do + empty = ArraySpecs.empty_recursive_array + empty.unshift(:new).should == [:new, empty] + + array = ArraySpecs.recursive_array + array.unshift(:new) + array[0..5].should == [:new, 1, 'two', 3.0, array, array] + end + + it "raises a FrozenError on a frozen array when the array is modified" do + -> { ArraySpecs.frozen_array.unshift(1) }.should.raise(FrozenError) + end + + # see [ruby-core:23666] + it "raises a FrozenError on a frozen array when the array would not be modified" do + -> { ArraySpecs.frozen_array.unshift }.should.raise(FrozenError) + end + + # 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 []=(*) + raise "[]= is called" + end + end + + array = subclass.new + array.unshift(1) + array.should == [1] + end end diff --git a/core/complex/abs_spec.rb b/core/complex/abs_spec.rb index 43912c517f..ed5aebb11d 100644 --- a/core/complex/abs_spec.rb +++ b/core/complex/abs_spec.rb @@ -1,6 +1,12 @@ require_relative '../../spec_helper' -require_relative 'shared/abs' describe "Complex#abs" do - it_behaves_like :complex_abs, :abs + it "returns the modulus: |a + bi| = sqrt((a ^ 2) + (b ^ 2))" do + Complex(0, 0).abs.should == 0 + Complex(3, 4).abs.should == 5 # well-known integer case + Complex(-3, 4).abs.should == 5 + Complex(1, -1).abs.should be_close(Math.sqrt(2), TOLERANCE) + Complex(6.5, 0).abs.should be_close(6.5, TOLERANCE) + Complex(0, -7.2).abs.should be_close(7.2, TOLERANCE) + end end diff --git a/core/complex/angle_spec.rb b/core/complex/angle_spec.rb index 4aa176956f..7551214d2b 100644 --- a/core/complex/angle_spec.rb +++ b/core/complex/angle_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/arg' describe "Complex#angle" do - it_behaves_like :complex_arg, :angle + it "is an alias of Complex#arg" do + Complex.instance_method(:angle).should == Complex.instance_method(:arg) + end end diff --git a/core/complex/arg_spec.rb b/core/complex/arg_spec.rb index 009f19429f..dd64102d77 100644 --- a/core/complex/arg_spec.rb +++ b/core/complex/arg_spec.rb @@ -1,6 +1,11 @@ require_relative '../../spec_helper' -require_relative 'shared/arg' describe "Complex#arg" do - it_behaves_like :complex_arg, :arg + it "returns the argument -- i.e., the angle from (1, 0) in the complex plane" do + two_pi = 2 * Math::PI + (Complex(1, 0).arg % two_pi).should be_close(0, TOLERANCE) + (Complex(0, 2).arg % two_pi).should be_close(Math::PI * 0.5, TOLERANCE) + (Complex(-100, 0).arg % two_pi).should be_close(Math::PI, TOLERANCE) + (Complex(0, -75.3).arg % two_pi).should be_close(Math::PI * 1.5, TOLERANCE) + end end diff --git a/core/complex/conj_spec.rb b/core/complex/conj_spec.rb index 5e3bc1acb8..063c85faec 100644 --- a/core/complex/conj_spec.rb +++ b/core/complex/conj_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/conjugate' describe "Complex#conj" do - it_behaves_like :complex_conjugate, :conj + it "is an alias of Complex#conjugate" do + Complex.instance_method(:conj).should == Complex.instance_method(:conjugate) + end end diff --git a/core/complex/conjugate_spec.rb b/core/complex/conjugate_spec.rb index f658bab4da..256fe4b3be 100644 --- a/core/complex/conjugate_spec.rb +++ b/core/complex/conjugate_spec.rb @@ -1,6 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/conjugate' describe "Complex#conjugate" do - it_behaves_like :complex_conjugate, :conjugate + it "returns the complex conjugate: conj a + bi = a - bi" do + Complex(3, 5).conjugate.should == Complex(3, -5) + Complex(3, -5).conjugate.should == Complex(3, 5) + Complex(-3.0, 5.2).conjugate.should be_close(Complex(-3.0, -5.2), TOLERANCE) + Complex(3.0, -5.2).conjugate.should be_close(Complex(3.0, 5.2), TOLERANCE) + end end diff --git a/core/complex/divide_spec.rb b/core/complex/divide_spec.rb index bebf862312..d5b4aa3885 100644 --- a/core/complex/divide_spec.rb +++ b/core/complex/divide_spec.rb @@ -1,6 +1,84 @@ require_relative '../../spec_helper' -require_relative 'shared/divide' describe "Complex#/" do - it_behaves_like :complex_divide, :/ + describe "with Complex" do + it "divides according to the usual rule for complex numbers" do + a = Complex((1 * 10) - (2 * 20), (1 * 20) + (2 * 10)) + b = Complex(1, 2) + (a / b).should == Complex(10, 20) + + c = Complex((1.5 * 100.2) - (2.1 * -30.3), (1.5 * -30.3) + (2.1 * 100.2)) + d = Complex(1.5, 2.1) + # remember the floating-point arithmetic + (c / d).should be_close(Complex(100.2, -30.3), TOLERANCE) + end + end + + describe "with Fixnum" do + it "divides both parts of the Complex number" do + (Complex(20, 40) / 2).should == Complex(10, 20) + (Complex(30, 30) / 10).should == Complex(3, 3) + end + + it "raises a ZeroDivisionError when given zero" do + -> { Complex(20, 40) / 0 }.should.raise(ZeroDivisionError) + end + + it "produces Rational parts" do + (Complex(5, 9) / 2).should.eql?(Complex(Rational(5,2), Rational(9,2))) + end + end + + describe "with Bignum" do + it "divides both parts of the Complex number" do + (Complex(20, 40) / 2).should == Complex(10, 20) + (Complex(15, 16) / 2.0).should be_close(Complex(7.5, 8), TOLERANCE) + end + end + + describe "with Float" do + it "divides both parts of the Complex number" do + (Complex(3, 9) / 1.5).should == Complex(2, 6) + (Complex(15, 16) / 2.0).should be_close(Complex(7.5, 8), TOLERANCE) + end + + it "returns Complex(Infinity, Infinity) when given zero" do + (Complex(20, 40) / 0.0).real.infinite?.should == 1 + (Complex(20, 40) / 0.0).imag.infinite?.should == 1 + (Complex(-20, 40) / 0.0).real.infinite?.should == -1 + (Complex(-20, 40) / 0.0).imag.infinite?.should == 1 + end + end + + describe "with Object" do + it "tries to coerce self into other" do + value = Complex(3, 9) + + obj = mock("Object") + obj.should_receive(:coerce).with(value).and_return([4, 2]) + (value / obj).should == 2 + end + end + + describe "with a Numeric which responds to #real? with true" do + it "returns Complex(real.quo(other), imag.quo(other))" do + other = mock_numeric('other') + real = mock_numeric('real') + imag = mock_numeric('imag') + other.should_receive(:real?).and_return(true) + real.should_receive(:quo).with(other).and_return(1) + imag.should_receive(:quo).with(other).and_return(2) + (Complex(real, imag) / other).should == Complex(1, 2) + end + end + + describe "with a Numeric which responds to #real? with false" do + it "coerces the passed argument to Complex and divides the resulting elements" do + complex = Complex(3, 0) + other = mock_numeric('other') + other.should_receive(:real?).any_number_of_times.and_return(false) + other.should_receive(:coerce).with(complex).and_return([5, 2]) + (complex / other).should.eql?(Rational(5, 2)) + end + end end diff --git a/core/complex/imag_spec.rb b/core/complex/imag_spec.rb index 2bafd1ab54..225f168e78 100644 --- a/core/complex/imag_spec.rb +++ b/core/complex/imag_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/image' describe "Complex#imag" do - it_behaves_like :complex_image, :imag + it "is an alias of Complex#imaginary" do + Complex.instance_method(:imag).should == Complex.instance_method(:imaginary) + end end diff --git a/core/complex/imaginary_spec.rb b/core/complex/imaginary_spec.rb index a8a1bfea90..ac9284e934 100644 --- a/core/complex/imaginary_spec.rb +++ b/core/complex/imaginary_spec.rb @@ -1,6 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/image' describe "Complex#imaginary" do - it_behaves_like :complex_image, :imaginary + it "returns the imaginary part of self" do + Complex(1, 0).imaginary.should == 0 + Complex(2, 1).imaginary.should == 1 + Complex(6.7, 8.9).imaginary.should == 8.9 + Complex(1, bignum_value).imaginary.should == bignum_value + end end diff --git a/core/complex/magnitude_spec.rb b/core/complex/magnitude_spec.rb index 86f3b29868..6341b4eec8 100644 --- a/core/complex/magnitude_spec.rb +++ b/core/complex/magnitude_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/abs' describe "Complex#magnitude" do - it_behaves_like :complex_abs, :magnitude + it "is an alias of Complex#abs" do + Complex.instance_method(:magnitude).should == Complex.instance_method(:abs) + end end diff --git a/core/complex/phase_spec.rb b/core/complex/phase_spec.rb index 89574bf533..2ab90989e1 100644 --- a/core/complex/phase_spec.rb +++ b/core/complex/phase_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/arg' describe "Complex#phase" do - it_behaves_like :complex_arg, :phase + it "is an alias of Complex#arg" do + Complex.instance_method(:phase).should == Complex.instance_method(:arg) + end end diff --git a/core/complex/quo_spec.rb b/core/complex/quo_spec.rb index ee6fd65c79..be0a44d532 100644 --- a/core/complex/quo_spec.rb +++ b/core/complex/quo_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/divide' describe "Complex#quo" do - it_behaves_like :complex_divide, :quo + it "is an alias of Complex#/" do + Complex.instance_method(:quo).should == Complex.instance_method(:/) + end end diff --git a/core/complex/rect_spec.rb b/core/complex/rect_spec.rb index 9e95f3efc2..72f2bf9930 100644 --- a/core/complex/rect_spec.rb +++ b/core/complex/rect_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -require_relative 'shared/rect' describe "Complex#rect" do - it_behaves_like :complex_rect, :rect + it "is an alias of Complex#rectangular" do + Complex.instance_method(:rect).should == Complex.instance_method(:rectangular) + end end describe "Complex.rect" do - it_behaves_like :complex_rect_class, :rect + it "is an alias of Complex#rectangular" do + Complex.method(:rect).should == Complex.method(:rectangular) + end end diff --git a/core/complex/rectangular_spec.rb b/core/complex/rectangular_spec.rb index d4b8ad9782..dda4099d6a 100644 --- a/core/complex/rectangular_spec.rb +++ b/core/complex/rectangular_spec.rb @@ -1,10 +1,96 @@ require_relative '../../spec_helper' -require_relative 'shared/rect' describe "Complex#rectangular" do - it_behaves_like :complex_rect, :rectangular + before :each do + @numbers = [ + Complex(1), + Complex(0, 20), + Complex(0, 0), + Complex(0.0), + Complex(9999999**99), + Complex(-20), + Complex.polar(76, 10) + ] + end + + it "returns an Array" do + @numbers.each do |number| + number.rectangular.should.instance_of?(Array) + end + end + + it "returns a two-element Array" do + @numbers.each do |number| + number.rectangular.size.should == 2 + end + end + + it "returns the real part of self as the first element" do + @numbers.each do |number| + number.rectangular.first.should == number.real + end + end + + it "returns the imaginary part of self as the last element" do + @numbers.each do |number| + number.rectangular.last.should == number.imaginary + end + end + + it "raises an ArgumentError if given any arguments" do + @numbers.each do |number| + -> { number.rectangular(number) }.should.raise(ArgumentError) + end + end end describe "Complex.rectangular" do - it_behaves_like :complex_rect_class, :rectangular + describe "passed a Numeric n which responds to #real? with true" do + it "returns a Complex with real part n and imaginary part 0" do + n = mock_numeric('n') + n.should_receive(:real?).any_number_of_times.and_return(true) + result = Complex.rectangular(n) + result.real.should == n + result.imag.should == 0 + end + end + + describe "passed a Numeric which responds to #real? with false" do + it "raises TypeError" do + n = mock_numeric('n') + n.should_receive(:real?).any_number_of_times.and_return(false) + -> { Complex.rectangular(n) }.should.raise(TypeError) + end + end + + describe "passed Numerics n1 and n2 and at least one responds to #real? with false" do + [[false, false], [false, true], [true, false]].each do |r1, r2| + it "raises TypeError" do + n1 = mock_numeric('n1') + n2 = mock_numeric('n2') + n1.should_receive(:real?).any_number_of_times.and_return(r1) + n2.should_receive(:real?).any_number_of_times.and_return(r2) + -> { Complex.rectangular(n1, n2) }.should.raise(TypeError) + end + end + end + + describe "passed Numerics n1 and n2 and both respond to #real? with true" do + it "returns a Complex with real part n1 and imaginary part n2" do + n1 = mock_numeric('n1') + n2 = mock_numeric('n2') + n1.should_receive(:real?).any_number_of_times.and_return(true) + n2.should_receive(:real?).any_number_of_times.and_return(true) + result = Complex.rectangular(n1, n2) + result.real.should == n1 + result.imag.should == n2 + end + end + + describe "passed a non-Numeric" do + it "raises TypeError" do + -> { Complex.rectangular(:sym) }.should.raise(TypeError) + -> { Complex.rectangular(0, :sym) }.should.raise(TypeError) + end + end end diff --git a/core/complex/shared/abs.rb b/core/complex/shared/abs.rb deleted file mode 100644 index 2299479341..0000000000 --- a/core/complex/shared/abs.rb +++ /dev/null @@ -1,10 +0,0 @@ -describe :complex_abs, shared: true do - it "returns the modulus: |a + bi| = sqrt((a ^ 2) + (b ^ 2))" do - Complex(0, 0).send(@method).should == 0 - Complex(3, 4).send(@method).should == 5 # well-known integer case - Complex(-3, 4).send(@method).should == 5 - Complex(1, -1).send(@method).should be_close(Math.sqrt(2), TOLERANCE) - Complex(6.5, 0).send(@method).should be_close(6.5, TOLERANCE) - Complex(0, -7.2).send(@method).should be_close(7.2, TOLERANCE) - end -end diff --git a/core/complex/shared/arg.rb b/core/complex/shared/arg.rb deleted file mode 100644 index c81f197433..0000000000 --- a/core/complex/shared/arg.rb +++ /dev/null @@ -1,9 +0,0 @@ -describe :complex_arg, shared: true do - it "returns the argument -- i.e., the angle from (1, 0) in the complex plane" do - two_pi = 2 * Math::PI - (Complex(1, 0).send(@method) % two_pi).should be_close(0, TOLERANCE) - (Complex(0, 2).send(@method) % two_pi).should be_close(Math::PI * 0.5, TOLERANCE) - (Complex(-100, 0).send(@method) % two_pi).should be_close(Math::PI, TOLERANCE) - (Complex(0, -75.3).send(@method) % two_pi).should be_close(Math::PI * 1.5, TOLERANCE) - end -end diff --git a/core/complex/shared/conjugate.rb b/core/complex/shared/conjugate.rb deleted file mode 100644 index d1ae47bcb6..0000000000 --- a/core/complex/shared/conjugate.rb +++ /dev/null @@ -1,8 +0,0 @@ -describe :complex_conjugate, shared: true do - it "returns the complex conjugate: conj a + bi = a - bi" do - Complex(3, 5).send(@method).should == Complex(3, -5) - Complex(3, -5).send(@method).should == Complex(3, 5) - Complex(-3.0, 5.2).send(@method).should be_close(Complex(-3.0, -5.2), TOLERANCE) - Complex(3.0, -5.2).send(@method).should be_close(Complex(3.0, 5.2), TOLERANCE) - end -end diff --git a/core/complex/shared/divide.rb b/core/complex/shared/divide.rb deleted file mode 100644 index ef79ecdf75..0000000000 --- a/core/complex/shared/divide.rb +++ /dev/null @@ -1,82 +0,0 @@ -describe :complex_divide, shared: true do - describe "with Complex" do - it "divides according to the usual rule for complex numbers" do - a = Complex((1 * 10) - (2 * 20), (1 * 20) + (2 * 10)) - b = Complex(1, 2) - a.send(@method, b).should == Complex(10, 20) - - c = Complex((1.5 * 100.2) - (2.1 * -30.3), (1.5 * -30.3) + (2.1 * 100.2)) - d = Complex(1.5, 2.1) - # remember the floating-point arithmetic - c.send(@method, d).should be_close(Complex(100.2, -30.3), TOLERANCE) - end - end - - describe "with Fixnum" do - it "divides both parts of the Complex number" do - Complex(20, 40).send(@method, 2).should == Complex(10, 20) - Complex(30, 30).send(@method, 10).should == Complex(3, 3) - end - - it "raises a ZeroDivisionError when given zero" do - -> { Complex(20, 40).send(@method, 0) }.should.raise(ZeroDivisionError) - end - - it "produces Rational parts" do - Complex(5, 9).send(@method, 2).should.eql?(Complex(Rational(5,2), Rational(9,2))) - end - end - - describe "with Bignum" do - it "divides both parts of the Complex number" do - Complex(20, 40).send(@method, 2).should == Complex(10, 20) - Complex(15, 16).send(@method, 2.0).should be_close(Complex(7.5, 8), TOLERANCE) - end - end - - describe "with Float" do - it "divides both parts of the Complex number" do - Complex(3, 9).send(@method, 1.5).should == Complex(2, 6) - Complex(15, 16).send(@method, 2.0).should be_close(Complex(7.5, 8), TOLERANCE) - end - - it "returns Complex(Infinity, Infinity) when given zero" do - Complex(20, 40).send(@method, 0.0).real.infinite?.should == 1 - Complex(20, 40).send(@method, 0.0).imag.infinite?.should == 1 - Complex(-20, 40).send(@method, 0.0).real.infinite?.should == -1 - Complex(-20, 40).send(@method, 0.0).imag.infinite?.should == 1 - end - end - - describe "with Object" do - it "tries to coerce self into other" do - value = Complex(3, 9) - - obj = mock("Object") - obj.should_receive(:coerce).with(value).and_return([4, 2]) - value.send(@method, obj).should == 2 - end - end - - describe "with a Numeric which responds to #real? with true" do - it "returns Complex(real.quo(other), imag.quo(other))" do - other = mock_numeric('other') - real = mock_numeric('real') - imag = mock_numeric('imag') - other.should_receive(:real?).and_return(true) - real.should_receive(:quo).with(other).and_return(1) - imag.should_receive(:quo).with(other).and_return(2) - Complex(real, imag).send(@method, other).should == Complex(1, 2) - end - end - - describe "with a Numeric which responds to #real? with false" do - it "coerces the passed argument to Complex and divides the resulting elements" do - complex = Complex(3, 0) - other = mock_numeric('other') - other.should_receive(:real?).any_number_of_times.and_return(false) - other.should_receive(:coerce).with(complex).and_return([5, 2]) - complex.send(@method, other).should.eql?(Rational(5, 2)) - end - end -end diff --git a/core/complex/shared/image.rb b/core/complex/shared/image.rb deleted file mode 100644 index f839dbcaf9..0000000000 --- a/core/complex/shared/image.rb +++ /dev/null @@ -1,8 +0,0 @@ -describe :complex_image, shared: true do - it "returns the imaginary part of self" do - Complex(1, 0).send(@method).should == 0 - Complex(2, 1).send(@method).should == 1 - Complex(6.7, 8.9).send(@method).should == 8.9 - Complex(1, bignum_value).send(@method).should == bignum_value - end -end diff --git a/core/complex/shared/rect.rb b/core/complex/shared/rect.rb deleted file mode 100644 index 858234961b..0000000000 --- a/core/complex/shared/rect.rb +++ /dev/null @@ -1,94 +0,0 @@ -describe :complex_rect, shared: true do - before :each do - @numbers = [ - Complex(1), - Complex(0, 20), - Complex(0, 0), - Complex(0.0), - Complex(9999999**99), - Complex(-20), - Complex.polar(76, 10) - ] - end - - it "returns an Array" do - @numbers.each do |number| - number.send(@method).should.instance_of?(Array) - end - end - - it "returns a two-element Array" do - @numbers.each do |number| - number.send(@method).size.should == 2 - end - end - - it "returns the real part of self as the first element" do - @numbers.each do |number| - number.send(@method).first.should == number.real - end - end - - it "returns the imaginary part of self as the last element" do - @numbers.each do |number| - number.send(@method).last.should == number.imaginary - end - end - - it "raises an ArgumentError if given any arguments" do - @numbers.each do |number| - -> { number.send(@method, number) }.should.raise(ArgumentError) - end - end -end - -describe :complex_rect_class, shared: true do - describe "passed a Numeric n which responds to #real? with true" do - it "returns a Complex with real part n and imaginary part 0" do - n = mock_numeric('n') - n.should_receive(:real?).any_number_of_times.and_return(true) - result = Complex.send(@method, n) - result.real.should == n - result.imag.should == 0 - end - end - - describe "passed a Numeric which responds to #real? with false" do - it "raises TypeError" do - n = mock_numeric('n') - n.should_receive(:real?).any_number_of_times.and_return(false) - -> { Complex.send(@method, n) }.should.raise(TypeError) - end - end - - describe "passed Numerics n1 and n2 and at least one responds to #real? with false" do - [[false, false], [false, true], [true, false]].each do |r1, r2| - it "raises TypeError" do - n1 = mock_numeric('n1') - n2 = mock_numeric('n2') - n1.should_receive(:real?).any_number_of_times.and_return(r1) - n2.should_receive(:real?).any_number_of_times.and_return(r2) - -> { Complex.send(@method, n1, n2) }.should.raise(TypeError) - end - end - end - - describe "passed Numerics n1 and n2 and both respond to #real? with true" do - it "returns a Complex with real part n1 and imaginary part n2" do - n1 = mock_numeric('n1') - n2 = mock_numeric('n2') - n1.should_receive(:real?).any_number_of_times.and_return(true) - n2.should_receive(:real?).any_number_of_times.and_return(true) - result = Complex.send(@method, n1, n2) - result.real.should == n1 - result.imag.should == n2 - end - end - - describe "passed a non-Numeric" do - it "raises TypeError" do - -> { Complex.send(@method, :sym) }.should.raise(TypeError) - -> { Complex.send(@method, 0, :sym) }.should.raise(TypeError) - end - end -end diff --git a/core/data/inspect_spec.rb b/core/data/inspect_spec.rb index 38642910a0..6c97a719e3 100644 --- a/core/data/inspect_spec.rb +++ b/core/data/inspect_spec.rb @@ -1,6 +1,63 @@ require_relative '../../spec_helper' -require_relative 'shared/inspect' +require_relative 'fixtures/classes' describe "Data#inspect" do - it_behaves_like :data_inspect, :inspect + it "returns a string representation showing members and values" do + a = DataSpecs::Measure.new(42, "km") + a.inspect.should == '#' + end + + it "returns a string representation without the class name for anonymous structs" do + Data.define(:a).new("").inspect.should == '#' + end + + it "returns a string representation without the class name for structs nested in anonymous classes" do + c = Class.new + c.class_eval <<~DOC + Foo = Data.define(:a) + DOC + + c::Foo.new("").inspect.should == '#' + end + + it "returns a string representation without the class name for structs nested in anonymous modules" do + m = Module.new + m.class_eval <<~DOC + Foo = Data.define(:a) + DOC + + m::Foo.new("").inspect.should == '#' + end + + it "does not call #name method" do + struct = DataSpecs::MeasureWithOverriddenName.new(42, "km") + struct.inspect.should == '#' + end + + it "does not call #name method when struct is anonymous" do + klass = Class.new(DataSpecs::Measure) do + def self.name + "A" + end + end + struct = klass.new(42, "km") + struct.inspect.should == '#' + end + + context "recursive structure" do + it "returns string representation with recursive attribute replaced with ..." do + a = DataSpecs::Measure.allocate + a.send(:initialize, amount: 42, unit: a) + + a.inspect.should == "#>" + end + + it "returns string representation with recursive attribute replaced with ... when an anonymous class" do + klass = Class.new(DataSpecs::Measure) + a = klass.allocate + a.send(:initialize, amount: 42, unit: a) + + a.inspect.should =~ /#:\.\.\.>>/ + end + end end diff --git a/core/data/shared/inspect.rb b/core/data/shared/inspect.rb deleted file mode 100644 index 6cd5664da7..0000000000 --- a/core/data/shared/inspect.rb +++ /dev/null @@ -1,62 +0,0 @@ -require_relative '../fixtures/classes' - -describe :data_inspect, shared: true do - it "returns a string representation showing members and values" do - a = DataSpecs::Measure.new(42, "km") - a.send(@method).should == '#' - end - - it "returns a string representation without the class name for anonymous structs" do - Data.define(:a).new("").send(@method).should == '#' - end - - it "returns a string representation without the class name for structs nested in anonymous classes" do - c = Class.new - c.class_eval <<~DOC - Foo = Data.define(:a) - DOC - - c::Foo.new("").send(@method).should == '#' - end - - it "returns a string representation without the class name for structs nested in anonymous modules" do - m = Module.new - m.class_eval <<~DOC - Foo = Data.define(:a) - DOC - - m::Foo.new("").send(@method).should == '#' - end - - it "does not call #name method" do - struct = DataSpecs::MeasureWithOverriddenName.new(42, "km") - struct.send(@method).should == '#' - end - - it "does not call #name method when struct is anonymous" do - klass = Class.new(DataSpecs::Measure) do - def self.name - "A" - end - end - struct = klass.new(42, "km") - struct.send(@method).should == '#' - end - - context "recursive structure" do - it "returns string representation with recursive attribute replaced with ..." do - a = DataSpecs::Measure.allocate - a.send(:initialize, amount: 42, unit: a) - - a.send(@method).should == "#>" - end - - it "returns string representation with recursive attribute replaced with ... when an anonymous class" do - klass = Class.new(DataSpecs::Measure) - a = klass.allocate - a.send(:initialize, amount: 42, unit: a) - - a.send(@method).should =~ /#:\.\.\.>>/ - end - end -end diff --git a/core/data/to_s_spec.rb b/core/data/to_s_spec.rb index 2b4a670e8e..a552e4659b 100644 --- a/core/data/to_s_spec.rb +++ b/core/data/to_s_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/inspect' +require_relative 'fixtures/classes' describe "Data#to_s" do - it_behaves_like :data_inspect, :to_s + it "is an alias of Data#inspect" do + a = DataSpecs::Measure.new(42, "km") + a.method(:to_s).should == a.method(:inspect) + end end diff --git a/core/dir/exist_spec.rb b/core/dir/exist_spec.rb index 0b8e521894..05ad67dd03 100644 --- a/core/dir/exist_spec.rb +++ b/core/dir/exist_spec.rb @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' -require_relative 'shared/exist' describe "Dir.exist?" do before :all do @@ -11,7 +10,61 @@ DirSpecs.delete_mock_dirs end - it_behaves_like :dir_exist, :exist? + it "returns true if the given directory exists" do + Dir.exist?(__dir__).should == true + end + + it "returns true for '.'" do + Dir.exist?('.').should == true + end + + it "returns true for '..'" do + Dir.exist?('..').should == true + end + + it "understands non-ASCII paths" do + subdir = File.join(tmp("\u{9876}\u{665}")) + Dir.exist?(subdir).should == false + Dir.mkdir(subdir) + Dir.exist?(subdir).should == true + Dir.rmdir(subdir) + end + + it "understands relative paths" do + Dir.exist?(__dir__ + '/../').should == true + end + + it "returns false if the given directory doesn't exist" do + Dir.exist?('y26dg27n2nwjs8a/').should == false + end + + it "doesn't require the name to have a trailing slash" do + dir = __dir__ + dir.sub!(/\/$/,'') + Dir.exist?(dir).should == true + end + + it "doesn't expand paths" do + skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME']) + Dir.exist?(File.expand_path('~')).should == true + Dir.exist?('~').should == false + end + + it "returns false if the argument exists but is a file" do + File.should.exist?(__FILE__) + Dir.exist?(__FILE__).should == false + end + + it "doesn't set $! when file doesn't exist" do + Dir.exist?("/path/to/non/existent/dir") + $!.should == nil + end + + it "calls #to_path on non String arguments" do + p = mock('path') + p.should_receive(:to_path).and_return(__dir__) + Dir.exist?(p) + end end describe "Dir.exists?" do diff --git a/core/dir/getwd_spec.rb b/core/dir/getwd_spec.rb index 132634347c..138481821f 100644 --- a/core/dir/getwd_spec.rb +++ b/core/dir/getwd_spec.rb @@ -1,15 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/common' -require_relative 'shared/pwd' describe "Dir.getwd" do - before :all do - DirSpecs.create_mock_dirs + it "is an alias of Dir.pwd" do + Dir.method(:getwd).should == Dir.method(:pwd) end - - after :all do - DirSpecs.delete_mock_dirs - end - - it_behaves_like :dir_pwd, :getwd end diff --git a/core/dir/open_spec.rb b/core/dir/open_spec.rb index 27f362320b..be01638fbc 100644 --- a/core/dir/open_spec.rb +++ b/core/dir/open_spec.rb @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' -require_relative 'shared/open' describe "Dir.open" do before :all do @@ -11,5 +10,75 @@ DirSpecs.delete_mock_dirs end - it_behaves_like :dir_open, :open + it "returns a Dir instance representing the specified directory" do + dir = Dir.open(DirSpecs.mock_dir) + dir.should.is_a?(Dir) + dir.close + end + + it "raises a SystemCallError if the directory does not exist" do + -> do + Dir.open(DirSpecs.nonexistent) + end.should.raise(SystemCallError) + end + + it "may take a block which is yielded to with the Dir instance" do + Dir.open(DirSpecs.mock_dir) {|dir| dir.should.is_a?(Dir)} + end + + it "returns the value of the block if a block is given" do + Dir.open(DirSpecs.mock_dir) {|dir| :value }.should == :value + end + + it "closes the Dir instance when the block exits if given a block" do + closed_dir = Dir.open(DirSpecs.mock_dir) { |dir| dir } + -> { closed_dir.read }.should.raise(IOError) + end + + it "closes the Dir instance when the block exits the block even due to an exception" do + closed_dir = nil + + -> do + Dir.open(DirSpecs.mock_dir) do |dir| + closed_dir = dir + raise "dir specs" + end + end.should.raise(RuntimeError, "dir specs") + + -> { closed_dir.read }.should.raise(IOError) + end + + it "calls #to_path on non-String arguments" do + p = mock('path') + p.should_receive(:to_path).and_return(DirSpecs.mock_dir) + Dir.open(p) { true } + end + + it "accepts an options Hash" do + dir = Dir.open(DirSpecs.mock_dir, encoding: "utf-8") {|d| d } + dir.should.is_a?(Dir) + end + + it "calls #to_hash to convert the options object" do + options = mock("dir_open") + options.should_receive(:to_hash).and_return({ encoding: Encoding::UTF_8 }) + + dir = Dir.open(DirSpecs.mock_dir, **options) {|d| d } + dir.should.is_a?(Dir) + end + + it "ignores the :encoding option if it is nil" do + dir = Dir.open(DirSpecs.mock_dir, encoding: nil) {|d| d } + dir.should.is_a?(Dir) + end + + platform_is_not :windows do + it 'sets the close-on-exec flag for the directory file descriptor' do + Dir.open(DirSpecs.mock_dir) do |dir| + io = IO.for_fd(dir.fileno) + io.autoclose = false + io.should.close_on_exec? + end + end + end end diff --git a/core/dir/path_spec.rb b/core/dir/path_spec.rb index b1c24c406b..02ddd2cd42 100644 --- a/core/dir/path_spec.rb +++ b/core/dir/path_spec.rb @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' -require_relative 'shared/path' describe "Dir#path" do before :all do @@ -11,5 +10,28 @@ DirSpecs.delete_mock_dirs end - it_behaves_like :dir_path, :path + it "returns the path that was supplied to .new or .open" do + dir = Dir.open DirSpecs.mock_dir + begin + dir.path.should == DirSpecs.mock_dir + ensure + dir.close rescue nil + end + end + + it "returns the path even when called on a closed Dir instance" do + dir = Dir.open DirSpecs.mock_dir + dir.close + dir.path.should == DirSpecs.mock_dir + end + + it "returns a String with the same encoding as the argument to .open" do + path = DirSpecs.mock_dir.force_encoding Encoding::IBM866 + dir = Dir.open path + begin + dir.path.encoding.should.equal?(Encoding::IBM866) + ensure + dir.close + end + end end diff --git a/core/dir/pos_spec.rb b/core/dir/pos_spec.rb index b382bff81f..f8ca06d778 100644 --- a/core/dir/pos_spec.rb +++ b/core/dir/pos_spec.rb @@ -1,30 +1,11 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' -require_relative 'shared/closed' require_relative 'shared/pos' describe "Dir#pos" do - before :all do - DirSpecs.create_mock_dirs - end - - after :all do - DirSpecs.delete_mock_dirs - end - - it_behaves_like :dir_pos, :pos -end - -describe "Dir#pos" do - before :all do - DirSpecs.create_mock_dirs + it "is an alias of Dir#tell" do + Dir.instance_method(:pos).should == Dir.instance_method(:tell) end - - after :all do - DirSpecs.delete_mock_dirs - end - - it_behaves_like :dir_closed, :pos end describe "Dir#pos=" do diff --git a/core/dir/pwd_spec.rb b/core/dir/pwd_spec.rb index ad01286c90..70208b03d6 100644 --- a/core/dir/pwd_spec.rb +++ b/core/dir/pwd_spec.rb @@ -1,7 +1,6 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' require_relative 'fixtures/common' -require_relative 'shared/pwd' describe "Dir.pwd" do before :all do @@ -12,7 +11,49 @@ DirSpecs.delete_mock_dirs end - it_behaves_like :dir_pwd, :pwd + before :each do + @fs_encoding = Encoding.find('filesystem') + end + + it "returns the current working directory" do + pwd = Dir.pwd + + File.directory?(pwd).should == true + + # On ubuntu gutsy, for example, /bin/pwd does not + # understand -P. With just `pwd -P`, /bin/pwd is run. + + # The following uses inode rather than file names to account for + # case insensitive file systems like default OS/X file systems + platform_is_not :windows do + File.stat(pwd).ino.should == File.stat(`/bin/sh -c "pwd -P"`.chomp).ino + end + platform_is :windows do + File.stat(pwd).ino.should == File.stat(File.expand_path(`cd`.chomp)).ino + end + end + + it "returns an absolute path" do + pwd = Dir.pwd + pwd.should == File.expand_path(pwd) + end + + it "returns an absolute path even when chdir to a relative path" do + Dir.chdir(".") do + pwd = Dir.pwd + File.directory?(pwd).should == true + pwd.should == File.expand_path(pwd) + end + end + + it "returns a String with the filesystem encoding" do + enc = Dir.pwd.encoding + if @fs_encoding == Encoding::US_ASCII + [Encoding::US_ASCII, Encoding::BINARY].should.include?(enc) + else + enc.should.equal?(@fs_encoding) + end + end end describe "Dir.pwd" do diff --git a/core/dir/shared/exist.rb b/core/dir/shared/exist.rb deleted file mode 100644 index 4ceaccea66..0000000000 --- a/core/dir/shared/exist.rb +++ /dev/null @@ -1,57 +0,0 @@ -describe :dir_exist, shared: true do - it "returns true if the given directory exists" do - Dir.send(@method, __dir__).should == true - end - - it "returns true for '.'" do - Dir.send(@method, '.').should == true - end - - it "returns true for '..'" do - Dir.send(@method, '..').should == true - end - - it "understands non-ASCII paths" do - subdir = File.join(tmp("\u{9876}\u{665}")) - Dir.send(@method, subdir).should == false - Dir.mkdir(subdir) - Dir.send(@method, subdir).should == true - Dir.rmdir(subdir) - end - - it "understands relative paths" do - Dir.send(@method, __dir__ + '/../').should == true - end - - it "returns false if the given directory doesn't exist" do - Dir.send(@method, 'y26dg27n2nwjs8a/').should == false - end - - it "doesn't require the name to have a trailing slash" do - dir = __dir__ - dir.sub!(/\/$/,'') - Dir.send(@method, dir).should == true - end - - it "doesn't expand paths" do - skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME']) - Dir.send(@method, File.expand_path('~')).should == true - Dir.send(@method, '~').should == false - end - - it "returns false if the argument exists but is a file" do - File.should.exist?(__FILE__) - Dir.send(@method, __FILE__).should == false - end - - it "doesn't set $! when file doesn't exist" do - Dir.send(@method, "/path/to/non/existent/dir") - $!.should == nil - end - - it "calls #to_path on non String arguments" do - p = mock('path') - p.should_receive(:to_path).and_return(__dir__) - Dir.send(@method, p) - end -end diff --git a/core/dir/shared/open.rb b/core/dir/shared/open.rb deleted file mode 100644 index 9ac3a40694..0000000000 --- a/core/dir/shared/open.rb +++ /dev/null @@ -1,73 +0,0 @@ -describe :dir_open, shared: true do - it "returns a Dir instance representing the specified directory" do - dir = Dir.send(@method, DirSpecs.mock_dir) - dir.should.is_a?(Dir) - dir.close - end - - it "raises a SystemCallError if the directory does not exist" do - -> do - Dir.send @method, DirSpecs.nonexistent - end.should.raise(SystemCallError) - end - - it "may take a block which is yielded to with the Dir instance" do - Dir.send(@method, DirSpecs.mock_dir) {|dir| dir.should.is_a?(Dir)} - end - - it "returns the value of the block if a block is given" do - Dir.send(@method, DirSpecs.mock_dir) {|dir| :value }.should == :value - end - - it "closes the Dir instance when the block exits if given a block" do - closed_dir = Dir.send(@method, DirSpecs.mock_dir) { |dir| dir } - -> { closed_dir.read }.should.raise(IOError) - end - - it "closes the Dir instance when the block exits the block even due to an exception" do - closed_dir = nil - - -> do - Dir.send(@method, DirSpecs.mock_dir) do |dir| - closed_dir = dir - raise "dir specs" - end - end.should.raise(RuntimeError, "dir specs") - - -> { closed_dir.read }.should.raise(IOError) - end - - it "calls #to_path on non-String arguments" do - p = mock('path') - p.should_receive(:to_path).and_return(DirSpecs.mock_dir) - Dir.send(@method, p) { true } - end - - it "accepts an options Hash" do - dir = Dir.send(@method, DirSpecs.mock_dir, encoding: "utf-8") {|d| d } - dir.should.is_a?(Dir) - end - - it "calls #to_hash to convert the options object" do - options = mock("dir_open") - options.should_receive(:to_hash).and_return({ encoding: Encoding::UTF_8 }) - - dir = Dir.send(@method, DirSpecs.mock_dir, **options) {|d| d } - dir.should.is_a?(Dir) - end - - it "ignores the :encoding option if it is nil" do - dir = Dir.send(@method, DirSpecs.mock_dir, encoding: nil) {|d| d } - dir.should.is_a?(Dir) - end - - platform_is_not :windows do - it 'sets the close-on-exec flag for the directory file descriptor' do - Dir.send(@method, DirSpecs.mock_dir) do |dir| - io = IO.for_fd(dir.fileno) - io.autoclose = false - io.should.close_on_exec? - end - end - end -end diff --git a/core/dir/shared/path.rb b/core/dir/shared/path.rb deleted file mode 100644 index 7647c04421..0000000000 --- a/core/dir/shared/path.rb +++ /dev/null @@ -1,30 +0,0 @@ -require_relative '../../../spec_helper' -require_relative '../fixtures/common' -require_relative 'closed' - -describe :dir_path, shared: true do - it "returns the path that was supplied to .new or .open" do - dir = Dir.open DirSpecs.mock_dir - begin - dir.send(@method).should == DirSpecs.mock_dir - ensure - dir.close rescue nil - end - end - - it "returns the path even when called on a closed Dir instance" do - dir = Dir.open DirSpecs.mock_dir - dir.close - dir.send(@method).should == DirSpecs.mock_dir - end - - it "returns a String with the same encoding as the argument to .open" do - path = DirSpecs.mock_dir.force_encoding Encoding::IBM866 - dir = Dir.open path - begin - dir.send(@method).encoding.should.equal?(Encoding::IBM866) - ensure - dir.close - end - end -end diff --git a/core/dir/shared/pos.rb b/core/dir/shared/pos.rb index 11712cc75d..741de8918c 100644 --- a/core/dir/shared/pos.rb +++ b/core/dir/shared/pos.rb @@ -1,30 +1,3 @@ -describe :dir_pos, shared: true do - before :each do - @dir = Dir.open DirSpecs.mock_dir - end - - after :each do - @dir.close rescue nil - end - - it "returns an Integer representing the current position in the directory" do - @dir.send(@method).should.is_a?(Integer) - @dir.send(@method).should.is_a?(Integer) - @dir.send(@method).should.is_a?(Integer) - end - - it "returns a different Integer if moved from previous position" do - a = @dir.send(@method) - @dir.read - b = @dir.send(@method) - - a.should.is_a?(Integer) - b.should.is_a?(Integer) - - a.should_not == b - end -end - describe :dir_pos_set, shared: true do before :each do @dir = Dir.open DirSpecs.mock_dir diff --git a/core/dir/shared/pwd.rb b/core/dir/shared/pwd.rb deleted file mode 100644 index ed47fe382a..0000000000 --- a/core/dir/shared/pwd.rb +++ /dev/null @@ -1,45 +0,0 @@ -describe :dir_pwd, shared: true do - before :each do - @fs_encoding = Encoding.find('filesystem') - end - - it "returns the current working directory" do - pwd = Dir.send(@method) - - File.directory?(pwd).should == true - - # On ubuntu gutsy, for example, /bin/pwd does not - # understand -P. With just `pwd -P`, /bin/pwd is run. - - # The following uses inode rather than file names to account for - # case insensitive file systems like default OS/X file systems - platform_is_not :windows do - File.stat(pwd).ino.should == File.stat(`/bin/sh -c "pwd -P"`.chomp).ino - end - platform_is :windows do - File.stat(pwd).ino.should == File.stat(File.expand_path(`cd`.chomp)).ino - end - end - - it "returns an absolute path" do - pwd = Dir.send(@method) - pwd.should == File.expand_path(pwd) - end - - it "returns an absolute path even when chdir to a relative path" do - Dir.chdir(".") do - pwd = Dir.send(@method) - File.directory?(pwd).should == true - pwd.should == File.expand_path(pwd) - end - end - - it "returns a String with the filesystem encoding" do - enc = Dir.send(@method).encoding - if @fs_encoding == Encoding::US_ASCII - [Encoding::US_ASCII, Encoding::BINARY].should.include?(enc) - else - enc.should.equal?(@fs_encoding) - end - end -end diff --git a/core/dir/tell_spec.rb b/core/dir/tell_spec.rb index af86dc1598..dcbb40438f 100644 --- a/core/dir/tell_spec.rb +++ b/core/dir/tell_spec.rb @@ -12,7 +12,30 @@ DirSpecs.delete_mock_dirs end - it_behaves_like :dir_pos, :tell - it_behaves_like :dir_closed, :tell + + before :each do + @dir = Dir.open DirSpecs.mock_dir + end + + after :each do + @dir.close rescue nil + end + + it "returns an Integer representing the current position in the directory" do + @dir.tell.should.is_a?(Integer) + @dir.tell.should.is_a?(Integer) + @dir.tell.should.is_a?(Integer) + end + + it "returns a different Integer if moved from previous position" do + a = @dir.tell + @dir.read + b = @dir.tell + + a.should.is_a?(Integer) + b.should.is_a?(Integer) + + a.should_not == b + end end diff --git a/core/dir/to_path_spec.rb b/core/dir/to_path_spec.rb index 77404a3dc8..2ed533e757 100644 --- a/core/dir/to_path_spec.rb +++ b/core/dir/to_path_spec.rb @@ -1,15 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/common' -require_relative 'shared/path' describe "Dir#to_path" do - before :all do - DirSpecs.create_mock_dirs + it "is an alias of Dir#path" do + Dir.instance_method(:to_path).should == Dir.instance_method(:path) end - - after :all do - DirSpecs.delete_mock_dirs - end - - it_behaves_like :dir_path, :to_path end diff --git a/core/encoding/name_spec.rb b/core/encoding/name_spec.rb index dce9347978..1d625c9379 100644 --- a/core/encoding/name_spec.rb +++ b/core/encoding/name_spec.rb @@ -1,6 +1,15 @@ require_relative "../../spec_helper" -require_relative 'shared/name' describe "Encoding#name" do - it_behaves_like :encoding_name, :name + it "returns a String" do + Encoding.list.each do |e| + e.name.should.instance_of?(String) + end + end + + it "uniquely identifies an encoding" do + Encoding.list.each do |e| + e.should == Encoding.find(e.name) + end + end end diff --git a/core/encoding/shared/name.rb b/core/encoding/shared/name.rb deleted file mode 100644 index 4d4b860a1f..0000000000 --- a/core/encoding/shared/name.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative '../../../spec_helper' - -describe :encoding_name, shared: true do - it "returns a String" do - Encoding.list.each do |e| - e.send(@method).should.instance_of?(String) - end - end - - it "uniquely identifies an encoding" do - Encoding.list.each do |e| - e.should == Encoding.find(e.send(@method)) - end - end -end diff --git a/core/encoding/to_s_spec.rb b/core/encoding/to_s_spec.rb index bab394a888..ee5e3b4abe 100644 --- a/core/encoding/to_s_spec.rb +++ b/core/encoding/to_s_spec.rb @@ -1,6 +1,7 @@ require_relative "../../spec_helper" -require_relative 'shared/name' describe "Encoding#to_s" do - it_behaves_like :encoding_name, :to_s + it "is an alias of Encoding#name" do + Encoding.instance_method(:to_s).should == Encoding.instance_method(:name) + end end