1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Move spec/rubyspec to spec/ruby for consistency

* Other ruby implementations use the spec/ruby directory.
  [Misc #13792] [ruby-core:82287]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-09-20 20:18:52 +00:00
parent 75bfc6440d
commit 1d15d5f080
4370 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,11 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF" do
it "is extended by the Enumerable module" do
ARGF.should be_kind_of(Enumerable)
end
it "is an instance of ARGF.class" do
ARGF.should be_an_instance_of(ARGF.class)
end
end

View file

@ -0,0 +1,19 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.argv" do
before :each do
@file1 = fixture __FILE__, "file1.txt"
@file2 = fixture __FILE__, "file2.txt"
end
it "returns ARGV for the initial ARGF" do
ARGF.argv.should equal ARGV
end
it "returns the remaining arguments to treat" do
argf [@file1, @file2] do
# @file1 is stored in current file
@argf.argv.should == [@file2]
end
end
end

View file

@ -0,0 +1,43 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.binmode" do
before :each do
@file1 = fixture __FILE__, "file1.txt"
@file2 = fixture __FILE__, "file2.txt"
@bin_file = fixture __FILE__, "bin_file.txt"
end
it "returns self" do
argf [@bin_file] do
@argf.binmode.should equal @argf
end
end
platform_is :windows do
it "puts reading into binmode" do
argf [@bin_file, @bin_file] do
@argf.gets.should == "test\n"
@argf.binmode
@argf.gets.should == "test\r\n"
end
end
it "puts alls subsequent stream reading through ARGF into binmode" do
argf [@bin_file, @bin_file] do
@argf.binmode
@argf.gets.should == "test\r\n"
@argf.gets.should == "test\r\n"
end
end
end
it "sets the file's encoding to ASCII-8BIT" do
argf [@bin_file, @file1] do
@argf.binmode
@argf.binmode?.should == true
@argf.gets.encoding.should == Encoding::ASCII_8BIT
@argf.skip
@argf.read.encoding.should == Encoding::ASCII_8BIT
end
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_byte', __FILE__)
describe "ARGF.bytes" do
it_behaves_like :argf_each_byte, :bytes
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_char', __FILE__)
describe "ARGF.chars" do
it_behaves_like :argf_each_char, :chars
end

View file

@ -0,0 +1,46 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.close" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
end
it "closes the current open stream" do
argf [@file1_name, @file2_name] do
io = @argf.to_io
@argf.close
io.closed?.should be_true
end
end
it "returns self" do
argf [@file1_name, @file2_name] do
@argf.close.should equal(@argf)
end
end
ruby_version_is ""..."2.3" do
it "raises an IOError if called on a closed stream" do
argf [@file1_name] do
lambda { @argf.close }.should_not raise_error
lambda { @argf.close }.should raise_error(IOError)
end
end
end
ruby_version_is "2.3" do
it "doesn't raise an IOError if called on a closed stream" do
argf [@file1_name] do
lambda { @argf.close }.should_not raise_error
lambda { @argf.close }.should_not raise_error
end
end
end
end
describe "ARGF.close" do
it "does not close STDIN" do
ruby_exe("ARGV.replace(['-']); ARGF.close; print ARGF.closed?").should == "false"
end
end

View file

@ -0,0 +1,18 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.closed?" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
end
it "returns true if the current stream has been closed" do
argf [@file1_name, @file2_name] do
stream = @argf.to_io
stream.close
@argf.closed?.should be_true
stream.reopen(@argf.filename, 'r')
end
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_codepoint', __FILE__)
describe "ARGF.codepoints" do
it_behaves_like :argf_each_codepoint, :codepoints
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_byte', __FILE__)
describe "ARGF.each_byte" do
it_behaves_like :argf_each_byte, :each_byte
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_char', __FILE__)
describe "ARGF.each_char" do
it_behaves_like :argf_each_char, :each_char
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_codepoint', __FILE__)
describe "ARGF.each_codepoint" do
it_behaves_like :argf_each_codepoint, :each_codepoint
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_line', __FILE__)
describe "ARGF.each_line" do
it_behaves_like :argf_each_line, :each_line
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_line', __FILE__)
describe "ARGF.each" do
it_behaves_like :argf_each_line, :each
end

View file

@ -0,0 +1,10 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/eof', __FILE__)
describe "ARGF.eof" do
it_behaves_like :argf_eof, :eof
end
describe "ARGF.eof?" do
it_behaves_like :argf_eof, :eof?
end

View file

@ -0,0 +1,21 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.file" 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 object on each file" do
argf [@file1, @file2] do
result = []
# returns first current file even when not yet open
result << @argf.file.path
result << @argf.file.path while @argf.gets
# returns last current file even when closed
result << @argf.file.path
result.should == [@file1, @file1, @file1, @file2, @file2, @file2]
end
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/filename', __FILE__)
describe "ARGF.filename" do
it_behaves_like :argf_filename, :filename
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/fileno', __FILE__)
describe "ARGF.fileno" do
it_behaves_like :argf_fileno, :fileno
end

View file

@ -0,0 +1,2 @@
test
test

View file

@ -0,0 +1,2 @@
file1.1
file1.2

View file

@ -0,0 +1,2 @@
line2.1
line2.2

View file

@ -0,0 +1,3 @@
puts $FILENAME while ARGF.gets
# returns last current file even when closed
puts $FILENAME

View file

@ -0,0 +1,5 @@
puts $.
ARGF.gets
puts $.
ARGF.gets
puts $.

View file

@ -0,0 +1,5 @@
puts ARGF.lineno
ARGF.gets
puts ARGF.lineno
ARGF.rewind
puts ARGF.lineno

View file

@ -0,0 +1,2 @@
stdin.1
stdin.2

View file

@ -0,0 +1,20 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/getc', __FILE__)
describe "ARGF.getc" do
it_behaves_like :argf_getc, :getc
end
describe "ARGF.getc" do
before :each do
@file1 = fixture __FILE__, "file1.txt"
@file2 = fixture __FILE__, "file2.txt"
end
it "returns nil when end of stream reached" do
argf [@file1, @file2] do
@argf.read
@argf.getc.should == nil
end
end
end

View file

@ -0,0 +1,51 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/gets', __FILE__)
describe "ARGF.gets" do
it_behaves_like :argf_gets, :gets
end
describe "ARGF.gets" do
it_behaves_like :argf_gets_inplace_edit, :gets
end
describe "ARGF.gets" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@file1 = File.readlines @file1_name
@file2 = File.readlines @file2_name
end
it "returns nil when reaching end of files" do
argf [@file1_name, @file2_name] do
total = @file1.size + @file2.size
total.times { @argf.gets }
@argf.gets.should == nil
end
end
with_feature :encoding do
before :each do
@external = Encoding.default_external
@internal = Encoding.default_internal
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = nil
end
after :each do
Encoding.default_external = @external
Encoding.default_internal = @internal
end
it "reads the contents of the file with default encoding" do
Encoding.default_external = Encoding::US_ASCII
argf [@file1_name, @file2_name] do
@argf.gets.encoding.should == Encoding::US_ASCII
end
end
end
end

View file

@ -0,0 +1,30 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.lineno" 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
# TODO: break this into four specs
it "returns the current line number on each file" do
argf [@file1, @file2] do
@argf.lineno = 0
@argf.gets
@argf.lineno.should == 1
@argf.gets
@argf.lineno.should == 2
@argf.gets
@argf.lineno.should == 3
@argf.gets
@argf.lineno.should == 4
end
end
it "aliases to $." do
script = fixture __FILE__, "lineno.rb"
out = ruby_exe(script, args: [@file1, @file2])
out.should == "0\n1\n2\n"
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/each_line', __FILE__)
describe "ARGF.lines" do
it_behaves_like :argf_each_line, :lines
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/filename', __FILE__)
describe "ARGF.path" do
it_behaves_like :argf_filename, :path
end

View file

@ -0,0 +1,38 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/pos', __FILE__)
describe "ARGF.pos" do
it_behaves_like :argf_pos, :pos
end
describe "ARGF.pos=" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@file1 = File.readlines @file1_name
@file2 = File.readlines @file2_name
end
# NOTE: this test assumes that fixtures files have two lines each
it "sets the correct position in files" do
argf [@file1_name, @file2_name] do
@argf.pos = @file1.first.size
@argf.gets.should == @file1.last
@argf.pos = 0
@argf.gets.should == @file1.first
# finish reading file1
@argf.gets
@argf.gets
@argf.pos = 1
@argf.gets.should == @file2.first[1..-1]
@argf.pos = @file2.first.size + @file2.last.size - 1
@argf.gets.should == @file2.last[-1,1]
@argf.pos = 1000
@argf.read.should == ""
end
end
end

View file

@ -0,0 +1,82 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/read', __FILE__)
platform_is_not :windows do
describe 'ARGF.read_nonblock' do
it_behaves_like :argf_read, :read_nonblock
before do
@file1_name = fixture(__FILE__, 'file1.txt')
@file2_name = fixture(__FILE__, 'file2.txt')
@file1 = File.read(@file1_name)
@file2 = File.read(@file2_name)
@chunk1 = File.read(@file1_name, 4)
@chunk2 = File.read(@file2_name, 4)
end
it 'reads up to the given amount of bytes' do
argf [@file1_name] do
@argf.read_nonblock(4).should == @chunk1
end
end
describe 'when using multiple files' do
it 'reads up to the given amount of bytes from the first file' do
argf [@file1_name, @file2_name] do
@argf.read_nonblock(4).should == @chunk1
end
end
it 'returns an empty String when reading after having read the first file in its entirety' do
argf [@file1_name, @file2_name] do
@argf.read_nonblock(File.size(@file1_name)).should == @file1
@argf.read_nonblock(4).should == ''
end
end
end
it 'reads up to the given bytes from STDIN' do
stdin = ruby_exe('print ARGF.read_nonblock(4)', :args => "< #{@file1_name}")
stdin.should == @chunk1
end
it 'reads up to the given bytes from a file when a file and STDIN are present' do
stdin = ruby_exe("print ARGF.read_nonblock(4)", :args => "#{@file1_name} - < #{@file2_name}")
stdin.should == @chunk1
end
context "with STDIN" do
before do
@r, @w = IO.pipe
@stdin = $stdin
$stdin = @r
end
after do
$stdin = @stdin
@w.close
@r.close unless @r.closed?
end
it 'raises IO::EAGAINWaitReadable when empty' do
argf ['-'] do
lambda {
@argf.read_nonblock(4)
}.should raise_error(IO::EAGAINWaitReadable)
end
end
ruby_version_is "2.3" do
it 'returns :wait_readable when the :exception is set to false' do
argf ['-'] do
@argf.read_nonblock(4, nil, exception: false).should == :wait_readable
end
end
end
end
end
end

View file

@ -0,0 +1,87 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/read', __FILE__)
describe "ARGF.read" do
it_behaves_like :argf_read, :read
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@stdin_name = fixture __FILE__, "stdin.txt"
@file1 = File.read @file1_name
@file2 = File.read @file2_name
@stdin = File.read @stdin_name
end
it "reads the contents of a file" do
argf [@file1_name] do
@argf.read().should == @file1
end
end
it "treats first nil argument as no length limit" do
argf [@file1_name] do
@argf.read(nil).should == @file1
end
end
it "reads the contents of two files" do
argf [@file1_name, @file2_name] do
@argf.read.should == @file1 + @file2
end
end
it "reads the contents of one file and some characters from the second" do
argf [@file1_name, @file2_name] do
len = @file1.size + (@file2.size / 2)
@argf.read(len).should == (@file1 + @file2)[0,len]
end
end
it "reads across two files consecutively" do
argf [@file1_name, @file2_name] do
@argf.read(@file1.size - 2).should == @file1[0..-3]
@argf.read(2+5).should == @file1[-2..-1] + @file2[0,5]
end
end
it "reads the contents of stdin" do
stdin = ruby_exe("print ARGF.read", args: "< #{@stdin_name}")
stdin.should == @stdin
end
it "reads the contents of one file and stdin" do
stdin = ruby_exe("print ARGF.read", args: "#{@file1_name} - < #{@stdin_name}")
stdin.should == @file1 + @stdin
end
it "reads the contents of the same file twice" do
argf [@file1_name, @file1_name] do
@argf.read.should == @file1 + @file1
end
end
with_feature :encoding do
before :each do
@external = Encoding.default_external
@internal = Encoding.default_internal
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = nil
end
after :each do
Encoding.default_external = @external
Encoding.default_internal = @internal
end
it "reads the contents of the file with default encoding" do
Encoding.default_external = Encoding::US_ASCII
argf [@file1_name, @file2_name] do
@argf.read.encoding.should == Encoding::US_ASCII
end
end
end
end

View file

@ -0,0 +1,19 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/getc', __FILE__)
describe "ARGF.getc" do
it_behaves_like :argf_getc, :readchar
end
describe "ARGF.readchar" do
before :each do
@file1 = fixture __FILE__, "file1.txt"
@file2 = fixture __FILE__, "file2.txt"
end
it "raises EOFError when end of stream reached" do
argf [@file1, @file2] do
lambda { while @argf.readchar; end }.should raise_error(EOFError)
end
end
end

View file

@ -0,0 +1,23 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/gets', __FILE__)
describe "ARGF.readline" do
it_behaves_like :argf_gets, :readline
end
describe "ARGF.readline" do
it_behaves_like :argf_gets_inplace_edit, :readline
end
describe "ARGF.readline" do
before :each do
@file1 = fixture __FILE__, "file1.txt"
@file2 = fixture __FILE__, "file2.txt"
end
it "raises an EOFError when reaching end of files" do
argf [@file1, @file2] do
lambda { while @argf.readline; end }.should raise_error(EOFError)
end
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/readlines', __FILE__)
describe "ARGF.readlines" do
it_behaves_like :argf_readlines, :readlines
end

View file

@ -0,0 +1,77 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/read', __FILE__)
describe "ARGF.readpartial" do
it_behaves_like :argf_read, :readpartial
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@stdin_name = fixture __FILE__, "stdin.txt"
@file1 = File.read @file1_name
@file2 = File.read @file2_name
@stdin = File.read @stdin_name
end
it "raises an ArgumentError if called without a maximum read length" do
argf [@file1_name] do
lambda { @argf.readpartial }.should raise_error(ArgumentError)
end
end
it "reads maximum number of bytes from one file at a time" do
argf [@file1_name, @file2_name] do
len = @file1.size + @file2.size
@argf.readpartial(len).should == @file1
end
end
it "clears output buffer even if EOFError is raised because @argf is at end" do
begin
output = "to be cleared"
argf [@file1_name] do
@argf.read
@argf.readpartial(1, output)
end
rescue EOFError
output.should == ""
end
end
it "reads maximum number of bytes from one file at a time" do
argf [@file1_name, @file2_name] do
len = @file1.size + @file2.size
@argf.readpartial(len).should == @file1
end
end
it "returns an empty string if EOFError is raised while reading any but the last file" do
argf [@file1_name, @file2_name] do
@argf.readpartial(@file1.size)
@argf.readpartial(1).should == ""
end
end
ruby_version_is "2.3" do
it "raises an EOFError if the exception was raised while reading the last file" do
argf [@file1_name, @file2_name] do
@argf.readpartial(@file1.size)
@argf.readpartial(1)
@argf.readpartial(@file2.size)
lambda { @argf.readpartial(1) }.should raise_error(EOFError)
lambda { @argf.readpartial(1) }.should raise_error(EOFError)
end
end
end
it "raises an EOFError if the exception was raised while reading STDIN" do
ruby_str = <<-STR
print ARGF.readpartial(#{@stdin.size})
ARGF.readpartial(1) rescue print $!.class
STR
stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}", escape: true)
stdin.should == @stdin + "EOFError"
end
end

View file

@ -0,0 +1,39 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.rewind" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@file1 = File.readlines @file1_name
@file2 = File.readlines @file2_name
end
# NOTE: this test assumes that fixtures files have two lines each
it "goes back to beginning of current file" do
argf [@file1_name, @file2_name] do
@argf.gets
@argf.rewind
@argf.gets.should == @file1.first
@argf.gets # finish reading file1
@argf.gets
@argf.rewind
@argf.gets.should == @file2.first
end
end
it "resets ARGF.lineno to 0" do
script = fixture __FILE__, "rewind.rb"
out = ruby_exe(script, args: [@file1_name, @file2_name])
out.should == "0\n1\n0\n"
end
it "raises an ArgumentError when end of stream reached" do
argf [@file1_name, @file2_name] do
@argf.read
lambda { @argf.rewind }.should raise_error(ArgumentError)
end
end
end

View file

@ -0,0 +1,63 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.seek" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@file1 = File.readlines @file1_name
@file2 = File.readlines @file2_name
end
it "sets the absolute position relative to beginning of file" do
argf [@file1_name, @file2_name] do
@argf.seek 2
@argf.gets.should == @file1.first[2..-1]
@argf.seek @file1.first.size
@argf.gets.should == @file1.last
@argf.seek 0, IO::SEEK_END
@argf.gets.should == @file2.first
end
end
it "sets the position relative to current position in file" do
argf [@file1_name, @file2_name] do
@argf.seek(0, IO::SEEK_CUR)
@argf.gets.should == @file1.first
@argf.seek(-@file1.first.size+2, IO::SEEK_CUR)
@argf.gets.should == @file1.first[2..-1]
@argf.seek(1, IO::SEEK_CUR)
@argf.gets.should == @file1.last[1..-1]
@argf.seek(3, IO::SEEK_CUR)
@argf.gets.should == @file2.first
@argf.seek(@file1.last.size, IO::SEEK_CUR)
@argf.gets.should == nil
end
end
it "sets the absolute position relative to end of file" do
argf [@file1_name, @file2_name] do
@argf.seek(-@file1.first.size-@file1.last.size, IO::SEEK_END)
@argf.gets.should == @file1.first
@argf.seek(-6, IO::SEEK_END)
@argf.gets.should == @file1.last[-6..-1]
@argf.seek(-4, IO::SEEK_END)
@argf.gets.should == @file1.last[4..-1]
@argf.gets.should == @file2.first
@argf.seek(-6, IO::SEEK_END)
@argf.gets.should == @file2.last[-6..-1]
end
end
end
describe "ARGF.seek" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
end
it "takes at least one argument (offset)" do
argf [@file1_name] do
lambda { @argf.seek }.should raise_error(ArgumentError)
end
end
end

View file

@ -0,0 +1,41 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.set_encoding" do
before :each do
@file = fixture __FILE__, "file1.txt"
end
it "sets the external encoding when passed an encoding instance" do
argf [@file] do
@argf.set_encoding(Encoding::US_ASCII)
@argf.external_encoding.should == Encoding::US_ASCII
@argf.gets.encoding.should == Encoding::US_ASCII
end
end
it "sets the external encoding when passed an encoding name" do
argf [@file] do
@argf.set_encoding("us-ascii")
@argf.external_encoding.should == Encoding::US_ASCII
@argf.gets.encoding.should == Encoding::US_ASCII
end
end
it "sets the external, internal encoding when passed two encoding instances" do
argf [@file] do
@argf.set_encoding(Encoding::US_ASCII, Encoding::EUC_JP)
@argf.external_encoding.should == Encoding::US_ASCII
@argf.internal_encoding.should == Encoding::EUC_JP
@argf.gets.encoding.should == Encoding::EUC_JP
end
end
it "sets the external, internal encoding when passed 'ext:int' String" do
argf [@file] do
@argf.set_encoding("us-ascii:euc-jp")
@argf.external_encoding.should == Encoding::US_ASCII
@argf.internal_encoding.should == Encoding::EUC_JP
@argf.gets.encoding.should == Encoding::EUC_JP
end
end
end

View file

@ -0,0 +1,58 @@
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 be_an_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 be_an_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

View file

@ -0,0 +1,58 @@
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 be_an_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 be_an_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

View file

@ -0,0 +1,58 @@
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 be_an_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 be_an_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

View file

@ -0,0 +1,62 @@
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 be_an_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

View file

@ -0,0 +1,24 @@
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
lambda { @argf.send(@method) }.should raise_error(IOError)
end
end
end

View file

@ -0,0 +1,28 @@
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

View file

@ -0,0 +1,24 @@
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 == [Fixnum, Fixnum, Fixnum, Fixnum]
end
end
it "raises an ArgumentError when called on a closed stream" do
argf [@file1] do
@argf.read
lambda { @argf.send(@method) }.should raise_error(ArgumentError)
end
end
end

View file

@ -0,0 +1,17 @@
describe :argf_getc, shared: true do
before :each do
@file1 = fixture __FILE__, "file1.txt"
@file2 = fixture __FILE__, "file2.txt"
@chars = File.read @file1
@chars += File.read @file2
end
it "reads each char of files" do
argf [@file1, @file2] do
chars = ""
@chars.size.times { chars << @argf.send(@method) }
chars.should == @chars
end
end
end

View file

@ -0,0 +1,99 @@
describe :argf_gets, shared: true do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@stdin_name = fixture __FILE__, "stdin.txt"
@file1 = File.readlines @file1_name
@file2 = File.readlines @file2_name
@stdin = File.read @stdin_name
end
it "reads one line of a file" do
argf [@file1_name] do
@argf.send(@method).should == @file1.first
end
end
it "reads all lines of a file" do
argf [@file1_name] do
lines = []
@file1.size.times { lines << @argf.send(@method) }
lines.should == @file1
end
end
it "reads all lines of stdin" do
total = @stdin.count $/
stdin = ruby_exe(
"#{total}.times { print ARGF.send(#{@method.inspect}) }",
args: "< #{@stdin_name}")
stdin.should == @stdin
end
it "reads all lines of two files" do
argf [@file1_name, @file2_name] do
total = @file1.size + @file2.size
lines = []
total.times { lines << @argf.send(@method) }
lines.should == @file1 + @file2
end
end
it "sets $_ global variable with each line read" do
argf [@file1_name, @file2_name] do
total = @file1.size + @file2.size
total.times do
line = @argf.send(@method)
$_.should == line
end
end
end
end
describe :argf_gets_inplace_edit, shared: true do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@tmp1_name = tmp "file1.txt"
@tmp2_name = tmp "file2.txt"
@tmp1_name_bak = @tmp1_name + ".bak"
@tmp2_name_bak = @tmp2_name + ".bak"
cp @file1_name, @tmp1_name
cp @file2_name, @tmp2_name
method = "ARGF.send(#{@method.inspect})"
@code = "begin while line = #{method} do puts 'x' end rescue EOFError; end"
end
after :each do
rm_r @tmp1_name, @tmp2_name, @tmp1_name_bak, @tmp2_name_bak
end
# -i with no backup extension is not supported on Windows
platform_is_not :windows do
it "modifies the files when in place edit mode is on" do
ruby_exe(@code,
options: "-i",
args: "#{@tmp1_name} #{@tmp2_name}")
File.read(@tmp1_name).should == "x\nx\n"
File.read(@tmp2_name).should == "x\nx\n"
end
end
it "modifies and backups two files when in place edit mode is on" do
ruby_exe(@code,
options: "-i.bak",
args: "#{@tmp1_name} #{@tmp2_name}")
File.read(@tmp1_name).should == "x\nx\n"
File.read(@tmp2_name).should == "x\nx\n"
File.read(@tmp1_name_bak).should == "file1.1\nfile1.2\n"
File.read(@tmp2_name_bak).should == "line2.1\nline2.2\n"
end
end

View file

@ -0,0 +1,31 @@
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
lambda { @argf.send(@method) }.should raise_error(ArgumentError)
end
end
end

View file

@ -0,0 +1,58 @@
describe :argf_read, shared: true do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@stdin_name = fixture __FILE__, "stdin.txt"
@file1 = File.read @file1_name
@stdin = File.read @stdin_name
end
it "treats second nil argument as no output buffer" do
argf [@file1_name] do
@argf.send(@method, @file1.size, nil).should == @file1
end
end
it "treats second argument as an output buffer" do
argf [@file1_name] do
buffer = ""
@argf.send(@method, @file1.size, buffer)
buffer.should == @file1
end
end
it "clears output buffer before appending to it" do
argf [@file1_name] do
buffer = "to be cleared"
@argf.send(@method, @file1.size, buffer)
buffer.should == @file1
end
end
it "reads a number of bytes from the first file" do
argf [@file1_name] do
@argf.send(@method, 5).should == @file1[0, 5]
end
end
it "reads from a single file consecutively" do
argf [@file1_name] do
@argf.send(@method, 1).should == @file1[0, 1]
@argf.send(@method, 2).should == @file1[1, 2]
@argf.send(@method, 3).should == @file1[3, 3]
end
end
it "reads a number of bytes from stdin" do
stdin = ruby_exe("print ARGF.#{@method}(10)", :args => "< #{@stdin_name}")
stdin.should == @stdin[0, 10]
end
platform_is_not :windows do
it "reads the contents of a special device file" do
argf ['/dev/zero'] do
@argf.send(@method, 100).should == "\000" * 100
end
end
end
end

View file

@ -0,0 +1,22 @@
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

View file

@ -0,0 +1,42 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.skip" do
before :each do
@file1_name = fixture __FILE__, "file1.txt"
@file2_name = fixture __FILE__, "file2.txt"
@file2 = File.readlines @file2_name
end
it "skips the current file" do
argf [@file1_name, @file2_name] do
@argf.read(1)
@argf.skip
@argf.gets.should == @file2.first
end
end
it "has no effect when called twice in a row" do
argf [@file1_name, @file2_name] do
@argf.read(1)
@argf.skip
@argf.skip
@argf.gets.should == @file2.first
end
end
it "has no effect at end of stream" do
argf [@file1_name, @file2_name] do
@argf.read
@argf.skip
@argf.gets.should == nil
end
end
# This bypasses argf helper because the helper will call argf.file
# which as a side-effect calls argf.file which will initialize
# internals of ARGF enough for this to work.
it "has no effect when nothing has been processed yet" do
lambda { ARGF.class.new(@file1_name).skip }.should_not raise_error
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/pos', __FILE__)
describe "ARGF.tell" do
it_behaves_like :argf_pos, :tell
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/readlines', __FILE__)
describe "ARGF.to_a" do
it_behaves_like :argf_readlines, :to_a
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/fileno', __FILE__)
describe "ARGF.to_i" do
it_behaves_like :argf_fileno, :to_i
end

View file

@ -0,0 +1,23 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.to_io" 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 IO of the current file" do
argf [@file1, @file2] do
result = []
4.times do
@argf.gets
result << @argf.to_io
end
result.each { |io| io.should be_kind_of(IO) }
result[0].should == result[1]
result[2].should == result[3]
end
end
end

View file

@ -0,0 +1,14 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "ARGF.to_s" do
before :each do
@file1 = fixture __FILE__, "file1.txt"
@file2 = fixture __FILE__, "file2.txt"
end
it "returns 'ARGF'" do
argf [@file1, @file2] do
@argf.to_s.should == "ARGF"
end
end
end

View file

@ -0,0 +1,19 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array.allocate" do
it "returns an instance of Array" do
ary = Array.allocate
ary.should be_an_instance_of(Array)
end
it "returns a fully-formed instance of Array" do
ary = Array.allocate
ary.size.should == 0
ary << 1
ary.should == [1]
end
it "does not accept any arguments" do
lambda { Array.allocate(1) }.should raise_error(ArgumentError)
end
end

View file

@ -0,0 +1,37 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#any?" do
describe 'with no block given (a default block of { |x| x } is implicit)' do
it "is false if the array is empty" do
empty_array = []
empty_array.any?.should == false
end
it "is false if the array is not empty, but all the members of the array are falsy" do
falsy_array = [false, nil, false]
falsy_array.any?.should == false
end
it "is true if the array has any truthy members" do
not_empty_array = ['anything', nil]
not_empty_array.any?.should == true
end
end
describe 'with a block given' do
it 'is false if the array is empty' do
empty_array = []
empty_array.any? {|v| 1 == 1 }.should == false
end
it 'is true if the block returns true for any member of the array' do
array_with_members = [false, false, true, false]
array_with_members.any? {|v| v == true }.should == true
end
it 'is false if the block returns false for all members of the array' do
array_with_members = [false, false, true, false]
array_with_members.any? {|v| v == 42 }.should == false
end
end
end

View file

@ -0,0 +1,35 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#<<" do
it "pushes the object onto the end of the array" do
([ 1, 2 ] << "c" << "d" << [ 3, 4 ]).should == [1, 2, "c", "d", [3, 4]]
end
it "returns self to allow chaining" do
a = []
b = a
(a << 1).should equal(b)
(a << 2 << 3).should equal(b)
end
it "correctly resizes the Array" do
a = []
a.size.should == 0
a << :foo
a.size.should == 1
a << :bar << :baz
a.size.should == 3
a = [1, 2, 3]
a.shift
a.shift
a.shift
a << :foo
a.should == [:foo]
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array << 5 }.should raise_error(RuntimeError)
end
end

