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,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

View file

@ -0,0 +1,156 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#initialize" do
before :each do
ScratchPad.clear
end
it "is private" do
Array.should have_private_instance_method("initialize")
end
it "is called on subclasses" do
b = ArraySpecs::SubArray.new :size_or_array, :obj
b.should == []
ScratchPad.recorded.should == [:size_or_array, :obj]
end
it "preserves the object's identity even when changing its value" do
a = [1, 2, 3]
a.send(:initialize).should equal(a)
a.should_not == [1, 2, 3]
end
it "raises an ArgumentError if passed 3 or more arguments" do
lambda do
[1, 2].send :initialize, 1, 'x', true
end.should raise_error(ArgumentError)
lambda do
[1, 2].send(:initialize, 1, 'x', true) {}
end.should raise_error(ArgumentError)
end
it "raises a RuntimeError on frozen arrays" do
lambda do
ArraySpecs.frozen_array.send :initialize
end.should raise_error(RuntimeError)
lambda do
ArraySpecs.frozen_array.send :initialize, ArraySpecs.frozen_array
end.should raise_error(RuntimeError)
end
it "calls #to_ary to convert the value to an array, even if it's private" do
a = ArraySpecs::PrivateToAry.new
[].send(:initialize, a).should == [1, 2, 3]
end
end
describe "Array#initialize with no arguments" do
it "makes the array empty" do
[1, 2, 3].send(:initialize).should be_empty
end
it "does not use the given block" do
lambda{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
end
end
describe "Array#initialize with (array)" do
it "replaces self with the other array" do
b = [4, 5, 6]
[1, 2, 3].send(:initialize, b).should == b
end
it "does not use the given block" do
lambda{ [1, 2, 3].send(:initialize) { raise } }.should_not raise_error
end
it "calls #to_ary to convert the value to an array" do
a = mock("array")
a.should_receive(:to_ary).and_return([1, 2])
a.should_not_receive(:to_int)
[].send(:initialize, a).should == [1, 2]
end
it "does not call #to_ary on instances of Array or subclasses of Array" do
a = [1, 2]
a.should_not_receive(:to_ary)
[].send(:initialize, a).should == a
end
it "raises a TypeError if an Array type argument and a default object" do
lambda { [].send(:initialize, [1, 2], 1) }.should raise_error(TypeError)
end
end
describe "Array#initialize with (size, object=nil)" do
it "sets the array to size and fills with the object" do
a = []
obj = [3]
a.send(:initialize, 2, obj).should == [obj, obj]
a[0].should equal(obj)
a[1].should equal(obj)
b = []
b.send(:initialize, 3, 14).should == [14, 14, 14]
b.should == [14, 14, 14]
end
it "sets the array to size and fills with nil when object is omitted" do
[].send(:initialize, 3).should == [nil, nil, nil]
end
it "raises an ArgumentError if size is negative" do
lambda { [].send(:initialize, -1, :a) }.should raise_error(ArgumentError)
lambda { [].send(:initialize, -1) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if size is too large" do
lambda { [].send(:initialize, fixnum_max+1) }.should raise_error(ArgumentError)
end
it "calls #to_int to convert the size argument to an Integer when object is given" do
obj = mock('1')
obj.should_receive(:to_int).and_return(1)
[].send(:initialize, obj, :a).should == [:a]
end
it "calls #to_int to convert the size argument to an Integer when object is not given" do
obj = mock('1')
obj.should_receive(:to_int).and_return(1)
[].send(:initialize, obj).should == [nil]
end
it "raises a TypeError if the size argument is not an Integer type" do
obj = mock('nonnumeric')
obj.stub!(:to_ary).and_return([1, 2])
lambda{ [].send(:initialize, obj, :a) }.should raise_error(TypeError)
end
it "yields the index of the element and sets the element to the value of the block" do
[].send(:initialize, 3) { |i| i.to_s }.should == ['0', '1', '2']
end
it "uses the block value instead of using the default value" do
lambda {
@result = [].send(:initialize, 3, :obj) { |i| i.to_s }
}.should complain(/block supersedes default value argument/)
@result.should == ['0', '1', '2']
end
it "returns the value passed to break" do
[].send(:initialize, 3) { break :a }.should == :a
end
it "sets the array to the values returned by the block before break is executed" do
a = [1, 2, 3]
a.send(:initialize, 3) do |i|
break if i == 2
i.to_s
end
a.should == ['0', '1']
end
end

View file

@ -0,0 +1,78 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#insert" do
it "returns self" do
ary = []
ary.insert(0).should equal(ary)
ary.insert(0, :a).should equal(ary)
end
it "inserts objects before the element at index for non-negative index" do
ary = []
ary.insert(0, 3).should == [3]
ary.insert(0, 1, 2).should == [1, 2, 3]
ary.insert(0).should == [1, 2, 3]
# Let's just assume insert() always modifies the array from now on.
ary.insert(1, 'a').should == [1, 'a', 2, 3]
ary.insert(0, 'b').should == ['b', 1, 'a', 2, 3]
ary.insert(5, 'c').should == ['b', 1, 'a', 2, 3, 'c']
ary.insert(7, 'd').should == ['b', 1, 'a', 2, 3, 'c', nil, 'd']
ary.insert(10, 5, 4).should == ['b', 1, 'a', 2, 3, 'c', nil, 'd', nil, nil, 5, 4]
end
it "appends objects to the end of the array for index == -1" do
[1, 3, 3].insert(-1, 2, 'x', 0.5).should == [1, 3, 3, 2, 'x', 0.5]
end
it "inserts objects after the element at index with negative index" do
ary = []
ary.insert(-1, 3).should == [3]
ary.insert(-2, 2).should == [2, 3]
ary.insert(-3, 1).should == [1, 2, 3]
ary.insert(-2, -3).should == [1, 2, -3, 3]
ary.insert(-1, []).should == [1, 2, -3, 3, []]
ary.insert(-2, 'x', 'y').should == [1, 2, -3, 3, 'x', 'y', []]
ary = [1, 2, 3]
end
it "pads with nils if the index to be inserted to is past the end" do
[].insert(5, 5).should == [nil, nil, nil, nil, nil, 5]
end
it "can insert before the first element with a negative index" do
[1, 2, 3].insert(-4, -3).should == [-3, 1, 2, 3]
end
it "raises an IndexError if the negative index is out of bounds" do
lambda { [].insert(-2, 1) }.should raise_error(IndexError)
lambda { [1].insert(-3, 2) }.should raise_error(IndexError)
end
it "does nothing of no object is passed" do
[].insert(0).should == []
[].insert(-1).should == []
[].insert(10).should == []
[].insert(-2).should == []
end
it "tries to convert the passed position argument to an Integer using #to_int" do
obj = mock('2')
obj.should_receive(:to_int).and_return(2)
[].insert(obj, 'x').should == [nil, nil, 'x']
end
it "raises an ArgumentError if no argument passed" do
lambda { [].insert() }.should raise_error(ArgumentError)
end
it "raises a RuntimeError on frozen arrays when the array is modified" do
lambda { ArraySpecs.frozen_array.insert(0, 'x') }.should raise_error(RuntimeError)
end
# see [ruby-core:23666]
it "raises a RuntimeError on frozen arrays when the array would not be modified" do
lambda { ArraySpecs.frozen_array.insert(0) }.should raise_error(RuntimeError)
end
end

View file

@ -0,0 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/inspect', __FILE__)
describe "Array#inspect" do
it_behaves_like :array_inspect, :inspect
end

View file

@ -0,0 +1,86 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#&" do
it "creates an array with elements common to both arrays (intersection)" do
([] & []).should == []
([1, 2] & []).should == []
([] & [1, 2]).should == []
([ 1, 3, 5 ] & [ 1, 2, 3 ]).should == [1, 3]
end
it "creates an array with no duplicates" do
([ 1, 1, 3, 5 ] & [ 1, 2, 3 ]).uniq!.should == nil
end
it "creates an array with elements in order they are first encountered" do
([ 1, 2, 3, 2, 5 ] & [ 5, 2, 3, 4 ]).should == [2, 3, 5]
end
it "does not modify the original Array" do
a = [1, 1, 3, 5]
a & [1, 2, 3]
a.should == [1, 1, 3, 5]
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
(empty & empty).should == empty
(ArraySpecs.recursive_array & []).should == []
([] & ArraySpecs.recursive_array).should == []
(ArraySpecs.recursive_array & ArraySpecs.recursive_array).should == [1, 'two', 3.0, ArraySpecs.recursive_array]
end
it "tries to convert the passed argument to an Array using #to_ary" do
obj = mock('[1,2,3]')
obj.should_receive(:to_ary).and_return([1, 2, 3])
([1, 2] & obj).should == ([1, 2])
end
it "determines equivalence between elements in the sense of eql?" do
not_supported_on :opal do
([5.0, 4.0] & [5, 4]).should == []
end
str = "x"
([str] & [str.dup]).should == [str]
obj1 = mock('1')
obj2 = mock('2')
obj1.should_receive(:hash).at_least(1).and_return(0)
obj2.should_receive(:hash).at_least(1).and_return(0)
obj1.should_receive(:eql?).at_least(1).and_return(true)
([obj1] & [obj2]).should == [obj1]
([obj1, obj1, obj2, obj2] & [obj2]).should == [obj1]
obj1 = mock('3')
obj2 = mock('4')
obj1.should_receive(:hash).at_least(1).and_return(0)
obj2.should_receive(:hash).at_least(1).and_return(0)
obj1.should_receive(:eql?).at_least(1).and_return(false)
([obj1] & [obj2]).should == []
([obj1, obj1, obj2, obj2] & [obj2]).should == [obj2]
end
it "does return subclass instances for Array subclasses" do
(ArraySpecs::MyArray[1, 2, 3] & []).should be_an_instance_of(Array)
(ArraySpecs::MyArray[1, 2, 3] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
([] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
end
it "does not call to_ary on array subclasses" do
([5, 6] & ArraySpecs::ToAryArray[1, 2, 5, 6]).should == [5, 6]
end
it "properly handles an identical item even when its #eql? isn't reflexive" do
x = mock('x')
x.should_receive(:hash).at_least(1).and_return(42)
x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
([x] & [x]).should == [x]
end
end

View file

@ -0,0 +1,48 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/join', __FILE__)
describe "Array#join" do
it_behaves_like :array_join_with_string_separator, :join
it_behaves_like :array_join_with_default_separator, :join
it "does not separate elements when the passed separator is nil" do
[1, 2, 3].join(nil).should == '123'
end
it "calls #to_str to convert the separator to a String" do
sep = mock("separator")
sep.should_receive(:to_str).and_return(", ")
[1, 2].join(sep).should == "1, 2"
end
it "does not call #to_str on the separator if the array is empty" do
sep = mock("separator")
sep.should_not_receive(:to_str)
[].join(sep).should == ""
end
it "raises a TypeError if the separator cannot be coerced to a String by calling #to_str" do
obj = mock("not a string")
lambda { [1, 2].join(obj) }.should raise_error(TypeError)
end
it "raises a TypeError if passed false as the separator" do
lambda { [1, 2].join(false) }.should raise_error(TypeError)
end
end
describe "Array#join with $," do
before :each do
@before_separator = $,
end
after :each do
$, = @before_separator
end
it "separates elements with default separator when the passed separator is nil" do
$, = "_"
[1, 2, 3].join(nil).should == '1_2_3'
end
end

View file

@ -0,0 +1,10 @@
require File.expand_path('../shared/keep_if', __FILE__)
describe "Array#keep_if" do
it "returns the same array if no changes were made" do
array = [1, 2, 3]
array.keep_if { true }.should equal(array)
end
it_behaves_like :keep_if, :keep_if
end

View file

@ -0,0 +1,87 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#last" do
it "returns the last element" do
[1, 1, 1, 1, 2].last.should == 2
end
it "returns nil if self is empty" do
[].last.should == nil
end
it "returns the last count elements if given a count" do
[1, 2, 3, 4, 5, 9].last(3).should == [4, 5, 9]
end
it "returns an empty array when passed a count on an empty array" do
[].last(0).should == []
[].last(1).should == []
end
it "returns an empty array when count == 0" do
[1, 2, 3, 4, 5].last(0).should == []
end
it "returns an array containing the last element when passed count == 1" do
[1, 2, 3, 4, 5].last(1).should == [5]
end
it "raises an ArgumentError when count is negative" do
lambda { [1, 2].last(-1) }.should raise_error(ArgumentError)
end
it "returns the entire array when count > length" do
[1, 2, 3, 4, 5, 9].last(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.last(0).replace([1,2])
ary.should == [1, 2, 3, 4, 5]
ary.last(1).replace([1,2])
ary.should == [1, 2, 3, 4, 5]
ary.last(6).replace([1,2])
ary.should == [1, 2, 3, 4, 5]
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.last.should equal(empty)
array = ArraySpecs.recursive_array
array.last.should equal(array)
end
it "tries to convert the passed argument to an Integer usinig #to_int" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(2)
[1, 2, 3, 4, 5].last(obj).should == [4, 5]
end
it "raises a TypeError if the passed argument is not numeric" do
lambda { [1,2].last(nil) }.should raise_error(TypeError)
lambda { [1,2].last("a") }.should raise_error(TypeError)
obj = mock("nonnumeric")
lambda { [1,2].last(obj) }.should raise_error(TypeError)
end
it "does not return subclass instance on Array subclasses" do
ArraySpecs::MyArray[].last(0).should be_an_instance_of(Array)
ArraySpecs::MyArray[].last(2).should be_an_instance_of(Array)
ArraySpecs::MyArray[1, 2, 3].last(0).should be_an_instance_of(Array)
ArraySpecs::MyArray[1, 2, 3].last(1).should be_an_instance_of(Array)
ArraySpecs::MyArray[1, 2, 3].last(2).should be_an_instance_of(Array)
end
it "is not destructive" do
a = [1, 2, 3]
a.last
a.should == [1, 2, 3]
a.last(2)
a.should == [1, 2, 3]
a.last(3)
a.should == [1, 2, 3]
end
end

View file

@ -0,0 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/length', __FILE__)
describe "Array#length" do
it_behaves_like(:array_length, :length)
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#map" do
it_behaves_like(:array_collect, :map)
end
describe "Array#map!" do
it_behaves_like(:array_collect_b, :map!)
end

View file

@ -0,0 +1,112 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#max" do
it "returns nil with no values" do
[].max.should == nil
end
it "returns only element in one element array" do
[1].max.should == 1
end
it "returns largest value with multiple elements" do
[1,2].max.should == 2
[2,1].max.should == 2
end
describe "given a block with one argument" do
it "yields in turn the last length-1 values from the array" do
ary = []
result = [1,2,3,4,5].max {|x| ary << x; x}
ary.should == [2,3,4,5]
result.should == 5
end
end
end
# From Enumerable#max, copied for better readability
describe "Array#max" do
before :each do
@a = [2, 4, 6, 8, 10]
@e_strs = ["333", "22", "666666", "1", "55555", "1010101010"]
@e_ints = [333, 22, 666666, 55555, 1010101010]
end
it "max should return the maximum element" do
[18, 42].max.should == 42
[2, 5, 3, 6, 1, 4].max.should == 6
end
it "returns the maximum element (basics cases)" do
[55].max.should == 55
[11,99].max.should == 99
[99,11].max.should == 99
[2, 33, 4, 11].max.should == 33
[1,2,3,4,5].max.should == 5
[5,4,3,2,1].max.should == 5
[1,4,3,5,2].max.should == 5
[5,5,5,5,5].max.should == 5
["aa","tt"].max.should == "tt"
["tt","aa"].max.should == "tt"
["2","33","4","11"].max.should == "4"
@e_strs.max.should == "666666"
@e_ints.max.should == 1010101010
end
it "returns nil for an empty Enumerable" do
[].max.should == nil
end
it "raises a NoMethodError for elements without #<=>" do
lambda do
[BasicObject.new, BasicObject.new].max
end.should raise_error(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
lambda do
[11,"22"].max
end.should raise_error(ArgumentError)
lambda do
[11,12,22,33].max{|a, b| nil}
end.should raise_error(ArgumentError)
end
it "returns the maximum element (with block)" do
# with a block
["2","33","4","11"].max {|a,b| a <=> b }.should == "4"
[ 2 , 33 , 4 , 11 ].max {|a,b| a <=> b }.should == 33
["2","33","4","11"].max {|a,b| b <=> a }.should == "11"
[ 2 , 33 , 4 , 11 ].max {|a,b| b <=> a }.should == 2
@e_strs.max {|a,b| a.length <=> b.length }.should == "1010101010"
@e_strs.max {|a,b| a <=> b }.should == "666666"
@e_strs.max {|a,b| a.to_i <=> b.to_i }.should == "1010101010"
@e_ints.max {|a,b| a <=> b }.should == 1010101010
@e_ints.max {|a,b| a.to_s <=> b.to_s }.should == 666666
end
it "returns the minimum for enumerables that contain nils" do
arr = [nil, nil, true]
arr.max { |a, b|
x = a.nil? ? 1 : a ? 0 : -1
y = b.nil? ? 1 : b ? 0 : -1
x <=> y
}.should == nil
end
it "gathers whole arrays as elements when each yields multiple" do
multi = [[1,2], [3,4,5], [6,7,8,9]]
multi.max.should == [6, 7, 8, 9]
end
end

View file

@ -0,0 +1,117 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#min" do
it "returns nil with no values" do
[].min.should == nil
end
it "returns only element in one element array" do
[1].min.should == 1
end
it "returns smallest value with multiple elements" do
[1,2].min.should == 1
[2,1].min.should == 1
end
describe "given a block with one argument" do
it "yields in turn the last length-1 values from the array" do
ary = []
result = [1,2,3,4,5].min {|x| ary << x; x}
ary.should == [2,3,4,5]
result.should == 1
end
end
end
# From Enumerable#min, copied for better readability
describe "Array#min" do
before :each do
@a = [2, 4, 6, 8, 10]
@e_strs = ["333", "22", "666666", "1", "55555", "1010101010"]
@e_ints = [ 333, 22, 666666, 55555, 1010101010]
end
it "min should return the minimum element" do
[18, 42].min.should == 18
[2, 5, 3, 6, 1, 4].min.should == 1
end
it "returns the minimum (basic cases)" do
[55].min.should == 55
[11,99].min.should == 11
[99,11].min.should == 11
[2, 33, 4, 11].min.should == 2
[1,2,3,4,5].min.should == 1
[5,4,3,2,1].min.should == 1
[4,1,3,5,2].min.should == 1
[5,5,5,5,5].min.should == 5
["aa","tt"].min.should == "aa"
["tt","aa"].min.should == "aa"
["2","33","4","11"].min.should == "11"
@e_strs.min.should == "1"
@e_ints.min.should == 22
end
it "returns nil for an empty Enumerable" do
[].min.should be_nil
end
it "raises a NoMethodError for elements without #<=>" do
lambda do
[BasicObject.new, BasicObject.new].min
end.should raise_error(NoMethodError)
end
it "raises an ArgumentError for incomparable elements" do
lambda do
[11,"22"].min
end.should raise_error(ArgumentError)
lambda do
[11,12,22,33].min{|a, b| nil}
end.should raise_error(ArgumentError)
end
it "returns the minimum when using a block rule" do
["2","33","4","11"].min {|a,b| a <=> b }.should == "11"
[ 2 , 33 , 4 , 11 ].min {|a,b| a <=> b }.should == 2
["2","33","4","11"].min {|a,b| b <=> a }.should == "4"
[ 2 , 33 , 4 , 11 ].min {|a,b| b <=> a }.should == 33
[ 1, 2, 3, 4 ].min {|a,b| 15 }.should == 1
[11,12,22,33].min{|a, b| 2 }.should == 11
@i = -2
[11,12,22,33].min{|a, b| @i += 1 }.should == 12
@e_strs.min {|a,b| a.length <=> b.length }.should == "1"
@e_strs.min {|a,b| a <=> b }.should == "1"
@e_strs.min {|a,b| a.to_i <=> b.to_i }.should == "1"
@e_ints.min {|a,b| a <=> b }.should == 22
@e_ints.min {|a,b| a.to_s <=> b.to_s }.should == 1010101010
end
it "returns the minimum for enumerables that contain nils" do
arr = [nil, nil, true]
arr.min { |a, b|
x = a.nil? ? -1 : a ? 0 : 1
y = b.nil? ? -1 : b ? 0 : 1
x <=> y
}.should == nil
end
it "gathers whole arrays as elements when each yields multiple" do
multi = [[1,2], [3,4,5], [6,7,8,9]]
multi.min.should == [1, 2]
end
end

View file

@ -0,0 +1,87 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#-" do
it "creates an array minus any items from other array" do
([] - [ 1, 2, 4 ]).should == []
([1, 2, 4] - []).should == [1, 2, 4]
([ 1, 2, 3, 4, 5 ] - [ 1, 2, 4 ]).should == [3, 5]
end
it "removes multiple items on the lhs equal to one on the rhs" do
([1, 1, 2, 2, 3, 3, 4, 5] - [1, 2, 4]).should == [3, 3, 5]
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
(empty - empty).should == []
([] - ArraySpecs.recursive_array).should == []
array = ArraySpecs.recursive_array
(array - array).should == []
end
it "tries to convert the passed arguments to Arrays using #to_ary" do
obj = mock('[2,3,3,4]')
obj.should_receive(:to_ary).and_return([2, 3, 3, 4])
([1, 1, 2, 2, 3, 4] - obj).should == [1, 1]
end
it "raises a TypeError if the argument cannot be coerced to an Array by calling #to_ary" do
obj = mock('not an array')
lambda { [1, 2, 3] - obj }.should raise_error(TypeError)
end
it "does not return subclass instance for Array subclasses" do
(ArraySpecs::MyArray[1, 2, 3] - []).should be_an_instance_of(Array)
(ArraySpecs::MyArray[1, 2, 3] - ArraySpecs::MyArray[]).should be_an_instance_of(Array)
([1, 2, 3] - ArraySpecs::MyArray[]).should be_an_instance_of(Array)
end
it "does not call to_ary on array subclasses" do
([5, 6, 7] - ArraySpecs::ToAryArray[7]).should == [5, 6]
end
it "removes an item identified as equivalent via #hash and #eql?" do
obj1 = mock('1')
obj2 = mock('2')
obj1.should_receive(:hash).at_least(1).and_return(0)
obj2.should_receive(:hash).at_least(1).and_return(0)
obj1.should_receive(:eql?).at_least(1).and_return(true)
([obj1] - [obj2]).should == []
([obj1, obj1, obj2, obj2] - [obj2]).should == []
end
it "doesn't remove an item with the same hash but not #eql?" do
obj1 = mock('1')
obj2 = mock('2')
obj1.should_receive(:hash).at_least(1).and_return(0)
obj2.should_receive(:hash).at_least(1).and_return(0)
obj1.should_receive(:eql?).at_least(1).and_return(false)
([obj1] - [obj2]).should == [obj1]
([obj1, obj1, obj2, obj2] - [obj2]).should == [obj1, obj1]
end
it "removes an identical item even when its #eql? isn't reflexive" do
x = mock('x')
x.should_receive(:hash).at_least(1).and_return(42)
x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
([x] - [x]).should == []
end
it "is not destructive" do
a = [1, 2, 3]
a - []
a.should == [1, 2, 3]
a - [1]
a.should == [1, 2, 3]
a - [1,2,3]
a.should == [1, 2, 3]
a - [:a, :b, :c]
a.should == [1, 2, 3]
end
end

View file

@ -0,0 +1,132 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/join', __FILE__)
describe "Array#*" do
it "tries to convert the passed argument to a String using #to_str" do
obj = mock('separator')
obj.should_receive(:to_str).and_return('::')
([1, 2, 3, 4] * obj).should == '1::2::3::4'
end
it "tires to convert the passed argument to an Integer using #to_int" do
obj = mock('count')
obj.should_receive(:to_int).and_return(2)
([1, 2, 3, 4] * obj).should == [1, 2, 3, 4, 1, 2, 3, 4]
end
it "raises a TypeError if the argument can neither be converted to a string nor an integer" do
obj = mock('not a string or integer')
lambda{ [1,2] * obj }.should raise_error(TypeError)
end
it "converts the passed argument to a String rather than an Integer" do
obj = mock('2')
def obj.to_int() 2 end
def obj.to_str() "2" end
([:a, :b, :c] * obj).should == "a2b2c"
end
it "raises a TypeError is the passed argument is nil" do
lambda{ [1,2] * nil }.should raise_error(TypeError)
end
it "raises an ArgumentError when passed 2 or more arguments" do
lambda{ [1,2].send(:*, 1, 2) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError when passed no arguments" do
lambda{ [1,2].send(:*) }.should raise_error(ArgumentError)
end
end
describe "Array#* with an integer" do
it "concatenates n copies of the array when passed an integer" do
([ 1, 2, 3 ] * 0).should == []
([ 1, 2, 3 ] * 1).should == [1, 2, 3]
([ 1, 2, 3 ] * 3).should == [1, 2, 3, 1, 2, 3, 1, 2, 3]
([] * 10).should == []
end
it "does not return self even if the passed integer is 1" do
ary = [1, 2, 3]
(ary * 1).should_not equal(ary)
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
(empty * 0).should == []
(empty * 1).should == empty
(empty * 3).should == [empty, empty, empty]
array = ArraySpecs.recursive_array
(array * 0).should == []
(array * 1).should == array
end
it "raises an ArgumentError when passed a negative integer" do
lambda { [ 1, 2, 3 ] * -1 }.should raise_error(ArgumentError)
lambda { [] * -1 }.should raise_error(ArgumentError)
end
describe "with a subclass of Array" do
before :each do
ScratchPad.clear
@array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
end
it "returns a subclass instance" do
(@array * 0).should be_an_instance_of(ArraySpecs::MyArray)
(@array * 1).should be_an_instance_of(ArraySpecs::MyArray)
(@array * 2).should be_an_instance_of(ArraySpecs::MyArray)
end
it "does not call #initialize on the subclass instance" do
(@array * 2).should == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
ScratchPad.recorded.should be_nil
end
end
it "copies the taint status of the original array even if the passed count is 0" do
ary = [1, 2, 3]
ary.taint
(ary * 0).tainted?.should == true
end
it "copies the taint status of the original array even if the array is empty" do
ary = []
ary.taint
(ary * 3).tainted?.should == true
end
it "copies the taint status of the original array if the passed count is not 0" do
ary = [1, 2, 3]
ary.taint
(ary * 1).tainted?.should == true
(ary * 2).tainted?.should == true
end
it "copies the untrusted status of the original array even if the passed count is 0" do
ary = [1, 2, 3]
ary.untrust
(ary * 0).untrusted?.should == true
end
it "copies the untrusted status of the original array even if the array is empty" do
ary = []
ary.untrust
(ary * 3).untrusted?.should == true
end
it "copies the untrusted status of the original array if the passed count is not 0" do
ary = [1, 2, 3]
ary.untrust
(ary * 1).untrusted?.should == true
(ary * 2).untrusted?.should == true
end
end
describe "Array#* with a string" do
it_behaves_like :array_join_with_string_separator, :*
end

View file

@ -0,0 +1,122 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array.new" do
it "returns an instance of Array" do
Array.new.should be_an_instance_of(Array)
end
it "returns an instance of a subclass" do
ArraySpecs::MyArray.new(1, 2).should be_an_instance_of(ArraySpecs::MyArray)
end
it "raises an ArgumentError if passed 3 or more arguments" do
lambda do
[1, 2].send :initialize, 1, 'x', true
end.should raise_error(ArgumentError)
lambda do
[1, 2].send(:initialize, 1, 'x', true) {}
end.should raise_error(ArgumentError)
end
end
describe "Array.new with no arguments" do
it "returns an empty array" do
Array.new.should be_empty
end
it "does not use the given block" do
lambda{ Array.new { raise } }.should_not raise_error
end
end
describe "Array.new with (array)" do
it "returns an array initialized to the other array" do
b = [4, 5, 6]
Array.new(b).should == b
end
it "does not use the given block" do
lambda{ Array.new([1, 2]) { raise } }.should_not raise_error
end
it "calls #to_ary to convert the value to an array" do
a = mock("array")
a.should_receive(:to_ary).and_return([1, 2])
a.should_not_receive(:to_int)
Array.new(a).should == [1, 2]
end
it "does not call #to_ary on instances of Array or subclasses of Array" do
a = [1, 2]
a.should_not_receive(:to_ary)
Array.new(a)
end
it "raises a TypeError if an Array type argument and a default object" do
lambda { Array.new([1, 2], 1) }.should raise_error(TypeError)
end
end
describe "Array.new with (size, object=nil)" do
it "returns an array of size filled with object" do
obj = [3]
a = Array.new(2, obj)
a.should == [obj, obj]
a[0].should equal(obj)
a[1].should equal(obj)
Array.new(3, 14).should == [14, 14, 14]
end
it "returns an array of size filled with nil when object is omitted" do
Array.new(3).should == [nil, nil, nil]
end
it "raises an ArgumentError if size is negative" do
lambda { Array.new(-1, :a) }.should raise_error(ArgumentError)
lambda { Array.new(-1) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if size is too large" do
lambda { Array.new(fixnum_max+1) }.should raise_error(ArgumentError)
end
it "calls #to_int to convert the size argument to an Integer when object is given" do
obj = mock('1')
obj.should_receive(:to_int).and_return(1)
Array.new(obj, :a).should == [:a]
end
it "calls #to_int to convert the size argument to an Integer when object is not given" do
obj = mock('1')
obj.should_receive(:to_int).and_return(1)
Array.new(obj).should == [nil]
end
it "raises a TypeError if the size argument is not an Integer type" do
obj = mock('nonnumeric')
obj.stub!(:to_ary).and_return([1, 2])
lambda{ Array.new(obj, :a) }.should raise_error(TypeError)
end
it "yields the index of the element and sets the element to the value of the block" do
Array.new(3) { |i| i.to_s }.should == ['0', '1', '2']
end
it "uses the block value instead of using the default value" do
lambda {
@result = Array.new(3, :obj) { |i| i.to_s }
}.should complain(/block supersedes default value argument/)
@result.should == ['0', '1', '2']
end
it "returns the value passed to break" do
a = Array.new(3) do |i|
break if i == 2
i.to_s
end
a.should == nil
end
end

View file

@ -0,0 +1,59 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/string', __FILE__)
describe "Array#pack with format 'A'" do
it_behaves_like :array_pack_basic, 'A'
it_behaves_like :array_pack_basic_non_float, 'A'
it_behaves_like :array_pack_no_platform, 'A'
it_behaves_like :array_pack_string, 'A'
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("A*").should == "abc"
end
it "padds the output with spaces when the count exceeds the size of the String" do
["abc"].pack("A6").should == "abc "
end
it "adds a space when the value is nil" do
[nil].pack("A").should == " "
end
it "pads the output with spaces when the value is nil" do
[nil].pack("A3").should == " "
end
it "does not pad with spaces when passed the '*' modifier and the value is nil" do
[nil].pack("A*").should == ""
end
end
describe "Array#pack with format 'a'" do
it_behaves_like :array_pack_basic, 'a'
it_behaves_like :array_pack_basic_non_float, 'a'
it_behaves_like :array_pack_no_platform, 'a'
it_behaves_like :array_pack_string, 'a'
it "adds all the bytes to the output when passed the '*' modifier" do
["abc"].pack("a*").should == "abc"
end
it "padds the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("a6").should == "abc\x00\x00\x00"
end
it "adds a NULL byte when the value is nil" do
[nil].pack("a").should == "\x00"
end
it "pads the output with NULL bytes when the value is nil" do
[nil].pack("a3").should == "\x00\x00\x00"
end
it "does not pad with NULL bytes when passed the '*' modifier and the value is nil" do
[nil].pack("a*").should == ""
end
end

View file

@ -0,0 +1,30 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
describe "Array#pack with format '@'" do
it_behaves_like :array_pack_basic, '@'
it_behaves_like :array_pack_basic_non_float, '@'
it_behaves_like :array_pack_no_platform, '@'
it "moves the insertion point to the index specified by the count modifier" do
[1, 2, 3, 4, 5].pack("C4@2C").should == "\x01\x02\x05"
end
it "does not consume any elements" do
[1, 2, 3].pack("C@3C").should == "\x01\x00\x00\x02"
end
it "extends the string with NULL bytes if the string size is less than the count" do
[1, 2, 3].pack("@3C*").should == "\x00\x00\x00\x01\x02\x03"
end
it "truncates the string if the string size is greater than the count" do
[1, 2, 3].pack("Cx5@2C").should == "\x01\x00\x02"
end
it "implicitly has a count of one when no count modifier is passed" do
[1, 2, 3].pack("C*@").should == "\x01"
end
end

View file

@ -0,0 +1,105 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/encodings', __FILE__)
describe "Array#pack with format 'B'" do
it_behaves_like :array_pack_basic, 'B'
it_behaves_like :array_pack_basic_non_float, 'B'
it_behaves_like :array_pack_arguments, 'B'
it_behaves_like :array_pack_hex, 'B'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
obj.should_receive(:to_str).and_return("``abcdef")
[obj].pack("B*").should == "\x2a"
end
it "encodes one bit for each character starting with the most significant bit" do
[ [["0"], "\x00"],
[["1"], "\x80"]
].should be_computed_by(:pack, "B")
end
it "implicitly has a count of one when not passed a count modifier" do
["1"].pack("B").should == "\x80"
end
it "implicitly has count equal to the string length when passed the '*' modifier" do
[ [["00101010"], "\x2a"],
[["00000000"], "\x00"],
[["11111111"], "\xff"],
[["10000000"], "\x80"],
[["00000001"], "\x01"]
].should be_computed_by(:pack, "B*")
end
it "encodes the least significant bit of a character other than 0 or 1" do
[ [["bbababab"], "\x2a"],
[["^&#&#^#^"], "\x2a"],
[["(()()()("], "\x2a"],
[["@@%@%@%@"], "\x2a"],
[["ppqrstuv"], "\x2a"],
[["rqtvtrqp"], "\x42"]
].should be_computed_by(:pack, "B*")
end
it "returns an ASCII-8BIT string" do
["1"].pack("B").encoding.should == Encoding::ASCII_8BIT
end
it "encodes the string as a sequence of bytes" do
["ああああああああ"].pack("B*").should == "\xdbm\xb6"
end
end
describe "Array#pack with format 'b'" do
it_behaves_like :array_pack_basic, 'b'
it_behaves_like :array_pack_basic_non_float, 'b'
it_behaves_like :array_pack_arguments, 'b'
it_behaves_like :array_pack_hex, 'b'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
obj.should_receive(:to_str).and_return("`abcdef`")
[obj].pack("b*").should == "\x2a"
end
it "encodes one bit for each character starting with the least significant bit" do
[ [["0"], "\x00"],
[["1"], "\x01"]
].should be_computed_by(:pack, "b")
end
it "implicitly has a count of one when not passed a count modifier" do
["1"].pack("b").should == "\x01"
end
it "implicitly has count equal to the string length when passed the '*' modifier" do
[ [["0101010"], "\x2a"],
[["00000000"], "\x00"],
[["11111111"], "\xff"],
[["10000000"], "\x01"],
[["00000001"], "\x80"]
].should be_computed_by(:pack, "b*")
end
it "encodes the least significant bit of a character other than 0 or 1" do
[ [["bababab"], "\x2a"],
[["&#&#^#^"], "\x2a"],
[["()()()("], "\x2a"],
[["@%@%@%@"], "\x2a"],
[["pqrstuv"], "\x2a"],
[["qrtrtvs"], "\x41"]
].should be_computed_by(:pack, "b*")
end
it "returns an ASCII-8BIT string" do
["1"].pack("b").encoding.should == Encoding::ASCII_8BIT
end
it "encodes the string as a sequence of bytes" do
["ああああああああ"].pack("b*").should == "\xdb\xb6m"
end
end

View file

@ -0,0 +1,75 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
describe :array_pack_8bit, shared: true do
it "encodes the least significant eight bits of a positive number" do
[ [[49], "1"],
[[0b11111111], "\xFF"],
[[0b100000000], "\x00"],
[[0b100000001], "\x01"]
].should be_computed_by(:pack, pack_format)
end
it "encodes the least significant eight bits of a negative number" do
[ [[-1], "\xFF"],
[[-0b10000000], "\x80"],
[[-0b11111111], "\x01"],
[[-0b100000000], "\x00"],
[[-0b100000001], "\xFF"]
].should be_computed_by(:pack, pack_format)
end
it "encodes a Float truncated as an Integer" do
[ [[5.2], "\x05"],
[[5.8], "\x05"]
].should be_computed_by(:pack, pack_format)
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(5)
[obj].pack(pack_format).should == "\x05"
end
it "encodes the number of array elements specified by the count modifier" do
[ [[1, 2, 3], pack_format(3), "\x01\x02\x03"],
[[1, 2, 3], pack_format(2) + pack_format(1), "\x01\x02\x03"]
].should be_computed_by(:pack)
end
it "encodes all remaining elements when passed the '*' modifier" do
[1, 2, 3, 4, 5].pack(pack_format('*')).should == "\x01\x02\x03\x04\x05"
end
it "ignores NULL bytes between directives" do
[1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02"
end
it "ignores spaces between directives" do
[1, 2, 3].pack(pack_format(' ', 2)).should == "\x01\x02"
end
end
describe "Array#pack with format 'C'" do
it_behaves_like :array_pack_basic, 'C'
it_behaves_like :array_pack_basic_non_float, 'C'
it_behaves_like :array_pack_8bit, 'C'
it_behaves_like :array_pack_arguments, 'C'
it_behaves_like :array_pack_numeric_basic, 'C'
it_behaves_like :array_pack_integer, 'C'
it_behaves_like :array_pack_no_platform, 'C'
end
describe "Array#pack with format 'c'" do
it_behaves_like :array_pack_basic, 'c'
it_behaves_like :array_pack_basic_non_float, 'c'
it_behaves_like :array_pack_8bit, 'c'
it_behaves_like :array_pack_arguments, 'c'
it_behaves_like :array_pack_numeric_basic, 'c'
it_behaves_like :array_pack_integer, 'c'
it_behaves_like :array_pack_no_platform, 'c'
end

View file

@ -0,0 +1,25 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
describe "Array#pack" do
it "ignores directives text from '#' to the first newline" do
[1, 2, 3].pack("c#this is a comment\nc").should == "\x01\x02"
end
it "ignores directives text from '#' to the end if no newline is present" do
[1, 2, 3].pack("c#this is a comment c").should == "\x01"
end
it "ignores comments at the start of the directives string" do
[1, 2, 3].pack("#this is a comment\nc").should == "\x01"
end
it "ignores the entire directive string if it is a comment" do
[1, 2, 3].pack("#this is a comment").should == ""
end
it "ignores multiple comments" do
[1, 2, 3].pack("c#comment\nc#comment\nc#c").should == "\x01\x02\x03"
end
end

View file

@ -0,0 +1,39 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/float', __FILE__)
describe "Array#pack with format 'D'" do
it_behaves_like :array_pack_basic, 'D'
it_behaves_like :array_pack_basic_float, 'D'
it_behaves_like :array_pack_arguments, 'D'
it_behaves_like :array_pack_no_platform, 'D'
it_behaves_like :array_pack_numeric_basic, 'D'
it_behaves_like :array_pack_float, 'D'
little_endian do
it_behaves_like :array_pack_double_le, 'D'
end
big_endian do
it_behaves_like :array_pack_double_be, 'D'
end
end
describe "Array#pack with format 'd'" do
it_behaves_like :array_pack_basic, 'd'
it_behaves_like :array_pack_basic_float, 'd'
it_behaves_like :array_pack_arguments, 'd'
it_behaves_like :array_pack_no_platform, 'd'
it_behaves_like :array_pack_numeric_basic, 'd'
it_behaves_like :array_pack_float, 'd'
little_endian do
it_behaves_like :array_pack_double_le, 'd'
end
big_endian do
it_behaves_like :array_pack_double_be, 'd'
end
end

View file

@ -0,0 +1,25 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/float', __FILE__)
describe "Array#pack with format 'E'" do
it_behaves_like :array_pack_basic, 'E'
it_behaves_like :array_pack_basic_float, 'E'
it_behaves_like :array_pack_arguments, 'E'
it_behaves_like :array_pack_no_platform, 'E'
it_behaves_like :array_pack_numeric_basic, 'E'
it_behaves_like :array_pack_float, 'E'
it_behaves_like :array_pack_double_le, 'E'
end
describe "Array#pack with format 'e'" do
it_behaves_like :array_pack_basic, 'e'
it_behaves_like :array_pack_basic_float, 'e'
it_behaves_like :array_pack_arguments, 'e'
it_behaves_like :array_pack_no_platform, 'e'
it_behaves_like :array_pack_numeric_basic, 'e'
it_behaves_like :array_pack_float, 'e'
it_behaves_like :array_pack_float_le, 'e'
end

View file

@ -0,0 +1,11 @@
require File.expand_path('../../../../spec_helper', __FILE__)
describe "Array#pack with empty format" do
it "returns an empty String" do
[1, 2, 3].pack("").should == ""
end
it "returns a String with US-ASCII encoding" do
[1, 2, 3].pack("").encoding.should == Encoding::US_ASCII
end
end

View file

@ -0,0 +1,39 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/float', __FILE__)
describe "Array#pack with format 'F'" do
it_behaves_like :array_pack_basic, 'F'
it_behaves_like :array_pack_basic_float, 'F'
it_behaves_like :array_pack_arguments, 'F'
it_behaves_like :array_pack_no_platform, 'F'
it_behaves_like :array_pack_numeric_basic, 'F'
it_behaves_like :array_pack_float, 'F'
little_endian do
it_behaves_like :array_pack_float_le, 'F'
end
big_endian do
it_behaves_like :array_pack_float_be, 'F'
end
end
describe "Array#pack with format 'f'" do
it_behaves_like :array_pack_basic, 'f'
it_behaves_like :array_pack_basic_float, 'f'
it_behaves_like :array_pack_arguments, 'f'
it_behaves_like :array_pack_no_platform, 'f'
it_behaves_like :array_pack_numeric_basic, 'f'
it_behaves_like :array_pack_float, 'f'
little_endian do
it_behaves_like :array_pack_float_le, 'f'
end
big_endian do
it_behaves_like :array_pack_float_be, 'f'
end
end

View file

@ -0,0 +1,25 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/float', __FILE__)
describe "Array#pack with format 'G'" do
it_behaves_like :array_pack_basic, 'G'
it_behaves_like :array_pack_basic_float, 'G'
it_behaves_like :array_pack_arguments, 'G'
it_behaves_like :array_pack_no_platform, 'G'
it_behaves_like :array_pack_numeric_basic, 'G'
it_behaves_like :array_pack_float, 'G'
it_behaves_like :array_pack_double_be, 'G'
end
describe "Array#pack with format 'g'" do
it_behaves_like :array_pack_basic, 'g'
it_behaves_like :array_pack_basic_float, 'g'
it_behaves_like :array_pack_arguments, 'g'
it_behaves_like :array_pack_no_platform, 'g'
it_behaves_like :array_pack_numeric_basic, 'g'
it_behaves_like :array_pack_float, 'g'
it_behaves_like :array_pack_float_be, 'g'
end

View file

@ -0,0 +1,197 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/encodings', __FILE__)
describe "Array#pack with format 'H'" do
it_behaves_like :array_pack_basic, 'H'
it_behaves_like :array_pack_basic_non_float, 'H'
it_behaves_like :array_pack_arguments, 'H'
it_behaves_like :array_pack_hex, 'H'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
obj.should_receive(:to_str).and_return("a")
[obj].pack("H").should == "\xa0"
end
it "encodes the first character as the most significant nibble when passed no count modifier" do
["ab"].pack("H").should == "\xa0"
end
it "implicitly has count equal to the string length when passed the '*' modifier" do
["deadbeef"].pack("H*").should == "\xde\xad\xbe\xef"
end
it "encodes count nibbles when passed a count modifier exceeding the string length" do
["ab"].pack('H8').should == "\xab\x00\x00\x00"
end
it "encodes the first character as the most significant nibble of a hex value" do
[ [["0"], "\x00"],
[["1"], "\x10"],
[["2"], "\x20"],
[["3"], "\x30"],
[["4"], "\x40"],
[["5"], "\x50"],
[["6"], "\x60"],
[["7"], "\x70"],
[["8"], "\x80"],
[["9"], "\x90"],
[["a"], "\xa0"],
[["b"], "\xb0"],
[["c"], "\xc0"],
[["d"], "\xd0"],
[["e"], "\xe0"],
[["f"], "\xf0"],
[["A"], "\xa0"],
[["B"], "\xb0"],
[["C"], "\xc0"],
[["D"], "\xd0"],
[["E"], "\xe0"],
[["F"], "\xf0"]
].should be_computed_by(:pack, "H")
end
it "encodes the second character as the least significant nibble of a hex value" do
[ [["00"], "\x00"],
[["01"], "\x01"],
[["02"], "\x02"],
[["03"], "\x03"],
[["04"], "\x04"],
[["05"], "\x05"],
[["06"], "\x06"],
[["07"], "\x07"],
[["08"], "\x08"],
[["09"], "\x09"],
[["0a"], "\x0a"],
[["0b"], "\x0b"],
[["0c"], "\x0c"],
[["0d"], "\x0d"],
[["0e"], "\x0e"],
[["0f"], "\x0f"],
[["0A"], "\x0a"],
[["0B"], "\x0b"],
[["0C"], "\x0c"],
[["0D"], "\x0d"],
[["0E"], "\x0e"],
[["0F"], "\x0f"]
].should be_computed_by(:pack, "H2")
end
it "encodes the least significant nibble of a non alphanumeric character as the most significant nibble of the hex value" do
[ [["^"], "\xe0"],
[["*"], "\xa0"],
[["#"], "\x30"],
[["["], "\xb0"],
[["]"], "\xd0"],
[["@"], "\x00"],
[["!"], "\x10"],
[["H"], "\x10"],
[["O"], "\x80"],
[["T"], "\xd0"],
[["Z"], "\x30"],
].should be_computed_by(:pack, "H")
end
it "returns an ASCII-8BIT string" do
["41"].pack("H").encoding.should == Encoding::ASCII_8BIT
end
end
describe "Array#pack with format 'h'" do
it_behaves_like :array_pack_basic, 'h'
it_behaves_like :array_pack_basic_non_float, 'h'
it_behaves_like :array_pack_arguments, 'h'
it_behaves_like :array_pack_hex, 'h'
it "calls #to_str to convert an Object to a String" do
obj = mock("pack H string")
obj.should_receive(:to_str).and_return("a")
[obj].pack("h").should == "\x0a"
end
it "encodes the first character as the least significant nibble when passed no count modifier" do
["ab"].pack("h").should == "\x0a"
end
it "implicitly has count equal to the string length when passed the '*' modifier" do
["deadbeef"].pack("h*").should == "\xed\xda\xeb\xfe"
end
it "encodes count nibbles when passed a count modifier exceeding the string length" do
["ab"].pack('h8').should == "\xba\x00\x00\x00"
end
it "encodes the first character as the least significant nibble of a hex value" do
[ [["0"], "\x00"],
[["1"], "\x01"],
[["2"], "\x02"],
[["3"], "\x03"],
[["4"], "\x04"],
[["5"], "\x05"],
[["6"], "\x06"],
[["7"], "\x07"],
[["8"], "\x08"],
[["9"], "\x09"],
[["a"], "\x0a"],
[["b"], "\x0b"],
[["c"], "\x0c"],
[["d"], "\x0d"],
[["e"], "\x0e"],
[["f"], "\x0f"],
[["A"], "\x0a"],
[["B"], "\x0b"],
[["C"], "\x0c"],
[["D"], "\x0d"],
[["E"], "\x0e"],
[["F"], "\x0f"]
].should be_computed_by(:pack, "h")
end
it "encodes the second character as the most significant nibble of a hex value" do
[ [["00"], "\x00"],
[["01"], "\x10"],
[["02"], "\x20"],
[["03"], "\x30"],
[["04"], "\x40"],
[["05"], "\x50"],
[["06"], "\x60"],
[["07"], "\x70"],
[["08"], "\x80"],
[["09"], "\x90"],
[["0a"], "\xa0"],
[["0b"], "\xb0"],
[["0c"], "\xc0"],
[["0d"], "\xd0"],
[["0e"], "\xe0"],
[["0f"], "\xf0"],
[["0A"], "\xa0"],
[["0B"], "\xb0"],
[["0C"], "\xc0"],
[["0D"], "\xd0"],
[["0E"], "\xe0"],
[["0F"], "\xf0"]
].should be_computed_by(:pack, "h2")
end
it "encodes the least significant nibble of a non alphanumeric character as the least significant nibble of the hex value" do
[ [["^"], "\x0e"],
[["*"], "\x0a"],
[["#"], "\x03"],
[["["], "\x0b"],
[["]"], "\x0d"],
[["@"], "\x00"],
[["!"], "\x01"],
[["H"], "\x01"],
[["O"], "\x08"],
[["T"], "\x0d"],
[["Z"], "\x03"],
].should be_computed_by(:pack, "h")
end
it "returns an ASCII-8BIT string" do
["41"].pack("h").encoding.should == Encoding::ASCII_8BIT
end
end

View file

@ -0,0 +1,133 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/integer', __FILE__)
describe "Array#pack with format 'I'" do
it_behaves_like :array_pack_basic, 'I'
it_behaves_like :array_pack_basic_non_float, 'I'
it_behaves_like :array_pack_arguments, 'I'
it_behaves_like :array_pack_numeric_basic, 'I'
it_behaves_like :array_pack_integer, 'I'
end
describe "Array#pack with format 'i'" do
it_behaves_like :array_pack_basic, 'i'
it_behaves_like :array_pack_basic_non_float, 'i'
it_behaves_like :array_pack_arguments, 'i'
it_behaves_like :array_pack_numeric_basic, 'i'
it_behaves_like :array_pack_integer, 'i'
end
describe "Array#pack with format 'I'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_32bit_le, 'I<'
end
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'I<_'
it_behaves_like :array_pack_32bit_le, 'I_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'I<!'
it_behaves_like :array_pack_32bit_le, 'I!<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_32bit_be, 'I>'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'I>_'
it_behaves_like :array_pack_32bit_be, 'I_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'I>!'
it_behaves_like :array_pack_32bit_be, 'I!>'
end
end
describe "Array#pack with format 'i'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_32bit_le, 'i<'
end
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'i<_'
it_behaves_like :array_pack_32bit_le, 'i_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'i<!'
it_behaves_like :array_pack_32bit_le, 'i!<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_32bit_be, 'i>'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'i>_'
it_behaves_like :array_pack_32bit_be, 'i_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'i>!'
it_behaves_like :array_pack_32bit_be, 'i!>'
end
end
little_endian do
describe "Array#pack with format 'I'" do
it_behaves_like :array_pack_32bit_le, 'I'
end
describe "Array#pack with format 'I' with modifier '_'" do
it_behaves_like :array_pack_32bit_le_platform, 'I_'
end
describe "Array#pack with format 'I' with modifier '!'" do
it_behaves_like :array_pack_32bit_le_platform, 'I!'
end
describe "Array#pack with format 'i'" do
it_behaves_like :array_pack_32bit_le, 'i'
end
describe "Array#pack with format 'i' with modifier '_'" do
it_behaves_like :array_pack_32bit_le_platform, 'i_'
end
describe "Array#pack with format 'i' with modifier '!'" do
it_behaves_like :array_pack_32bit_le_platform, 'i!'
end
end
big_endian do
describe "Array#pack with format 'I'" do
it_behaves_like :array_pack_32bit_be, 'I'
end
describe "Array#pack with format 'I' with modifier '_'" do
it_behaves_like :array_pack_32bit_be_platform, 'I_'
end
describe "Array#pack with format 'I' with modifier '!'" do
it_behaves_like :array_pack_32bit_be_platform, 'I!'
end
describe "Array#pack with format 'i'" do
it_behaves_like :array_pack_32bit_be, 'i'
end
describe "Array#pack with format 'i' with modifier '_'" do
it_behaves_like :array_pack_32bit_be_platform, 'i_'
end
describe "Array#pack with format 'i' with modifier '!'" do
it_behaves_like :array_pack_32bit_be_platform, 'i!'
end
end

View file

@ -0,0 +1,222 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/integer', __FILE__)
ruby_version_is '2.3' do
# To handle the special case of x64-mingw32
pointer_size = RUBY_PLATFORM =~ /\bx64\b/ ? 64 : 1.size * 8
guard -> { pointer_size == 64 } do
describe "Array#pack with format 'J'" do
it_behaves_like :array_pack_basic, 'J'
it_behaves_like :array_pack_basic_non_float, 'J'
it_behaves_like :array_pack_arguments, 'J'
it_behaves_like :array_pack_numeric_basic, 'J'
it_behaves_like :array_pack_integer, 'J'
end
describe "Array#pack with format 'j'" do
it_behaves_like :array_pack_basic, 'j'
it_behaves_like :array_pack_basic_non_float, 'j'
it_behaves_like :array_pack_arguments, 'j'
it_behaves_like :array_pack_numeric_basic, 'j'
it_behaves_like :array_pack_integer, 'j'
end
little_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_le, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_le, 'j!'
end
end
end
big_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_be, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_be, 'j!'
end
end
end
describe "Array#pack with format 'J'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'J<_'
it_behaves_like :array_pack_64bit_le, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_64bit_le, 'J<!'
it_behaves_like :array_pack_64bit_le, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'J>_'
it_behaves_like :array_pack_64bit_be, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'J>!'
it_behaves_like :array_pack_64bit_be, 'J!>'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'j<_'
it_behaves_like :array_pack_64bit_le, 'j_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_64bit_le, 'j<!'
it_behaves_like :array_pack_64bit_le, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'j>_'
it_behaves_like :array_pack_64bit_be, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'j>!'
it_behaves_like :array_pack_64bit_be, 'j!>'
end
end
end
guard -> { pointer_size == 32 } do
describe "Array#pack with format 'J'" do
it_behaves_like :array_pack_basic, 'J'
it_behaves_like :array_pack_basic_non_float, 'J'
it_behaves_like :array_pack_arguments, 'J'
it_behaves_like :array_pack_numeric_basic, 'J'
it_behaves_like :array_pack_integer, 'J'
end
describe "Array#pack with format 'j'" do
it_behaves_like :array_pack_basic, 'j'
it_behaves_like :array_pack_basic_non_float, 'j'
it_behaves_like :array_pack_arguments, 'j'
it_behaves_like :array_pack_numeric_basic, 'j'
it_behaves_like :array_pack_integer, 'j'
end
big_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'j!'
end
end
end
little_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'j!'
end
end
end
describe "Array#pack with format 'J'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'J<_'
it_behaves_like :array_pack_32bit_le, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'J<!'
it_behaves_like :array_pack_32bit_le, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'J>_'
it_behaves_like :array_pack_32bit_be, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'J>!'
it_behaves_like :array_pack_32bit_be, 'J!>'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'j<_'
it_behaves_like :array_pack_32bit_le, 'j_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'j<!'
it_behaves_like :array_pack_32bit_le, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'j>_'
it_behaves_like :array_pack_32bit_be, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'j>!'
it_behaves_like :array_pack_32bit_be, 'j!>'
end
end
end
end

View file

@ -0,0 +1,221 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/integer', __FILE__)
describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_basic, 'L'
it_behaves_like :array_pack_basic_non_float, 'L'
it_behaves_like :array_pack_arguments, 'L'
it_behaves_like :array_pack_numeric_basic, 'L'
it_behaves_like :array_pack_integer, 'L'
end
describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_basic, 'l'
it_behaves_like :array_pack_basic_non_float, 'l'
it_behaves_like :array_pack_arguments, 'l'
it_behaves_like :array_pack_numeric_basic, 'l'
it_behaves_like :array_pack_integer, 'l'
end
describe "Array#pack with format 'L'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_32bit_le, 'L<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_32bit_be, 'L>'
end
guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'L<_'
it_behaves_like :array_pack_32bit_le, 'L_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'L<!'
it_behaves_like :array_pack_32bit_le, 'L!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'L>_'
it_behaves_like :array_pack_32bit_be, 'L_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'L>!'
it_behaves_like :array_pack_32bit_be, 'L!>'
end
end
guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'L<_'
it_behaves_like :array_pack_64bit_le, 'L_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_64bit_le, 'L<!'
it_behaves_like :array_pack_64bit_le, 'L!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'L>_'
it_behaves_like :array_pack_64bit_be, 'L_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'L>!'
it_behaves_like :array_pack_64bit_be, 'L!>'
end
end
end
describe "Array#pack with format 'l'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_32bit_le, 'l<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_32bit_be, 'l>'
end
guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'l<_'
it_behaves_like :array_pack_32bit_le, 'l_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'l<!'
it_behaves_like :array_pack_32bit_le, 'l!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'l>_'
it_behaves_like :array_pack_32bit_be, 'l_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'l>!'
it_behaves_like :array_pack_32bit_be, 'l!>'
end
end
guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'l<_'
it_behaves_like :array_pack_64bit_le, 'l_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_64bit_le, 'l<!'
it_behaves_like :array_pack_64bit_le, 'l!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'l>_'
it_behaves_like :array_pack_64bit_be, 'l_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'l>!'
it_behaves_like :array_pack_64bit_be, 'l!>'
end
end
end
little_endian do
describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_32bit_le, 'L'
end
describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_32bit_le, 'l'
end
guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'L_'
end
describe "Array#pack with format 'L' with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'L!'
end
describe "Array#pack with format 'l' with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'l_'
end
describe "Array#pack with format 'l' with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'l!'
end
end
guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'L_'
end
describe "Array#pack with format 'L' with modifier '!'" do
it_behaves_like :array_pack_64bit_le, 'L!'
end
describe "Array#pack with format 'l' with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'l_'
end
describe "Array#pack with format 'l' with modifier '!'" do
it_behaves_like :array_pack_64bit_le, 'l!'
end
end
end
big_endian do
describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_32bit_be, 'L'
end
describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_32bit_be, 'l'
end
guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'L_'
end
describe "Array#pack with format 'L' with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'L!'
end
describe "Array#pack with format 'l' with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'l_'
end
describe "Array#pack with format 'l' with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'l!'
end
end
guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'L_'
end
describe "Array#pack with format 'L' with modifier '!'" do
it_behaves_like :array_pack_64bit_be, 'L!'
end
describe "Array#pack with format 'l' with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'l_'
end
describe "Array#pack with format 'l' with modifier '!'" do
it_behaves_like :array_pack_64bit_be, 'l!'
end
end
end

View file

@ -0,0 +1,306 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
describe "Array#pack with format 'M'" do
it_behaves_like :array_pack_basic, 'M'
it_behaves_like :array_pack_basic_non_float, 'M'
it_behaves_like :array_pack_arguments, 'M'
it "encodes an empty string as an empty string" do
[""].pack("M").should == ""
end
it "encodes nil as an empty string" do
[nil].pack("M").should == ""
end
it "appends a soft line break at the end of an encoded string" do
["a"].pack("M").should == "a=\n"
end
it "does not append a soft break if the string ends with a newline" do
["a\n"].pack("M").should == "a\n"
end
it "encodes one element for each directive" do
["a", "b", "c"].pack("MM").should == "a=\nb=\n"
end
it "encodes byte values 33..60 directly" do
[ [["!\"\#$%&'()*+,-./"], "!\"\#$%&'()*+,-./=\n"],
[["0123456789"], "0123456789=\n"],
[[":;<"], ":;<=\n"]
].should be_computed_by(:pack, "M")
end
it "encodes byte values 62..126 directly" do
[ [[">?@"], ">?@=\n"],
[["ABCDEFGHIJKLMNOPQRSTUVWXYZ"], "ABCDEFGHIJKLMNOPQRSTUVWXYZ=\n"],
[["[\\]^_`"], "[\\]^_`=\n"],
[["abcdefghijklmnopqrstuvwxyz"], "abcdefghijklmnopqrstuvwxyz=\n"],
[["{|}~"], "{|}~=\n"]
].should be_computed_by(:pack, "M")
end
it "encodes an '=' character in hex format" do
["="].pack("M").should == "=3D=\n"
end
it "encodes an embedded space directly" do
["a b"].pack("M").should == "a b=\n"
end
it "encodes a space at the end of the string directly" do
["a "].pack("M").should == "a =\n"
end
it "encodes an embedded tab directly" do
["a\tb"].pack("M").should == "a\tb=\n"
end
it "encodes a tab at the end of the string directly" do
["a\t"].pack("M").should == "a\t=\n"
end
it "encodes an embedded newline directly" do
["a\nb"].pack("M").should == "a\nb=\n"
end
it "encodes 0..31 except tab and newline in hex format" do
[ [["\x00\x01\x02\x03\x04\x05\x06"], "=00=01=02=03=04=05=06=\n"],
[["\a\b\v\f\r"], "=07=08=0B=0C=0D=\n"],
[["\x0e\x0f\x10\x11\x12\x13\x14"], "=0E=0F=10=11=12=13=14=\n"],
[["\x15\x16\x17\x18\x19\x1a"], "=15=16=17=18=19=1A=\n"],
[["\e"], "=1B=\n"],
[["\x1c\x1d\x1e\x1f"], "=1C=1D=1E=1F=\n"]
].should be_computed_by(:pack, "M")
end
it "encodes a tab followed by a newline with an encoded newline" do
["\t\n"].pack("M").should == "\t=\n\n"
end
it "encodes 127..255 in hex format" do
[ [["\x7f\x80\x81\x82\x83\x84\x85\x86"], "=7F=80=81=82=83=84=85=86=\n"],
[["\x87\x88\x89\x8a\x8b\x8c\x8d\x8e"], "=87=88=89=8A=8B=8C=8D=8E=\n"],
[["\x8f\x90\x91\x92\x93\x94\x95\x96"], "=8F=90=91=92=93=94=95=96=\n"],
[["\x97\x98\x99\x9a\x9b\x9c\x9d\x9e"], "=97=98=99=9A=9B=9C=9D=9E=\n"],
[["\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6"], "=9F=A0=A1=A2=A3=A4=A5=A6=\n"],
[["\xa7\xa8\xa9\xaa\xab\xac\xad\xae"], "=A7=A8=A9=AA=AB=AC=AD=AE=\n"],
[["\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6"], "=AF=B0=B1=B2=B3=B4=B5=B6=\n"],
[["\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe"], "=B7=B8=B9=BA=BB=BC=BD=BE=\n"],
[["\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"], "=BF=C0=C1=C2=C3=C4=C5=C6=\n"],
[["\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce"], "=C7=C8=C9=CA=CB=CC=CD=CE=\n"],
[["\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6"], "=CF=D0=D1=D2=D3=D4=D5=D6=\n"],
[["\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde"], "=D7=D8=D9=DA=DB=DC=DD=DE=\n"],
[["\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6"], "=DF=E0=E1=E2=E3=E4=E5=E6=\n"],
[["\xe7\xe8\xe9\xea\xeb\xec\xed\xee"], "=E7=E8=E9=EA=EB=EC=ED=EE=\n"],
[["\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6"], "=EF=F0=F1=F2=F3=F4=F5=F6=\n"],
[["\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe"], "=F7=F8=F9=FA=FB=FC=FD=FE=\n"],
[["\xff"], "=FF=\n"]
].should be_computed_by(:pack, "M")
end
it "emits a soft line break when the output exceeds 72 characters when passed '*', 0, 1, or no count modifier" do
s1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
r1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=\na=\n"
s2 = "\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19"
r2 = "=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=19=\n=19=\n"
s3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x15a"
r3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=15=\na=\n"
s4 = "\x15aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x15a"
r4 = "=15aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=\na=15a=\n"
[ [[s1], "M", r1],
[[s1], "M0", r1],
[[s1], "M1", r1],
[[s2], "M", r2],
[[s2], "M0", r2],
[[s2], "M1", r2],
[[s3], "M", r3],
[[s3], "M0", r3],
[[s3], "M1", r3],
[[s4], "M", r4],
[[s4], "M0", r4],
[[s4], "M1", r4]
].should be_computed_by(:pack)
end
it "emits a soft line break when the output exceeds count characters" do
[ [["abcdefghi"], "M2", "abc=\ndef=\nghi=\n"],
[["abcdefghi"], "M3", "abcd=\nefgh=\ni=\n"],
[["abcdefghi"], "M4", "abcde=\nfghi=\n"],
[["abcdefghi"], "M5", "abcdef=\nghi=\n"],
[["abcdefghi"], "M6", "abcdefg=\nhi=\n"],
[["\x19\x19\x19\x19"], "M2", "=19=\n=19=\n=19=\n=19=\n"],
[["\x19\x19\x19\x19"], "M3", "=19=19=\n=19=19=\n"],
[["\x19\x19\x19\x19"], "M4", "=19=19=\n=19=19=\n"],
[["\x19\x19\x19\x19"], "M5", "=19=19=\n=19=19=\n"],
[["\x19\x19\x19\x19"], "M6", "=19=19=19=\n=19=\n"],
[["\x19\x19\x19\x19"], "M7", "=19=19=19=\n=19=\n"]
].should be_computed_by(:pack)
end
it "encodes a recursive array" do
empty = ArraySpecs.empty_recursive_array
empty.pack('M').should be_an_instance_of(String)
array = ArraySpecs.recursive_array
array.pack('M').should == "1=\n"
end
it "calls #to_s to convert an object to a String" do
obj = mock("pack M string")
obj.should_receive(:to_s).and_return("packing")
[obj].pack("M").should == "packing=\n"
end
it "converts the object to a String representation if #to_s does not return a String" do
obj = mock("pack M non-string")
obj.should_receive(:to_s).and_return(2)
[obj].pack("M").should be_an_instance_of(String)
end
it "encodes a Symbol as a String" do
[:symbol].pack("M").should == "symbol=\n"
end
it "encodes an Integer as a String" do
[ [[1], "1=\n"],
[[bignum_value], "#{bignum_value}=\n"]
].should be_computed_by(:pack, "M")
end
it "encodes a Float as a String" do
[1.0].pack("M").should == "1.0=\n"
end
it "converts Floats to the minimum unique representation" do
[1.0 / 3.0].pack("M").should == "0.3333333333333333=\n"
end
it "sets the output string to US-ASCII encoding" do
["abcd"].pack("M").encoding.should == Encoding::US_ASCII
end
end
describe "Array#pack with format 'm'" do
it_behaves_like :array_pack_basic, 'm'
it_behaves_like :array_pack_basic_non_float, 'm'
it_behaves_like :array_pack_arguments, 'm'
it "encodes an empty string as an empty string" do
[""].pack("m").should == ""
end
it "appends a newline to the end of the encoded string" do
["a"].pack("m").should == "YQ==\n"
end
it "encodes one element per directive" do
["abc", "DEF"].pack("mm").should == "YWJj\nREVG\n"
end
it "encodes 1, 2, or 3 characters in 4 output characters (Base64 encoding)" do
[ [["a"], "YQ==\n"],
[["ab"], "YWI=\n"],
[["abc"], "YWJj\n"],
[["abcd"], "YWJjZA==\n"],
[["abcde"], "YWJjZGU=\n"],
[["abcdef"], "YWJjZGVm\n"],
[["abcdefg"], "YWJjZGVmZw==\n"],
].should be_computed_by(:pack, "m")
end
it "emits a newline after complete groups of count / 3 input characters when passed a count modifier" do
["abcdefg"].pack("m3").should == "YWJj\nZGVm\nZw==\n"
end
it "implicitly has a count of 45 when passed '*', 1, 2 or no count modifier" do
s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
r = "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\nYWFhYWE=\n"
[ [[s], "m", r],
[[s], "m*", r],
[[s], "m1", r],
[[s], "m2", r],
].should be_computed_by(:pack)
end
it "encodes all ascii characters" do
[ [["\x00\x01\x02\x03\x04\x05\x06"], "AAECAwQFBg==\n"],
[["\a\b\t\n\v\f\r"], "BwgJCgsMDQ==\n"],
[["\x0E\x0F\x10\x11\x12\x13\x14\x15\x16"], "Dg8QERITFBUW\n"],
[["\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f"], "FxgZGhscHR4f\n"],
[["!\"\#$%&'()*+,-./"], "ISIjJCUmJygpKissLS4v\n"],
[["0123456789"], "MDEyMzQ1Njc4OQ==\n"],
[[":;<=>?@"], "Ojs8PT4/QA==\n"],
[["ABCDEFGHIJKLMNOPQRSTUVWXYZ"], "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=\n"],
[["[\\]^_`"], "W1xdXl9g\n"],
[["abcdefghijklmnopqrstuvwxyz"], "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=\n"],
[["{|}~"], "e3x9fg==\n"],
[["\x7f\xc2\x80\xc2\x81\xc2\x82\xc2\x83"], "f8KAwoHCgsKD\n"],
[["\xc2\x84\xc2\x85\xc2\x86\xc2\x87\xc2"], "woTChcKGwofC\n"],
[["\x88\xc2\x89\xc2\x8a\xc2\x8b\xc2\x8c"], "iMKJworCi8KM\n"],
[["\xc2\x8d\xc2\x8e\xc2\x8f\xc2\x90\xc2"], "wo3CjsKPwpDC\n"],
[["\x91\xc2\x92\xc2\x93\xc2\x94\xc2\x95"], "kcKSwpPClMKV\n"],
[["\xc2\x96\xc2\x97\xc2\x98\xc2\x99\xc2"], "wpbCl8KYwpnC\n"],
[["\x9a\xc2\x9b\xc2\x9c\xc2\x9d\xc2\x9e"], "msKbwpzCncKe\n"],
[["\xc2\x9f\xc2\xa0\xc2\xa1\xc2\xa2\xc2"], "wp/CoMKhwqLC\n"],
[["\xa3\xc2\xa4\xc2\xa5\xc2\xa6\xc2\xa7"], "o8KkwqXCpsKn\n"],
[["\xc2\xa8\xc2\xa9\xc2\xaa\xc2\xab\xc2"], "wqjCqcKqwqvC\n"],
[["\xac\xc2\xad\xc2\xae\xc2\xaf\xc2\xb0"], "rMKtwq7Cr8Kw\n"],
[["\xc2\xb1\xc2\xb2\xc2\xb3\xc2\xb4\xc2"], "wrHCssKzwrTC\n"],
[["\xb5\xc2\xb6\xc2\xb7\xc2\xb8\xc2\xb9"], "tcK2wrfCuMK5\n"],
[["\xc2\xba\xc2\xbb\xc2\xbc\xc2\xbd\xc2"], "wrrCu8K8wr3C\n"],
[["\xbe\xc2\xbf\xc3\x80\xc3\x81\xc3\x82"], "vsK/w4DDgcOC\n"],
[["\xc3\x83\xc3\x84\xc3\x85\xc3\x86\xc3"], "w4PDhMOFw4bD\n"],
[["\x87\xc3\x88\xc3\x89\xc3\x8a\xc3\x8b"], "h8OIw4nDisOL\n"],
[["\xc3\x8c\xc3\x8d\xc3\x8e\xc3\x8f\xc3"], "w4zDjcOOw4/D\n"],
[["\x90\xc3\x91\xc3\x92\xc3\x93\xc3\x94"], "kMORw5LDk8OU\n"],
[["\xc3\x95\xc3\x96\xc3\x97\xc3\x98\xc3"], "w5XDlsOXw5jD\n"],
[["\x99\xc3\x9a\xc3\x9b\xc3\x9c\xc3\x9d"], "mcOaw5vDnMOd\n"],
[["\xc3\x9e\xc3\x9f\xc3\xa0\xc3\xa1\xc3"], "w57Dn8Ogw6HD\n"],
[["\xa2\xc3\xa3\xc3\xa4\xc3\xa5\xc3\xa6"], "osOjw6TDpcOm\n"],
[["\xc3\xa7\xc3\xa8\xc3\xa9\xc3\xaa\xc3"], "w6fDqMOpw6rD\n"],
[["\xab\xc3\xac\xc3\xad\xc3\xae\xc3\xaf"], "q8Osw63DrsOv\n"],
[["\xc3\xb0\xc3\xb1\xc3\xb2\xc3\xb3\xc3"], "w7DDscOyw7PD\n"],
[["\xb4\xc3\xb5\xc3\xb6\xc3\xb7\xc3\xb8"], "tMO1w7bDt8O4\n"],
[["\xc3\xb9\xc3\xba\xc3\xbb\xc3\xbc\xc3"], "w7nDusO7w7zD\n"],
[["\xbd\xc3\xbe\xc3\xbf"], "vcO+w78=\n"]
].should be_computed_by(:pack, "m")
end
it "calls #to_str to convert an object to a String" do
obj = mock("pack m string")
obj.should_receive(:to_str).and_return("abc")
[obj].pack("m").should == "YWJj\n"
end
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack m non-string")
lambda { [obj].pack("m") }.should raise_error(TypeError)
end
it "raises a TypeError if passed nil" do
lambda { [nil].pack("m") }.should raise_error(TypeError)
end
it "raises a TypeError if passed an Integer" do
lambda { [0].pack("m") }.should raise_error(TypeError)
lambda { [bignum_value].pack("m") }.should raise_error(TypeError)
end
it "does not emit a newline if passed zero as the count modifier" do
s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
r = "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE="
[s].pack("m0").should == r
end
it "sets the output string to US-ASCII encoding" do
["abcd"].pack("m").encoding.should == Encoding::US_ASCII
end
end

View file

@ -0,0 +1,25 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/integer', __FILE__)
describe "Array#pack with format 'N'" do
it_behaves_like :array_pack_basic, 'N'
it_behaves_like :array_pack_basic_non_float, 'N'
it_behaves_like :array_pack_arguments, 'N'
it_behaves_like :array_pack_numeric_basic, 'N'
it_behaves_like :array_pack_integer, 'N'
it_behaves_like :array_pack_no_platform, 'N'
it_behaves_like :array_pack_32bit_be, 'N'
end
describe "Array#pack with format 'n'" do
it_behaves_like :array_pack_basic, 'n'
it_behaves_like :array_pack_basic_non_float, 'n'
it_behaves_like :array_pack_arguments, 'n'
it_behaves_like :array_pack_numeric_basic, 'n'
it_behaves_like :array_pack_integer, 'n'
it_behaves_like :array_pack_no_platform, 'n'
it_behaves_like :array_pack_16bit_be, 'n'
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/basic', __FILE__)
describe "Array#pack with format 'P'" do
it_behaves_like :array_pack_basic_non_float, 'P'
end
describe "Array#pack with format 'p'" do
it_behaves_like :array_pack_basic_non_float, 'p'
end

View file

@ -0,0 +1,7 @@
require File.expand_path('../../../../spec_helper', __FILE__)
describe "Array#pack with format '%'" do
it "raises an Argument Error" do
lambda { [1].pack("%") }.should raise_error(ArgumentError)
end
end

View file

@ -0,0 +1,61 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/integer', __FILE__)
describe "Array#pack with format 'Q'" do
it_behaves_like :array_pack_basic, 'Q'
it_behaves_like :array_pack_basic_non_float, 'Q'
it_behaves_like :array_pack_arguments, 'Q'
it_behaves_like :array_pack_numeric_basic, 'Q'
it_behaves_like :array_pack_integer, 'Q'
end
describe "Array#pack with format 'q'" do
it_behaves_like :array_pack_basic, 'q'
it_behaves_like :array_pack_basic_non_float, 'q'
it_behaves_like :array_pack_arguments, 'q'
it_behaves_like :array_pack_numeric_basic, 'q'
it_behaves_like :array_pack_integer, 'q'
end
describe "Array#pack with format 'Q'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_64bit_le, 'Q<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_64bit_be, 'Q>'
end
end
describe "Array#pack with format 'q'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_64bit_le, 'q<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_64bit_be, 'q>'
end
end
little_endian do
describe "Array#pack with format 'Q'" do
it_behaves_like :array_pack_64bit_le, 'Q'
end
describe "Array#pack with format 'q'" do
it_behaves_like :array_pack_64bit_le, 'q'
end
end
big_endian do
describe "Array#pack with format 'Q'" do
it_behaves_like :array_pack_64bit_be, 'Q'
end
describe "Array#pack with format 'q'" do
it_behaves_like :array_pack_64bit_be, 'q'
end
end

View file

@ -0,0 +1,133 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/integer', __FILE__)
describe "Array#pack with format 'S'" do
it_behaves_like :array_pack_basic, 'S'
it_behaves_like :array_pack_basic_non_float, 'S'
it_behaves_like :array_pack_arguments, 'S'
it_behaves_like :array_pack_numeric_basic, 'S'
it_behaves_like :array_pack_integer, 'S'
end
describe "Array#pack with format 's'" do
it_behaves_like :array_pack_basic, 's'
it_behaves_like :array_pack_basic_non_float, 's'
it_behaves_like :array_pack_arguments, 's'
it_behaves_like :array_pack_numeric_basic, 's'
it_behaves_like :array_pack_integer, 's'
end
describe "Array#pack with format 'S'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_16bit_le, 'S<'
end
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_16bit_le, 'S<_'
it_behaves_like :array_pack_16bit_le, 'S_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_16bit_le, 'S<!'
it_behaves_like :array_pack_16bit_le, 'S!<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_16bit_be, 'S>'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_16bit_be, 'S>_'
it_behaves_like :array_pack_16bit_be, 'S_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_16bit_be, 'S>!'
it_behaves_like :array_pack_16bit_be, 'S!>'
end
end
describe "Array#pack with format 's'" do
describe "with modifier '<'" do
it_behaves_like :array_pack_16bit_le, 's<'
end
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_16bit_le, 's<_'
it_behaves_like :array_pack_16bit_le, 's_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_16bit_le, 's<!'
it_behaves_like :array_pack_16bit_le, 's!<'
end
describe "with modifier '>'" do
it_behaves_like :array_pack_16bit_be, 's>'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_16bit_be, 's>_'
it_behaves_like :array_pack_16bit_be, 's_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_16bit_be, 's>!'
it_behaves_like :array_pack_16bit_be, 's!>'
end
end
little_endian do
describe "Array#pack with format 'S'" do
it_behaves_like :array_pack_16bit_le, 'S'
end
describe "Array#pack with format 'S' with modifier '_'" do
it_behaves_like :array_pack_16bit_le, 'S_'
end
describe "Array#pack with format 'S' with modifier '!'" do
it_behaves_like :array_pack_16bit_le, 'S!'
end
describe "Array#pack with format 's'" do
it_behaves_like :array_pack_16bit_le, 's'
end
describe "Array#pack with format 's' with modifier '_'" do
it_behaves_like :array_pack_16bit_le, 's_'
end
describe "Array#pack with format 's' with modifier '!'" do
it_behaves_like :array_pack_16bit_le, 's!'
end
end
big_endian do
describe "Array#pack with format 'S'" do
it_behaves_like :array_pack_16bit_be, 'S'
end
describe "Array#pack with format 'S' with modifier '_'" do
it_behaves_like :array_pack_16bit_be, 'S_'
end
describe "Array#pack with format 'S' with modifier '!'" do
it_behaves_like :array_pack_16bit_be, 'S!'
end
describe "Array#pack with format 's'" do
it_behaves_like :array_pack_16bit_be, 's'
end
describe "Array#pack with format 's' with modifier '_'" do
it_behaves_like :array_pack_16bit_be, 's_'
end
describe "Array#pack with format 's' with modifier '!'" do
it_behaves_like :array_pack_16bit_be, 's!'
end
end

View file

@ -0,0 +1,65 @@
describe :array_pack_arguments, shared: true do
it "raises an ArgumentError if there are fewer elements than the format requires" do
lambda { [].pack(pack_format(1)) }.should raise_error(ArgumentError)
end
end
describe :array_pack_basic, shared: true do
before :each do
@obj = ArraySpecs.universal_pack_object
end
it "raises a TypeError when passed nil" do
lambda { [@obj].pack(nil) }.should raise_error(TypeError)
end
it "raises a TypeError when passed an Integer" do
lambda { [@obj].pack(1) }.should raise_error(TypeError)
end
end
describe :array_pack_basic_non_float, shared: true do
before :each do
@obj = ArraySpecs.universal_pack_object
end
it "ignores whitespace in the format string" do
[@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
end
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
[@obj, @obj].pack(d).should be_an_instance_of(String)
end
it "taints the output string if the format string is tainted" do
[@obj, @obj].pack("x"+pack_format.taint).tainted?.should be_true
end
end
describe :array_pack_basic_float, shared: true do
it "ignores whitespace in the format string" do
[9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
end
it "calls #to_str to coerce the directives string" do
d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format)
[1.2, 4.7].pack(d).should be_an_instance_of(String)
end
it "taints the output string if the format string is tainted" do
[3.2, 2.8].pack("x"+pack_format.taint).tainted?.should be_true
end
end
describe :array_pack_no_platform, shared: true do
it "raises ArgumentError when the format modifier is '_'" do
lambda{ [1].pack(pack_format("_")) }.should raise_error(ArgumentError)
end
it "raises ArgumentError when the format modifier is '!'" do
lambda{ [1].pack(pack_format("!")) }.should raise_error(ArgumentError)
end
end

View file

@ -0,0 +1,16 @@
describe :array_pack_hex, shared: true do
it "encodes no bytes when passed zero as the count modifier" do
["abc"].pack(pack_format(0)).should == ""
end
it "raises a TypeError if the object does not respond to #to_str" do
obj = mock("pack hex non-string")
lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
end
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack hex non-string")
obj.should_receive(:to_str).and_return(1)
lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
end
end

View file

@ -0,0 +1,249 @@
# -*- encoding: ascii-8bit -*-
describe :array_pack_float_le, shared: true do
it "encodes a positive Float" do
[1.42].pack(pack_format).should == "\x8f\xc2\xb5?"
end
it "encodes a negative Float" do
[-34.2].pack(pack_format).should == "\xcd\xcc\x08\xc2"
end
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "\x00\x00\x00A"
end
it "raises a TypeError if passed a String representation of a floating point number" do
lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
[2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "\x9a\x999@33\xb3?"
end
it "encodes all remaining elements when passed the '*' modifier" do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "\x9a\x999@33\xb3?33\x03A"
end
it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A"
end
it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "\x9a\x99\xa9@33\x13A"
end
it "encodes positive Infinity" do
[infinity_value].pack(pack_format).should == "\x00\x00\x80\x7f"
end
it "encodes negative Infinity" do
[-infinity_value].pack(pack_format).should == "\x00\x00\x80\xff"
end
platform_is "86" do # x86 / x86_64
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\x00\x00\xc0\xff"
end
end
platform_is "powerpc64" do
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\x00\x00\xc0\x7f"
end
end
it "encodes a positive Float outside the range of a single precision float" do
[1e150].pack(pack_format).should == "\x00\x00\x80\x7f"
end
it "encodes a negative Float outside the range of a single precision float" do
[-1e150].pack(pack_format).should == "\x00\x00\x80\xff"
end
end
describe :array_pack_float_be, shared: true do
it "encodes a positive Float" do
[1.42].pack(pack_format).should == "?\xb5\xc2\x8f"
end
it "encodes a negative Float" do
[-34.2].pack(pack_format).should == "\xc2\x08\xcc\xcd"
end
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "A\x00\x00\x00"
end
it "raises a TypeError if passed a String representation of a floating point number" do
lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
[2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "@9\x99\x9a?\xb333"
end
it "encodes all remaining elements when passed the '*' modifier" do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@9\x99\x9a?\xb333A\x0333"
end
it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333"
end
it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "@\xa9\x99\x9aA\x1333"
end
it "encodes positive Infinity" do
[infinity_value].pack(pack_format).should == "\x7f\x80\x00\x00"
end
it "encodes negative Infinity" do
[-infinity_value].pack(pack_format).should == "\xff\x80\x00\x00"
end
platform_is "86" do # x86 / x86_64
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\xff\xc0\x00\x00"
end
end
platform_is "powerpc64" do
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\x7f\xc0\x00\x00"
end
end
it "encodes a positive Float outside the range of a single precision float" do
[1e150].pack(pack_format).should == "\x7f\x80\x00\x00"
end
it "encodes a negative Float outside the range of a single precision float" do
[-1e150].pack(pack_format).should == "\xff\x80\x00\x00"
end
end
describe :array_pack_double_le, shared: true do
it "encodes a positive Float" do
[1.42].pack(pack_format).should == "\xb8\x1e\x85\xebQ\xb8\xf6?"
end
it "encodes a negative Float" do
[-34.2].pack(pack_format).should == "\x9a\x99\x99\x99\x99\x19A\xc0"
end
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\x20@"
end
it "raises a TypeError if passed a String representation of a floating point number" do
lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
[2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "333333\x07@ffffff\xf6?"
end
it "encodes all remaining elements when passed the '*' modifier" do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "333333\x07@ffffff\xf6?ffffff\x20@"
end
it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@"
end
it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "333333\x15@ffffff\x22@"
end
it "encodes positive Infinity" do
[infinity_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf0\x7f"
end
it "encodes negative Infinity" do
[-infinity_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf0\xff"
end
platform_is "86" do # x86 / x86_64
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf8\xff"
end
end
platform_is "powerpc64" do
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xf8\x7f"
end
end
it "encodes a positive Float outside the range of a single precision float" do
[1e150].pack(pack_format).should == "\xaf\x96P\x2e5\x8d\x13_"
end
it "encodes a negative Float outside the range of a single precision float" do
[-1e150].pack(pack_format).should == "\xaf\x96P\x2e5\x8d\x13\xdf"
end
end
describe :array_pack_double_be, shared: true do
it "encodes a positive Float" do
[1.42].pack(pack_format).should == "?\xf6\xb8Q\xeb\x85\x1e\xb8"
end
it "encodes a negative Float" do
[-34.2].pack(pack_format).should == "\xc0A\x19\x99\x99\x99\x99\x9a"
end
it "converts an Integer to a Float" do
[8].pack(pack_format).should == "@\x20\x00\x00\x00\x00\x00\x00"
end
it "raises a TypeError if passed a String representation of a floating point number" do
lambda { ["13"].pack(pack_format) }.should raise_error(TypeError)
end
it "encodes the number of array elements specified by the count modifier" do
[2.9, 1.4, 8.2].pack(pack_format(nil, 2)).should == "@\x07333333?\xf6ffffff"
end
it "encodes all remaining elements when passed the '*' modifier" do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@\x07333333?\xf6ffffff@\x20ffffff"
end
it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff"
end
it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "@\x15333333@\x22ffffff"
end
it "encodes positive Infinity" do
[infinity_value].pack(pack_format).should == "\x7f\xf0\x00\x00\x00\x00\x00\x00"
end
it "encodes negative Infinity" do
[-infinity_value].pack(pack_format).should == "\xff\xf0\x00\x00\x00\x00\x00\x00"
end
platform_is "86" do # x86 / x86_64
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\xff\xf8\x00\x00\x00\x00\x00\x00"
end
end
platform_is "powerpc64" do
it "encodes NaN" do
[nan_value].pack(pack_format).should == "\x7f\xf8\x00\x00\x00\x00\x00\x00"
end
end
it "encodes a positive Float outside the range of a single precision float" do
[1e150].pack(pack_format).should == "_\x13\x8d5\x2eP\x96\xaf"
end
it "encodes a negative Float outside the range of a single precision float" do
[-1e150].pack(pack_format).should == "\xdf\x13\x8d5\x2eP\x96\xaf"
end
end

View file

@ -0,0 +1,381 @@
# -*- encoding: ascii-8bit -*-
describe :array_pack_16bit_le, shared: true do
it "encodes the least significant 16 bits of a positive number" do
[ [[0x0000_0021], "\x21\x00"],
[[0x0000_4321], "\x21\x43"],
[[0x0065_4321], "\x21\x43"],
[[0x7865_4321], "\x21\x43"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the least significant 16 bits of a negative number" do
[ [[-0x0000_0021], "\xdf\xff"],
[[-0x0000_4321], "\xdf\xbc"],
[[-0x0065_4321], "\xdf\xbc"],
[[-0x7865_4321], "\xdf\xbc"]
].should be_computed_by(:pack, pack_format())
end
it "encodes a Float truncated as an Integer" do
[ [[2019902241.2], "\x21\x43"],
[[2019902241.8], "\x21\x43"],
[[-2019902241.2], "\xdf\xbc"],
[[-2019902241.8], "\xdf\xbc"]
].should be_computed_by(:pack, pack_format())
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(0x1234_5678)
[obj].pack(pack_format()).should == "\x78\x56"
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2))
str.should == "\x78\x65\xcd\xab"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*'))
str.should == "\x78\x65\xcd\xab\x21\x43"
end
it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x78\x65\xcd\xab"
end
it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
str.should == "\x78\x65\xcd\xab"
end
end
describe :array_pack_16bit_be, shared: true do
it "encodes the least significant 16 bits of a positive number" do
[ [[0x0000_0021], "\x00\x21"],
[[0x0000_4321], "\x43\x21"],
[[0x0065_4321], "\x43\x21"],
[[0x7865_4321], "\x43\x21"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the least significant 16 bits of a negative number" do
[ [[-0x0000_0021], "\xff\xdf"],
[[-0x0000_4321], "\xbc\xdf"],
[[-0x0065_4321], "\xbc\xdf"],
[[-0x7865_4321], "\xbc\xdf"]
].should be_computed_by(:pack, pack_format())
end
it "encodes a Float truncated as an Integer" do
[ [[2019902241.2], "\x43\x21"],
[[2019902241.8], "\x43\x21"],
[[-2019902241.2], "\xbc\xdf"],
[[-2019902241.8], "\xbc\xdf"]
].should be_computed_by(:pack, pack_format())
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(0x1234_5678)
[obj].pack(pack_format()).should == "\x56\x78"
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2))
str.should == "\x65\x78\xab\xcd"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*'))
str.should == "\x65\x78\xab\xcd\x43\x21"
end
it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x65\x78\xab\xcd"
end
it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
str.should == "\x65\x78\xab\xcd"
end
end
describe :array_pack_32bit_le, shared: true do
it "encodes the least significant 32 bits of a positive number" do
[ [[0x0000_0021], "\x21\x00\x00\x00"],
[[0x0000_4321], "\x21\x43\x00\x00"],
[[0x0065_4321], "\x21\x43\x65\x00"],
[[0x7865_4321], "\x21\x43\x65\x78"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the least significant 32 bits of a negative number" do
[ [[-0x0000_0021], "\xdf\xff\xff\xff"],
[[-0x0000_4321], "\xdf\xbc\xff\xff"],
[[-0x0065_4321], "\xdf\xbc\x9a\xff"],
[[-0x7865_4321], "\xdf\xbc\x9a\x87"]
].should be_computed_by(:pack, pack_format())
end
it "encodes a Float truncated as an Integer" do
[ [[2019902241.2], "\x21\x43\x65\x78"],
[[2019902241.8], "\x21\x43\x65\x78"],
[[-2019902241.2], "\xdf\xbc\x9a\x87"],
[[-2019902241.8], "\xdf\xbc\x9a\x87"]
].should be_computed_by(:pack, pack_format())
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(0x1234_5678)
[obj].pack(pack_format()).should == "\x78\x56\x34\x12"
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2))
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*'))
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
end
it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
end
end
describe :array_pack_32bit_be, shared: true do
it "encodes the least significant 32 bits of a positive number" do
[ [[0x0000_0021], "\x00\x00\x00\x21"],
[[0x0000_4321], "\x00\x00\x43\x21"],
[[0x0065_4321], "\x00\x65\x43\x21"],
[[0x7865_4321], "\x78\x65\x43\x21"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the least significant 32 bits of a negative number" do
[ [[-0x0000_0021], "\xff\xff\xff\xdf"],
[[-0x0000_4321], "\xff\xff\xbc\xdf"],
[[-0x0065_4321], "\xff\x9a\xbc\xdf"],
[[-0x7865_4321], "\x87\x9a\xbc\xdf"]
].should be_computed_by(:pack, pack_format())
end
it "encodes a Float truncated as an Integer" do
[ [[2019902241.2], "\x78\x65\x43\x21"],
[[2019902241.8], "\x78\x65\x43\x21"],
[[-2019902241.2], "\x87\x9a\xbc\xdf"],
[[-2019902241.8], "\x87\x9a\xbc\xdf"]
].should be_computed_by(:pack, pack_format())
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(0x1234_5678)
[obj].pack(pack_format()).should == "\x12\x34\x56\x78"
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2))
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*'))
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
end
it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
end
end
describe :array_pack_32bit_le_platform, shared: true do
it "encodes the least significant 32 bits of a number" do
[ [[0x7865_4321], "\x21\x43\x65\x78"],
[[-0x7865_4321], "\xdf\xbc\x9a\x87"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2))
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*'))
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
platform_is wordsize: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x21\x43\x65\x78"],
[[-0xff_7865_4321], "\xdf\xbc\x9a\x87"]
].should be_computed_by(:pack, pack_format())
end
end
end
describe :array_pack_32bit_be_platform, shared: true do
it "encodes the least significant 32 bits of a number" do
[ [[0x7865_4321], "\x78\x65\x43\x21"],
[[-0x7865_4321], "\x87\x9a\xbc\xdf"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format(2))
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0x1243_6578, 0xdef0_abcd, 0x7865_4321].pack(pack_format('*'))
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
platform_is wordsize: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x78\x65\x43\x21"],
[[-0xff_7865_4321], "\x87\x9a\xbc\xdf"]
].should be_computed_by(:pack, pack_format())
end
end
end
describe :array_pack_64bit_le, shared: true do
it "encodes the least significant 64 bits of a positive number" do
[ [[0x0000_0000_0000_0021], "\x21\x00\x00\x00\x00\x00\x00\x00"],
[[0x0000_0000_0000_4321], "\x21\x43\x00\x00\x00\x00\x00\x00"],
[[0x0000_0000_0065_4321], "\x21\x43\x65\x00\x00\x00\x00\x00"],
[[0x0000_0000_7865_4321], "\x21\x43\x65\x78\x00\x00\x00\x00"],
[[0x0000_0090_7865_4321], "\x21\x43\x65\x78\x90\x00\x00\x00"],
[[0x0000_ba90_7865_4321], "\x21\x43\x65\x78\x90\xba\x00\x00"],
[[0x00dc_ba90_7865_4321], "\x21\x43\x65\x78\x90\xba\xdc\x00"],
[[0x7edc_ba90_7865_4321], "\x21\x43\x65\x78\x90\xba\xdc\x7e"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the least significant 64 bits of a negative number" do
[ [[-0x0000_0000_0000_0021], "\xdf\xff\xff\xff\xff\xff\xff\xff"],
[[-0x0000_0000_0000_4321], "\xdf\xbc\xff\xff\xff\xff\xff\xff"],
[[-0x0000_0000_0065_4321], "\xdf\xbc\x9a\xff\xff\xff\xff\xff"],
[[-0x0000_0000_7865_4321], "\xdf\xbc\x9a\x87\xff\xff\xff\xff"],
[[-0x0000_0090_7865_4321], "\xdf\xbc\x9a\x87\x6f\xff\xff\xff"],
[[-0x0000_ba90_7865_4321], "\xdf\xbc\x9a\x87\x6f\x45\xff\xff"],
[[-0x00dc_ba90_7865_4321], "\xdf\xbc\x9a\x87\x6f\x45\x23\xff"],
[[-0x7edc_ba90_7865_4321], "\xdf\xbc\x9a\x87\x6f\x45\x23\x81"]
].should be_computed_by(:pack, pack_format())
end
it "encodes a Float truncated as an Integer" do
[ [[9.14138647331322368e+18], "\x00\x44\x65\x78\x90\xba\xdc\x7e"],
[[-9.14138647331322368e+18], "\x00\xbc\x9a\x87\x6f\x45\x23\x81"]
].should be_computed_by(:pack, pack_format())
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(0x1234_5678_90ab_cdef)
[obj].pack(pack_format()).should == "\xef\xcd\xab\x90\x78\x56\x34\x12"
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1234_5678_90ab_cdef,
0xdef0_abcd_3412_7856,
0x7865_4321_dcba_def0].pack(pack_format(2))
str.should == "\xef\xcd\xab\x90\x78\x56\x34\x12\x56\x78\x12\x34\xcd\xab\xf0\xde"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format('*'))
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end
it "ignores NULL bytes between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end
it "ignores spaces between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2))
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end
end
describe :array_pack_64bit_be, shared: true do
it "encodes the least significant 64 bits of a positive number" do
[ [[0x0000_0000_0000_0021], "\x00\x00\x00\x00\x00\x00\x00\x21"],
[[0x0000_0000_0000_4321], "\x00\x00\x00\x00\x00\x00\x43\x21"],
[[0x0000_0000_0065_4321], "\x00\x00\x00\x00\x00\x65\x43\x21"],
[[0x0000_0000_7865_4321], "\x00\x00\x00\x00\x78\x65\x43\x21"],
[[0x0000_0090_7865_4321], "\x00\x00\x00\x90\x78\x65\x43\x21"],
[[0x0000_ba90_7865_4321], "\x00\x00\xba\x90\x78\x65\x43\x21"],
[[0x00dc_ba90_7865_4321], "\x00\xdc\xba\x90\x78\x65\x43\x21"],
[[0x7edc_ba90_7865_4321], "\x7e\xdc\xba\x90\x78\x65\x43\x21"]
].should be_computed_by(:pack, pack_format())
end
it "encodes the least significant 64 bits of a negative number" do
[ [[-0x0000_0000_0000_0021], "\xff\xff\xff\xff\xff\xff\xff\xdf"],
[[-0x0000_0000_0000_4321], "\xff\xff\xff\xff\xff\xff\xbc\xdf"],
[[-0x0000_0000_0065_4321], "\xff\xff\xff\xff\xff\x9a\xbc\xdf"],
[[-0x0000_0000_7865_4321], "\xff\xff\xff\xff\x87\x9a\xbc\xdf"],
[[-0x0000_0090_7865_4321], "\xff\xff\xff\x6f\x87\x9a\xbc\xdf"],
[[-0x0000_ba90_7865_4321], "\xff\xff\x45\x6f\x87\x9a\xbc\xdf"],
[[-0x00dc_ba90_7865_4321], "\xff\x23\x45\x6f\x87\x9a\xbc\xdf"],
[[-0x7edc_ba90_7865_4321], "\x81\x23\x45\x6f\x87\x9a\xbc\xdf"]
].should be_computed_by(:pack, pack_format())
end
it "encodes a Float truncated as an Integer" do
[ [[9.14138647331322368e+18], "\x7e\xdc\xba\x90\x78\x65\x44\x00"],
[[-9.14138647331322368e+18], "\x81\x23\x45\x6f\x87\x9a\xbc\x00"]
].should be_computed_by(:pack, pack_format())
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(0x1234_5678_90ab_cdef)
[obj].pack(pack_format()).should == "\x12\x34\x56\x78\x90\xab\xcd\xef"
end
it "encodes the number of array elements specified by the count modifier" do
str = [0x1234_5678_90ab_cdef,
0xdef0_abcd_3412_7856,
0x7865_4321_dcba_def0].pack(pack_format(2))
str.should == "\x12\x34\x56\x78\x90\xab\xcd\xef\xde\xf0\xab\xcd\x34\x12\x78\x56"
end
it "encodes all remaining elements when passed the '*' modifier" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format('*'))
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end
it "ignores NULL bytes between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end
it "ignores spaces between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2))
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end
end

View file

@ -0,0 +1,44 @@
describe :array_pack_numeric_basic, shared: true do
it "returns an empty String if count is zero" do
[1].pack(pack_format(0)).should == ""
end
it "raises a TypeError when passed nil" do
lambda { [nil].pack(pack_format) }.should raise_error(TypeError)
end
it "raises a TypeError when passed true" do
lambda { [true].pack(pack_format) }.should raise_error(TypeError)
end
it "raises a TypeError when passed false" do
lambda { [false].pack(pack_format) }.should raise_error(TypeError)
end
it "returns an ASCII-8BIT string" do
[0xFF].pack(pack_format).encoding.should == Encoding::ASCII_8BIT
[0xE3, 0x81, 0x82].pack(pack_format(3)).encoding.should == Encoding::ASCII_8BIT
end
end
describe :array_pack_integer, shared: true do
it "raises a TypeError when the object does not respond to #to_int" do
obj = mock('not an integer')
lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
end
it "raises a TypeError when passed a String" do
lambda { ["5"].pack(pack_format) }.should raise_error(TypeError)
end
end
describe :array_pack_float, shared: true do
it "raises a TypeError if a String does not represent a floating point number" do
lambda { ["a"].pack(pack_format) }.should raise_error(TypeError)
end
it "raises a TypeError when the object does not respond to #to_f" do
obj = mock('not an float')
lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
end
end

View file

@ -0,0 +1,80 @@
# -*- encoding: binary -*-
describe :array_pack_string, shared: true do
it "adds count bytes of a String to the output" do
["abc"].pack(pack_format(2)).should == "ab"
end
it "implicitly has a count of one when no count is specified" do
["abc"].pack(pack_format).should == "a"
end
it "does not add any bytes when the count is zero" do
["abc"].pack(pack_format(0)).should == ""
end
it "is not affected by a previous count modifier" do
["abcde", "defg"].pack(pack_format(3)+pack_format).should == "abcd"
end
it "raises an ArgumentError when the Array is empty" do
lambda { [].pack(pack_format) }.should raise_error(ArgumentError)
end
it "raises an ArgumentError when the Array has too few elements" do
lambda { ["a"].pack(pack_format(nil, 2)) }.should raise_error(ArgumentError)
end
it "calls #to_str to convert the element to a String" do
obj = mock('pack string')
obj.should_receive(:to_str).and_return("abc")
[obj].pack(pack_format).should == "a"
end
it "raises a TypeError when the object does not respond to #to_str" do
obj = mock("not a string")
lambda { [obj].pack(pack_format) }.should raise_error(TypeError)
end
it "returns a tainted string when a pack argument is tainted" do
["abcd".taint, 0x20].pack(pack_format("3C")).tainted?.should be_true
end
it "does not return a tainted string when the array is tainted" do
["abcd", 0x20].taint.pack(pack_format("3C")).tainted?.should be_false
end
it "returns a tainted string when the format is tainted" do
["abcd", 0x20].pack(pack_format("3C").taint).tainted?.should be_true
end
it "returns a tainted string when an empty format is tainted" do
["abcd", 0x20].pack("".taint).tainted?.should be_true
end
it "returns a untrusted string when the format is untrusted" do
["abcd", 0x20].pack(pack_format("3C").untrust).untrusted?.should be_true
end
it "returns a untrusted string when the empty format is untrusted" do
["abcd", 0x20].pack("".untrust).untrusted?.should be_true
end
it "returns a untrusted string when a pack argument is untrusted" do
["abcd".untrust, 0x20].pack(pack_format("3C")).untrusted?.should be_true
end
it "returns a trusted string when the array is untrusted" do
["abcd", 0x20].untrust.pack(pack_format("3C")).untrusted?.should be_false
end
it "returns a string in encoding of common to the concatenated results" do
f = pack_format("*")
[ [["\u{3042 3044 3046 3048}", 0x2000B].pack(f+"U"), Encoding::ASCII_8BIT],
[["abcde\xd1", "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::ASCII_8BIT],
[["a".force_encoding("ascii"), "\xFF\xFe\x81\x82"].pack(f+"u"), Encoding::ASCII_8BIT],
# under discussion [ruby-dev:37294]
[["\u{3042 3044 3046 3048}", 1].pack(f+"N"), Encoding::ASCII_8BIT]
].should be_computed_by(:encoding)
end
end

View file

@ -0,0 +1,94 @@
# -*- encoding: utf-8 -*-
describe :array_pack_unicode, shared: true do
it "encodes ASCII values as a Unicode codepoint" do
[ [[0], "\x00"],
[[1], "\x01"],
[[8], "\x08"],
[[15], "\x0f"],
[[24], "\x18"],
[[31], "\x1f"],
[[127], "\x7f"],
[[128], "\xc2\x80"],
[[129], "\xc2\x81"],
[[255], "\xc3\xbf"]
].should be_computed_by(:pack, "U")
end
it "encodes UTF-8 BMP codepoints" do
[ [[0x80], "\xc2\x80"],
[[0x7ff], "\xdf\xbf"],
[[0x800], "\xe0\xa0\x80"],
[[0xffff], "\xef\xbf\xbf"]
].should be_computed_by(:pack, "U")
end
it "constructs strings with valid encodings" do
str = [0x85].pack("U*")
str.should == "\xc2\x85"
str.valid_encoding?.should be_true
end
it "encodes values larger than UTF-8 max codepoints" do
[
[[0x00110000], [244, 144, 128, 128].pack('C*').force_encoding('utf-8')],
[[0x04000000], [252, 132, 128, 128, 128, 128].pack('C*').force_encoding('utf-8')],
[[0x7FFFFFFF], [253, 191, 191, 191, 191, 191].pack('C*').force_encoding('utf-8')]
].should be_computed_by(:pack, "U")
end
it "encodes UTF-8 max codepoints" do
[ [[0x10000], "\xf0\x90\x80\x80"],
[[0xfffff], "\xf3\xbf\xbf\xbf"],
[[0x100000], "\xf4\x80\x80\x80"],
[[0x10ffff], "\xf4\x8f\xbf\xbf"]
].should be_computed_by(:pack, "U")
end
it "encodes the number of array elements specified by the count modifier" do
[ [[0x41, 0x42, 0x43, 0x44], "U2", "\x41\x42"],
[[0x41, 0x42, 0x43, 0x44], "U2U", "\x41\x42\x43"]
].should be_computed_by(:pack)
end
it "encodes all remaining elements when passed the '*' modifier" do
[0x41, 0x42, 0x43, 0x44].pack("U*").should == "\x41\x42\x43\x44"
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(5)
[obj].pack("U").should == "\x05"
end
it "raises a TypeError if #to_int does not return an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return("5")
lambda { [obj].pack("U") }.should raise_error(TypeError)
end
it "ignores NULL bytes between directives" do
[1, 2, 3].pack("U\x00U").should == "\x01\x02"
end
it "ignores spaces between directives" do
[1, 2, 3].pack("U U").should == "\x01\x02"
end
it "raises a RangeError if passed a negative number" do
lambda { [-1].pack("U") }.should raise_error(RangeError)
end
it "raises a RangeError if passed a number larger than an unsigned 32-bit integer" do
lambda { [2**32].pack("U") }.should raise_error(RangeError)
end
it "sets the output string to UTF-8 encoding" do
[ [[0x00].pack("U"), Encoding::UTF_8],
[[0x41].pack("U"), Encoding::UTF_8],
[[0x7F].pack("U"), Encoding::UTF_8],
[[0x80].pack("U"), Encoding::UTF_8],
[[0x10FFFF].pack("U"), Encoding::UTF_8]
].should be_computed_by(:encoding)
end
end

View file

@ -0,0 +1,128 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/unicode', __FILE__)
describe "Array#pack with format 'U'" do
it_behaves_like :array_pack_basic, 'U'
it_behaves_like :array_pack_basic_non_float, 'U'
it_behaves_like :array_pack_arguments, 'U'
it_behaves_like :array_pack_unicode, 'U'
end
describe "Array#pack with format 'u'" do
it_behaves_like :array_pack_basic, 'u'
it_behaves_like :array_pack_basic_non_float, 'u'
it_behaves_like :array_pack_arguments, 'u'
it "encodes an empty string as an empty string" do
[""].pack("u").should == ""
end
it "appends a newline to the end of the encoded string" do
["a"].pack("u").should == "!80``\n"
end
it "encodes one element per directive" do
["abc", "DEF"].pack("uu").should == "#86)C\n#1$5&\n"
end
it "prepends the length of each segment of the input string as the first character (+32) in each line of the output" do
["abcdefghijklm"].pack("u7").should == "&86)C9&5F\n&9VAI:FML\n!;0``\n"
end
it "encodes 1, 2, or 3 characters in 4 output characters (uuencoding)" do
[ [["a"], "!80``\n"],
[["ab"], "\"86(`\n"],
[["abc"], "#86)C\n"],
[["abcd"], "$86)C9```\n"],
[["abcde"], "%86)C9&4`\n"],
[["abcdef"], "&86)C9&5F\n"],
[["abcdefg"], "'86)C9&5F9P``\n"],
].should be_computed_by(:pack, "u")
end
it "emits a newline after complete groups of count / 3 input characters when passed a count modifier" do
["abcdefg"].pack("u3").should == "#86)C\n#9&5F\n!9P``\n"
end
it "implicitly has a count of 45 when passed '*', 0, 1, 2 or no count modifier" do
s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
r = "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n%86%A86$`\n"
[ [[s], "u", r],
[[s], "u*", r],
[[s], "u0", r],
[[s], "u1", r],
[[s], "u2", r],
].should be_computed_by(:pack)
end
it "encodes all ascii characters" do
[ [["\x00\x01\x02\x03\x04\x05\x06"], "'``$\"`P0%!@``\n"],
[["\a\b\t\n\v\f\r"], "'!P@)\"@L,#0``\n"],
[["\x0E\x0F\x10\x11\x12\x13\x14\x15\x16"], ")\#@\\0$1(3%!46\n"],
[["\x17\x18\x19\x1a\e\x1c\x1d\x1e\x1f"], ")%Q@9&AL<'1X?\n"],
[["!\"\#$%&'()*+,-./"], "/(2(C)\"4F)R@I*BLL+2XO\n"],
[["0123456789"], "*,\#$R,S0U-C<X.0``\n"],
[[":;<=>?@"], "'.CL\\/3X_0```\n"],
[["ABCDEFGHIJKLMNOPQRSTUVWXYZ"], ":04)#1$5&1TA)2DM,34Y/4%%24U155E=865H`\n"],
[["[\\]^_`"], "&6UQ=7E]@\n"],
[["abcdefghijklmnopqrstuvwxyz"], ":86)C9&5F9VAI:FML;6YO<'%R<W1U=G=X>7H`\n"],
[["{|}~"], "$>WQ]?@``\n"],
[["\x7f\xc2\x80\xc2\x81\xc2\x82\xc2\x83"], ")?\\*`PH'\"@L*#\n"],
[["\xc2\x84\xc2\x85\xc2\x86\xc2\x87\xc2"], ")PH3\"A<*&PH?\"\n"],
[["\x88\xc2\x89\xc2\x8a\xc2\x8b\xc2\x8c"], ")B,*)PHK\"B\\*,\n"],
[["\xc2\x8d\xc2\x8e\xc2\x8f\xc2\x90\xc2"], ")PHW\"CL*/PI#\"\n"],
[["\x91\xc2\x92\xc2\x93\xc2\x94\xc2\x95"], ")D<*2PI/\"E,*5\n"],
[["\xc2\x96\xc2\x97\xc2\x98\xc2\x99\xc2"], ")PI;\"E\\*8PIG\"\n"],
[["\x9a\xc2\x9b\xc2\x9c\xc2\x9d\xc2\x9e"], ")FL*;PIS\"G<*>\n"],
[["\xc2\x9f\xc2\xa0\xc2\xa1\xc2\xa2\xc2"], ")PI_\"H,*APJ+\"\n"],
[["\xa3\xc2\xa4\xc2\xa5\xc2\xa6\xc2\xa7"], ")H\\*DPJ7\"IL*G\n"],
[["\xc2\xa8\xc2\xa9\xc2\xaa\xc2\xab\xc2"], ")PJC\"J<*JPJO\"\n"],
[["\xac\xc2\xad\xc2\xae\xc2\xaf\xc2\xb0"], ")K,*MPJ[\"K\\*P\n"],
[["\xc2\xb1\xc2\xb2\xc2\xb3\xc2\xb4\xc2"], ")PK'\"LL*SPK3\"\n"],
[["\xb5\xc2\xb6\xc2\xb7\xc2\xb8\xc2\xb9"], ")M<*VPK?\"N,*Y\n"],
[["\xc2\xba\xc2\xbb\xc2\xbc\xc2\xbd\xc2"], ")PKK\"N\\*\\PKW\"\n"],
[["\xbe\xc2\xbf\xc3\x80\xc3\x81\xc3\x82"], ")OL*_PX#\#@<.\"\n"],
[["\xc3\x83\xc3\x84\xc3\x85\xc3\x86\xc3"], ")PX/#A,.%PX;#\n"],
[["\x87\xc3\x88\xc3\x89\xc3\x8a\xc3\x8b"], ")A\\.(PXG#BL.+\n"],
[["\xc3\x8c\xc3\x8d\xc3\x8e\xc3\x8f\xc3"], ")PXS#C<..PX_#\n"],
[["\x90\xc3\x91\xc3\x92\xc3\x93\xc3\x94"], ")D,.1PY+#D\\.4\n"],
[["\xc3\x95\xc3\x96\xc3\x97\xc3\x98\xc3"], ")PY7#EL.7PYC#\n"],
[["\x99\xc3\x9a\xc3\x9b\xc3\x9c\xc3\x9d"], ")F<.:PYO#G,.=\n"],
[["\xc3\x9e\xc3\x9f\xc3\xa0\xc3\xa1\xc3"], ")PY[#G\\.@PZ'#\n"],
[["\xa2\xc3\xa3\xc3\xa4\xc3\xa5\xc3\xa6"], ")HL.CPZ3#I<.F\n"],
[["\xc3\xa7\xc3\xa8\xc3\xa9\xc3\xaa\xc3"], ")PZ?#J,.IPZK#\n"],
[["\xab\xc3\xac\xc3\xad\xc3\xae\xc3\xaf"], ")J\\.LPZW#KL.O\n"],
[["\xc3\xb0\xc3\xb1\xc3\xb2\xc3\xb3\xc3"], ")P[##L<.RP[/#\n"],
[["\xb4\xc3\xb5\xc3\xb6\xc3\xb7\xc3\xb8"], ")M,.UP[;#M\\.X\n"],
[["\xc3\xb9\xc3\xba\xc3\xbb\xc3\xbc\xc3"], ")P[G#NL.[P[S#\n"],
[["\xbd\xc3\xbe\xc3\xbf"], "%O<.^P[\\`\n"]
].should be_computed_by(:pack, "u")
end
it "calls #to_str to convert an object to a String" do
obj = mock("pack m string")
obj.should_receive(:to_str).and_return("abc")
[obj].pack("u").should == "#86)C\n"
end
it "raises a TypeError if #to_str does not return a String" do
obj = mock("pack m non-string")
lambda { [obj].pack("u") }.should raise_error(TypeError)
end
it "raises a TypeError if passed nil" do
lambda { [nil].pack("u") }.should raise_error(TypeError)
end
it "raises a TypeError if passed an Integer" do
lambda { [0].pack("u") }.should raise_error(TypeError)
lambda { [bignum_value].pack("u") }.should raise_error(TypeError)
end
it "sets the output string to US-ASCII encoding" do
["abcd"].pack("u").encoding.should == Encoding::US_ASCII
end
end

View file

@ -0,0 +1,25 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
require File.expand_path('../shared/integer', __FILE__)
describe "Array#pack with format 'V'" do
it_behaves_like :array_pack_basic, 'V'
it_behaves_like :array_pack_basic_non_float, 'V'
it_behaves_like :array_pack_arguments, 'V'
it_behaves_like :array_pack_numeric_basic, 'V'
it_behaves_like :array_pack_integer, 'V'
it_behaves_like :array_pack_no_platform, 'V'
it_behaves_like :array_pack_32bit_le, 'V'
end
describe "Array#pack with format 'v'" do
it_behaves_like :array_pack_basic, 'v'
it_behaves_like :array_pack_basic_non_float, 'v'
it_behaves_like :array_pack_arguments, 'v'
it_behaves_like :array_pack_numeric_basic, 'v'
it_behaves_like :array_pack_integer, 'v'
it_behaves_like :array_pack_no_platform, 'v'
it_behaves_like :array_pack_16bit_le, 'v'
end

View file

@ -0,0 +1,42 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/numeric_basic', __FILE__)
describe "Array#pack with format 'w'" do
it_behaves_like :array_pack_basic, 'w'
it_behaves_like :array_pack_basic_non_float, 'w'
it_behaves_like :array_pack_arguments, 'w'
it_behaves_like :array_pack_numeric_basic, 'w'
it "encodes a BER-compressed integer" do
[ [[0], "\x00"],
[[1], "\x01"],
[[9999], "\xce\x0f"],
[[2**65], "\x84\x80\x80\x80\x80\x80\x80\x80\x80\x00"]
].should be_computed_by(:pack, "w")
end
it "calls #to_int to convert the pack argument to an Integer" do
obj = mock('to_int')
obj.should_receive(:to_int).and_return(5)
[obj].pack("w").should == "\x05"
end
it "ignores NULL bytes between directives" do
[1, 2, 3].pack("w\x00w").should == "\x01\x02"
end
it "ignores spaces between directives" do
[1, 2, 3].pack("w w").should == "\x01\x02"
end
it "raises an ArgumentError when passed a negative value" do
lambda { [-1].pack("w") }.should raise_error(ArgumentError)
end
it "returns an ASCII-8BIT string" do
[1].pack('w').encoding.should == Encoding::ASCII_8BIT
end
end

View file

@ -0,0 +1,64 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
describe "Array#pack with format 'x'" do
it_behaves_like :array_pack_basic, 'x'
it_behaves_like :array_pack_basic_non_float, 'x'
it_behaves_like :array_pack_no_platform, 'x'
it "adds a NULL byte with an empty array" do
[].pack("x").should == "\x00"
end
it "adds a NULL byte without consuming an element" do
[1, 2].pack("CxC").should == "\x01\x00\x02"
end
it "is not affected by a previous count modifier" do
[].pack("x3x").should == "\x00\x00\x00\x00"
end
it "adds multiple NULL bytes when passed a count modifier" do
[].pack("x3").should == "\x00\x00\x00"
end
it "does not add a NULL byte if the count modifier is zero" do
[].pack("x0").should == ""
end
it "does not add a NULL byte when passed the '*' modifier" do
[].pack("x*").should == ""
end
end
describe "Array#pack with format 'X'" do
it_behaves_like :array_pack_basic, 'X'
it_behaves_like :array_pack_basic_non_float, 'X'
it_behaves_like :array_pack_no_platform, 'X'
it "reduces the output string by one byte at the point it is encountered" do
[1, 2, 3].pack("C2XC").should == "\x01\x03"
end
it "does not consume any elements" do
[1, 2, 3].pack("CXC").should == "\x02"
end
it "reduces the output string by multiple bytes when passed a count modifier" do
[1, 2, 3, 4, 5].pack("C2X2C").should == "\x03"
end
it "has no affect when passed the '*' modifier" do
[1, 2, 3].pack("C2X*C").should == "\x01\x02\x03"
end
it "raises an ArgumentError if the output string is empty" do
lambda { [1, 2, 3].pack("XC") }.should raise_error(ArgumentError)
end
it "raises an ArgumentError if the count modifier is greater than the bytes in the string" do
lambda { [1, 2, 3].pack("C2X3") }.should raise_error(ArgumentError)
end
end

View file

@ -0,0 +1,32 @@
# -*- encoding: ascii-8bit -*-
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
require File.expand_path('../shared/basic', __FILE__)
require File.expand_path('../shared/string', __FILE__)
describe "Array#pack with format 'Z'" do
it_behaves_like :array_pack_basic, 'Z'
it_behaves_like :array_pack_basic_non_float, 'Z'
it_behaves_like :array_pack_no_platform, 'Z'
it_behaves_like :array_pack_string, 'Z'
it "adds all the bytes and appends a NULL byte when passed the '*' modifier" do
["abc"].pack("Z*").should == "abc\x00"
end
it "padds the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("Z6").should == "abc\x00\x00\x00"
end
it "adds a NULL byte when the value is nil" do
[nil].pack("Z").should == "\x00"
end
it "pads the output with NULL bytes when the value is nil" do
[nil].pack("Z3").should == "\x00\x00\x00"
end
it "does not append a NULL byte when passed the '*' modifier and the value is nil" do
[nil].pack("Z*").should == "\x00"
end
end

View file

@ -0,0 +1,43 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#partition" do
it "returns two arrays" do
[].partition {}.should == [[], []]
end
it "returns in the left array values for which the block evaluates to true" do
ary = [0, 1, 2, 3, 4, 5]
ary.partition { |i| true }.should == [ary, []]
ary.partition { |i| 5 }.should == [ary, []]
ary.partition { |i| false }.should == [[], ary]
ary.partition { |i| nil }.should == [[], ary]
ary.partition { |i| i % 2 == 0 }.should == [[0, 2, 4], [1, 3, 5]]
ary.partition { |i| i / 3 == 0 }.should == [[0, 1, 2], [3, 4, 5]]
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.partition { true }.should == [[empty], []]
empty.partition { false }.should == [[], [empty]]
array = ArraySpecs.recursive_array
array.partition { true }.should == [
[1, 'two', 3.0, array, array, array, array, array],
[]
]
condition = true
array.partition { condition = !condition }.should == [
['two', array, array, array],
[1, 3.0, array, array]
]
end
it "does not return subclass instances on Array subclasses" do
result = ArraySpecs::MyArray[1, 2, 3].partition { |x| x % 2 == 0 }
result.should be_an_instance_of(Array)
result[0].should be_an_instance_of(Array)
result[1].should be_an_instance_of(Array)
end
end

View file

@ -0,0 +1,138 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#permutation" do
before :each do
@numbers = (1..3).to_a
@yielded = []
end
it "returns an Enumerator of all permutations when called without a block or arguments" do
enum = @numbers.permutation
enum.should be_an_instance_of(Enumerator)
enum.to_a.sort.should == [
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
].sort
end
it "returns an Enumerator of permutations of given length when called with an argument but no block" do
enum = @numbers.permutation(1)
enum.should be_an_instance_of(Enumerator)
enum.to_a.sort.should == [[1],[2],[3]]
end
it "yields all permutations to the block then returns self when called with block but no arguments" do
array = @numbers.permutation {|n| @yielded << n}
array.should be_an_instance_of(Array)
array.sort.should == @numbers.sort
@yielded.sort.should == [
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
].sort
end
it "yields all permutations of given length to the block then returns self when called with block and argument" do
array = @numbers.permutation(2) {|n| @yielded << n}
array.should be_an_instance_of(Array)
array.sort.should == @numbers.sort
@yielded.sort.should == [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]].sort
end
it "returns the empty permutation ([[]]) when the given length is 0" do
@numbers.permutation(0).to_a.should == [[]]
@numbers.permutation(0) { |n| @yielded << n }
@yielded.should == [[]]
end
it "returns the empty permutation([]) when called on an empty Array" do
[].permutation.to_a.should == [[]]
[].permutation { |n| @yielded << n }
@yielded.should == [[]]
end
it "returns no permutations when the given length has no permutations" do
@numbers.permutation(9).entries.size == 0
@numbers.permutation(9) { |n| @yielded << n }
@yielded.should == []
end
it "handles duplicate elements correctly" do
@numbers << 1
@numbers.permutation(2).sort.should == [
[1,1],[1,1],[1,2],[1,2],[1,3],[1,3],
[2,1],[2,1],[2,3],
[3,1],[3,1],[3,2]
].sort
end
it "handles nested Arrays correctly" do
# The ugliness is due to the order of permutations returned by
# permutation being undefined combined with #sort croaking on Arrays of
# Arrays.
@numbers << [4,5]
got = @numbers.permutation(2).to_a
expected = [
[1, 2], [1, 3], [1, [4, 5]],
[2, 1], [2, 3], [2, [4, 5]],
[3, 1], [3, 2], [3, [4, 5]],
[[4, 5], 1], [[4, 5], 2], [[4, 5], 3]
]
expected.each {|e| got.include?(e).should be_true}
got.size.should == expected.size
end
it "truncates Float arguments" do
@numbers.permutation(3.7).to_a.sort.should ==
@numbers.permutation(3).to_a.sort
end
it "returns an Enumerator which works as expected even when the array was modified" do
@numbers = [1, 2]
enum = @numbers.permutation
@numbers << 3
enum.to_a.sort.should == [
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
].sort
end
it "generates from a defensive copy, ignoring mutations" do
accum = []
ary = [1,2,3]
ary.permutation(3) do |x|
accum << x
ary[0] = 5
end
accum.should == [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
end
describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
describe "with an array size greater than 0" do
it "returns the descending factorial of array size and given length" do
@numbers.permutation(4).size.should == 0
@numbers.permutation(3).size.should == 6
@numbers.permutation(2).size.should == 6
@numbers.permutation(1).size.should == 3
@numbers.permutation(0).size.should == 1
end
it "returns the descending factorial of array size with array size when there's no param" do
@numbers.permutation.size.should == 6
[1,2,3,4].permutation.size.should == 24
[1].permutation.size.should == 1
end
end
describe "with an empty array" do
it "returns 1 when the given length is 0" do
[].permutation(0).size.should == 1
end
it "returns 1 when there's param" do
[].permutation.size.should == 1
end
end
end
end
end
end

View file

@ -0,0 +1,57 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#+" do
it "concatenates two arrays" do
([ 1, 2, 3 ] + [ 3, 4, 5 ]).should == [1, 2, 3, 3, 4, 5]
([ 1, 2, 3 ] + []).should == [1, 2, 3]
([] + [ 1, 2, 3 ]).should == [1, 2, 3]
([] + []).should == []
end
it "can concatenate an array with itself" do
ary = [1, 2, 3]
(ary + ary).should == [1, 2, 3, 1, 2, 3]
end
it "tries to convert the passed argument to an Array using #to_ary" do
obj = mock('["x", "y"]')
obj.should_receive(:to_ary).and_return(["x", "y"])
([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
(empty + empty).should == [empty, empty]
array = ArraySpecs.recursive_array
(empty + array).should == [empty, 1, 'two', 3.0, array, array, array, array, array]
(array + array).should == [
1, 'two', 3.0, array, array, array, array, array,
1, 'two', 3.0, array, array, array, array, array]
end
it "does return subclass instances with Array subclasses" do
(ArraySpecs::MyArray[1, 2, 3] + []).should be_an_instance_of(Array)
(ArraySpecs::MyArray[1, 2, 3] + ArraySpecs::MyArray[]).should be_an_instance_of(Array)
([1, 2, 3] + ArraySpecs::MyArray[]).should be_an_instance_of(Array)
end
it "does not call to_ary on array subclasses" do
([5, 6] + ArraySpecs::ToAryArray[1, 2]).should == [5, 6, 1, 2]
end
it "does not get infected even if an original array is tainted" do
([1, 2] + [3, 4]).tainted?.should be_false
([1, 2].taint + [3, 4]).tainted?.should be_false
([1, 2] + [3, 4].taint).tainted?.should be_false
([1, 2].taint + [3, 4].taint).tainted?.should be_false
end
it "does not infected even if an original array is untrusted" do
([1, 2] + [3, 4]).untrusted?.should be_false
([1, 2].untrust + [3, 4]).untrusted?.should be_false
([1, 2] + [3, 4].untrust).untrusted?.should be_false
([1, 2].untrust + [3, 4].untrust).untrusted?.should be_false
end
end

View file

@ -0,0 +1,168 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#pop" do
it "removes and returns the last element of the array" do
a = ["a", 1, nil, true]
a.pop.should == true
a.should == ["a", 1, nil]
a.pop.should == nil
a.should == ["a", 1]
a.pop.should == 1
a.should == ["a"]
a.pop.should == "a"
a.should == []
end
it "returns nil if there are no more elements" do
[].pop.should == nil
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.pop.should == []
array = ArraySpecs.recursive_array
array.pop.should == [1, 'two', 3.0, array, array, array, array]
end
it "keeps taint status" do
a = [1, 2].taint
a.pop
a.tainted?.should be_true
a.pop
a.tainted?.should be_true
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array.pop }.should raise_error(RuntimeError)
end
it "raises a RuntimeError on an empty frozen array" do
lambda { ArraySpecs.empty_frozen_array.pop }.should raise_error(RuntimeError)
end
it "keeps untrusted status" do
a = [1, 2].untrust
a.pop
a.untrusted?.should be_true
a.pop
a.untrusted?.should be_true
end
describe "passed a number n as an argument" do
it "removes and returns an array with the last n elements of the array" do
a = [1, 2, 3, 4, 5, 6]
a.pop(0).should == []
a.should == [1, 2, 3, 4, 5, 6]
a.pop(1).should == [6]
a.should == [1, 2, 3, 4, 5]
a.pop(2).should == [4, 5]
a.should == [1, 2, 3]
a.pop(3).should == [1, 2, 3]
a.should == []
end
it "returns an array with the last n elements even if shift was invoked" do
a = [1, 2, 3, 4]
a.shift
a.pop(3).should == [2, 3, 4]
end
it "returns a new empty array if there are no more elements" do
a = []
popped1 = a.pop(1)
popped1.should == []
a.should == []
popped2 = a.pop(2)
popped2.should == []
a.should == []
popped1.should_not equal(popped2)
end
it "returns whole elements if n exceeds size of the array" do
a = [1, 2, 3, 4, 5]
a.pop(6).should == [1, 2, 3, 4, 5]
a.should == []
end
it "does not return self even when it returns whole elements" do
a = [1, 2, 3, 4, 5]
a.pop(5).should_not equal(a)
a = [1, 2, 3, 4, 5]
a.pop(6).should_not equal(a)
end
it "raises an ArgumentError if n is negative" do
lambda{ [1, 2, 3].pop(-1) }.should raise_error(ArgumentError)
end
it "tries to convert n to an Integer using #to_int" do
a = [1, 2, 3, 4]
a.pop(2.3).should == [3, 4]
obj = mock('to_int')
obj.should_receive(:to_int).and_return(2)
a.should == [1, 2]
a.pop(obj).should == [1, 2]
a.should == []
end
it "raises a TypeError when the passed n can be coerced to Integer" do
lambda{ [1, 2].pop("cat") }.should raise_error(TypeError)
lambda{ [1, 2].pop(nil) }.should raise_error(TypeError)
end
it "raises an ArgumentError if more arguments are passed" do
lambda{ [1, 2].pop(1, 2) }.should raise_error(ArgumentError)
end
it "does not return subclass instances with Array subclass" do
ArraySpecs::MyArray[1, 2, 3].pop(2).should be_an_instance_of(Array)
end
it "returns an untainted array even if the array is tainted" do
ary = [1, 2].taint
ary.pop(2).tainted?.should be_false
ary.pop(0).tainted?.should be_false
end
it "keeps taint status" do
a = [1, 2].taint
a.pop(2)
a.tainted?.should be_true
a.pop(2)
a.tainted?.should be_true
end
it "returns a trusted array even if the array is untrusted" do
ary = [1, 2].untrust
ary.pop(2).untrusted?.should be_false
ary.pop(0).untrusted?.should be_false
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array.pop(2) }.should raise_error(RuntimeError)
lambda { ArraySpecs.frozen_array.pop(0) }.should raise_error(RuntimeError)
end
it "keeps untrusted status" do
a = [1, 2].untrust
a.pop(2)
a.untrusted?.should be_true
a.pop(2)
a.untrusted?.should be_true
end
end
end

View file

@ -0,0 +1,68 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#product" do
it "returns converted arguments using :to_ary" do
lambda{ [1].product(2..3) }.should raise_error(TypeError)
ar = ArraySpecs::ArrayConvertable.new(2,3)
[1].product(ar).should == [[1,2],[1,3]]
ar.called.should == :to_ary
end
it "returns the expected result" do
[1,2].product([3,4,5],[6,8]).should == [[1, 3, 6], [1, 3, 8], [1, 4, 6], [1, 4, 8], [1, 5, 6], [1, 5, 8],
[2, 3, 6], [2, 3, 8], [2, 4, 6], [2, 4, 8], [2, 5, 6], [2, 5, 8]]
end
it "has no required argument" do
[1,2].product.should == [[1],[2]]
end
it "returns an empty array when the argument is an empty array" do
[1, 2].product([]).should == []
end
it "does not attempt to produce an unreasonable number of products" do
a = (0..100).to_a
lambda do
a.product(a, a, a, a, a, a, a, a, a, a)
end.should raise_error(RangeError)
end
describe "when given a block" do
it "yields all combinations in turn" do
acc = []
[1,2].product([3,4,5],[6,8]){|array| acc << array}
acc.should == [[1, 3, 6], [1, 3, 8], [1, 4, 6], [1, 4, 8], [1, 5, 6], [1, 5, 8],
[2, 3, 6], [2, 3, 8], [2, 4, 6], [2, 4, 8], [2, 5, 6], [2, 5, 8]]
acc = []
[1,2].product([3,4,5],[],[6,8]){|array| acc << array}
acc.should be_empty
end
it "returns self" do
a = [1, 2, 3].freeze
a.product([1, 2]) { |p| p.first }.should == a
end
it "will ignore unreasonable numbers of products and yield anyway" do
a = (0..100).to_a
lambda do
a.product(a, a, a, a, a, a, a, a, a, a)
end.should raise_error(RangeError)
end
end
describe "when given an empty block" do
it "returns self" do
arr = [1,2]
arr.product([3,4,5],[6,8]){}.should equal(arr)
arr = []
arr.product([3,4,5],[6,8]){}.should equal(arr)
arr = [1,2]
arr.product([]){}.should equal(arr)
end
end
end

View file

@ -0,0 +1,36 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#push" do
it "appends the arguments to the array" do
a = [ "a", "b", "c" ]
a.push("d", "e", "f").should equal(a)
a.push().should == ["a", "b", "c", "d", "e", "f"]
a.push(5)
a.should == ["a", "b", "c", "d", "e", "f", 5]
a = [0, 1]
a.push(2)
a.should == [0, 1, 2]
end
it "isn't confused by previous shift" do
a = [ "a", "b", "c" ]
a.shift
a.push("foo")
a.should == ["b", "c", "foo"]
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.push(:last).should == [empty, :last]
array = ArraySpecs.recursive_array
array.push(:last).should == [1, 'two', 3.0, array, array, array, array, array, :last]
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array.push(1) }.should raise_error(RuntimeError)
lambda { ArraySpecs.frozen_array.push }.should raise_error(RuntimeError)
end
end

View file

@ -0,0 +1,38 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
describe "Array#rassoc" do
it "returns the first contained array whose second element is == object" do
ary = [[1, "a", 0.5], [2, "b"], [3, "b"], [4, "c"], [], [5], [6, "d"]]
ary.rassoc("a").should == [1, "a", 0.5]
ary.rassoc("b").should == [2, "b"]
ary.rassoc("d").should == [6, "d"]
ary.rassoc("z").should == nil
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.rassoc([]).should be_nil
[[empty, empty]].rassoc(empty).should == [empty, empty]
array = ArraySpecs.recursive_array
array.rassoc(array).should be_nil
[[empty, array]].rassoc(array).should == [empty, array]
end
it "calls elem == obj on the second element of each contained array" do
key = 'foobar'
o = mock('foobar')
def o.==(other); other == 'foobar'; end
[[1, :foobar], [2, o], [3, mock('foo')]].rassoc(key).should == [2, o]
end
it "does not check the last element in each contained but speficically the second" do
key = 'foobar'
o = mock('foobar')
def o.==(other); other == 'foobar'; end
[[1, :foobar, o], [2, o, 1], [3, mock('foo')]].rassoc(key).should == [2, o, 1]
end
end

View file

@ -0,0 +1,117 @@
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#reject" do
it "returns a new array without elements for which block is true" do
ary = [1, 2, 3, 4, 5]
ary.reject { true }.should == []
ary.reject { false }.should == ary
ary.reject { false }.object_id.should_not == ary.object_id
ary.reject { nil }.should == ary
ary.reject { nil }.object_id.should_not == ary.object_id
ary.reject { 5 }.should == []
ary.reject { |i| i < 3 }.should == [3, 4, 5]
ary.reject { |i| i % 2 == 0 }.should == [1, 3, 5]
end
it "returns self when called on an Array emptied with #shift" do
array = [1]
array.shift
array.reject { |x| true }.should == []
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty.reject { false }.should == [empty]
empty.reject { true }.should == []
array = ArraySpecs.recursive_array
array.reject { false }.should == [1, 'two', 3.0, array, array, array, array, array]
array.reject { true }.should == []
end
it "does not return subclass instance on Array subclasses" do
ArraySpecs::MyArray[1, 2, 3].reject { |x| x % 2 == 0 }.should be_an_instance_of(Array)
end
it "does not retain instance variables" do
array = []
array.instance_variable_set("@variable", "value")
array.reject { false }.instance_variable_get("@variable").should == nil
end
it_behaves_like :enumeratorize, :reject
it_behaves_like :enumeratorized_with_origin_size, :reject, [1,2,3]
end
describe "Array#reject!" do
it "removes elements for which block is true" do
a = [3, 4, 5, 6, 7, 8, 9, 10, 11]
a.reject! { |i| i % 2 == 0 }.should equal(a)
a.should == [3, 5, 7, 9, 11]
a.reject! { |i| i > 8 }
a.should == [3, 5, 7]
a.reject! { |i| i < 4 }
a.should == [5, 7]
a.reject! { |i| i == 5 }
a.should == [7]
a.reject! { true }
a.should == []
a.reject! { true }
a.should == []
end
it "properly handles recursive arrays" do
empty = ArraySpecs.empty_recursive_array
empty_dup = empty.dup
empty.reject! { false }.should == nil
empty.should == empty_dup
empty = ArraySpecs.empty_recursive_array
empty.reject! { true }.should == []
empty.should == []
array = ArraySpecs.recursive_array
array_dup = array.dup
array.reject! { false }.should == nil
array.should == array_dup
array = ArraySpecs.recursive_array
array.reject! { true }.should == []
array.should == []
end
it "returns nil when called on an Array emptied with #shift" do
array = [1]
array.shift
array.reject! { |x| true }.should == nil
end
it "returns nil if no changes are made" do
a = [1, 2, 3]
a.reject! { |i| i < 0 }.should == nil
a.reject! { true }
a.reject! { true }.should == nil
end
it "returns an Enumerator if no block given, and the array is frozen" do
ArraySpecs.frozen_array.reject!.should be_an_instance_of(Enumerator)
end
it "raises a RuntimeError on a frozen array" do
lambda { ArraySpecs.frozen_array.reject! {} }.should raise_error(RuntimeError)
end
it "raises a RuntimeError on an empty frozen array" do
lambda { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(RuntimeError)
end
it_behaves_like :enumeratorize, :reject!
it_behaves_like :enumeratorized_with_origin_size, :reject!, [1,2,3]
it_behaves_like :delete_if, :reject!
end

View file

@ -0,0 +1,84 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#repeated_combination" do
before :each do
@array = [10, 11, 12]
end
it "returns an enumerator when no block is provided" do
@array.repeated_combination(2).should be_an_instance_of(Enumerator)
end
it "returns self when a block is given" do
@array.repeated_combination(2){}.should equal(@array)
end
it "yields nothing for negative length and return self" do
@array.repeated_combination(-1){ fail }.should equal(@array)
@array.repeated_combination(-10){ fail }.should equal(@array)
end
it "yields the expected repeated_combinations" do
@array.repeated_combination(2).to_a.sort.should == [[10, 10], [10, 11], [10, 12], [11, 11], [11, 12], [12, 12]]
@array.repeated_combination(3).to_a.sort.should == [[10, 10, 10], [10, 10, 11], [10, 10, 12], [10, 11, 11], [10, 11, 12],
[10, 12, 12], [11, 11, 11], [11, 11, 12], [11, 12, 12], [12, 12, 12]]
end
it "yields [] when length is 0" do
@array.repeated_combination(0).to_a.should == [[]] # one repeated_combination of length 0
[].repeated_combination(0).to_a.should == [[]] # one repeated_combination of length 0
end
it "yields nothing when the array is empty and num is non zero" do
[].repeated_combination(5).to_a.should == [] # one repeated_combination of length 0
end
it "yields a partition consisting of only singletons" do
@array.repeated_combination(1).sort.to_a.should == [[10],[11],[12]]
end
it "accepts sizes larger than the original array" do
@array.repeated_combination(4).to_a.sort.should ==
[[10, 10, 10, 10], [10, 10, 10, 11], [10, 10, 10, 12],
[10, 10, 11, 11], [10, 10, 11, 12], [10, 10, 12, 12],
[10, 11, 11, 11], [10, 11, 11, 12], [10, 11, 12, 12],
[10, 12, 12, 12], [11, 11, 11, 11], [11, 11, 11, 12],
[11, 11, 12, 12], [11, 12, 12, 12], [12, 12, 12, 12]]
end
it "generates from a defensive copy, ignoring mutations" do
accum = []
@array.repeated_combination(2) do |x|
accum << x
@array[0] = 1
end
accum.sort.should == [[10, 10], [10, 11], [10, 12], [11, 11], [11, 12], [12, 12]]
end
describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
it "returns 0 when the combination_size is < 0" do
@array.repeated_combination(-1).size.should == 0
[].repeated_combination(-2).size.should == 0
end
it "returns 1 when the combination_size is 0" do
@array.repeated_combination(0).size.should == 1
[].repeated_combination(0).size.should == 1
end
it "returns the binomial coeficient between combination_size and array size + combination_size -1" do
@array.repeated_combination(5).size.should == 21
@array.repeated_combination(4).size.should == 15
@array.repeated_combination(3).size.should == 10
@array.repeated_combination(2).size.should == 6
@array.repeated_combination(1).size.should == 3
@array.repeated_combination(0).size.should == 1
[].repeated_combination(0).size.should == 1
[].repeated_combination(1).size.should == 0
end
end
end
end
end

View file

@ -0,0 +1,94 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#repeated_permutation" do
before :each do
@numbers = [10, 11, 12]
@permutations = [[10, 10], [10, 11], [10, 12], [11, 10], [11, 11], [11, 12], [12, 10], [12, 11], [12, 12]]
end
it "returns an Enumerator of all repeated permutations of given length when called without a block" do
enum = @numbers.repeated_permutation(2)
enum.should be_an_instance_of(Enumerator)
enum.to_a.sort.should == @permutations
end
it "yields all repeated_permutations to the block then returns self when called with block but no arguments" do
yielded = []
@numbers.repeated_permutation(2) {|n| yielded << n}.should equal(@numbers)
yielded.sort.should == @permutations
end
it "yields the empty repeated_permutation ([[]]) when the given length is 0" do
@numbers.repeated_permutation(0).to_a.should == [[]]
[].repeated_permutation(0).to_a.should == [[]]
end
it "does not yield when called on an empty Array with a nonzero argument" do
[].repeated_permutation(10).to_a.should == []
end
it "handles duplicate elements correctly" do
@numbers[-1] = 10
@numbers.repeated_permutation(2).sort.should ==
[[10, 10], [10, 10], [10, 10], [10, 10], [10, 11], [10, 11], [11, 10], [11, 10], [11, 11]]
end
it "truncates Float arguments" do
@numbers.repeated_permutation(3.7).to_a.sort.should ==
@numbers.repeated_permutation(3).to_a.sort
end
it "returns an Enumerator which works as expected even when the array was modified" do
@numbers.shift
enum = @numbers.repeated_permutation(2)
@numbers.unshift 10
enum.to_a.sort.should == @permutations
end
it "allows permutations larger than the number of elements" do
[1,2].repeated_permutation(3).sort.should ==
[[1, 1, 1], [1, 1, 2], [1, 2, 1],
[1, 2, 2], [2, 1, 1], [2, 1, 2],
[2, 2, 1], [2, 2, 2]]
end
it "generates from a defensive copy, ignoring mutations" do
accum = []
ary = [1,2]
ary.repeated_permutation(3) do |x|
accum << x
ary[0] = 5
end
accum.sort.should ==
[[1, 1, 1], [1, 1, 2], [1, 2, 1],
[1, 2, 2], [2, 1, 1], [2, 1, 2],
[2, 2, 1], [2, 2, 2]]
end
describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
it "returns 0 when combination_size is < 0" do
@numbers.repeated_permutation(-1).size.should == 0
[].repeated_permutation(-1).size.should == 0
end
it "returns array size ** combination_size" do
@numbers.repeated_permutation(4).size.should == 81
@numbers.repeated_permutation(3).size.should == 27
@numbers.repeated_permutation(2).size.should == 9
@numbers.repeated_permutation(1).size.should == 3
@numbers.repeated_permutation(0).size.should == 1
[].repeated_permutation(4).size.should == 0
[].repeated_permutation(3).size.should == 0
[].repeated_permutation(2).size.should == 0
[].repeated_permutation(1).size.should == 0
[].repeated_permutation(0).size.should == 1
end
end
end
end
end

View file

@ -0,0 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)
require File.expand_path('../shared/replace', __FILE__)
describe "Array#replace" do
it_behaves_like(:array_replace, :replace)
end

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