swh:1:snp:a72e953ecd624a7df6e6196bbdd05851996c5e40
Raw File
Tip revision: 8c2c0d792a180d1d71936cf870370637c4308905 authored by Andy Ferris on 17 February 2018, 12:22:24 UTC
Add `@inbounds` annotation in `broadcast`
Tip revision: 8c2c0d7
loading.jl
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Test

# Tests for @__LINE__ inside and outside of macros
@test (@__LINE__) == 6

macro macro_caller_lineno()
    @test 9 == (@__LINE__) != __source__.line > 12
    return __source__.line
end

@test @macro_caller_lineno() == (@__LINE__) > 12

# @__LINE__ in a macro expands to the location of the macrocall in the source
# while __source__.line is the location of the macro caller
macro nested_LINE_expansion()
    return quote
        return (@emit_LINE, $(__source__.line))
    end
end
macro nested_LINE_expansion2()
    return :((@emit_LINE, $(__source__.line)))
end
macro emit_LINE()
    return quote
        (@__LINE__, $(__source__.line))
    end
end
@test (@emit_LINE) == ((@__LINE__) - 3, @__LINE__)
@test @nested_LINE_expansion() == ((@__LINE__() - 4, @__LINE__() - 12), @__LINE__())
@test @nested_LINE_expansion2() == ((@__LINE__() - 5, @__LINE__() - 9), @__LINE__())

loaded_files = String[]
push!(Base.include_callbacks, (mod::Module, fn::String) -> push!(loaded_files, fn))
include("test_sourcepath.jl")
@test length(loaded_files) == 1 && endswith(loaded_files[1], "test_sourcepath.jl")
pop!(Base.include_callbacks)
thefname = "the fname!//\\&\1*"
include_string_test_func = include_string(@__MODULE__, "include_string_test() = @__FILE__", thefname)
@test include_string_test_func() == thefname
@test include_string(@__MODULE__, "Base.source_path()", thefname) == Base.source_path()
@test basename(@__FILE__) == "loading.jl"
@test isabspath(@__FILE__)

@test isdir(@__DIR__)
@test @__DIR__() == dirname(@__FILE__)
let exename = `$(Base.julia_cmd()) --compiled-modules=yes --startup-file=no`,
    wd = sprint(show, abspath(pwd(), "")),
    s_dir = sprint(show, joinpath(realpath(tempdir()), ""))
    @test wd != s_dir
    @test readchomp(`$exename -E "@__DIR__" -i`) == wd
    @test readchomp(`$exename -E "cd(()->eval(:(@__DIR__)), $s_dir)" -i`) == s_dir
    @test readchomp(`$exename -E "@__DIR__"`) == wd # non-interactive
end

# Issue #5789 and PR #13542:
mktempdir() do dir
    cd(dir) do
        let true_filename = "cAsEtEsT.jl", lowered_filename="casetest.jl"
            touch(true_filename)
            @test Base.isfile_casesensitive(true_filename)
            @test !Base.isfile_casesensitive(lowered_filename)

            # check that case-sensitivity only applies to basename of a path:
            if isfile(lowered_filename) # case-insensitive filesystem
                mkdir("cAsEtEsT")
                touch(joinpath("cAsEtEsT", true_filename))
                @test Base.isfile_casesensitive(joinpath("casetest", true_filename))
                @test !Base.isfile_casesensitive(joinpath("casetest", lowered_filename))
            end
        end

        # Test Unicode normalization; pertinent for OS X
        let nfc_name = "\U00F4.jl"
            touch(nfc_name)
            @test Base.isfile_casesensitive(nfc_name)
        end
    end
end

import Base: SHA1, PkgId, load_path, identify_package, locate_package, version_slug
import UUIDs: UUID, uuid4, uuid_version
import Random: shuffle, randstring
using Test

saved_load_path = copy(LOAD_PATH)
saved_depot_path = copy(DEPOT_PATH)
push!(empty!(LOAD_PATH), "project")
push!(empty!(DEPOT_PATH), "depot")

@test load_path() == [abspath("project","Project.toml")]