View file

@ -0,0 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array" do
it "includes Enumerable" do
Array.include?(Enumerable).should == true
end
end

View file

@ -0,0 +1,40 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#assoc" do
it "returns the first array whose 1st item is == obj or nil" do
s1 = ["colors", "red", "blue", "green"]
s2 = [:letters, "a", "b", "c"]
s3 = [4]
s4 = ["colors", "cyan", "yellow", "magenda"]
s5 = [:letters, "a", "i", "u"]
s_nil = [nil, nil]
a = [s1, s2, s3, s4, s5, s_nil]
a.assoc(s1.first).should equal(s1)
a.assoc(s2.first).should equal(s2)
a.assoc(s3.first).should equal(s3)
a.assoc(s4.first).should equal(s1)
a.assoc(s5.first).should equal(s2)
a.assoc(s_nil.first).should equal(s_nil)
a.assoc(4).should equal(s3)
a.assoc("key not in array").should be_nil
end
it "calls == on first element of each array" do
key1 = 'it'
key2 = mock('key2')
items = [['not it', 1], [ArraySpecs::AssocKey.new, 2], ['na', 3]]
items.assoc(key1).should equal(items[1])
items.assoc(key2).should be_nil
end
it "ignores any non-Array elements" do
[1, 2, 3].assoc(2).should be_nil
s1 = [4]
s2 = [5, 4, 3]
a = ["foo", [], s1, s2, nil, []]
a.assoc(s1.first).should equal(s1)
a.assoc(s2.first).should equal(s2)
end
end

View file

