From 36c7f59f488dd7d116536c0f9864e7b47845ec45 Mon Sep 17 00:00:00 2001 From: David Gold Date: Thu, 9 Jul 2015 14:32:19 -0400 Subject: [PATCH] Add tests for abstractarray.jl Squashed: -Revision to fix error -Add test for `ind2sub` method -Remove definitions for `Base.unsafe_*` methods for test types; these methods should be tested against their definitions in Base --- test/abstractarray.jl | 286 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 284 insertions(+), 2 deletions(-) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 44e4194b189cf..1dae9ca2ef06b 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -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) @@ -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 @@ -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) @@ -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) @@ -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()