@testset "project & manifest identify_package & locate_package" begin
    local path
    for (names, uuid, path) in [
        ("Foo",     "767738be-2f1f-45a9-b806-0234f3164144", "project/deps/Foo1/src/Foo.jl"      ),
        ("Bar.Foo", "6f418443-bd2e-4783-b551-cdbac608adf2", "project/deps/Foo2.jl/src/Foo.jl"   ),
        ("Bar",     "2a550a13-6bab-4a91-a4ee-dff34d6b99d0", "project/deps/Bar/src/Bar.jl"       ),
        ("Foo.Baz", "6801f525-dc68-44e8-a4e8-cabd286279e7", "depot/packages/Baz/81oL/src/Baz.jl"),
        ("Foo.Qux", "b5ec9b9c-e354-47fd-b367-a348bdc8f909", "project/deps/Qux.jl"               ),
    ]
        n = map(String, split(names, '.'))
        pkg = identify_package(n...)
        @test pkg == PkgId(UUID(uuid), n[end])
        @test joinpath(@__DIR__, normpath(path)) == locate_package(pkg)
    end
    @test identify_package("Baz") == nothing
    @test identify_package("Qux") == nothing
    @testset "equivalent package names" begin
        local classes = [
            ["Foo"],
            ["Bar", "Foo.Bar"],
            ["Foo.Baz", "Bar.Baz", "Foo.Bar.Baz"],
            ["Bar.Foo", "Foo.Bar.Foo", "Foo.Baz.Foo", "Bar.Baz.Foo"],
            ["Foo.Qux", "Foo.Baz.Qux", "Bar.Baz.Qux", "Foo.Bar.Foo.Qux",
             "Bar.Foo.Qux", "Foo.Baz.Foo.Qux", "Bar.Baz.Foo.Qux", "Foo.Bar.Baz.Foo.Qux"],
            ["Baz", "Qux", "Bar.Qux", "Bar.Baz.Bar", "Bar.Foo.Bar", "Bar.Foo.Baz",
             "Bar.Foo.Qux.Foo", "Bar.Foo.Qux.Bar", "Bar.Foo.Qux.Baz"],
        ]
        for i = 1:length(classes)
            A = classes[i]
            for x in A
                X = identify_package(map(String, split(x, '.'))...)
                for y in A
                    Y = identify_package(map(String, split(y, '.'))...)
                    @test X == Y
                end
                for j = i+1:length(classes)
                    B = classes[j]
                    for z in B
                        Z = identify_package(map(String, split(z, '.'))...)
                        @test X != Z
                    end
                end
            end
        end
    end
end

@testset "project & manifest import" begin
    @test !@isdefined Foo
    @test !@isdefined Bar
    import Foo
    @test @isdefined Foo
    @test !@isdefined Bar
    import Bar
    @test @isdefined Foo
    @test @isdefined Bar

    @testset "module graph structure" begin
        local classes = Dict(
            "Foo1" => [Foo],
            "Bar"  => [Bar, Foo.Bar],
            "Baz"  => [Foo.Baz, Bar.Baz, Foo.Bar.Baz],
            "Foo2" => [Bar.Foo, Foo.Bar.Foo, Foo.Baz.Foo, Bar.Baz.Foo],
            "Qux"  => [Foo.Qux, Foo.Baz.Qux, Bar.Baz.Qux, Foo.Bar.Foo.Qux,
                       Bar.Foo.Qux, Foo.Baz.Foo.Qux, Bar.Baz.Foo.Qux,
                       Foo.Bar.Baz.Foo.Qux],
        )
        for (i, (this, mods)) in enumerate(classes)
            for x in mods
                @test x.this == this
                for y in mods
                    @test x === y
                end
                for (j, (that, mods′)) in enumerate(classes)
                    i == j && continue
                    for z in mods′
                        @test x !== z
                    end
                end
            end
        end
    end
    @test Foo.which == "path"
end

function gen_entry_point(entry::String, pkg::PkgId)
    mkpath(dirname(entry))
    open(entry, "w") do io
        print(io, """
        __precompile__(true)
        module $(pkg.name)
        uuid = $(pkg.uuid === nothing ? "nothing" : "Base.UUID(\"$(pkg.uuid)\")")
        name = "$(pkg.name)"
        end
        """)
    end
end

function gen_project_file(project_file::String, pkg::PkgId, deps::Pair{String,UUID}...)
    mkpath(dirname(project_file))
    open(project_file, "w") do io
        println(io, "name = $(repr(pkg.name))")
        pkg.uuid !== nothing && println(io, "uuid = $(repr(string(pkg.uuid)))")
        println(io, "\n[deps]")
        for (name, uuid) in deps
            println(io, "$name = ", repr(string(uuid)))
        end
    end