@ -0,0 +1,56 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#at" do
it "returns the (n+1)'th element for the passed index n" do
a = [1, 2, 3, 4, 5, 6]
a.at(0).should == 1
a.at(1).should == 2
a.at(5).should == 6
end
it "returns nil if the given index is greater than or equal to the array's length" do
a = [1, 2, 3, 4, 5, 6]
a.at(6).should == nil
a.at(7).should == nil
end
it "returns the (-n)'th elemet from the last, for the given negative index n" do
a = [1, 2, 3, 4, 5, 6]
a.at(-1).should == 6
a.at(-2).should == 5
a.at(-6).should == 1
end
it "returns nil if the given index is less than -len, where len is length of the array" do
a = [1, 2, 3, 4, 5, 6]
a.at(-7).should == nil
a.at(-8).should == nil
end
it "does not extend the array unless the given index is out of range" do
a = [1, 2, 3, 4, 5, 6]
a.length.should == 6
a.at(100)
a.length.should == 6
a.at(-100)
a.length.should == 6
end
it "tries to convert the passed argument to an Integer using #to_int" do
a = ["a", "b", "c"]
a.at(0.5).should == "a"
obj = mock('to_int')
obj.should_receive(:to_int).and_return(2)
a.at(obj).should == "c"
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
lambda { [].at("cat") }.should raise_error(TypeError)
end
it "raises an ArgumentError when 2 or more arguments is passed" do
lambda { [:a, :b].at(0,1) }.should raise_error(ArgumentError)
end
end

View file

