#######################################################################
# Coverage.jl
# Take Julia test coverage results and bundle them up in JSONs
# https://github.com/IainNZ/Coverage.jl
#######################################################################

using Coverage, Base.Test, Compat
using Compat.String

# test our filename matching. These aren't exported functions but it's probably
# a good idea to have explicit tests for them, as they're used to match files
# that get deleted

@test Coverage.iscovfile("test.jl.cov")
@test Coverage.iscovfile("test.jl.2934.cov")
@test Coverage.iscovfile("/home/somebody/test.jl.2934.cov")
@test !Coverage.iscovfile("test.ji.2934.cov")
@test !Coverage.iscovfile("test.jl.2934.cove")
@test !Coverage.iscovfile("test.jicov")
@test !Coverage.iscovfile("test.c.cov")
@test Coverage.iscovfile("test.jl.cov", "test.jl")
@test !Coverage.iscovfile("test.jl.cov", "other.jl")
@test Coverage.iscovfile("test.jl.8392.cov", "test.jl")
@test Coverage.iscovfile("/somedir/test.jl.8392.cov", "/somedir/test.jl")
@test !Coverage.iscovfile("/otherdir/test.jl.cov", "/somedir/test.jl")

cd(Pkg.dir("Coverage")) do
    datadir = joinpath("test", "data")
    # Process a saved set of coverage data...
    r = process_file(joinpath(datadir,"Coverage.jl"))
    # ... and memory data
    analyze_malloc(datadir)
    lcov = IOBuffer()
    # we only have a single file, but we want to test on the Vector of file results
    LCOV.write(lcov, FileCoverage[r])
    open(joinpath(datadir, "expected.info")) do f
        @test takebuf_string(lcov) == readstring(f)
    end

    # Test a file from scratch
    srcname = joinpath("test", "data","testparser.jl")
    covname = srcname*".cov"
    # clean out any previous coverage files. Don't use clean_folder because we
    # need to preserve the pre-baked coverage file Coverage.jl.cov
    clean_file(srcname)
    cmdstr = "include(\"$srcname\"); using Base.Test; @test f2(2) == 4"
    run(`julia --code-coverage=user -e $cmdstr`)
    r = process_file(srcname, datadir)
    # The next one is the correct one, but julia & JuliaParser don't insert a line number after the 1-line @doc -> test
    # See https://github.com/JuliaLang/julia/issues/9663 (when this is fixed, can uncomment the next line on julia 0.4)
    target = Union{Int64,Void}[nothing, 1, nothing, 0, nothing, 0, nothing, nothing, nothing, 0, nothing, nothing, nothing, nothing, nothing, nothing, 0, nothing, nothing, 0, nothing, nothing, nothing, nothing]
    #target = Union{Int64,Void}[nothing, 1, nothing, 0, nothing, 0, nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, 0, nothing, nothing, 0, nothing, nothing, nothing, nothing]
    @test r.coverage[1:length(target)] == target

    covtarget = (sum(x->x != nothing && x > 0, target), sum(x->x != nothing, target))
    @test get_summary(r) == covtarget
    @test get_summary(process_folder(datadir)) != covtarget

    #json_data = Codecov.build_json_data(Codecov.process_folder("data"))
    #@test typeof(json_data["coverage"]["data/Coverage.jl"]) == Array{Union{Int64,Void},1}
    open("fakefile",true,true,true,false,false)
    @test isempty(Coverage.process_cov("fakefile",datadir))
    rm("fakefile")
end




######################
# codecovio.jl tests #
######################

"""
extracts the api URL from stdout in a codecov.io submit call
very helpful for testing codecovio.jl
"""
function extract_codecov_url(fun)
    originalSTDOUT = STDOUT

    (outRead, outWrite) = redirect_stdout()

    fun()

    close(outWrite)

    data = String(readavailable(outRead))

    close(outRead)
    redirect_stdout(originalSTDOUT)

    lines = split(data, "\n")

    url = "None"
    get_next = false
    for line in lines
        if get_next
            url = line
            get_next = false
        end
        if contains(line, "Codecov.io API URL")
            get_next = true
        end
    end

    #println("url: $(url)")
    @assert url != "None" "unable to find codecov api url in stdout, check for changes in codecovio.jl"
    return url
end



# empty file coverage for testing
fcs = FileCoverage[]