end

function gen_implicit(dir::String, pkg::PkgId, proj::Bool, deps::Pair{String,UUID}...)
    entry_point = joinpath(dir, pkg.name, "src", "$(pkg.name).jl")
    gen_entry_point(entry_point, pkg)
    proj && gen_project_file(joinpath(dir, pkg.name, "Project.toml"), pkg, deps...)
    return entry_point
end

function gen_depot_ver(depot::String, pkg::PkgId, deps::Pair{String,UUID}...)
    pkg.uuid === nothing && return nothing, nothing
    tree = SHA1(rand(UInt8, 20)) # fake tree hash
    dir = joinpath(depot, "packages", version_slug(pkg.uuid, tree))
    entry = joinpath(dir, "src", "$(pkg.name).jl")
    gen_entry_point(entry, pkg)
    gen_project_file(joinpath(dir, "Project.toml"), pkg, deps...)
    return tree, entry
end

let n = 0
    global function gen_explicit(dir::String, pkg::PkgId=PkgId("Env$(n += 1)"))
        gen_project_file(joinpath(dir, "Project.toml"), pkg)
        close(open(joinpath(dir, "Manifest.toml"), "w"))
    end
end

function gen_manifest(dir::String, name::String, uuid::UUID, tree::SHA1,
    deps::Pair{String,UUID}...; toplevel::Bool = true)
    toplevel && open(joinpath(dir, "Project.toml"), "a") do io
        println(io, "$name = \"$uuid\"")
    end
    open(joinpath(dir, "Manifest.toml"), "a") do io
        println(io, "[[$name]]")
        println(io, "uuid = \"$uuid\"")
        println(io, "git-tree-sha1 = \"$(bytes2hex(tree.bytes))\"")
        if !isempty(deps)
            println(io, "    [$name.deps]")
            for (n, u) in deps
                println(io, "    $n = \"$u\"")
            end
        end
        println(io)
    end
end

false && let name = "Flarp"
uuidA = UUID("b2cb3794-8625-4058-bcde-7eeb13ac1c8b")
uuidB = UUID("1513c021-3639-4616-a37b-ee45c9d2f773")
uuids = [nothing, uuidA, uuidB]

ft(::UUID)    =  true:true
ft(::Nothing) = false:true

@testset "direct dependency loading: implict + implicit" begin
    for uuid1 in uuids, proj1 in ft(uuid1),
        uuid2 in uuids, proj2 in ft(uuid2)
        pkg1 = uuid1 === nothing ? PkgId(name) : PkgId(uuid1, name)
        pkg2 = uuid2 === nothing ? PkgId(name) : PkgId(uuid2, name)
        empty!(LOAD_PATH)
        mktempdir() do dir1
            push!(LOAD_PATH, dir1)
            path1 = gen_implicit(dir1, pkg1, proj1)
            @test identify_package(name) == pkg1
            @test locate_package(pkg1) == path1
            path = uuid1 == coalesce(uuid2, uuid1) ? path1 : nothing
            @test locate_package(pkg2) == path
            mktempdir() do dir2
                push!(LOAD_PATH, dir2)
                path2 = gen_implicit(dir2, pkg2, proj2)
                @test identify_package(name) == pkg1
                @test locate_package(pkg1) == path1
                path = uuid1 == coalesce(uuid2, uuid1) ? path1 : path2
                @test locate_package(pkg2) == path
            end
        end
    end
end

@testset "direct dependency loading: explicit + explicit" begin
    mktempdir() do depot
        push!(empty!(DEPOT_PATH), depot)
        pkgs  = [PkgId(uuid, name) for uuid in uuids]
        pairs = [gen_depot_ver(depot, pkg) for pkg in pkgs, _ in 1:2]
        trees = first.(pairs)
        paths = last.(pairs)
        for i = 1:length(uuids), k = 1:2,
            j = 1:length(uuids), l = 1:2
            uuids[i] !== nothing && uuids[j] !== nothing || continue
            empty!(LOAD_PATH)
            mktempdir() do dir1
                push!(LOAD_PATH, dir1)
                gen_explicit(dir1)
                gen_manifest(dir1, name, uuids[i], trees[i,k])
                @test identify_package(name) == pkgs[i]
                @test locate_package(pkgs[i]) == paths[i,k]
                path = uuids[i] == uuids[j] ? paths[i,k] : nothing
                @test locate_package(pkgs[j]) == path
                mktempdir() do dir2
                    push!(LOAD_PATH, dir2)
                    gen_explicit(dir2)
                    gen_manifest(dir2, name, uuids[j], trees[j,l])
                    @test identify_package(name) == pkgs[i]
                    @test locate_package(pkgs[i]) == paths[i,k]
                    path = uuids[i] == uuids[j] ? paths[i,k] : paths[j,l]
                    @test locate_package(pkgs[j]) == path
                end
            end
        end
    end