@ -0,0 +1,87 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../enumerable/shared/enumeratorized', __FILE__)
ruby_version_is "2.3" do
describe "Array#bsearch_index" do
context "when not passed a block" do
before :each do
@enum = [1, 2, 42, 100, 666].bsearch_index
end
it "returns an Enumerator" do
@enum.should be_an_instance_of(Enumerator)
end
it "returns an Enumerator with unknown size" do
@enum.size.should be_nil
end
it "returns index of element when block condition is satisfied" do
@enum.each { |x| x >= 33 }.should == 2
end
end
it "raises a TypeError when block returns a String" do
lambda { [1, 2, 3].bsearch_index { "not ok" } }.should raise_error(TypeError)
end
it "returns nil when block is empty" do
[1, 2, 3].bsearch_index {}.should be_nil
end
context "minimum mode" do
before :each do
@array = [0, 4, 7, 10, 12]
end
it "returns index of first element which satisfies the block" do
@array.bsearch_index { |x| x >= 4 }.should == 1
@array.bsearch_index { |x| x >= 6 }.should == 2
@array.bsearch_index { |x| x >= -1 }.should == 0
end
it "returns nil when block condition is never satisfied" do
@array.bsearch_index { false }.should be_nil
@array.bsearch_index { |x| x >= 100 }.should be_nil
end
end
context "find any mode" do
before :each do
@array = [0, 4, 7, 10, 12]
end
it "returns the index of any matched elements where element is between 4 <= x < 8" do
[1, 2].should include(@array.bsearch_index { |x| 1 - x / 4 })
end
it "returns the index of any matched elements where element is between 8 <= x < 10" do
@array.bsearch_index { |x| 4 - x / 2 }.should be_nil
end
it "returns nil when block never returns 0" do
@array.bsearch_index { |x| 1 }.should be_nil
@array.bsearch_index { |x| -1 }.should be_nil
end
it "returns the middle element when block always returns zero" do
@array.bsearch_index { |x| 0 }.should == 2
end
context "magnitude does not effect the result" do
it "returns the index of any matched elements where element is between 4n <= xn < 8n" do
[1, 2].should include(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
end
it "returns nil when block never returns 0" do
@array.bsearch_index { |x| 1 * (2**100) }.should be_nil
@array.bsearch_index { |x| (-1) * (2**100) }.should be_nil
end
it "handles values from Bignum#coerce" do
[1, 2].should include(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
end
end
end
end

View file

@ -0,0 +1,84 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../enumerable/shared/enumeratorized', __FILE__)
describe "Array#bsearch" do
it "returns an Enumerator when not passed a block" do
[1].bsearch.should be_an_instance_of(Enumerator)
end
it_behaves_like :enumeratorized_with_unknown_size, :bsearch, [1,2,3]
it "raises a TypeError if the block returns an Object" do
lambda { [1].bsearch { Object.new } }.should raise_error(TypeError)
end
it "raises a TypeError if the block returns a String" do
lambda { [1].bsearch { "1" } }.should raise_error(TypeError)
end
context "with a block returning true or false" do
it "returns nil if the block returns false for every element" do
[0, 1, 2, 3].bsearch { |x| x > 3 }.should be_nil
end
it "returns nil if the block returns nil for every element" do
[0, 1, 2, 3].bsearch { |x| nil }.should be_nil
end
it "returns element at zero if the block returns true for every element" do
[0, 1, 2, 3].bsearch { |x| x < 4 }.should == 0
end
it "returns the element at the smallest index for which block returns true" do
[0, 1, 3, 4].bsearch { |x| x >= 2 }.should == 3
[0, 1, 3, 4].bsearch { |x| x >= 1 }.should == 1
end
end
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
[0, 1, 2, 3].bsearch { |x| x <=> 5 }.should be_nil
end
it "returns nil if the block returns greater than zero for every element" do
[0, 1, 2, 3].bsearch { |x| x <=> -1 }.should be_nil
end
it "returns nil if the block never returns zero" do
[0, 1, 3, 4].bsearch { |x| x <=> 2 }.should be_nil
end
it "accepts (+/-)Float::INFINITY from the block" do
[0, 1, 3, 4].bsearch { |x| Float::INFINITY }.should be_nil
[0, 1, 3, 4].bsearch { |x| -Float::INFINITY }.should be_nil
end
it "returns an element at an index for which block returns 0.0" do
result = [0, 1, 2, 3, 4].bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
result.should == 2
end
it "returns an element at an index for which block returns 0" do
result = [0, 1, 2, 3, 4].bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
[1, 2].should include(result)
end
end
context "with a block that calls break" do
it "returns nil if break is called without a value" do
['a', 'b', 'c'].bsearch { |v| break }.should be_nil
end
it "returns nil if break is called with a nil value" do
['a', 'b', 'c'].bsearch { |v| break nil }.should be_nil
end
it "returns object if break is called with an object" do
['a', 'b', 'c'].bsearch { |v| break 1234 }.should == 1234
['a', 'b', 'c'].bsearch { |v| break 'hi' }.should == 'hi'
['a', 'b', 'c'].bsearch { |v| break [42] }.should == [42]
end
end
end

View file

@ -0,0 +1,49 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#clear" do
it "removes all elements" do
a = [1, 2, 3, 4]
a.clear.should equal(a)
a.should == []
end
it "returns self" do
a = [1]
oid = a.object_id
a.clear.object_id.should == oid
end
it "leaves the Array empty" do
a = [1]
a.clear
a.empty?.should == true
a.size.should == 0
end
it "keeps tainted status" do
a = [1]
a.taint
a.tainted?.should be_true
a.clear
a.tainted?.should be_true
end
it "does not accept any arguments" do
lambda { [1].clear(true) }.should raise_error(ArgumentError)
end
it "keeps untrusted status" do
a = [1]
a.untrust
a.untrusted?.should be_true
a.clear
a.untrusted?.should be_true
end
it "raises a RuntimeError on a frozen array" do
a = [1]
a.freeze
lambda { a.clear }.should raise_error(RuntimeError)
end
end

View file

@ -0,0 +1,31 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/clone', __FILE__)
describe "Array#clone" do
it_behaves_like :array_clone, :clone
it "copies frozen status from the original" do
a = [1, 2, 3, 4]
b = [1, 2, 3, 4]
a.freeze
aa = a.clone
bb = b.clone
aa.frozen?.should == true
bb.frozen?.should == false
end
it "copies singleton methods" do
a = [1, 2, 3, 4]
b = [1, 2, 3, 4]
def a.a_singleton_method; end
aa = a.clone
bb = b.clone
a.respond_to?(:a_singleton_method).should be_true
b.respond_to?(:a_singleton_method).should be_false
aa.respond_to?(:a_singleton_method).should be_true
bb.respond_to?(:a_singleton_method).should be_false
end
end

View file

@ -0,0 +1,11 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/collect', __FILE__)
describe "Array#collect" do
it_behaves_like(:array_collect, :collect)
end
describe "Array#collect!" do
it_behaves_like(:array_collect_b, :collect!)
end

View file

@ -0,0 +1,74 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#combination" do
before :each do
@array = [1, 2, 3, 4]
end
it "returns an enumerator when no block is provided" do
@array.combination(2).should be_an_instance_of(Enumerator)
end
it "returns self when a block is given" do
@array.combination(2){}.should equal(@array)
end
it "yields nothing for out of bounds length and return self" do
@array.combination(5).to_a.should == []
@array.combination(-1).to_a.should == []
end
it "yields the expected combinations" do
@array.combination(3).to_a.sort.should == [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
end
it "yields nothing if the argument is out of bounds" do
@array.combination(-1).to_a.should == []
@array.combination(5).to_a.should == []
end
it "yields a copy of self if the argument is the size of the receiver" do
r = @array.combination(4).to_a
r.should == [@array]
r[0].should_not equal(@array)
end
it "yields [] when length is 0" do
@array.combination(0).to_a.should == [[]] # one combination of length 0
[].combination(0).to_a.should == [[]] # one combination of length 0
end
it "yields a partition consisting of only singletons" do
@array.combination(1).to_a.sort.should == [[1],[2],[3],[4]]
end
it "generates from a defensive copy, ignoring mutations" do
accum = []
@array.combination(2) do |x|
accum << x
@array[0] = 1
end
accum.should == [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
end
describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
it "returns 0 when the number of combinations is < 0" do
@array.combination(-1).size.should == 0
[].combination(-2).size.should == 0
end
it "returns the binomial coeficient between the array size the number of combinations" do
@array.combination(5).size.should == 0
@array.combination(4).size.should == 1
@array.combination(3).size.should == 4
@array.combination(2).size.should == 6
@array.combination(1).size.should == 4
@array.combination(0).size.should == 1
[].combination(0).size.should == 1
[].combination(1).size.should == 0
end
end
end
end
end

View file

@ -0,0 +1,77 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#compact" do
it "returns a copy of array with all nil elements removed" do
a = [1, 2, 4]
a.compact.should == [1, 2, 4]
a = [1, nil, 2, 4]
a.compact.should == [1, 2, 4]
a = [1, 2, 4, nil]
a.compact.should == [1, 2, 4]
a = [nil, 1, 2, 4]
a.compact.should == [1, 2, 4]
end
it "does not return self" do
a = [1, 2, 3]
a.compact.should_not equal(a)
end
it "does not return subclass instance for Array subclasses" do
ArraySpecs::MyArray[1, 2, 3, nil].compact.should be_an_instance_of(Array)
end
it "does not keep tainted status even if all elements are removed" do
a = [nil, nil]
a.taint
a.compact.tainted?.should be_false
end
it "does not keep untrusted status even if all elements are removed" do
a = [nil, nil]
a.untrust
a.compact.untrusted?.should be_false
end
end
describe "Array#compact!" do
it "removes all nil elements" do
a = ['a', nil, 'b', false, 'c']
a.compact!.should equal(a)
a.should == ["a", "b", false, "c"]
a = [nil, 'a', 'b', false, 'c']
a.compact!.should equal(a)
a.should == ["a", "b", false, "c"]
a = ['a', 'b', false, 'c', nil]
a.compact!.should equal(a)
a.should == ["a", "b", false, "c"]
end
it "returns self if some nil elements are removed" do
a = ['a', nil, 'b', false, 'c']
a.compact!.object_id.should == a.object_id
end
it "returns nil if there are no nil elements to remove" do
[1, 2, false, 3].compact!.should == nil
end
it "keeps tainted status even if all elements are removed" do
a = [nil, nil]
a.taint
a.compact!
a.tainted?.should be_true
end
it "keeps untrusted status even if all elements are removed" do
a = [nil, nil]
a.untrust
a.compact!
a.untrusted?.should be_true
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array.compact! }.should raise_error(RuntimeError)
end
end

View file

@ -0,0 +1,97 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#<=>" do
it "calls <=> left to right and return first non-0 result" do
[-1, +1, nil, "foobar"].each do |result|
lhs = Array.new(3) { mock("#{result}") }
rhs = Array.new(3) { mock("#{result}") }
lhs[0].should_receive(:<=>).with(rhs[0]).and_return(0)
lhs[1].should_receive(:<=>).with(rhs[1]).and_return(result)
lhs[2].should_not_receive(:<=>)
(lhs <=> rhs).should == result
end
end
it "returns 0 if the arrays are equal" do
([] <=> []).should == 0
([1, 2, 3, 4, 5, 6] <=> [1, 2, 3, 4, 5.0, 6.0]).should == 0
end
it "returns -1 if the array is shorter than the other array" do
([] <=> [1]).should == -1
([1, 1] <=> [1, 1, 1]).should == -1
end
it "returns +1 if the array is longer than the other array" do
([1] <=> []).should == +1
([1, 1, 1] <=> [1, 1]).should == +1
end
it "returns -1 if the arrays have same length and a pair of corresponding elements returns -1 for <=>" do
eq_l = mock('an object equal to the other')
eq_r = mock('an object equal to the other')
eq_l.should_receive(:<=>).with(eq_r).any_number_of_times.and_return(0)
less = mock('less than the other')
greater = mock('greater then the other')
less.should_receive(:<=>).with(greater).any_number_of_times.and_return(-1)
rest = mock('an rest element of the arrays')
rest.should_receive(:<=>).with(rest).any_number_of_times.and_return(0)
lhs = [eq_l, eq_l, less, rest]
rhs = [eq_r, eq_r, greater, rest]
(lhs <=> rhs).should == -1
end
it "returns +1 if the arrays have same length and a pair of corresponding elements returns +1 for <=>" do
eq_l = mock('an object equal to the other')
eq_r = mock('an object equal to the other')
eq_l.should_receive(:<=>).with(eq_r).any_number_of_times.and_return(0)
greater = mock('greater then the other')
less = mock('less than the other')
greater.should_receive(:<=>).with(less).any_number_of_times.and_return(+1)
rest = mock('an rest element of the arrays')
rest.should_receive(:<=>).with(rest).any_number_of_times.and_return(0)
lhs = [eq_l, eq_l, greater, rest]
rhs = [eq_r, eq_r, less, rest]
(lhs <=> rhs).should == +1
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
(empty <=> empty).should == 0
(empty <=> []).should == 1
([] <=> empty).should == -1
(ArraySpecs.recursive_array <=> []).should == 1
([] <=> ArraySpecs.recursive_array).should == -1
(ArraySpecs.recursive_array <=> ArraySpecs.empty_recursive_array).should == nil
array = ArraySpecs.recursive_array
(array <=> array).should == 0
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])
([4, 5] <=> obj).should == ([4, 5] <=> obj.to_ary)
end
it "does not call #to_ary on Array subclasses" do
obj = ArraySpecs::ToAryArray[5, 6, 7]
obj.should_not_receive(:to_ary)
([5, 6, 7] <=> obj).should == 0
end
it "returns nil when the argument is not array-like" do
([] <=> false).should be_nil
end
end

View file

@ -0,0 +1,132 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#concat" do
it "returns the array itself" do
ary = [1,2,3]
ary.concat([4,5,6]).equal?(ary).should be_true
end
it "appends the elements in the other array" do
ary = [1, 2, 3]
ary.concat([9, 10, 11]).should equal(ary)
ary.should == [1, 2, 3, 9, 10, 11]
ary.concat([])
ary.should == [1, 2, 3, 9, 10, 11]
end
it "does not loop endlessly when argument is self" do
ary = ["x", "y"]
ary.concat(ary).should == ["x", "y", "x", "y"]
end
it "tries to convert the passed argument to an Array using #to_ary" do
obj = mock('to_ary')
obj.should_receive(:to_ary).and_return(["x", "y"])
[4, 5, 6].concat(obj).should == [4, 5, 6, "x", "y"]
end
it "does not call #to_ary on Array subclasses" do
obj = ArraySpecs::ToAryArray[5, 6, 7]
obj.should_not_receive(:to_ary)
[].concat(obj).should == [5, 6, 7]
end
it "raises a RuntimeError when Array is frozen and modification occurs" do
lambda { ArraySpecs.frozen_array.concat [1] }.should raise_error(RuntimeError)
end
# see [ruby-core:23666]
it "raises a RuntimeError when Array is frozen and no modification occurs" do
lambda { ArraySpecs.frozen_array.concat([]) }.should raise_error(RuntimeError)
end
it "keeps tainted status" do
ary = [1, 2]
ary.taint
ary.concat([3])
ary.tainted?.should be_true
ary.concat([])
ary.tainted?.should be_true
end
it "is not infected by the other" do
ary = [1,2]
other = [3]; other.taint
ary.tainted?.should be_false
ary.concat(other)
ary.tainted?.should be_false
end
it "keeps the tainted status of elements" do
ary = [ Object.new, Object.new, Object.new ]
ary.each {|x| x.taint }
ary.concat([ Object.new ])
ary[0].tainted?.should be_true
ary[1].tainted?.should be_true
ary[2].tainted?.should be_true
ary[3].tainted?.should be_false
end
it "keeps untrusted status" do
ary = [1, 2]
ary.untrust
ary.concat([3])
ary.untrusted?.should be_true
ary.concat([])
ary.untrusted?.should be_true
end
it "is not infected untrustedness by the other" do
ary = [1,2]
other = [3]; other.untrust
ary.untrusted?.should be_false
ary.concat(other)
ary.untrusted?.should be_false
end
it "keeps the untrusted status of elements" do
ary = [ Object.new, Object.new, Object.new ]
ary.each {|x| x.untrust }
ary.concat([ Object.new ])
ary[0].untrusted?.should be_true
ary[1].untrusted?.should be_true
ary[2].untrusted?.should be_true
ary[3].untrusted?.should be_false
end
it "appends elements to an Array with enough capacity that has been shifted" do
ary = [1, 2, 3, 4, 5]
2.times { ary.shift }
2.times { ary.pop }
ary.concat([5, 6]).should == [3, 5, 6]
end
it "appends elements to an Array without enough capacity that has been shifted" do
ary = [1, 2, 3, 4]
3.times { ary.shift }
ary.concat([5, 6]).should == [4, 5, 6]
end
ruby_version_is "2.4" do
it "takes multiple arguments" do
ary = [1, 2]
ary.concat [3, 4]
ary.should == [1, 2, 3, 4]
end
it "concatenates the initial value when given arguments contain 2 self" do
ary = [1, 2]
ary.concat ary, ary
ary.should == [1, 2, 1, 2, 1, 2]
end
it "returns self when given no arguments" do
ary = [1, 2]
ary.concat.should equal(ary)
ary.should == [1, 2]
end
end
end

View file

@ -0,0 +1,24 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array.[]" do
it "returns a new array populated with the given elements" do
obj = Object.new
Array.[](5, true, nil, 'a', "Ruby", obj).should == [5, true, nil, "a", "Ruby", obj]
a = ArraySpecs::MyArray.[](5, true, nil, 'a', "Ruby", obj)
a.should be_an_instance_of(ArraySpecs::MyArray)
a.inspect.should == [5, true, nil, "a", "Ruby", obj].inspect
end
end
describe "Array[]" do
it "is a synonym for .[]" do
obj = Object.new
Array[5, true, nil, 'a', "Ruby", obj].should == Array.[](5, true, nil, "a", "Ruby", obj)
a = ArraySpecs::MyArray[5, true, nil, 'a', "Ruby", obj]
a.should be_an_instance_of(ArraySpecs::MyArray)
a.inspect.should == [5, true, nil, "a", "Ruby", obj].inspect
end
end

View file

@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#count" do
it "returns the number of elements" do
[:a, :b, :c].count.should == 3
end
it "returns the number of elements that equal the argument" do
[:a, :b, :b, :c].count(:b).should == 2
end
it "returns the number of element for which the block evaluates to true" do
[:a, :b, :c].count { |s| s != :b }.should == 2
end
end

View file

@ -0,0 +1,101 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../enumerable/shared/enumeratorized', __FILE__)
describe "Array#cycle" do
before :each do
ScratchPad.record []
@array = [1, 2, 3]
@prc = lambda { |x| ScratchPad << x }
end
it "does not yield and returns nil when the array is empty and passed value is an integer" do
[].cycle(6, &@prc).should be_nil
ScratchPad.recorded.should == []
end
it "does not yield and returns nil when the array is empty and passed value is nil" do
[].cycle(nil, &@prc).should be_nil
ScratchPad.recorded.should == []
end
it "does not yield and returns nil when passed 0" do
@array.cycle(0, &@prc).should be_nil
ScratchPad.recorded.should == []
end
it "iterates the array 'count' times yielding each item to the block" do
@array.cycle(2, &@prc)
ScratchPad.recorded.should == [1, 2, 3, 1, 2, 3]
end
it "iterates indefinitely when not passed a count" do
@array.cycle do |x|
ScratchPad << x
break if ScratchPad.recorded.size > 7
end
ScratchPad.recorded.should == [1, 2, 3, 1, 2, 3, 1, 2]
end
it "iterates indefinitely when passed nil" do
@array.cycle(nil) do |x|
ScratchPad << x
break if ScratchPad.recorded.size > 7
end
ScratchPad.recorded.should == [1, 2, 3, 1, 2, 3, 1, 2]
end
it "does not rescue StopIteration when not passed a count" do
lambda do
@array.cycle { raise StopIteration }
end.should raise_error(StopIteration)
end
it "does not rescue StopIteration when passed a count" do
lambda do
@array.cycle(3) { raise StopIteration }
end.should raise_error(StopIteration)
end
it "iterates the array Integer(count) times when passed a Float count" do
@array.cycle(2.7, &@prc)
ScratchPad.recorded.should == [1, 2, 3, 1, 2, 3]
end
it "calls #to_int to convert count to an Integer" do
count = mock("cycle count 2")
count.should_receive(:to_int).and_return(2)
@array.cycle(count, &@prc)
ScratchPad.recorded.should == [1, 2, 3, 1, 2, 3]
end
it "raises a TypeError if #to_int does not return an Integer" do
count = mock("cycle count 2")
count.should_receive(:to_int).and_return("2")
lambda { @array.cycle(count, &@prc) }.should raise_error(TypeError)
end
it "raises a TypeError if passed a String" do
lambda { @array.cycle("4") { } }.should raise_error(TypeError)
end
it "raises a TypeError if passed an Object" do
lambda { @array.cycle(mock("cycle count")) { } }.should raise_error(TypeError)
end
it "raises a TypeError if passed true" do
lambda { @array.cycle(true) { } }.should raise_error(TypeError)
end
it "raises a TypeError if passed false" do
lambda { @array.cycle(false) { } }.should raise_error(TypeError)
end
before :all do
@object = [1, 2, 3, 4]
@empty_object = []
end
it_should_behave_like :enumeratorized_with_cycle_size
end

View file

@ -0,0 +1,61 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#delete_at" do
it "removes the element at the specified index" do
a = [1, 2, 3, 4]
a.delete_at(2)
a.should == [1, 2, 4]
a.delete_at(-1)
a.should == [1, 2]
end
it "returns the removed element at the specified index" do
a = [1, 2, 3, 4]
a.delete_at(2).should == 3
a.delete_at(-1).should == 4
end
it "returns nil and makes no modification if the index is out of range" do
a = [1, 2]
a.delete_at(3).should == nil
a.should == [1, 2]
a.delete_at(-3).should == nil
a.should == [1, 2]
end
it "tries to convert the passed argument to an Integer using #to_int" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(-1)
[1, 2].delete_at(obj).should == 2
end
it "accepts negative indices" do
a = [1, 2]
a.delete_at(-2).should == 1
end
it "raises a RuntimeError on a frozen array" do
lambda { [1,2,3].freeze.delete_at(0) }.should raise_error(RuntimeError)
end
it "keeps tainted status" do
ary = [1, 2]
ary.taint
ary.tainted?.should be_true
ary.delete_at(0)
ary.tainted?.should be_true
ary.delete_at(0) # now empty
ary.tainted?.should be_true
end
it "keeps untrusted status" do
ary = [1, 2]
ary.untrust
ary.untrusted?.should be_true
ary.delete_at(0)
ary.untrusted?.should be_true
ary.delete_at(0) # now empty
ary.untrusted?.should be_true
end
end

View file

@ -0,0 +1,66 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/enumeratorize', __FILE__)
require File.expand_path('../shared/delete_if', __FILE__)
require File.expand_path('../../enumerable/shared/enumeratorized', __FILE__)
describe "Array#delete_if" do
before do
@a = [ "a", "b", "c" ]
end
it "removes each element for which block returns true" do
@a = [ "a", "b", "c" ]
@a.delete_if { |x| x >= "b" }
@a.should == ["a"]
end
it "returns self" do
@a.delete_if{ true }.equal?(@a).should be_true
end
it_behaves_like :enumeratorize, :delete_if
it "returns self when called on an Array emptied with #shift" do
array = [1]
array.shift
array.delete_if { |x| true }.should equal(array)
end
it "returns an Enumerator if no block given, and the enumerator can modify the original array" do
enum = @a.delete_if
enum.should be_an_instance_of(Enumerator)
@a.should_not be_empty
enum.each { true }
@a.should be_empty
end
it "returns an Enumerator if no block given, and the array is frozen" do
@a.freeze.delete_if.should be_an_instance_of(Enumerator)
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array.delete_if {} }.should raise_error(RuntimeError)
end
it "raises a RuntimeError on an empty frozen array" do
lambda { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(RuntimeError)
end
it "keeps tainted status" do
@a.taint
@a.tainted?.should be_true
@a.delete_if{ true }
@a.tainted?.should be_true
end
it "keeps untrusted status" do
@a.untrust
@a.untrusted?.should be_true
@a.delete_if{ true }
@a.untrusted?.should be_true
end
it_behaves_like :enumeratorized_with_origin_size, :delete_if, [1,2,3]
it_behaves_like :delete_if, :delete_if
end

View file

@ -0,0 +1,66 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#delete" do
it "removes elements that are #== to object" do
x = mock('delete')
def x.==(other) 3 == other end
a = [1, 2, 3, x, 4, 3, 5, x]
a.delete mock('not contained')
a.should == [1, 2, 3, x, 4, 3, 5, x]
a.delete 3
a.should == [1, 2, 4, 5]
end
it "calculates equality correctly for reference values" do
a = ["foo", "bar", "foo", "quux", "foo"]
a.delete "foo"
a.should == ["bar","quux"]
end
it "returns object or nil if no elements match object" do
[1, 2, 4, 5].delete(1).should == 1
[1, 2, 4, 5].delete(3).should == nil
end
it "may be given a block that is executed if no element matches object" do
[1].delete(1) {:not_found}.should == 1
[].delete('a') {:not_found}.should == :not_found
end
it "returns nil if the array is empty due to a shift" do
a = [1]
a.shift
a.delete(nil).should == nil
end
it "returns nil on a frozen array if a modification does not take place" do
[1, 2, 3].freeze.delete(0).should == nil
end
it "raises a RuntimeError on a frozen array" do
lambda { [1, 2, 3].freeze.delete(1) }.should raise_error(RuntimeError)
end
it "keeps tainted status" do
a = [1, 2]
a.taint
a.tainted?.should be_true
a.delete(2)
a.tainted?.should be_true
a.delete(1) # now empty
a.tainted?.should be_true
end
it "keeps untrusted status" do
a = [1, 2]
a.untrust
a.untrusted?.should be_true
a.delete(2)
a.untrusted?.should be_true
a.delete(1) # now empty
a.untrusted?.should be_true
end
end

View file

@ -0,0 +1,54 @@
require File.expand_path('../../../spec_helper', __FILE__)
ruby_version_is '2.3' do
describe "Array#dig" do
it "returns #at with one arg" do
['a'].dig(0).should == 'a'
['a'].dig(1).should be_nil
end
it "recurses array elements" do
a = [ [ 1, [2, '3'] ] ]
a.dig(0, 0).should == 1
a.dig(0, 1, 1).should == '3'
a.dig(0, -1, 0).should == 2
end
it "returns the nested value specified if the sequence includes a key" do
a = [42, { foo: :bar }]
a.dig(1, :foo).should == :bar
end
it "raises a TypeError for a non-numeric index" do
lambda {
['a'].dig(:first)
}.should raise_error(TypeError)
end
it "raises a TypeError if any intermediate step does not respond to #dig" do
a = [1, 2]
lambda {
a.dig(0, 1)
}.should raise_error(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
lambda {
[10].dig()
}.should raise_error(ArgumentError)
end
it "returns nil if any intermediate step is nil" do
a = [[1, [2, 3]]]
a.dig(1, 2, 3).should == nil
end
it "calls #dig on the result of #at with the remaining arguments" do
h = [[nil, [nil, nil, 42]]]
h[0].should_receive(:dig).with(1, 2).and_return(42)
h.dig(0, 1, 2).should == 42
end
end
end

View file

@ -0,0 +1,33 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#drop" do
it "removes the specified number of elements from the start of the array" do
[1, 2, 3, 4, 5].drop(2).should == [3, 4, 5]
end
it "raises an ArgumentError if the number of elements specified is negative" do
lambda { [1, 2].drop(-3) }.should raise_error(ArgumentError)
end
it "returns an empty Array if all elements are dropped" do
[1, 2].drop(2).should == []
end
it "returns an empty Array when called on an empty Array" do
[].drop(0).should == []
end
it "does not remove any elements when passed zero" do
[1, 2].drop(0).should == [1, 2]
end
it "returns an empty Array if more elements than exist are dropped" do
[1, 2].drop(3).should == []
end
it 'acts correctly after a shift' do
ary = [nil, 1, 2]
ary.shift
ary.drop(1).should == [2]
end
end

View file

@ -0,0 +1,15 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#drop_while" do
it "removes elements from the start of the array while the block evaluates to true" do
[1, 2, 3, 4].drop_while { |n| n < 4 }.should == [4]
end
it "removes elements from the start of the array until the block returns nil" do
[1, 2, 3, nil, 5].drop_while { |n| n }.should == [nil, 5]
end
it "removes elements from the start of the array until the block returns false" do
[1, 2, 3, false, 5].drop_while { |n| n }.should == [false, 5]
end
end

View file

@ -0,0 +1,31 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/clone', __FILE__)
describe "Array#dup" do
it_behaves_like :array_clone, :dup # FIX: no, clone and dup are not alike
it "does not copy frozen status from the original" do
a = [1, 2, 3, 4]
b = [1, 2, 3, 4]
a.freeze
aa = a.dup
bb = b.dup
aa.frozen?.should be_false
bb.frozen?.should be_false
end
it "does not copy singleton methods" do
a = [1, 2, 3, 4]
b = [1, 2, 3, 4]
def a.a_singleton_method; end
aa = a.dup
bb = b.dup
a.respond_to?(:a_singleton_method).should be_true
b.respond_to?(:a_singleton_method).should be_false
aa.respond_to?(:a_singleton_method).should be_false
bb.respond_to?(:a_singleton_method).should be_false
end
end

View file

@ -0,0 +1,42 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/enumeratorize', __FILE__)
require File.expand_path('../../enumerable/shared/enumeratorized', __FILE__)
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
describe "Array#each_index" do
before :each do
ScratchPad.record []
end
it "passes the index of each element to the block" do
a = ['a', 'b', 'c', 'd']
a.each_index { |i| ScratchPad << i }
ScratchPad.recorded.should == [0, 1, 2, 3]
end
it "returns self" do
a = [:a, :b, :c]
a.each_index { |i| }.should equal(a)
end
it "is not confused by removing elements from the front" do
a = [1, 2, 3]
a.shift
ScratchPad.record []
a.each_index { |i| ScratchPad << i }
ScratchPad.recorded.should == [0, 1]
a.shift
ScratchPad.record []
a.each_index { |i| ScratchPad << i }
ScratchPad.recorded.should == [0]
end
it_behaves_like :enumeratorize, :each_index
it_behaves_like :enumeratorized_with_origin_size, :each_index, [1,2,3]
end

View file

@ -0,0 +1,32 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/enumeratorize', __FILE__)
require File.expand_path('../../enumerable/shared/enumeratorized', __FILE__)
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
describe "Array#each" do
it "yields each element to the block" do
a = []
x = [1, 2, 3]
x.each { |item| a << item }.should equal(x)
a.should == [1, 2, 3]
end
it "yields each element to a block that takes multiple arguments" do
a = [[1, 2], :a, [3, 4]]
b = []
a.each { |x, y| b << x }
b.should == [1, :a, 3]
b = []
a.each { |x, y| b << y }
b.should == [2, nil, 4]
end
it_behaves_like :enumeratorize, :each
it_behaves_like :enumeratorized_with_origin_size, :each, [1,2,3]
end

View file

@ -0,0 +1,50 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/slice', __FILE__)
describe "Array#[]" do
it_behaves_like(:array_slice, :[])
end
describe "Array.[]" do
it "[] should return a new array populated with the given elements" do
array = Array[1, 'a', nil]
array[0].should == 1
array[1].should == 'a'
array[2].should == nil
end
it "when applied to a literal nested array, unpacks its elements into the containing array" do
Array[1, 2, *[3, 4, 5]].should == [1, 2, 3, 4, 5]
end
it "when applied to a nested referenced array, unpacks its elements into the containing array" do
splatted_array = Array[3, 4, 5]
Array[1, 2, *splatted_array].should == [1, 2, 3, 4, 5]
end
it "can unpack 2 or more nested referenced array" do
splatted_array = Array[3, 4, 5]
splatted_array2 = Array[6, 7, 8]
Array[1, 2, *splatted_array, *splatted_array2].should == [1, 2, 3, 4, 5, 6, 7, 8]
end
it "constructs a nested Hash for tailing key-value pairs" do
Array[1, 2, 3 => 4, 5 => 6].should == [1, 2, { 3 => 4, 5 => 6 }]
end
describe "with a subclass of Array" do
before :each do
ScratchPad.clear
end
it "returns an instance of the subclass" do
ArraySpecs::MyArray[1, 2, 3].should be_an_instance_of(ArraySpecs::MyArray)
end
it "does not call #initialize on the subclass instance" do
ArraySpecs::MyArray[1, 2, 3].should == [1, 2, 3]
ScratchPad.recorded.should be_nil
end
end
end

View file

@ -0,0 +1,417 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#[]=" do
it "sets the value of the element at index" do
a = [1, 2, 3, 4]
a[2] = 5
a[-1] = 6
a[5] = 3
a.should == [1, 2, 5, 6, nil, 3]
a = []
a[4] = "e"
a.should == [nil, nil, nil, nil, "e"]
a[3] = "d"
a.should == [nil, nil, nil, "d", "e"]
a[0] = "a"
a.should == ["a", nil, nil, "d", "e"]
a[-3] = "C"
a.should == ["a", nil, "C", "d", "e"]
a[-1] = "E"
a.should == ["a", nil, "C", "d", "E"]
a[-5] = "A"
a.should == ["A", nil, "C", "d", "E"]
a[5] = "f"
a.should == ["A", nil, "C", "d", "E", "f"]
a[1] = []
a.should == ["A", [], "C", "d", "E", "f"]
a[-1] = nil
a.should == ["A", [], "C", "d", "E", nil]
end
it "sets the section defined by [start,length] to other" do
a = [1, 2, 3, 4, 5, 6]
a[0, 1] = 2
a[3, 2] = ['a', 'b', 'c', 'd']
a.should == [2, 2, 3, "a", "b", "c", "d", 6]
end
it "replaces the section defined by [start,length] with the given values" do
a = [1, 2, 3, 4, 5, 6]
a[3, 2] = 'a', 'b', 'c', 'd'
a.should == [1, 2, 3, "a", "b", "c", "d", 6]
end
it "just sets the section defined by [start,length] to other even if other is nil" do
a = ['a', 'b', 'c', 'd', 'e']
a[1, 3] = nil
a.should == ["a", nil, "e"]
end
it "returns nil if the rhs is nil" do
a = [1, 2, 3]
(a[1, 3] = nil).should == nil
(a[1..3] = nil).should == nil
end
it "sets the section defined by range to other" do
a = [6, 5, 4, 3, 2, 1]
a[1...2] = 9
a[3..6] = [6, 6, 6]
a.should == [6, 9, 4, 6, 6, 6]
end
it "replaces the section defined by range with the given values" do
a = [6, 5, 4, 3, 2, 1]
a[3..6] = :a, :b, :c
a.should == [6, 5, 4, :a, :b, :c]
end
it "just sets the section defined by range to other even if other is nil" do
a = [1, 2, 3, 4, 5]
a[0..1] = nil
a.should == [nil, 3, 4, 5]
end
it 'expands and nil-pads the array if section assigned by range is outside array boundaries' do
a = ['a']
a[3..4] = ['b', 'c']
a.should == ['a', nil, nil, 'b', 'c']
end
it "calls to_int on its start and length arguments" do
obj = mock('to_int')
obj.stub!(:to_int).and_return(2)
a = [1, 2, 3, 4]
a[obj, 0] = [9]
a.should == [1, 2, 9, 3, 4]
a[obj, obj] = []
a.should == [1, 2, 4]
a[obj] = -1
a.should == [1, 2, -1]
end
it "checks frozen before attempting to coerce arguments" do
a = [1,2,3,4].freeze
lambda {a[:foo] = 1}.should raise_error(RuntimeError)
lambda {a[:foo, :bar] = 1}.should raise_error(RuntimeError)
end
it "sets elements in the range arguments when passed ranges" do
ary = [1, 2, 3]
rhs = [nil, [], ["x"], ["x", "y"]]
(0 .. ary.size + 2).each do |a|
(a .. ary.size + 3).each do |b|
rhs.each do |c|
ary1 = ary.dup
ary1[a .. b] = c
ary2 = ary.dup
ary2[a, 1 + b-a] = c
ary1.should == ary2
ary1 = ary.dup
ary1[a ... b] = c
ary2 = ary.dup
ary2[a, b-a] = c
ary1.should == ary2
end
end
end
end
it "inserts the given elements with [range] which the range is zero-width" do
ary = [1, 2, 3]
ary[1...1] = 0
ary.should == [1, 0, 2, 3]
ary[1...1] = [5]
ary.should == [1, 5, 0, 2, 3]
ary[1...1] = :a, :b, :c
ary.should == [1, :a, :b, :c, 5, 0, 2, 3]
end
it "inserts the given elements with [start, length] which length is zero" do
ary = [1, 2, 3]
ary[1, 0] = 0
ary.should == [1, 0, 2, 3]
ary[1, 0] = [5]
ary.should == [1, 5, 0, 2, 3]
ary[1, 0] = :a, :b, :c
ary.should == [1, :a, :b, :c, 5, 0, 2, 3]
end
# Now we only have to test cases where the start, length interface would
# have raise an exception because of negative size
it "inserts the given elements with [range] which the range has negative width" do
ary = [1, 2, 3]
ary[1..0] = 0
ary.should == [1, 0, 2, 3]
ary[1..0] = [4, 3]
ary.should == [1, 4, 3, 0, 2, 3]
ary[1..0] = :a, :b, :c
ary.should == [1, :a, :b, :c, 4, 3, 0, 2, 3]
end
it "just inserts nil if the section defined by range is zero-width and the rhs is nil" do
ary = [1, 2, 3]
ary[1...1] = nil
ary.should == [1, nil, 2, 3]
end
it "just inserts nil if the section defined by range has negative width and the rhs is nil" do
ary = [1, 2, 3]
ary[1..0] = nil
ary.should == [1, nil, 2, 3]
end
it "does nothing if the section defined by range is zero-width and the rhs is an empty array" do
ary = [1, 2, 3]
ary[1...1] = []
ary.should == [1, 2, 3]
end
it "does nothing if the section defined by range has negative width and the rhs is an empty array" do
ary = [1, 2, 3, 4, 5]
ary[1...0] = []
ary.should == [1, 2, 3, 4, 5]
ary[-2..2] = []
ary.should == [1, 2, 3, 4, 5]
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] = ["a", "b", "c"]
a.should == [1, "a", "b", "c", 4]
a[to .. from] = ["x"]
a.should == [1, "a", "b", "x", "c", 4]
lambda { a["a" .. "b"] = [] }.should raise_error(TypeError)
lambda { a[from .. "b"] = [] }.should raise_error(TypeError)
end
it "raises an IndexError when passed indexes out of bounds" do
a = [1, 2, 3, 4]
lambda { a[-5] = "" }.should raise_error(IndexError)
lambda { a[-5, -1] = "" }.should raise_error(IndexError)
lambda { a[-5, 0] = "" }.should raise_error(IndexError)
lambda { a[-5, 1] = "" }.should raise_error(IndexError)
lambda { a[-5, 2] = "" }.should raise_error(IndexError)
lambda { a[-5, 10] = "" }.should raise_error(IndexError)
lambda { a[-5..-5] = "" }.should raise_error(RangeError)
lambda { a[-5...-5] = "" }.should raise_error(RangeError)
lambda { a[-5..-4] = "" }.should raise_error(RangeError)
lambda { a[-5...-4] = "" }.should raise_error(RangeError)
lambda { a[-5..10] = "" }.should raise_error(RangeError)
lambda { a[-5...10] = "" }.should raise_error(RangeError)
# ok
a[0..-9] = [1]
a.should == [1, 1, 2, 3, 4]
end
it "calls to_ary on its rhs argument for multi-element sets" do
obj = mock('to_ary')
def obj.to_ary() [1, 2, 3] end
ary = [1, 2]
ary[0, 0] = obj
ary.should == [1, 2, 3, 1, 2]
ary[1, 10] = obj
ary.should == [1, 1, 2, 3]
end
it "does not call to_ary on rhs array subclasses for multi-element sets" do
ary = []
ary[0, 0] = ArraySpecs::ToAryArray[5, 6, 7]
ary.should == [5, 6, 7]
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array[0, 0] = [] }.should raise_error(RuntimeError)
end
end
describe "Array#[]= with [index]" do
it "returns value assigned if idx is inside array" do
a = [1, 2, 3, 4, 5]
(a[3] = 6).should == 6
end
it "returns value assigned if idx is right beyond right array boundary" do
a = [1, 2, 3, 4, 5]
(a[5] = 6).should == 6
end
it "returns value assigned if idx far beyond right array boundary" do
a = [1, 2, 3, 4, 5]
(a[10] = 6).should == 6
end
it "sets the value of the element at index" do
a = [1, 2, 3, 4]
a[2] = 5
a[-1] = 6
a[5] = 3
a.should == [1, 2, 5, 6, nil, 3]
end
it "sets the value of the element if it is right beyond the array boundary" do
a = [1, 2, 3, 4]
a[4] = 8
a.should == [1, 2, 3, 4, 8]
end
end
describe "Array#[]= with [index, count]" do
it "returns non-array value if non-array value assigned" do
a = [1, 2, 3, 4, 5]
(a[2, 3] = 10).should == 10
end
it "returns array if array assigned" do
a = [1, 2, 3, 4, 5]
(a[2, 3] = [4, 5]).should == [4, 5]
end
it "just sets the section defined by [start,length] to nil even if the rhs is nil" do
a = ['a', 'b', 'c', 'd', 'e']
a[1, 3] = nil
a.should == ["a", nil, "e"]
end
it "just sets the section defined by [start,length] to nil if negative index within bounds, cnt > 0 and the rhs is nil" do
a = ['a', 'b', 'c', 'd', 'e']
a[-3, 2] = nil
a.should == ["a", "b", nil, "e"]
end
it "replaces the section defined by [start,length] to other" do
a = [1, 2, 3, 4, 5, 6]
a[0, 1] = 2
a[3, 2] = ['a', 'b', 'c', 'd']
a.should == [2, 2, 3, "a", "b", "c", "d", 6]
end
it "replaces the section to other if idx < 0 and cnt > 0" do
a = [1, 2, 3, 4, 5, 6]
a[-3, 2] = ["x", "y", "z"]
a.should == [1, 2, 3, "x", "y", "z", 6]
end
it "replaces the section to other even if cnt spanning beyond the array boundary" do
a = [1, 2, 3, 4, 5]
a[-1, 3] = [7, 8]
a.should == [1, 2, 3, 4, 7, 8]
end
it "pads the Array with nils if the span is past the end" do
a = [1, 2, 3, 4, 5]
a[10, 1] = [1]
a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 1]
b = [1, 2, 3, 4, 5]
b[10, 0] = [1]
a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 1]
end
it "inserts other section in place defined by idx" do
a = [1, 2, 3, 4, 5]
a[3, 0] = [7, 8]
a.should == [1, 2, 3, 7, 8, 4, 5]
b = [1, 2, 3, 4, 5]
b[1, 0] = b
b.should == [1, 1, 2, 3, 4, 5, 2, 3, 4, 5]
end
it "raises an IndexError when passed start and negative length" do
a = [1, 2, 3, 4]
lambda { a[-2, -1] = "" }.should raise_error(IndexError)
lambda { a[0, -1] = "" }.should raise_error(IndexError)
lambda { a[2, -1] = "" }.should raise_error(IndexError)
lambda { a[4, -1] = "" }.should raise_error(IndexError)
lambda { a[10, -1] = "" }.should raise_error(IndexError)
lambda { [1, 2, 3, 4, 5][2, -1] = [7, 8] }.should raise_error(IndexError)
end
end
describe "Array#[]= with [m..n]" do
it "returns non-array value if non-array value assigned" do
a = [1, 2, 3, 4, 5]
(a[2..4] = 10).should == 10
end
it "returns array if array assigned" do
a = [1, 2, 3, 4, 5]
(a[2..4] = [7, 8]).should == [7, 8]
end
it "just sets the section defined by range to nil even if the rhs is nil" do
a = [1, 2, 3, 4, 5]
a[0..1] = nil
a.should == [nil, 3, 4, 5]
end
it "just sets the section defined by range to nil if m and n < 0 and the rhs is nil" do
a = [1, 2, 3, 4, 5]
a[-3..-2] = nil
a.should == [1, 2, nil, 5]
end
it "replaces the section defined by range" do
a = [6, 5, 4, 3, 2, 1]
a[1...2] = 9
a[3..6] = [6, 6, 6]
a.should == [6, 9, 4, 6, 6, 6]
end
it "replaces the section if m and n < 0" do
a = [1, 2, 3, 4, 5]
a[-3..-2] = [7, 8, 9]
a.should == [1, 2, 7, 8, 9, 5]
end
it "replaces the section if m < 0 and n > 0" do
a = [1, 2, 3, 4, 5]
a[-4..3] = [8]
a.should == [1, 8, 5]
end
it "inserts the other section at m if m > n" do
a = [1, 2, 3, 4, 5]
a[3..1] = [8]
a.should == [1, 2, 3, 8, 4, 5]
end
it "accepts 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] = ["a", "b"]
a.should == [1, "a", "b", 4]
a[range_excl] = ["A", "B"]
a.should == [1, "A", "B", 4]
end
end
describe "Array#[] after a shift" do
it "works for insertion" do
a = [1,2]
a.shift
a.shift
a[0,0] = [3,4]
a.should == [3,4]
end
end

