Skip to content

Commit

Permalink
Merge pull request #12086 from davidagold/abstractarraystest
Browse files Browse the repository at this point in the history
Add tests for `base/abstractarray.jl`
  • Loading branch information
mbauman committed Jul 10, 2015
2 parents 9593d05 + 36c7f59 commit f2f5585
Showing 1 changed file with 284 additions and 2 deletions.
286 changes: 284 additions & 2 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ Base.setindex!{T}(A::TSlow{T,4}, v, i1::Int, i2::Int, i3::Int, i4::Int) =
Base.setindex!{T}(A::TSlow{T,5}, v, i1::Int, i2::Int, i3::Int, i4::Int, i5::Int) =
(A.data[(i1,i2,i3,i4,i5)] = v)


import Base: trailingsize
const can_inline = Base.JLOptions().can_inline != 0
function test_scalar_indexing{T}(::Type{T}, shape)
Expand All @@ -85,6 +84,8 @@ function test_scalar_indexing{T}(::Type{T}, shape)
for i1 = 1:size(B, 1)
i += 1
@test A[i1,i2,i3,i4,i5] == B[i1,i2,i3,i4,i5] == i
@test A[i1,i2,i3,i4,i5] ==
Base.unsafe_getindex(B, i1, i2, i3, i4, i5) == i
end
end
end
Expand Down Expand Up @@ -117,6 +118,9 @@ function test_scalar_indexing{T}(::Type{T}, shape)
@test A[] == B[] == A[1] == B[1] == 1
# Test multidimensional scalar indexed assignment
C = T(Int, shape)
D1 = T(Int, shape)
D2 = T(Int, shape)
D3 = T(Int, shape)
i=0
for i5 = 1:trailingsize(B, 5)
for i4 = 1:size(B, 4)
Expand All @@ -125,12 +129,19 @@ function test_scalar_indexing{T}(::Type{T}, shape)
for i1 = 1:size(B, 1)
i += 1
C[i1,i2,i3,i4,i5] = i
# test general unsafe_setindex!
Base.unsafe_setindex!(D1, i, i1,i2,i3,i4,i5)
# test for dropping trailing dims
Base.unsafe_setindex!(D2, i, i1,i2,i3,i4,i5, 1, 1, 1)
# test for expanding index argument to appropriate dims
Base.unsafe_setindex!(D3, i, i1,i2,i3,i4)
end
end
end
end
end
@test C == B == A
@test D1 == D2 == C == B == A
@test D3[:, :, :, :, 1] == D2[:, :, :, :, 1]
# Test linear indexing and partial linear indexing
C = T(Int, shape)
fill!(C, 0)
Expand Down Expand Up @@ -180,7 +191,278 @@ function test_vector_indexing{T}(::Type{T}, shape)
@test B[1:end,1:end] == A[1:end,1:end] == reshape(1:N, shape[1], prod(shape[2:end]))
end

function test_primitives{T}(::Type{T}, shape)
N = prod(shape)
A = reshape(1:N, shape)
B = T(A)

# elsize{T}(::AbstractArray{T})
@test Base.elsize(B) == sizeof(T.parameters)

# last(a)
@test last(B) == B[length(B)]

# strides(a::AbstractArray)
strides_B = strides(B)
for (i, _stride) in enumerate(collect(strides_B))
@test _stride == stride(B, i)
end

# isassigned(a::AbstractArray, i::Int...)
j = rand(1:length(B))
@test isassigned(B, j) == true
if T == T24Linear
@test isassigned(B, length(B) + 1) == false
end

# reshape(a::AbstractArray, dims::Dims)
@test_throws ArgumentError reshape(B, (0, 1))

# copy!(dest::AbstractArray, src::AbstractArray)
@test_throws BoundsError copy!(Array(Int, 10), [1:11...])

# convert{T, N}(::Type{Array}, A::AbstractArray{T, N})
X = [1:10...]
@test convert(Array, X) == X
end

function test_in_bounds()
@test Base.in_bounds((5, 5, 5), 5) == true
end

type UnimplementedFastArray{T, N} <: AbstractArray{T, N} end
Base.linearindexing(::UnimplementedFastArray) = Base.LinearFast()

type UnimplementedSlowArray{T, N} <: AbstractArray{T, N} end
Base.linearindexing(::UnimplementedSlowArray) = Base.LinearSlow()

type UnimplementedArray{T, N} <: AbstractArray{T, N} end