end

@testset "direct dependency loading: explicit + implicit" begin
    mktempdir() do depot
        push!(empty!(DEPOT_PATH), depot)
        pkgs  = [PkgId(uuid, name) for uuid in uuids]
        pairs = [gen_depot_ver(depot, pkg) for pkg in pkgs, _ in 1:2]
        trees = first.(pairs)
        paths = last.(pairs)
        for i = 1:length(uuids), k = 1:2,
            j = 1:length(uuids), l = 1:2, proj in ft(uuids[j])
            uuids[i] !== nothing || continue
            empty!(LOAD_PATH)
            mktempdir() do dir1
                push!(LOAD_PATH, dir1)
                gen_explicit(dir1)
                gen_manifest(dir1, name, uuids[i], trees[i,k])
                @test identify_package(name) == pkgs[i]
                @test locate_package(pkgs[i]) == paths[i,k]
                path = uuids[i] == coalesce(uuids[j], uuids[i]) ? paths[i,k] : nothing
                @test locate_package(pkgs[j]) == path
                mktempdir() do dir2
                    push!(LOAD_PATH, dir2)
                    path2 = gen_implicit(dir2, pkgs[j], proj)
                    @test identify_package(name) == pkgs[i]
                    @test locate_package(pkgs[i]) == paths[i,k]
                    path = uuids[i] == coalesce(uuids[j], uuids[i]) ? paths[i,k] : path2
                    @test locate_package(pkgs[j]) == path
                end
            end
        end
    end
end

uuidT = UUID("a54bd003-d8dc-4161-b186-d5516cd448e9")

@testset "indirect dependency loading: explicit + explicit" begin
    mktempdir() do depot
        push!(empty!(DEPOT_PATH), depot)
        # generate top-level package
        top = PkgId(uuidT, "TopLevel")
        top_tree, _ = gen_depot_ver(depot, top)
        # generate dependency packages
        pkgs  = [PkgId(uuid, name) for uuid in uuids]
        pairs = [gen_depot_ver(depot, pkg) for pkg in pkgs, _ in 1:2]
        trees = first.(pairs)
        paths = last.(pairs)
        for i = 1:length(uuids), k = 1:2, s = false:true,
            j = 1:length(uuids), l = 1:2, t = false:true
            uuids[i] !== nothing && uuids[j] !== nothing || continue
            empty!(LOAD_PATH)
            mktempdir() do dir1
                push!(LOAD_PATH, dir1)
                gen_explicit(dir1)
                gen_manifest(dir1, name, uuids[i], trees[i,k], toplevel=false)
                s && gen_manifest(dir1, top.name, top.uuid, top_tree, name => uuids[i])
                @test identify_package(top, name) == (s ? pkgs[i] : nothing)
                @test locate_package(pkgs[i]) == paths[i,k]
                path = uuids[i] == uuids[j] ? paths[i,k] : nothing
                @test locate_package(pkgs[j]) == path
                mktempdir() do dir2
                    push!(LOAD_PATH, dir2)
                    gen_explicit(dir2)
                    t && gen_manifest(dir1, top.name, top.uuid, top_tree, name => uuids[j])
                    gen_manifest(dir2, name, uuids[j], trees[j,l], toplevel=false)
                    pkg = (s ? pkgs[i] : t ? pkgs[j] : nothing)
                    @test identify_package(top, name) == pkg
                    @test locate_package(pkgs[i]) == paths[i,k]
                    path = uuids[i] == uuids[j] ? paths[i,k] : paths[j,l]
                    @test locate_package(pkgs[j]) == path
                end
            end
        end
    end
end
end # let

## systematic generation of test environments ##