View file

@ -0,0 +1,10 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#empty?" do
it "returns true if the array has no elements" do
[].empty?.should == true
[1].empty?.should == false
[1, 2].empty?.should == false
end
end

View file

@ -0,0 +1,19 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/eql', __FILE__)
describe "Array#eql?" do
it_behaves_like :array_eql, :eql?
it "returns false if any corresponding elements are not #eql?" do
[1, 2, 3, 4].send(@method, [1, 2, 3, 4.0]).should be_false
end
it "returns false if other is not a kind of Array" do
obj = mock("array eql?")
obj.should_not_receive(:to_ary)
obj.should_not_receive(@method)
[1, 2, 3].send(@method, obj).should be_false
end
end

View file

@ -0,0 +1,51 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/eql', __FILE__)
describe "Array#==" do
it_behaves_like :array_eql, :==
it "compares with an equivalent Array-like object using #to_ary" do
obj = mock('array-like')
obj.should_receive(:respond_to?).at_least(1).with(:to_ary).and_return(true)
obj.should_receive(:==).with([1]).at_least(1).and_return(true)
([1] == obj).should be_true
([[1]] == [obj]).should be_true
([[[1], 3], 2] == [[obj, 3], 2]).should be_true
# recursive arrays
arr1 = [[1]]
arr1 << arr1
arr2 = [obj]
arr2 << arr2
(arr1 == arr2).should be_true
(arr2 == arr1).should be_true
end
it "returns false if any corresponding elements are not #==" do
a = ["a", "b", "c"]
b = ["a", "b", "not equal value"]
a.should_not == b
c = mock("c")
c.should_receive(:==).and_return(false)
["a", "b", c].should_not == a
end
it "returns true if corresponding elements are #==" do
[].should == []
["a", "c", 7].should == ["a", "c", 7]
[1, 2, 3].should == [1.0, 2.0, 3.0]
obj = mock('5')
obj.should_receive(:==).and_return(true)
[obj].should == [5]
end
# As per bug #1720
it "returns false for [NaN] == [NaN]" do
[nan_value].should_not == [nan_value]
end
end

