Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for base/abstractarray.jl #12086

Merged
merged 1 commit into from
Jul 10, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()