const M = 3 # number of node names
const N = 12 # different UUIDs per name
const NODES = 1:M*N
const NAMES = map(string, ('A':'Z')[1:M])
const UUIDS = [uuid4() for i = 1:M, j = 1:N]
const KIND = [(i + j) % 3 for i = 1:M, j = 1:N]
const KIND0 = filter(i -> KIND[i] == 0, NODES)
const KIND2 = filter(i -> KIND[i] == 2, NODES)

# kind 0: no project file
# kind 1: project file without name or uuid
# kind 2: project file with name and uuid

# explicit env: root can be anything, everything else kind 2
# implicit env: nodes can be anything, names must be unique

# allowed dependencies between kinds (explicit and implicit):
allowed(i::Int, j::Int) = KIND[i] ≤ KIND[j] && !(KIND[i] == KIND[j] == 1)

# node names/labels
L(i::Int) = NAMES[mod1(i, M)]

# first generate random dependency graphs

const graphs = Any[]

while length(graphs) < 100
    if (flat = rand(Bool))
        root = rand(KIND0)
        pool = root ∪ filter(i -> L(i) ≠ L(root), NODES)
        size = rand(1:N)
    else
        root = rand(NODES)
        pool = filter(i -> i ≠ root, KIND2)
        size = rand(1:length(NODES)÷2)
    end
    graph = Dict(root => Int[])
    KIND[root] ≠ 0 && push!(graph[root], root)
    for _ = 1:size
        i = rand(keys(graph))
        J = filter(pool) do j
            allowed(i, j) && all(L(j) ≠ L(k) for k in graph[i])
        end
        isempty(J) && continue
        j = rand(J)
        push!(graph[i], j)
        if j ∉ keys(graph)
            graph[j] = [j]
            flat && filter!(k -> L(k) ≠ L(j), pool)
            isempty(pool) && break
        end
    end
    roots = flat ? reduce(∪, values(graph)) : graph[root]
    for i in keys(graph)
        KIND[i] == 0 && delete!(graph, i)
    end
    t = (flat, root,
        Dict(L(i) => i for i in roots),
        Dict(i => Dict(L(j) => j for j in deps) for (i, deps) in graph))
    t in graphs || push!(graphs, t)
end

# materialize dependency graphs as explicit environments

const envs = Dict{String,eltype(graphs)}()

for (flat, root, roots, graph) in graphs
    if flat
        all(KIND[i] == 2 for i in values(roots)) || continue
        all(KIND[i] == 2 for i in keys(graph)) || continue
    end
    dir = mktempdir()
    envs[dir] = (flat, root, roots, graph)

    # generate project file
    open(joinpath(dir, "Project.toml"), "w") do io
        name, uuid, kind = L(root), UUIDS[root], KIND[root]
        kind != 0 && println(io, "name = ", repr(name))
        kind == 2 && println(io, "uuid = ", repr(string(uuid)))
        println(io, "[deps]")
        for (n, i) in roots
            i == root && continue
            @assert KIND[i] == 2
            println(io, "$n = ", repr(string(UUIDS[i])))
        end
    end

    # count manifest entries
    counts = Dict(name => 0 for name in NAMES)
    for (i, _) in graph
        i == root && continue
        @assert KIND[i] == 2
        counts[L(i)] += 1
    end

    # generate manifest file
    open(joinpath(dir, "Manifest.toml"), "w") do io
        for (i, deps) in graph
            i == root && continue
            name, uuid = L(i), UUIDS[i]
            println(io, "[[$name]]")
            println(io, "uuid = ", repr(string(uuid)))
            deps = delete!(copy(deps), name)
            isempty(deps) && continue
            if all(counts[n] == 1 for n in keys(deps))
                println(io, "deps = ", repr(keys(deps)))
            else
                println(io, "  [$name.deps]")
                for (n, j) in deps
                    @assert KIND[j] == 2
                    println(io, "  $n = ", repr(string(UUIDS[j])))
                end
            end
        end
    end
end

# materialize dependency graphs as implicit environments (if possible)