View file

@ -0,0 +1,55 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#fetch" do
it "returns the element at the passed index" do
[1, 2, 3].fetch(1).should == 2
[nil].fetch(0).should == nil
end
it "counts negative indices backwards from end" do
[1, 2, 3, 4].fetch(-1).should == 4
end
it "raises an IndexError if there is no element at index" do
lambda { [1, 2, 3].fetch(3) }.should raise_error(IndexError)
lambda { [1, 2, 3].fetch(-4) }.should raise_error(IndexError)
lambda { [].fetch(0) }.should raise_error(IndexError)
end
it "returns default if there is no element at index if passed a default value" do
[1, 2, 3].fetch(5, :not_found).should == :not_found
[1, 2, 3].fetch(5, nil).should == nil
[1, 2, 3].fetch(-4, :not_found).should == :not_found
[nil].fetch(0, :not_found).should == nil
end
it "returns the value of block if there is no element at index if passed a block" do
[1, 2, 3].fetch(9) { |i| i * i }.should == 81
[1, 2, 3].fetch(-9) { |i| i * i }.should == 81
end
it "passes the original index argument object to the block, not the converted Integer" do
o = mock('5')
def o.to_int(); 5; end
[1, 2, 3].fetch(o) { |i| i }.should equal(o)
end
it "gives precedence to the default block over the default argument" do
lambda {
@result = [1, 2, 3].fetch(9, :foo) { |i| i * i }
}.should complain(/block supersedes default value argument/)
@result.should == 81
end
it "tries to convert the passed argument to an Integer using #to_int" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(2)
["a", "b", "c"].fetch(obj).should == "c"
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
lambda { [].fetch("cat") }.should raise_error(TypeError)
end
end

View file

@ -0,0 +1,317 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#fill" do
before :all do
@never_passed = lambda do |i|
raise ExpectationNotMetError, "the control path should not pass here"
end
end
it "returns self" do
ary = [1, 2, 3]
ary.fill(:a).should equal(ary)
end
it "is destructive" do
ary = [1, 2, 3]
ary.fill(:a)
ary.should == [:a, :a, :a]
end
it "does not replicate the filler" do
ary = [1, 2, 3, 4]
str = "x"
ary.fill(str).should == [str, str, str, str]
str << "y"
ary.should == [str, str, str, str]
ary[0].should equal(str)
ary[1].should equal(str)
ary[2].should equal(str)
ary[3].should equal(str)
end
it "replaces all elements in the array with the filler if not given a index nor a length" do
ary = ['a', 'b', 'c', 'duh']
ary.fill(8).should == [8, 8, 8, 8]
str = "x"
ary.fill(str).should == [str, str, str, str]
end
it "replaces all elements with the value of block (index given to block)" do
[nil, nil, nil, nil].fill { |i| i * 2 }.should == [0, 2, 4, 6]
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array.fill('x') }.should raise_error(RuntimeError)
end
it "raises a RuntimeError on an empty frozen array" do
lambda { ArraySpecs.empty_frozen_array.fill('x') }.should raise_error(RuntimeError)
end
it "raises an ArgumentError if 4 or more arguments are passed when no block given" do
lambda { [].fill('a') }.should_not raise_error(ArgumentError)
lambda { [].fill('a', 1) }.should_not raise_error(ArgumentError)
lambda { [].fill('a', 1, 2) }.should_not raise_error(ArgumentError)
lambda { [].fill('a', 1, 2, true) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if no argument passed and no block given" do
lambda { [].fill }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if 3 or more arguments are passed when a block given" do
lambda { [].fill() {|i|} }.should_not raise_error(ArgumentError)
lambda { [].fill(1) {|i|} }.should_not raise_error(ArgumentError)
lambda { [].fill(1, 2) {|i|} }.should_not raise_error(ArgumentError)
lambda { [].fill(1, 2, true) {|i|} }.should raise_error(ArgumentError)
end
end
describe "Array#fill with (filler, index, length)" do
it "replaces length elements beginning with the index with the filler if given an index and a length" do
ary = [1, 2, 3, 4, 5, 6]
ary.fill('x', 2, 3).should == [1, 2, 'x', 'x', 'x', 6]
end
it "replaces length elements beginning with the index with the value of block" do
[true, false, true, false, true, false, true].fill(1, 4) { |i| i + 3 }.should == [true, 4, 5, 6, 7, false, true]
end
it "replaces all elements after the index if given an index and no length" do
ary = [1, 2, 3]
ary.fill('x', 1).should == [1, 'x', 'x']
ary.fill(1){|i| i*2}.should == [1, 2, 4]
end
it "replaces all elements after the index if given an index and nil as a length" do
a = [1, 2, 3]
a.fill('x', 1, nil).should == [1, 'x', 'x']
a.fill(1, nil){|i| i*2}.should == [1, 2, 4]
a.fill('y', nil).should == ['y', 'y', 'y']
end
it "replaces the last (-n) elements if given an index n which is negative and no length" do
a = [1, 2, 3, 4, 5]
a.fill('x', -2).should == [1, 2, 3, 'x', 'x']
a.fill(-2){|i| i.to_s}.should == [1, 2, 3, '3', '4']
end
it "replaces the last (-n) elements if given an index n which is negative and nil as a length" do
a = [1, 2, 3, 4, 5]
a.fill('x', -2, nil).should == [1, 2, 3, 'x', 'x']
a.fill(-2, nil){|i| i.to_s}.should == [1, 2, 3, '3', '4']
end
it "makes no modifications if given an index greater than end and no length" do
[1, 2, 3, 4, 5].fill('a', 5).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill(5, &@never_passed).should == [1, 2, 3, 4, 5]
end
it "makes no modifications if given an index greater than end and nil as a length" do
[1, 2, 3, 4, 5].fill('a', 5, nil).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill(5, nil, &@never_passed).should == [1, 2, 3, 4, 5]
end
it "replaces length elements beginning with start index if given an index >= 0 and a length >= 0" do
[1, 2, 3, 4, 5].fill('a', 2, 0).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill('a', 2, 2).should == [1, 2, "a", "a", 5]
[1, 2, 3, 4, 5].fill(2, 0, &@never_passed).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill(2, 2){|i| i*2}.should == [1, 2, 4, 6, 5]
end
it "increases the Array size when necessary" do
a = [1, 2, 3]
a.size.should == 3
a.fill 'a', 0, 10
a.size.should == 10
end
it "pads between the last element and the index with nil if given an index which is greater than size of the array" do
[1, 2, 3, 4, 5].fill('a', 8, 5).should == [1, 2, 3, 4, 5, nil, nil, nil, 'a', 'a', 'a', 'a', 'a']
[1, 2, 3, 4, 5].fill(8, 5){|i| 'a'}.should == [1, 2, 3, 4, 5, nil, nil, nil, 'a', 'a', 'a', 'a', 'a']
end
it "replaces length elements beginning with the (-n)th if given an index n < 0 and a length > 0" do
[1, 2, 3, 4, 5].fill('a', -2, 2).should == [1, 2, 3, "a", "a"]
[1, 2, 3, 4, 5].fill('a', -2, 4).should == [1, 2, 3, "a", "a", "a", "a"]
[1, 2, 3, 4, 5].fill(-2, 2){|i| 'a'}.should == [1, 2, 3, "a", "a"]
[1, 2, 3, 4, 5].fill(-2, 4){|i| 'a'}.should == [1, 2, 3, "a", "a", "a", "a"]
end
it "starts at 0 if the negative index is before the start of the array" do
[1, 2, 3, 4, 5].fill('a', -25, 3).should == ['a', 'a', 'a', 4, 5]
[1, 2, 3, 4, 5].fill('a', -10, 10).should == %w|a a a a a a a a a a|
[1, 2, 3, 4, 5].fill(-25, 3){|i| 'a'}.should == ['a', 'a', 'a', 4, 5]
[1, 2, 3, 4, 5].fill(-10, 10){|i| 'a'}.should == %w|a a a a a a a a a a|
end
it "makes no modifications if the given length <= 0" do
[1, 2, 3, 4, 5].fill('a', 2, 0).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill('a', -2, 0).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill('a', 2, -2).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill('a', -2, -2).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill(2, 0, &@never_passed).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill(-2, 0, &@never_passed).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill(2, -2, &@never_passed).should == [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5].fill(-2, -2, &@never_passed).should == [1, 2, 3, 4, 5]
end
# See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/17481
it "does not raise an exception if the given length is negative and its absolute value does not exceed the index" do
lambda { [1, 2, 3, 4].fill('a', 3, -1)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill('a', 3, -2)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill('a', 3, -3)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill(3, -1, &@never_passed)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill(3, -2, &@never_passed)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill(3, -3, &@never_passed)}.should_not raise_error(ArgumentError)
end
it "does not raise an exception even if the given length is negative and its absolute value exceeds the index" do
lambda { [1, 2, 3, 4].fill('a', 3, -4)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill('a', 3, -5)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill('a', 3, -10000)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill(3, -4, &@never_passed)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill(3, -5, &@never_passed)}.should_not raise_error(ArgumentError)
lambda { [1, 2, 3, 4].fill(3, -10000, &@never_passed)}.should_not raise_error(ArgumentError)
end
it "tries to convert the second and third arguments to Integers using #to_int" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(2, 2)
filler = mock('filler')
filler.should_not_receive(:to_int)
[1, 2, 3, 4, 5].fill(filler, obj, obj).should == [1, 2, filler, filler, 5]
end
it "raises a TypeError if the index is not numeric" do
lambda { [].fill 'a', true }.should raise_error(TypeError)
obj = mock('nonnumeric')
lambda { [].fill('a', obj) }.should raise_error(TypeError)
end
not_supported_on :opal do
it "raises an ArgumentError or RangeError for too-large sizes" do
arr = [1, 2, 3]
lambda { arr.fill(10, 1, fixnum_max) }.should raise_error(ArgumentError)
lambda { arr.fill(10, 1, bignum_value) }.should raise_error(RangeError)
end
end
end
describe "Array#fill with (filler, range)" do
it "replaces elements in range with object" do
[1, 2, 3, 4, 5, 6].fill(8, 0..3).should == [8, 8, 8, 8, 5, 6]
[1, 2, 3, 4, 5, 6].fill(8, 0...3).should == [8, 8, 8, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', 4..6).should == [1, 2, 3, 4, 'x', 'x', 'x']
[1, 2, 3, 4, 5, 6].fill('x', 4...6).should == [1, 2, 3, 4, 'x', 'x']
[1, 2, 3, 4, 5, 6].fill('x', -2..-1).should == [1, 2, 3, 4, 'x', 'x']
[1, 2, 3, 4, 5, 6].fill('x', -2...-1).should == [1, 2, 3, 4, 'x', 6]
[1, 2, 3, 4, 5, 6].fill('x', -2...-2).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', -2..-2).should == [1, 2, 3, 4, 'x', 6]
[1, 2, 3, 4, 5, 6].fill('x', -2..0).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', 0...0).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', 1..1).should == [1, 'x', 3, 4, 5, 6]
end
it "replaces all elements in range with the value of block" do
[1, 1, 1, 1, 1, 1].fill(1..6) { |i| i + 1 }.should == [1, 2, 3, 4, 5, 6, 7]
end
it "increases the Array size when necessary" do
[1, 2, 3].fill('x', 1..6).should == [1, 'x', 'x', 'x', 'x', 'x', 'x']
[1, 2, 3].fill(1..6){|i| i+1}.should == [1, 2, 3, 4, 5, 6, 7]
end
it "raises a TypeError with range and length argument" do
lambda { [].fill('x', 0 .. 2, 5) }.should raise_error(TypeError)
end
it "replaces elements between the (-m)th to the last and the (n+1)th from the first if given an range m..n where m < 0 and n >= 0" do
[1, 2, 3, 4, 5, 6].fill('x', -4..4).should == [1, 2, 'x', 'x', 'x', 6]
[1, 2, 3, 4, 5, 6].fill('x', -4...4).should == [1, 2, 'x', 'x', 5, 6]
[1, 2, 3, 4, 5, 6].fill(-4..4){|i| (i+1).to_s}.should == [1, 2, '3', '4', '5', 6]
[1, 2, 3, 4, 5, 6].fill(-4...4){|i| (i+1).to_s}.should == [1, 2, '3', '4', 5, 6]
end
it "replaces elements between the (-m)th and (-n)th to the last if given an range m..n where m < 0 and n < 0" do
[1, 2, 3, 4, 5, 6].fill('x', -4..-2).should == [1, 2, 'x', 'x', 'x', 6]
[1, 2, 3, 4, 5, 6].fill('x', -4...-2).should == [1, 2, 'x', 'x', 5, 6]
[1, 2, 3, 4, 5, 6].fill(-4..-2){|i| (i+1).to_s}.should == [1, 2, '3', '4', '5', 6]
[1, 2, 3, 4, 5, 6].fill(-4...-2){|i| (i+1).to_s}.should == [1, 2, '3', '4', 5, 6]
end
it "replaces elements between the (m+1)th from the first and (-n)th to the last if given an range m..n where m >= 0 and n < 0" do
[1, 2, 3, 4, 5, 6].fill('x', 2..-2).should == [1, 2, 'x', 'x', 'x', 6]
[1, 2, 3, 4, 5, 6].fill('x', 2...-2).should == [1, 2, 'x', 'x', 5, 6]
[1, 2, 3, 4, 5, 6].fill(2..-2){|i| (i+1).to_s}.should == [1, 2, '3', '4', '5', 6]
[1, 2, 3, 4, 5, 6].fill(2...-2){|i| (i+1).to_s}.should == [1, 2, '3', '4', 5, 6]
end
it "makes no modifications if given an range which implies a section of zero width" do
[1, 2, 3, 4, 5, 6].fill('x', 2...2).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', -4...2).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', -4...-4).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', 2...-4).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(2...2, &@never_passed).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(-4...2, &@never_passed).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(-4...-4, &@never_passed).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(2...-4, &@never_passed).should == [1, 2, 3, 4, 5, 6]
end
it "makes no modifications if given an range which implies a section of negative width" do
[1, 2, 3, 4, 5, 6].fill('x', 2..1).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', -4..1).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', -2..-4).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill('x', 2..-5).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(2..1, &@never_passed).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(-4..1, &@never_passed).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(-2..-4, &@never_passed).should == [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].fill(2..-5, &@never_passed).should == [1, 2, 3, 4, 5, 6]
end
it "raises an exception if some of the given range lies before the first of the array" do
lambda { [1, 2, 3].fill('x', -5..-3) }.should raise_error(RangeError)
lambda { [1, 2, 3].fill('x', -5...-3) }.should raise_error(RangeError)
lambda { [1, 2, 3].fill('x', -5..-4) }.should raise_error(RangeError)
lambda { [1, 2, 3].fill(-5..-3, &@never_passed) }.should raise_error(RangeError)
lambda { [1, 2, 3].fill(-5...-3, &@never_passed) }.should raise_error(RangeError)
lambda { [1, 2, 3].fill(-5..-4, &@never_passed) }.should raise_error(RangeError)
end
it "tries to convert the start and end of the passed range to Integers using #to_int" do
obj = mock('to_int')
def obj.<=>(rhs); rhs == self ? 0 : nil end
obj.should_receive(:to_int).twice.and_return(2)
filler = mock('filler')
filler.should_not_receive(:to_int)
[1, 2, 3, 4, 5].fill(filler, obj..obj).should == [1, 2, filler, 4, 5]
end
it "raises a TypeError if the start or end of the passed range is not numeric" do
obj = mock('nonnumeric')
def obj.<=>(rhs); rhs == self ? 0 : nil end
lambda { [].fill('a', obj..obj) }.should raise_error(TypeError)
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/index', __FILE__)
describe "Array#find_index" do
it_behaves_like :array_index, :find_index
end

