"Fossies" - the Fresh Open Source Software Archive

Member "julia-1.1.1/share/julia/test/runtests.jl" (16 May 2019, 12023 Bytes) of package /linux/misc/julia-1.1.1-linux-i686.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Julia source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # This file is a part of Julia. License is MIT: https://julialang.org/license
    2 
    3 using Test
    4 using Distributed
    5 import REPL
    6 using Base.Printf: @sprintf
    7 
    8 include("choosetests.jl")
    9 include("testenv.jl")
   10 
   11 tests, net_on, exit_on_error, seed = choosetests(ARGS)
   12 tests = unique(tests)
   13 
   14 const max_worker_rss = if haskey(ENV, "JULIA_TEST_MAXRSS_MB")
   15     parse(Int, ENV["JULIA_TEST_MAXRSS_MB"]) * 2^20
   16 else
   17     typemax(Csize_t)
   18 end
   19 limited_worker_rss = max_worker_rss != typemax(Csize_t)
   20 
   21 function test_path(test)
   22     t = split(test, '/')
   23     if t[1] in STDLIBS
   24         if length(t) == 2
   25             return joinpath(STDLIB_DIR, t[1], "test", t[2])
   26         else
   27             return joinpath(STDLIB_DIR, t[1], "test", "runtests")
   28         end
   29     else
   30         return joinpath(@__DIR__, test)
   31     end
   32 end
   33 
   34 # Check all test files exist
   35 isfiles = isfile.(test_path.(tests) .* ".jl")
   36 if !all(isfiles)
   37     error("did not find test files for the following tests: ",
   38           join(tests[.!(isfiles)], ", "))
   39 end
   40 
   41 const node1_tests = String[]
   42 function move_to_node1(t)
   43     if t in tests
   44         splice!(tests, findfirst(isequal(t), tests))
   45         push!(node1_tests, t)
   46     end
   47     nothing
   48 end
   49 
   50 # Base.compilecache only works from node 1, so precompile test is handled specially
   51 move_to_node1("precompile")
   52 move_to_node1("SharedArrays")
   53 # Ensure things like consuming all kernel pipe memory doesn't interfere with other tests
   54 move_to_node1("stress")
   55 
   56 # In a constrained memory environment, run the "distributed" test after all other tests
   57 # since it starts a lot of workers and can easily exceed the maximum memory
   58 limited_worker_rss && move_to_node1("Distributed")
   59 
   60 import LinearAlgebra
   61 cd(@__DIR__) do
   62     n = 1
   63     if net_on
   64         n = min(Sys.CPU_THREADS, length(tests))
   65         n > 1 && addprocs_with_testenv(n)
   66         LinearAlgebra.BLAS.set_num_threads(1)
   67     end
   68     skipped = 0
   69 
   70     @everywhere include("testdefs.jl")
   71 
   72     #pretty print the information about gc and mem usage
   73     testgroupheader = "Test"
   74     workerheader = "(Worker)"
   75     name_align    = maximum([length(testgroupheader) + length(" ") + length(workerheader); map(x -> length(x) + 3 + ndigits(nworkers()), tests)])
   76     elapsed_align = length("Time (s)")
   77     gc_align      = length("GC (s)")
   78     percent_align = length("GC %")
   79     alloc_align   = length("Alloc (MB)")
   80     rss_align     = length("RSS (MB)")
   81     printstyled(testgroupheader, color=:white)
   82     printstyled(lpad(workerheader, name_align - length(testgroupheader) + 1), " | ", color=:white)
   83     printstyled("Time (s) | GC (s) | GC % | Alloc (MB) | RSS (MB)\n", color=:white)
   84     results=[]
   85     print_lock = ReentrantLock()
   86 
   87     function print_testworker_stats(test, wrkr, resp)
   88         lock(print_lock)
   89         try
   90             printstyled(test, color=:white)
   91             printstyled(lpad("($wrkr)", name_align - length(test) + 1, " "), " | ", color=:white)
   92             time_str = @sprintf("%7.2f",resp[2])
   93             printstyled(lpad(time_str, elapsed_align, " "), " | ", color=:white)
   94             gc_str = @sprintf("%5.2f", resp[5].total_time / 10^9)
   95             printstyled(lpad(gc_str, gc_align, " "), " | ", color=:white)
   96 
   97             # since there may be quite a few digits in the percentage,
   98             # the left-padding here is less to make sure everything fits
   99             percent_str = @sprintf("%4.1f", 100 * resp[5].total_time / (10^9 * resp[2]))
  100             printstyled(lpad(percent_str, percent_align, " "), " | ", color=:white)
  101             alloc_str = @sprintf("%5.2f", resp[3] / 2^20)
  102             printstyled(lpad(alloc_str, alloc_align, " "), " | ", color=:white)
  103             rss_str = @sprintf("%5.2f", resp[6] / 2^20)
  104             printstyled(lpad(rss_str, rss_align, " "), "\n", color=:white)
  105         finally
  106             unlock(print_lock)
  107         end
  108     end
  109 
  110     all_tests = [tests; node1_tests]
  111 
  112     local stdin_monitor
  113     all_tasks = Task[]
  114     try
  115         # Monitor stdin and kill this task on ^C
  116         # but don't do this on Windows, because it may deadlock in the kernel
  117         if !Sys.iswindows() && isa(stdin, Base.TTY)
  118             t = current_task()
  119             stdin_monitor = @async begin
  120                 term = REPL.Terminals.TTYTerminal("xterm", stdin, stdout, stderr)
  121                 try
  122                     REPL.Terminals.raw!(term, true)
  123                     while true
  124                         if read(term, Char) == '\x3'
  125                             Base.throwto(t, InterruptException())
  126                             break
  127                         end
  128                     end
  129                 catch e
  130                     isa(e, InterruptException) || rethrow()
  131                 finally
  132                     REPL.Terminals.raw!(term, false)
  133                 end
  134             end
  135         end
  136         @sync begin
  137             for p in workers()
  138                 @async begin
  139                     push!(all_tasks, current_task())
  140                     while length(tests) > 0
  141                         test = popfirst!(tests)
  142                         local resp
  143                         wrkr = p
  144                         try
  145                             resp = remotecall_fetch(runtests, wrkr, test, test_path(test); seed=seed)
  146                         catch e
  147                             isa(e, InterruptException) && return
  148                             resp = [e]
  149                         end
  150                         push!(results, (test, resp))
  151                         if resp[1] isa Exception
  152                             if exit_on_error
  153                                 skipped = length(tests)
  154                                 empty!(tests)
  155                             end
  156                         elseif resp[end] > max_worker_rss
  157                             if n > 1
  158                                 rmprocs(wrkr, waitfor=30)
  159                                 p = addprocs_with_testenv(1)[1]
  160                                 remotecall_fetch(include, p, "testdefs.jl")
  161                             else # single process testing
  162                                 error("Halting tests. Memory limit reached : $resp > $max_worker_rss")
  163                             end
  164                         end
  165 
  166                         !isa(resp[1], Exception) && print_testworker_stats(test, wrkr, resp)
  167                     end
  168                     if p != 1
  169                         # Free up memory =)
  170                         rmprocs(p, waitfor=30)
  171                     end
  172                 end
  173             end
  174         end
  175 
  176         n > 1 && length(node1_tests) > 1 && print("\nExecuting tests that run on node 1 only:\n")
  177         for t in node1_tests
  178             # As above, try to run each test
  179             # which must run on node 1. If
  180             # the test fails, catch the error,
  181             # and either way, append the results
  182             # to the overall aggregator
  183             isolate = true
  184             t == "SharedArrays" && (isolate = false)
  185             local resp
  186             try
  187                 resp = eval(Expr(:call, () -> runtests(t, test_path(t), isolate, seed=seed))) # runtests is defined by the include above
  188                 print_testworker_stats(t, 1, resp)
  189             catch e
  190                 resp = [e]
  191             end
  192             push!(results, (t, resp))
  193         end
  194     catch e
  195         isa(e, InterruptException) || rethrow()
  196         # If the test suite was merely interrupted, still print the
  197         # summary, which can be useful to diagnose what's going on
  198         foreach(task->try; schedule(task, InterruptException(); error=true); catch; end, all_tasks)
  199         foreach(wait, all_tasks)
  200     finally
  201         if @isdefined stdin_monitor
  202             schedule(stdin_monitor, InterruptException(); error=true)
  203         end
  204     end
  205 
  206     #=
  207 `   Construct a testset on the master node which will hold results from all the
  208     test files run on workers and on node1. The loop goes through the results,
  209     inserting them as children of the overall testset if they are testsets,
  210     handling errors otherwise.
  211 
  212     Since the workers don't return information about passing/broken tests, only
  213     errors or failures, those Result types get passed `nothing` for their test
  214     expressions (and expected/received result in the case of Broken).
  215 
  216     If a test failed, returning a `RemoteException`, the error is displayed and
  217     the overall testset has a child testset inserted, with the (empty) Passes
  218     and Brokens from the worker and the full information about all errors and
  219     failures encountered running the tests. This information will be displayed
  220     as a summary at the end of the test run.
  221 
  222     If a test failed, returning an `Exception` that is not a `RemoteException`,
  223     it is likely the julia process running the test has encountered some kind
  224     of internal error, such as a segfault.  The entire testset is marked as
  225     Errored, and execution continues until the summary at the end of the test
  226     run, where the test file is printed out as the "failed expression".
  227     =#
  228     o_ts = Test.DefaultTestSet("Overall")
  229     Test.push_testset(o_ts)
  230     completed_tests = Set{String}()
  231     for res in results
  232         push!(completed_tests, res[1])
  233         if isa(res[2][1], Test.DefaultTestSet)
  234             Test.push_testset(res[2][1])
  235             Test.record(o_ts, res[2][1])
  236             Test.pop_testset()
  237         elseif isa(res[2][1], Tuple{Int,Int})
  238             fake = Test.DefaultTestSet(res[1])
  239             for i in 1:res[2][1][1]
  240                 Test.record(fake, Test.Pass(:test, nothing, nothing, nothing))
  241             end
  242             for i in 1:res[2][1][2]
  243                 Test.record(fake, Test.Broken(:test, nothing))
  244             end
  245             Test.push_testset(fake)
  246             Test.record(o_ts, fake)
  247             Test.pop_testset()
  248         elseif isa(res[2][1], RemoteException) && isa(res[2][1].captured.ex, Test.TestSetException)
  249             println("Worker $(res[2][1].pid) failed running test $(res[1]):")
  250             Base.showerror(stdout,res[2][1].captured)
  251             fake = Test.DefaultTestSet(res[1])
  252             for i in 1:res[2][1].captured.ex.pass
  253                 Test.record(fake, Test.Pass(:test, nothing, nothing, nothing))
  254             end
  255             for i in 1:res[2][1].captured.ex.broken
  256                 Test.record(fake, Test.Broken(:test, nothing))
  257             end
  258             for t in res[2][1].captured.ex.errors_and_fails
  259                 Test.record(fake, t)
  260             end
  261             Test.push_testset(fake)
  262             Test.record(o_ts, fake)
  263             Test.pop_testset()
  264         elseif isa(res[2][1], Exception)
  265             # If this test raised an exception that is not a remote testset exception,
  266             # i.e. not a RemoteException capturing a TestSetException that means
  267             # the test runner itself had some problem, so we may have hit a segfault,
  268             # deserialization errors or something similar.  Record this testset as Errored.
  269             fake = Test.DefaultTestSet(res[1])
  270             Test.record(fake, Test.Error(:test_error, res[1], res[2][1], [], LineNumberNode(1)))
  271             Test.push_testset(fake)
  272             Test.record(o_ts, fake)
  273             Test.pop_testset()
  274         else
  275             error(string("Unknown result type : ", typeof(res)))
  276         end
  277     end
  278     for test in all_tests
  279         (test in completed_tests) && continue
  280         fake = Test.DefaultTestSet(test)
  281         Test.record(fake, Test.Error(:test_interrupted, test, InterruptException(), [], LineNumberNode(1)))
  282         Test.push_testset(fake)
  283         Test.record(o_ts, fake)
  284         Test.pop_testset()
  285     end
  286     println()
  287     Test.print_test_results(o_ts,1)
  288     if !o_ts.anynonpass
  289         println("    \033[32;1mSUCCESS\033[0m")
  290     else
  291         println("    \033[31;1mFAILURE\033[0m\n")
  292         skipped > 0 &&
  293             println("$skipped test", skipped > 1 ? "s were" : " was", " skipped due to failure.")
  294         println("The global RNG seed was 0x$(string(seed, base = 16)).\n")
  295         Test.print_test_errors(o_ts)
  296         throw(Test.FallbackTestSetException("Test run finished with errors"))
  297     end
  298 end