Repository: JuliaLang/julia
File: test/arrayops.jl (Julia)

Code before:
            @test accumulate(op, arr, dims=10) ≈ arr

            if eltype(arr) in [Int, Float64] # eltype of out easy
                out = similar(arr)
                @test accumulate!(op, out, arr) ≈ accumulate_arr
                @test out ≈ accumulate_arr
            end
        end
        arr_cop = similar(arr)
        cumprod!(arr_cop, arr)
        @test arr_cop ≈ cumprod(arr)
    end

    # exotic indexing
    arr = randn(4)
    oarr = OffsetArray(arr, (-3,))
    @test accumulate(+, oarr).parent == accumulate(+, arr)
    @test accumulate(+, oarr, init = 10).parent == accumulate(+, arr; init = 10)

    @inferred accumulate(+, randn(3))
    @inferred accumulate(+, randn(3); init=1)

    # inbounds propagation
    Base.@propagate_inbounds op_bounds(a, b) = (1, 2)[a] + (1, 2)[b]
    @test_throws BoundsError accumulate(op_bounds, 1:10)
    @test_throws BoundsError Base.accumulate_pairwise(op_bounds, 1:10)

    # asymmetric operation
    op(x,y) = 2x+y
    @test accumulate(op, [10, 20, 30]) == [10, op(10, 20), op(op(10, 20), 30)] == [10, 40, 110]
    @test accumulate(op, [10 20 30], dims=2) == [10 op(10, 20) op(op(10, 20), 30)] == [10 40 110]

    #25506
    @test accumulate((acc, x) -> acc+x[1], [(1,2), (3,4), (5,6)]; init=0) == [1, 4, 9]
    @test accumulate(*, ['a', 'b']) == ["a", "ab"]
    @inferred accumulate(*, String[])
    @test accumulate(*, ['a' 'b'; 'c' 'd'], dims=1) == ["a" "b"; "ac" "bd"]
    @test accumulate(*, ['a' 'b'; 'c' 'd'], dims=2) == ["a" "ab"; "c" "cd"]

    # #53438
    v = [(1, 2), (3, 4)]
    @test_throws MethodError accumulate(+, v)
    @test_throws MethodError cumsum(v)
    @test_throws MethodError cumprod(v)
    @test_throws MethodError accumulate(+, v; init=(0, 0))
    @test_throws MethodError accumulate(+, v; dims=1, init=(0, 0))

    # Some checks to ensure we're identifying the widest needed eltype
    # as identified in PR 53461
    @testset "Base._accumulate_promote_op" begin
        # A somewhat contrived example where each call to `foo`

Review comment (suggestion):
This will always pass because tests are run with bounds checked :)

You can put this in boundscheck_exec to explicitly test it when checkbounds isn't entirely disabled.

You could also just test with `getindex` directly:

```julia
julia> accumulate(getindex, [1:10,2:10,2:10,2:10])
4-element Vector{UnitRange{Int64}}:
 1:10
 2:10
 3:11
 4:12

julia> accumulate((x,i)->getindex(x,i), [1:10,2:10,2:10,2:10])
ERROR: BoundsError: attempt to access 9-element UnitRange{Int64} at index [2:10]
```

Code after:
            @test accumulate(op, arr, dims=10) ≈ arr

            if eltype(arr) in [Int, Float64] # eltype of out easy
                out = similar(arr)
                @test accumulate!(op, out, arr) ≈ accumulate_arr
                @test out ≈ accumulate_arr
            end
        end
        arr_cop = similar(arr)
        cumprod!(arr_cop, arr)
        @test arr_cop ≈ cumprod(arr)
    end

    # exotic indexing
    arr = randn(4)
    oarr = OffsetArray(arr, (-3,))
    @test accumulate(+, oarr).parent == accumulate(+, arr)
    @test accumulate(+, oarr, init = 10).parent == accumulate(+, arr; init = 10)

    @inferred accumulate(+, randn(3))
    @inferred accumulate(+, randn(3); init=1)

    # asymmetric operation
    op(x,y) = 2x+y
    @test accumulate(op, [10, 20, 30]) == [10, op(10, 20), op(op(10, 20), 30)] == [10, 40, 110]
    @test accumulate(op, [10 20 30], dims=2) == [10 op(10, 20) op(op(10, 20), 30)] == [10 40 110]

    #25506
    @test accumulate((acc, x) -> acc+x[1], [(1,2), (3,4), (5,6)]; init=0) == [1, 4, 9]
    @test accumulate(*, ['a', 'b']) == ["a", "ab"]
    @inferred accumulate(*, String[])
    @test accumulate(*, ['a' 'b'; 'c' 'd'], dims=1) == ["a" "b"; "ac" "bd"]
    @test accumulate(*, ['a' 'b'; 'c' 'd'], dims=2) == ["a" "ab"; "c" "cd"]

    # #53438
    v = [(1, 2), (3, 4)]
    @test_throws MethodError accumulate(+, v)
    @test_throws MethodError cumsum(v)
    @test_throws MethodError cumprod(v)
    @test_throws MethodError accumulate(+, v; init=(0, 0))
    @test_throws MethodError accumulate(+, v; dims=1, init=(0, 0))

    # Some checks to ensure we're identifying the widest needed eltype
    # as identified in PR 53461
    @testset "Base._accumulate_promote_op" begin
        # A somewhat contrived example where each call to `foo`
        # will return a different type
        foo(x::Bool, y::Int)::Int = x + y
        foo(x::Int, y::Int)::Float64 = x + y
        foo(x::Float64, y::Int)::ComplexF64 = x + y * im
        foo(x::ComplexF64, y::Int)::String = string(x, "+", y)