View file

@ -0,0 +1,93 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#first" do
it "returns the first element" do
%w{a b c}.first.should == 'a'
[nil].first.should == nil
end
it "returns nil if self is empty" do
[].first.should == nil
end
it "returns the first count elements if given a count" do
[true, false, true, nil, false].first(2).should == [true, false]
end
it "returns an empty array when passed count on an empty array" do
[].first(0).should == []
[].first(1).should == []
[].first(2).should == []
end
it "returns an empty array when passed count == 0" do
[1, 2, 3, 4, 5].first(0).should == []
end
it "returns an array containing the first element when passed count == 1" do
[1, 2, 3, 4, 5].first(1).should == [1]
end
it "raises an ArgumentError when count is negative" do
lambda { [1, 2].first(-1) }.should raise_error(ArgumentError)
end
it "raises a RangeError when count is a Bignum" do
lambda { [].first(bignum_value) }.should raise_error(RangeError)
end
it "returns the entire array when count > length" do
[1, 2, 3, 4, 5, 9].first(10).should == [1, 2, 3, 4, 5, 9]
end
it "returns an array which is independent to the original when passed count" do
ary = [1, 2, 3, 4, 5]
ary.first(0).replace([1,2])
ary.should == [1, 2, 3, 4, 5]
ary.first(1).replace([1,2])
ary.should == [1, 2, 3, 4, 5]
ary.first(6).replace([1,2])
ary.should == [1, 2, 3, 4, 5]
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.first.should equal(empty)
ary = ArraySpecs.head_recursive_array
ary.first.should equal(ary)
end
it "tries to convert the passed argument to an Integer using #to_int" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(2)
[1, 2, 3, 4, 5].first(obj).should == [1, 2]
end
it "raises a TypeError if the passed argument is not numeric" do
lambda { [1,2].first(nil) }.should raise_error(TypeError)
lambda { [1,2].first("a") }.should raise_error(TypeError)
obj = mock("nonnumeric")
lambda { [1,2].first(obj) }.should raise_error(TypeError)
end
it "does not return subclass instance when passed count on Array subclasses" do
ArraySpecs::MyArray[].first(0).should be_an_instance_of(Array)
ArraySpecs::MyArray[].first(2).should be_an_instance_of(Array)
ArraySpecs::MyArray[1, 2, 3].first(0).should be_an_instance_of(Array)
ArraySpecs::MyArray[1, 2, 3].first(1).should be_an_instance_of(Array)
ArraySpecs::MyArray[1, 2, 3].first(2).should be_an_instance_of(Array)
end
it "is not destructive" do
a = [1, 2, 3]
a.first
a.should == [1, 2, 3]
a.first(2)
a.should == [1, 2, 3]
a.first(3)
a.should == [1, 2, 3]
end
end

View file

@ -0,0 +1,525 @@
class Object
# This helper is defined here rather than in MSpec because
# it is only used in #pack specs.
def pack_format(count=nil, repeat=nil)
format = "#{instance_variable_get(:@method)}#{count}"
format *= repeat if repeat
format
end
end
module ArraySpecs
SampleRange = 0..1000
SampleCount = 1000
def self.frozen_array
frozen_array = [1,2,3]
frozen_array.freeze
frozen_array
end
def self.empty_frozen_array
frozen_array = []
frozen_array.freeze
frozen_array
end
def self.recursive_array
a = [1, 'two', 3.0]
5.times { a << a }
a
end
def self.head_recursive_array
a = []
5.times { a << a }
a << 1 << 'two' << 3.0
a
end
def self.empty_recursive_array
a = []
a << a
a
end
class MyArray < Array
# The #initialize method has a different signature than Array to help
# catch places in the specs that do not assert the #initialize is not
# called when Array methods make new instances.
def initialize(a, b)
self << a << b
ScratchPad.record :my_array_initialize
end
end
class Sexp < Array
def initialize(*args)
super(args)
end
end
# TODO: replace specs that use this with #should_not_receive(:to_ary)
# expectations on regular objects (e.g. Array instances).
class ToAryArray < Array
def to_ary() ["to_ary", "was", "called!"] end
end
class MyRange < Range; end
class AssocKey
def ==(other); other == 'it'; end
end
class D
def <=>(obj)
return 4 <=> obj unless obj.class == D
0
end
end
class SubArray < Array
def initialize(*args)
ScratchPad.record args
end
end
class ArrayConvertable
attr_accessor :called
def initialize(*values, &block)
@values = values;
end
def to_a
self.called = :to_a
@values
end
def to_ary
self.called = :to_ary
@values
end
end
class SortSame
def <=>(other); 0; end
def ==(other); true; end
end
class UFOSceptic
def <=>(other); raise "N-uh, UFO:s do not exist!"; end
end
class MockForCompared
@@count = 0
@@compared = false
def initialize
@@compared = false
@order = (@@count += 1)
end
def <=>(rhs)
@@compared = true
return rhs.order <=> self.order
end
def self.compared?
@@compared
end
protected
attr_accessor :order
end
class ComparableWithFixnum
include Comparable
def initialize(num)
@num = num
end
def <=>(fixnum)
@num <=> fixnum
end
end
class Uncomparable
def <=>(obj)
nil
end
end
def self.universal_pack_object
obj = mock("string float int")
obj.stub!(:to_int).and_return(1)
obj.stub!(:to_str).and_return("1")
obj.stub!(:to_f).and_return(1.0)
obj
end
LargeArray = ["test_create_table_with_force_true_does_not_drop_nonexisting_table",
"test_add_table",
"assert_difference",
"assert_operator",
"instance_variables",
"class",
"instance_variable_get",
"__class__",
"expects",
"assert_no_difference",
"name",
"assert_blank",
"assert_not_same",
"is_a?",
"test_add_table_with_decimals",
"test_create_table_with_timestamps_should_create_datetime_columns",
"assert_present",
"assert_no_match",
"__instance_of__",
"assert_deprecated",
"assert",
"assert_throws",
"kind_of?",
"try",
"__instance_variable_get__",
"object_id",
"timeout",
"instance_variable_set",
"assert_nothing_thrown",
"__instance_variable_set__",
"copy_object",
"test_create_table_with_timestamps_should_create_datetime_columns_with_options",
"assert_not_deprecated",
"assert_in_delta",
"id",
"copy_metaclass",
"test_create_table_without_a_block",
"dup",
"assert_not_nil",
"send",
"__instance_variables__",
"to_sql",
"mock",
"assert_send",
"instance_variable_defined?",
"clone",
"require",
"test_migrator",
"__instance_variable_defined_eh__",
"frozen?",
"test_add_column_not_null_with_default",
"freeze",
"test_migrator_one_up",
"test_migrator_one_down",
"singleton_methods",
"method_exists?",
"create_fixtures",
"test_migrator_one_up_one_down",
"test_native_decimal_insert_manual_vs_automatic",
"instance_exec",
"__is_a__",
"test_migrator_double_up",
"stub",
"private_methods",
"stubs",
"test_migrator_double_down",
"fixture_path",
"private_singleton_methods",
"stub_everything",
"test_migrator_one_up_with_exception_and_rollback",
"sequence",
"protected_methods",
"enum_for",
"test_finds_migrations",
"run_before_mocha",
"states",
"protected_singleton_methods",
"to_json",
"instance_values",
"==",
"mocha_setup",
"public_methods",
"test_finds_pending_migrations",
"mocha_verify",
"assert_kind_of",
"===",
"=~",
"test_relative_migrations",
"mocha_teardown",
"gem",
"mocha",
"test_only_loads_pending_migrations",
"test_add_column_with_precision_and_scale",
"require_or_load",
"eql?",
"require_dependency",
"test_native_types",
"test_target_version_zero_should_run_only_once",
"extend",
"to_matcher",
"unloadable",
"require_association",
"hash",
"__id__",
"load_dependency",
"equals",
"test_migrator_db_has_no_schema_migrations_table",
"test_migrator_verbosity",
"kind_of",
"to_yaml",
"to_bool",
"test_migrator_verbosity_off",
"taint",
"test_migrator_going_down_due_to_version_target",
"tainted?",
"mocha_inspect",
"test_migrator_rollback",
"vim",
"untaint",
"taguri=",
"test_migrator_forward",
"test_schema_migrations_table_name",
"test_proper_table_name",
"all_of",
"test_add_drop_table_with_prefix_and_suffix",
"_setup_callbacks",
"setup",
"Not",
"test_create_table_with_binary_column",
"assert_not_equal",
"enable_warnings",
"acts_like?",
"Rational",
"_removed_setup_callbacks",
"Table",
"bind",
"any_of",
"__method__",
"test_migrator_with_duplicates",
"_teardown_callbacks",
"method",
"test_migrator_with_duplicate_names",
"_removed_teardown_callbacks",
"any_parameters",
"test_migrator_with_missing_version_numbers",
"test_add_remove_single_field_using_string_arguments",
"test_create_table_with_custom_sequence_name",
"test_add_remove_single_field_using_symbol_arguments",
"_one_time_conditions_valid_14?",
"_one_time_conditions_valid_16?",
"run_callbacks",
"anything",
"silence_warnings",
"instance_variable_names",
"_fixture_path",
"copy_instance_variables_from",
"fixture_path?",
"has_entry",
"__marshal__",
"_fixture_table_names",
"__kind_of__",
"fixture_table_names?",
"test_add_rename",
"assert_equal",
"_fixture_class_names",
"fixture_class_names?",
"has_entries",
"_use_transactional_fixtures",
"people",
"test_rename_column_using_symbol_arguments",
"use_transactional_fixtures?",
"instance_eval",
"blank?",
"with_warnings",
"__nil__",
"load",
"metaclass",
"_use_instantiated_fixtures",
"has_key",
"class_eval",
"present?",
"test_rename_column",
"teardown",
"use_instantiated_fixtures?",
"method_name",
"silence_stderr",
"presence",
"test_rename_column_preserves_default_value_not_null",
"silence_stream",
"_pre_loaded_fixtures",
"__metaclass__",
"__fixnum__",
"pre_loaded_fixtures?",
"has_value",
"suppress",
"to_yaml_properties",
"test_rename_nonexistent_column",
"test_add_index",
"includes",
"find_correlate_in",
"equality_predicate_sql",
"assert_nothing_raised",
"let",
"not_predicate_sql",
"test_rename_column_with_sql_reserved_word",
"singleton_class",
"test_rename_column_with_an_index",
"display",
"taguri",
"to_yaml_style",
"test_remove_column_with_index",
"size",
"current_adapter?",
"test_remove_column_with_multi_column_index",
"respond_to?",
"test_change_type_of_not_null_column",
"is_a",
"to_a",
"test_rename_table_for_sqlite_should_work_with_reserved_words",
"require_library_or_gem",
"setup_fixtures",
"equal?",
"teardown_fixtures",
"nil?",
"fixture_table_names",
"fixture_class_names",
"test_create_table_without_id",
"use_transactional_fixtures",
"test_add_column_with_primary_key_attribute",
"repair_validations",
"use_instantiated_fixtures",
"instance_of?",
"test_create_table_adds_id",
"test_rename_table",
"pre_loaded_fixtures",
"to_enum",
"test_create_table_with_not_null_column",
"instance_of",
"test_change_column_nullability",
"optionally",
"test_rename_table_with_an_index",
"run",
"test_change_column",
"default_test",
"assert_raise",
"test_create_table_with_defaults",
"assert_nil",
"flunk",
"regexp_matches",
"duplicable?",
"reset_mocha",
"stubba_method",
"filter_backtrace",
"test_create_table_with_limits",
"responds_with",
"stubba_object",
"test_change_column_with_nil_default",
"assert_block",
"__show__",
"assert_date_from_db",
"__respond_to_eh__",
"run_in_transaction?",
"inspect",
"assert_sql",
"test_change_column_with_new_default",
"yaml_equivalent",
"build_message",
"to_s",
"test_change_column_default",
"assert_queries",
"pending",
"as_json",
"assert_no_queries",
"test_change_column_quotes_column_names",
"assert_match",
"test_keeping_default_and_notnull_constaint_on_change",
"methods",
"connection_allow_concurrency_setup",
"connection_allow_concurrency_teardown",
"test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
"__send__",
"make_connection",
"assert_raises",
"tap",
"with_kcode",
"assert_instance_of",
"test_create_table_with_primary_key_prefix_as_table_name",
"assert_respond_to",
"test_change_column_default_to_null",
"assert_same",
"__extend__"]
LargeTestArraySorted = ["test_add_column_not_null_with_default",
"test_add_column_with_precision_and_scale",
"test_add_column_with_primary_key_attribute",
"test_add_drop_table_with_prefix_and_suffix",
"test_add_index",
"test_add_remove_single_field_using_string_arguments",
"test_add_remove_single_field_using_symbol_arguments",
"test_add_rename",
"test_add_table",
"test_add_table_with_decimals",
"test_change_column",
"test_change_column_default",
"test_change_column_default_to_null",
"test_change_column_nullability",
"test_change_column_quotes_column_names",
"test_change_column_with_new_default",
"test_change_column_with_nil_default",
"test_change_type_of_not_null_column",
"test_create_table_adds_id",
"test_create_table_with_binary_column",
"test_create_table_with_custom_sequence_name",
"test_create_table_with_defaults",
"test_create_table_with_force_true_does_not_drop_nonexisting_table",
"test_create_table_with_limits",
"test_create_table_with_not_null_column",
"test_create_table_with_primary_key_prefix_as_table_name",
"test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
"test_create_table_with_timestamps_should_create_datetime_columns",
"test_create_table_with_timestamps_should_create_datetime_columns_with_options",
"test_create_table_without_a_block",
"test_create_table_without_id",
"test_finds_migrations",
"test_finds_pending_migrations",
"test_keeping_default_and_notnull_constaint_on_change",
"test_migrator",
"test_migrator_db_has_no_schema_migrations_table",
"test_migrator_double_down",
"test_migrator_double_up",
"test_migrator_forward",
"test_migrator_going_down_due_to_version_target",
"test_migrator_one_down",
"test_migrator_one_up",
"test_migrator_one_up_one_down",
"test_migrator_one_up_with_exception_and_rollback",
"test_migrator_rollback",
"test_migrator_verbosity",
"test_migrator_verbosity_off",
"test_migrator_with_duplicate_names",
"test_migrator_with_duplicates",
"test_migrator_with_missing_version_numbers",
"test_native_decimal_insert_manual_vs_automatic",
"test_native_types",
"test_only_loads_pending_migrations",
"test_proper_table_name",
"test_relative_migrations",
"test_remove_column_with_index",
"test_remove_column_with_multi_column_index",
"test_rename_column",
"test_rename_column_preserves_default_value_not_null",
"test_rename_column_using_symbol_arguments",
"test_rename_column_with_an_index",
"test_rename_column_with_sql_reserved_word",
"test_rename_nonexistent_column",
"test_rename_table",
"test_rename_table_for_sqlite_should_work_with_reserved_words",
"test_rename_table_with_an_index",
"test_schema_migrations_table_name",
"test_target_version_zero_should_run_only_once"]
class PrivateToAry
private
def to_ary
[1, 2, 3]
end
end
end