# setup base system ENV vars for testing
withenv(
    "CODECOV_URL" => nothing,
    "CODECOV_TOKEN" => nothing,
    "TRAVIS_BRANCH" => nothing,
    "TRAVIS_COMMIT" => nothing,
    "TRAVIS_PULL_REQUEST" => nothing,
    "TRAVIS_JOB_ID" => nothing,
    "TRAVIS_REPO_SLUG" => nothing,
    "TRAVIS_JOB_NUMBER" => nothing
    ) do

    # test local submission process

    # default values
    codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit_local(fcs; dry_run = true) )
    @test contains(codecov_url, "codecov.io")
    @test contains(codecov_url, "commit")
    @test contains(codecov_url, "branch")
    @test !contains(codecov_url, "service")

    # default values in depreciated call
    codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit_local(fcs) )
    @test contains(codecov_url, "codecov.io")
    @test contains(codecov_url, "commit")
    @test contains(codecov_url, "branch")
    @test !contains(codecov_url, "service")

    # env var url override
    withenv( "CODECOV_URL" => "https://enterprise-codecov-1.com" ) do

        codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit_local(fcs; dry_run = true) )
        @test contains(codecov_url, "enterprise-codecov-1.com")
        @test contains(codecov_url, "commit")
        @test contains(codecov_url, "branch")
        @test !contains(codecov_url, "service")

        # function argument url override
        codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit_local(fcs; dry_run = true, codecov_url = "https://enterprise-codecov-2.com") )
        @test contains(codecov_url, "enterprise-codecov-2.com")
        @test contains(codecov_url, "commit")
        @test contains(codecov_url, "branch")
        @test !contains(codecov_url, "service")

        # env var token
        withenv( "CODECOV_TOKEN" => "token_name_1" ) do

            codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit_local(fcs; dry_run = true) )
            @test contains(codecov_url, "enterprise-codecov-1.com")
            @test contains(codecov_url, "token=token_name_1")
            @test !contains(codecov_url, "service")

            # function argument token url override
            codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit_local(fcs; dry_run = true, token="token_name_2") )
            @test contains(codecov_url, "enterprise-codecov-1.com")
            @test contains(codecov_url, "token=token_name_2")
            @test !contains(codecov_url, "service")
        end
    end


    # test travis-ci submission process

    #setup travis env
    withenv(
        "TRAVIS_BRANCH" => "t_branch",
        "TRAVIS_COMMIT" => "t_commit",
        "TRAVIS_PULL_REQUEST" => "t_pr",
        "TRAVIS_JOB_ID" => "t_job_id",
        "TRAVIS_REPO_SLUG" => "t_slug",
        "TRAVIS_JOB_NUMBER" => "t_job_num"
        ) do

        # default values
        codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit(fcs; dry_run = true) )
        @test contains(codecov_url, "codecov.io")
        @test contains(codecov_url, "service=travis-org")
        @test contains(codecov_url, "branch=t_branch")
        @test contains(codecov_url, "commit=t_commit")
        @test contains(codecov_url, "pull_request=t_pr")
        @test contains(codecov_url, "job=t_job_id")
        @test contains(codecov_url, "slug=t_slug")
        @test contains(codecov_url, "build=t_job_num")

        # env var url override
        withenv( "CODECOV_URL" => "https://enterprise-codecov-1.com" ) do

            codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit(fcs; dry_run = true) )
            @test contains(codecov_url, "enterprise-codecov-1.com")
            @test contains(codecov_url, "service=travis-org")
            @test contains(codecov_url, "branch=t_branch")
            @test contains(codecov_url, "commit=t_commit")
            @test contains(codecov_url, "pull_request=t_pr")
            @test contains(codecov_url, "job=t_job_id")
            @test contains(codecov_url, "slug=t_slug")
            @test contains(codecov_url, "build=t_job_num")

            # function argument url override
            codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit(fcs; dry_run = true, codecov_url = "https://enterprise-codecov-2.com") )
            @test contains(codecov_url, "enterprise-codecov-2.com")
            @test contains(codecov_url, "service=travis-org")
            @test contains(codecov_url, "branch=t_branch")
            @test contains(codecov_url, "commit=t_commit")
            @test contains(codecov_url, "pull_request=t_pr")
            @test contains(codecov_url, "job=t_job_id")
            @test contains(codecov_url, "slug=t_slug")
            @test contains(codecov_url, "build=t_job_num")

            # env var token
            withenv( "CODECOV_TOKEN" => "token_name_1" ) do

                codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit(fcs; dry_run = true) )
                @test contains(codecov_url, "enterprise-codecov-1.com")
                @test contains(codecov_url, "token=token_name_1")
                @test contains(codecov_url, "branch=t_branch")
                @test contains(codecov_url, "commit=t_commit")
                @test contains(codecov_url, "pull_request=t_pr")
                @test contains(codecov_url, "job=t_job_id")
                @test contains(codecov_url, "slug=t_slug")
                @test contains(codecov_url, "build=t_job_num")

                # function argument token url override
                codecov_url = extract_codecov_url( () -> Coverage.Codecov.submit(fcs; dry_run = true, token="token_name_2") )
                @test contains(codecov_url, "enterprise-codecov-1.com")
                @test contains(codecov_url, "token=token_name_2")
                @test contains(codecov_url, "branch=t_branch")
                @test contains(codecov_url, "commit=t_commit")
                @test contains(codecov_url, "pull_request=t_pr")
                @test contains(codecov_url, "job=t_job_id")
                @test contains(codecov_url, "slug=t_slug")
                @test contains(codecov_url, "build=t_job_num")
            end
        end
    end

end