for (flat, root, roots, graph) in graphs
    flat || continue
    dir = mktempdir()
    envs[dir] = (flat, root, roots, graph)

    for (name, i) in roots
        uuid, kind = UUIDS[i], KIND[i]
        # generate package entry point
        entry = joinpath(dir, name, "src", "$name.jl")
        mkpath(dirname(entry))
        open(entry, "w") do io
            print(io, """
            module $name
            name = $(repr(name))
            uuid = $(repr(string(uuid)))
            end
            """)
        end
        kind == 0 && continue
        deps = delete!(copy(graph[i]), name)
        # generate project file
        open(joinpath(dir, name, "Project.toml"), "w") do io
            kind != 0 && println(io, "name = ", repr(name))
            kind == 2 && println(io, "uuid = ", repr(string(uuid)))
            isempty(deps) || println(io, "[deps]")
            for (n, j) in deps
                @assert KIND[j] == 2
                println(io, "  $n = ", repr(string(UUIDS[j])))
            end
        end
    end
end

## use generated environments to test package loading ##

function pkg_id(id::Int)
    PkgId(KIND[id] == 2 ? UUIDS[id] : nothing, L(id))
end
function pkg_id(ids::Dict{String,Int}, name::String)
    haskey(ids, name) ? pkg_id(ids[name]) : nothing
end

function ≊(a::PkgId, b::PkgId)
    a.name == b.name || return false
    a.uuid == b.uuid && return true
    a.uuid == nothing && uuid_version(b.uuid) == 5 ||
    b.uuid == nothing && uuid_version(a.uuid) == 5
end
≊(a::Union{Nothing,PkgId}, b::Union{Nothing,PkgId}) = a == b

function add_id!(ids::Vector{Pair{Int,PkgId}},
    nodes::Dict{String,Int}, name::String, id::PkgId)
    node = nodes[name]
    any(node == i for (i, _) in ids) && return ids
    push!(ids, node => id)
end
function add_id!(ids::Vector{Pair{Int,PkgId}},
    nodes::Dict{String,Int}, name::String, ::Nothing)
    return ids # no op
end

function test_identify(roots::Dict{String,Int}, graph::Dict{Int,Dict{String,Int}})
    ids = Pair{Int,PkgId}[]
    # check & add named roots
    for name in NAMES
        id = identify_package(name)
        @test id ≊ pkg_id(roots, name)
        add_id!(ids, roots, name, id)
    end
    # add nodes reachable by uuid
    for (node, deps) in graph
        KIND[node] == 2 || continue
        add_id!(ids, deps, L(node), pkg_id(node))
    end
    # check all nodes reachable via `where`
    let i = 0
        while (i += 1) ≤ length(ids)
            node, where = ids[i]
            deps = get(graph, node, roots)
            for name in NAMES
                id = identify_package(where, name)
                @test id ≊ pkg_id(deps, name)
                add_id!(ids, deps, name, id)
            end
        end
    end
    # check all other package ids return nothing
    let ids = Dict(ids)
        for node in NODES
            node in keys(ids) && continue
            where = pkg_id(node)
            where.uuid == nothing && continue
            for name in NAMES
                id = where.name == name ? where : nothing
                @test identify_package(where, name) == id
            end
        end
    end
end

empty!(DEPOT_PATH)

@testset "identify_package with one env in load path" begin
    for (env, (_, _, roots, graph)) in envs
        push!(empty!(LOAD_PATH), env)
        test_identify(roots, graph)
    end
end

@testset "identify_package with two envs in load path" begin
    for x = false:true,
        (env1, (_, _, roots1, graph1)) in (x ? envs : rand(envs, 10)),
        (env2, (_, _, roots2, graph2)) in (x ? rand(envs, 10) : envs)
        push!(empty!(LOAD_PATH), env1, env2)
        roots = merge(roots2, roots1)
        graph = merge(graph2, graph1)
        test_identify(roots, graph)
    end
end

@testset "identify_package with three envs in load path" begin
    for (env1, (_, _, roots1, graph1)) in rand(envs, 10),
        (env2, (_, _, roots2, graph2)) in rand(envs, 10),
        (env3, (_, _, roots3, graph3)) in rand(envs, 10)
        push!(empty!(LOAD_PATH), env1, env2, env3)
        roots = merge(roots3, roots2, roots1)
        graph = merge(graph3, graph2, graph1)
        test_identify(roots, graph)
    end
end

## cleanup after tests ##

for env in keys(envs)
    rm(env, force=true, recursive=true)
end

append!(empty!(DEPOT_PATH), saved_depot_path)
append!(empty!(LOAD_PATH), saved_load_path)
back to top