View file

@ -0,0 +1,69 @@
# encoding: utf-8
module ArraySpecs
def self.array_with_usascii_and_7bit_utf8_strings
[
'foo'.force_encoding('US-ASCII'),
'bar'
]
end
def self.array_with_usascii_and_utf8_strings
[
'foo'.force_encoding('US-ASCII'),
'báz'
]
end
def self.array_with_7bit_utf8_and_usascii_strings
[
'bar',
'foo'.force_encoding('US-ASCII')
]
end
def self.array_with_utf8_and_usascii_strings
[
'báz',
'bar',
'foo'.force_encoding('US-ASCII')
]
end
def self.array_with_usascii_and_utf8_strings
[
'foo'.force_encoding('US-ASCII'),
'bar',
'báz'
]
end
def self.array_with_utf8_and_7bit_ascii8bit_strings
[
'bar',
'báz',
'foo'.force_encoding('ASCII-8BIT')
]
end
def self.array_with_utf8_and_ascii8bit_strings
[
'bar',
'báz',
[255].pack('C').force_encoding('ASCII-8BIT')
]
end
def self.array_with_usascii_and_7bit_ascii8bit_strings
[
'bar'.force_encoding('US-ASCII'),
'foo'.force_encoding('ASCII-8BIT')
]
end
def self.array_with_usascii_and_ascii8bit_strings
[
'bar'.force_encoding('US-ASCII'),
[255].pack('C').force_encoding('ASCII-8BIT')
]
end
end

View file

@ -0,0 +1,270 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#flatten" do
it "returns a one-dimensional flattening recursively" do
[[[1, [2, 3]],[2, 3, [4, [4, [5, 5]], [1, 2, 3]]], [4]], []].flatten.should == [1, 2, 3, 2, 3, 4, 4, 5, 5, 1, 2, 3, 4]
end
it "takes an optional argument that determines the level of recursion" do
[ 1, 2, [3, [4, 5] ] ].flatten(1).should == [1, 2, 3, [4, 5]]
end
it "returns dup when the level of recursion is 0" do
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(0).should == a
a.flatten(0).should_not equal(a)
end
it "ignores negative levels" do
[ 1, 2, [ 3, 4, [5, 6] ] ].flatten(-1).should == [1, 2, 3, 4, 5, 6]
[ 1, 2, [ 3, 4, [5, 6] ] ].flatten(-10).should == [1, 2, 3, 4, 5, 6]
end
it "tries to convert passed Objects to Integers using #to_int" do
obj = mock("Converted to Integer")
obj.should_receive(:to_int).and_return(1)
[ 1, 2, [3, [4, 5] ] ].flatten(obj).should == [1, 2, 3, [4, 5]]
end
it "raises a TypeError when the passed Object can't be converted to an Integer" do
obj = mock("Not converted")
lambda { [ 1, 2, [3, [4, 5] ] ].flatten(obj) }.should raise_error(TypeError)
end
it "does not call flatten on elements" do
obj = mock('[1,2]')
obj.should_not_receive(:flatten)
[obj, obj].flatten.should == [obj, obj]
obj = [5, 4]
obj.should_not_receive(:flatten)
[obj, obj].flatten.should == [5, 4, 5, 4]
end
it "raises an ArgumentError on recursive arrays" do
x = []
x << x
lambda { x.flatten }.should raise_error(ArgumentError)
x = []
y = []
x << y
y << x
lambda { x.flatten }.should raise_error(ArgumentError)
end
it "flattens any element which responds to #to_ary, using the return value of said method" do
x = mock("[3,4]")
x.should_receive(:to_ary).at_least(:once).and_return([3, 4])
[1, 2, x, 5].flatten.should == [1, 2, 3, 4, 5]
y = mock("MyArray[]")
y.should_receive(:to_ary).at_least(:once).and_return(ArraySpecs::MyArray[])
[y].flatten.should == []
z = mock("[2,x,y,5]")
z.should_receive(:to_ary).and_return([2, x, y, 5])
[1, z, 6].flatten.should == [1, 2, 3, 4, 5, 6]
end
ruby_version_is "2.3" do
it "does not call #to_ary on elements beyond the given level" do
obj = mock("1")
obj.should_not_receive(:to_ary)
[[obj]].flatten(1)
end
end
it "returns subclass instance for Array subclasses" do
ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray)
ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4]
[ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
end
it "is not destructive" do
ary = [1, [2, 3]]
ary.flatten
ary.should == [1, [2, 3]]
end
describe "with a non-Array object in the Array" do
before :each do
@obj = mock("Array#flatten")
ScratchPad.record []
end
it "does not call #to_ary if the method is not defined" do
[@obj].flatten.should == [@obj]
end
it "does not raise an exception if #to_ary returns nil" do
@obj.should_receive(:to_ary).and_return(nil)
[@obj].flatten.should == [@obj]
end
it "raises a TypeError if #to_ary does not return an Array" do
@obj.should_receive(:to_ary).and_return(1)
lambda { [@obj].flatten }.should raise_error(TypeError)
end
it "does not call #to_ary if not defined when #respond_to_missing? returns false" do
def @obj.respond_to_missing?(*args) ScratchPad << args; false end
[@obj].flatten.should == [@obj]
ScratchPad.recorded.should == [[:to_ary, false]]
end
it "calls #to_ary if not defined when #respond_to_missing? returns true" do
def @obj.respond_to_missing?(*args) ScratchPad << args; true end
lambda { [@obj].flatten }.should raise_error(NoMethodError)
ScratchPad.recorded.should == [[:to_ary, false]]
end
it "calls #method_missing if defined" do
@obj.should_receive(:method_missing).with(:to_ary).and_return([1, 2, 3])
[@obj].flatten.should == [1, 2, 3]
end
end
it "returns a tainted array if self is tainted" do
[].taint.flatten.tainted?.should be_true
end
it "returns an untrusted array if self is untrusted" do
[].untrust.flatten.untrusted?.should be_true
end
it "performs respond_to? and method_missing-aware checks when coercing elements to array" do
bo = BasicObject.new
[bo].flatten.should == [bo]
def bo.method_missing(name, *)
[1,2]
end
[bo].flatten.should == [1,2]
def bo.respond_to?(name, *)
false
end
[bo].flatten.should == [bo]
def bo.respond_to?(name, *)
true
end
[bo].flatten.should == [1,2]
end
end
describe "Array#flatten!" do
it "modifies array to produce a one-dimensional flattening recursively" do
a = [[[1, [2, 3]],[2, 3, [4, [4, [5, 5]], [1, 2, 3]]], [4]], []]
a.flatten!
a.should == [1, 2, 3, 2, 3, 4, 4, 5, 5, 1, 2, 3, 4]
end
it "returns self if made some modifications" do
a = [[[1, [2, 3]],[2, 3, [4, [4, [5, 5]], [1, 2, 3]]], [4]], []]
a.flatten!.should equal(a)
end
it "returns nil if no modifications took place" do
a = [1, 2, 3]
a.flatten!.should == nil
a = [1, [2, 3]]
a.flatten!.should_not == nil
end
it "should not check modification by size" do
a = [1, 2, [3]]
a.flatten!.should_not == nil
a.should == [1, 2, 3]
end
it "takes an optional argument that determines the level of recursion" do
[ 1, 2, [3, [4, 5] ] ].flatten!(1).should == [1, 2, 3, [4, 5]]
end
# redmine #1440
it "returns nil when the level of recursion is 0" do
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten!(0).should == nil
end
it "treats negative levels as no arguments" do
[ 1, 2, [ 3, 4, [5, 6] ] ].flatten!(-1).should == [1, 2, 3, 4, 5, 6]
[ 1, 2, [ 3, 4, [5, 6] ] ].flatten!(-10).should == [1, 2, 3, 4, 5, 6]
end
it "tries to convert passed Objects to Integers using #to_int" do
obj = mock("Converted to Integer")
obj.should_receive(:to_int).and_return(1)
[ 1, 2, [3, [4, 5] ] ].flatten!(obj).should == [1, 2, 3, [4, 5]]
end
it "raises a TypeError when the passed Object can't be converted to an Integer" do
obj = mock("Not converted")
lambda { [ 1, 2, [3, [4, 5] ] ].flatten!(obj) }.should raise_error(TypeError)
end
it "does not call flatten! on elements" do
obj = mock('[1,2]')
obj.should_not_receive(:flatten!)
[obj, obj].flatten!.should == nil
obj = [5, 4]
obj.should_not_receive(:flatten!)
[obj, obj].flatten!.should == [5, 4, 5, 4]
end
it "raises an ArgumentError on recursive arrays" do
x = []
x << x
lambda { x.flatten! }.should raise_error(ArgumentError)
x = []
y = []
x << y
y << x
lambda { x.flatten! }.should raise_error(ArgumentError)
end
it "flattens any elements which responds to #to_ary, using the return value of said method" do
x = mock("[3,4]")
x.should_receive(:to_ary).at_least(:once).and_return([3, 4])
[1, 2, x, 5].flatten!.should == [1, 2, 3, 4, 5]
y = mock("MyArray[]")
y.should_receive(:to_ary).at_least(:once).and_return(ArraySpecs::MyArray[])
[y].flatten!.should == []
z = mock("[2,x,y,5]")
z.should_receive(:to_ary).and_return([2, x, y, 5])
[1, z, 6].flatten!.should == [1, 2, 3, 4, 5, 6]
ary = [ArraySpecs::MyArray[1, 2, 3]]
ary.flatten!
ary.should be_an_instance_of(Array)
ary.should == [1, 2, 3]
end
it "raises a RuntimeError on frozen arrays when the array is modified" do
nested_ary = [1, 2, []]
nested_ary.freeze
lambda { nested_ary.flatten! }.should raise_error(RuntimeError)
end
# see [ruby-core:23663]
it "raises a RuntimeError on frozen arrays when the array would not be modified" do
lambda { ArraySpecs.frozen_array.flatten! }.should raise_error(RuntimeError)
lambda { ArraySpecs.empty_frozen_array.flatten! }.should raise_error(RuntimeError)
end
end

View file

@ -0,0 +1,16 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#frozen?" do
it "returns true if array is frozen" do
a = [1, 2, 3]
a.frozen?.should == false
a.freeze
a.frozen?.should == true
end
it "returns false for an array being sorted by #sort" do
a = [1, 2, 3]
a.sort { |x,y| a.frozen?.should == false; x <=> y }
end
end

View file

@ -0,0 +1,83 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#hash" do
it "returns the same fixnum for arrays with the same content" do
[].respond_to?(:hash).should == true
[[], [1, 2, 3]].each do |ary|
ary.hash.should == ary.dup.hash
ary.hash.should be_an_instance_of(Fixnum)
end
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
lambda { empty.hash }.should_not raise_error
array = ArraySpecs.recursive_array
lambda { array.hash }.should_not raise_error
end
it "returns the same hash for equal recursive arrays" do
rec = []; rec << rec
rec.hash.should == [rec].hash
rec.hash.should == [[rec]].hash
# This is because rec.eql?([[rec]])
# Remember that if two objects are eql?
# then the need to have the same hash
# Check the Array#eql? specs!
end
it "returns the same hash for equal recursive arrays through hashes" do
h = {} ; rec = [h] ; h[:x] = rec
rec.hash.should == [h].hash
rec.hash.should == [{x: rec}].hash
# Like above, this is because rec.eql?([{x: rec}])
end
it "calls to_int on result of calling hash on each element" do
ary = Array.new(5) do
obj = mock('0')
obj.should_receive(:hash).and_return(obj)
obj.should_receive(:to_int).and_return(0)
obj
end
ary.hash
hash = mock('1')
hash.should_receive(:to_int).and_return(1.hash)
obj = mock('@hash')
obj.instance_variable_set(:@hash, hash)
def obj.hash() @hash end
[obj].hash.should == [1].hash
end
it "ignores array class differences" do
ArraySpecs::MyArray[].hash.should == [].hash
ArraySpecs::MyArray[1, 2].hash.should == [1, 2].hash
end
it "returns same hash code for arrays with the same content" do
a = [1, 2, 3, 4]
a.fill 'a', 0..3
b = %w|a a a a|
a.hash.should == b.hash
end
it "returns the same value if arrays are #eql?" do
a = [1, 2, 3, 4]
a.fill 'a', 0..3
b = %w|a a a a|
a.hash.should == b.hash
a.should eql(b)
end
it "produces different hashes for nested arrays with different values and empty terminator" do
[1, [1, []]].hash.should_not == [2, [2, []]].hash
end
end

View file

@ -0,0 +1,33 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#include?" do
it "returns true if object is present, false otherwise" do
[1, 2, "a", "b"].include?("c").should == false
[1, 2, "a", "b"].include?("a").should == true
end
it "determines presence by using element == obj" do
o = mock('')
[1, 2, "a", "b"].include?(o).should == false
def o.==(other); other == 'a'; end
[1, 2, o, "b"].include?('a').should == true
[1, 2.0, 3].include?(2).should == true
end
it "calls == on elements from left to right until success" do
key = "x"
one = mock('one')
two = mock('two')
three = mock('three')
one.should_receive(:==).any_number_of_times.and_return(false)
two.should_receive(:==).any_number_of_times.and_return(true)
three.should_not_receive(:==)
ary = [one, two, three]
ary.include?(key).should == true
end
end

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/index', __FILE__)
describe "Array#index" do
it_behaves_like(:array_index, :index)
end

Some files were not shown because too many files have changed in this diff Show more