function test_getindex_internals{T}(::Type{T}, shape)
N = prod(shape)
A = reshape(1:N, shape)
B = T(A)

@test getindex(A) == 1
@test getindex(B) == 1
@test Base.unsafe_getindex(A) == 1
@test Base.unsafe_getindex(B) == 1
end

function test_getindex_internals()
U = UnimplementedFastArray{Int, 2}()
V = UnimplementedSlowArray{Int, 2}()
@test_throws ErrorException getindex(U, 1)
@test_throws ErrorException Base.unsafe_getindex(U, 1)
@test_throws ErrorException getindex(V, 1, 1)
@test_throws ErrorException Base.unsafe_getindex(V, 1, 1)
end

function test_setindex!_internals{T}(::Type{T}, shape)
N = prod(shape)
A = reshape(1:N, shape)
B = T(A)

Base.unsafe_setindex!(B, 1)
@test B[1] == 1
end

function test_setindex!_internals()
U = UnimplementedFastArray{Int, 2}()
V = UnimplementedSlowArray{Int, 2}()
@test_throws ErrorException setindex!(U, 1)
@test_throws ErrorException Base.unsafe_setindex!(U, 1)
@test_throws ErrorException Base.unsafe_setindex!(U, 1, 1)
end

function test_get()
A = T24Linear([1:24...])
B = TSlow([1:24...])

@test get(A, (), 0) == Int[]
@test get(B, (), 0) == TSlow(Int, 0)
end

function test_cat()
A = T24Linear([1:24...])
b_int = reshape([1:27...], 3, 3, 3)
b_float = reshape(Float64[1:27...], 3, 3, 3)
b2hcat = Array(Float64, 3, 6, 3)
b1 = reshape([1:9...], 3, 3)
b2 = reshape([10:18...], 3, 3)
b3 = reshape([19:27...], 3, 3)
b2hcat[:, :, 1] = hcat(b1, b1)
b2hcat[:, :, 2] = hcat(b2, b2)
b2hcat[:, :, 3] = hcat(b3, b3)
b3hcat = Array(Float64, 3, 9, 3)
b3hcat[:, :, 1] = hcat(b1, b1, b1)
b3hcat[:, :, 2] = hcat(b2, b2, b2)
b3hcat[:, :, 3] = hcat(b3, b3, b3)
B = TSlow(b_int)
B1 = TSlow([1:24...])
B2 = TSlow([1:25...])
C1 = TSlow([1 2; 3 4])
C2 = TSlow([1 2 3; 4 5 6])
C3 = TSlow([1 2; 3 4; 5 6])
D = [1:24...]
i = rand(1:10)

@test cat(i) == Any[]
@test vcat() == Any[]
@test hcat() == Any[]
@test hcat(1, 1.0, 3, 3.0) == [1.0 1.0 3.0 3.0]
@test_throws ArgumentError hcat(B1, B2)
@test_throws ArgumentError vcat(C1, C2)

@test vcat(B) == B
@test hcat(B) == B
@test Base.typed_hcat(Float64, B) == TSlow(b_float)
@test Base.typed_hcat(Float64, B, B) == TSlow(b2hcat)
@test Base.typed_hcat(Float64, B, B, B) == TSlow(b3hcat)

@test vcat(B1, B2) == TSlow(vcat([1:24...], [1:25...]))
@test hcat(C1, C2) == TSlow([1 2 1 2 3; 3 4 4 5 6])
@test hcat(C1, C2, C1) == TSlow([1 2 1 2 3 1 2; 3 4 4 5 6 3 4])

# hvcat
for nbc in (1, 2, 3, 4, 5, 6)
@test hvcat(nbc, 1:120...) ==
transpose(reshape([1:120...], nbc, round(Int, 120 / nbc)))
end

@test_throws ArgumentError hvcat(7, 1:20...)
@test_throws ArgumentError hvcat((2), C1, C3)
@test_throws ArgumentError hvcat((1), C1, C2)
@test_throws ArgumentError hvcat((1), C2, C3)

tup = tuple(rand(1:10, i)...)
@test hvcat(tup) == []

# check for shape mismatch
@test_throws ArgumentError hvcat((2, 2), 1, 2, 3, 4, 5)
@test_throws ArgumentError Base.typed_hvcat(Int, (2, 2), 1, 2, 3, 4, 5)
# check for # of columns mismatch b/w rows
@test_throws ArgumentError hvcat((3, 2), 1, 2, 3, 4, 5, 6)
@test_throws ArgumentError Base.typed_hvcat(Int, (3, 2), 1, 2, 3, 4, 5, 6)
end

function test_ind2sub()
n = rand(2:5)
dims = tuple(rand(1:5, n)...)
len = prod(dims)
A = reshape(1:len, dims...)
I = ind2sub(dims, [1:len...])
for i in 1:len
idx = [ I[j][i] for j in 1:n ]
@test A[idx...] == A[i]
end
end

function test_cartesianmap()
f(x, y, z, B::Array) = push!(B, (x, y, z))
B = NTuple{3, Int}[]
cartesianmap(f, (3, 3, 3, 1), B)
@test B == NTuple{3, Int}[(1,1,1), (2,1,1), (3,1,1), (1,2,1), (2,2,1), (3,2,1),
(1,3,1), (2,3,1), (3,3,1), (1,1,2), (2,1,2), (3,1,2), (1,2,2), (2,2,2),
(3,2,2), (1,3,2), (2,3,2), (3,3,2), (1,1,3), (2,1,3), (3,1,3), (1,2,3),
(2,2,3), (3,2,3), (1,3,3), (2,3,3), (3,3,3)]
@test_throws ArgumentError cartesianmap(f, (1,), B)
end

type GenericIterator{N} end
Base.start{N}(::GenericIterator{N}) = 1
Base.next{N}(::GenericIterator{N}, i) = (i, i + 1)
Base.done{N}(::GenericIterator{N}, i) = i > N ? true : false

function test_map()

for typ in (Float16, Float32, Float64,
Int8, Int16, Int32, Int64, Int128,
UInt8, UInt16, UInt32, UInt64, UInt128
),
arg_typ in (Integer,
Signed,
Unsigned
)
X = typ[1:10...]
_typ = typeof(arg_typ(one(typ)))
@test map(arg_typ, X) == _typ[1:10...]
end

# generic map
f(x) = x + 1
I = GenericIterator{10}()
@test map(f, I) == Any[2:11...]

# AbstractArray map for 2 arg case
f(x, y) = x + y
A = Array(Int, 10)
B = Float64[1:10...]
C = Float64[1:10...]
@test Base.map_to!(f, 1, A, B, C) == Real[ 2 * i for i in 1:10 ]
@test map(f, Int[], Float64[]) == Float64[]

# AbstractArray map for N-arg case
f(x, y, z) = x + y + z
D = Float64[1:10...]

@test map!(f, A, B, C, D) == Int[ 3 * i for i in 1:10 ]
@test Base.map_to_n!(f, 1, A, (B, C, D)) == Real[ 3 * i for i in 1:10 ]
@test map(f, B, C, D) == Float64[ 3 * i for i in 1:10 ]
@test map(f, Int[], Int[], Complex{Int}[]) == Number[]
end

function test_map_promote()
A = [1:10...]
f(x) = iseven(x) ? 1.0 : 1
@test Base.map_promote(f, A) == fill(1.0, 10)
end

function test_UInt_indexing()
A = [1:100...]
_A = Expr(:quote, A)
for i in 1:100
_i8 = convert(UInt8, i)
_i16 = convert(UInt16, i)
_i32 = convert(UInt32, i)
for _i in (_i8, _i16, _i32)
@eval begin
@test $_A[$_i] == $i
end
end
end
end

function test_vcat_depwarn()
if (Base.JLOptions()).depwarn > 1
@test_throws ErrorException [1:10]
@test_throws ErrorException [[1, 2], [3, 4]]
@test_throws ErrorException [[1, 2], [3, 4], [5, 6]]
else
[1:10]
[[1, 2], [3, 4]]
[[1, 2], [3, 4], [5, 6]]
nothing
end
end

#----- run tests -------------------------------------------------------------#

for T in (T24Linear, TSlow), shape in ((24,), (2, 12), (2,3,4), (1,2,3,4), (4,3,2,1))
test_scalar_indexing(T, shape)
test_vector_indexing(T, shape)
test_primitives(T, shape)
test_getindex_internals(T, shape)
test_setindex!_internals(T, shape)
end
test_in_bounds()
test_getindex_internals()
test_setindex!_internals()
test_get()
test_cat()
test_ind2sub()
test_cartesianmap()
test_map()
test_map_promote()
test_UInt_indexing()
test_vcat_depwarn()

0 comments on commit f2f5585

Please sign in to comment.