diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml index f24f6c33..a1dc3262 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/Test.yml @@ -23,7 +23,7 @@ jobs: fail-fast: false matrix: version: ['1.10', '1.12'] - os: [ubuntu-24.04, ubuntu-24.04-arm, macOS-15-intel, windows-2022] + os: [ubuntu-24.04, ubuntu-24.04-arm, macOS-26-intel, windows-2022] arch: [x64, arm64] pocl: [jll, local] memory_backend: [usm, svm, buffer] @@ -35,11 +35,11 @@ jobs: arch: arm64 - os: ubuntu-24.04-arm arch: x64 - # macOS-15-intel is Intel-only - - os: macOS-15-intel + # macOS-26-intel is Intel-only + - os: macOS-26-intel arch: arm64 # we only test building PoCL on Linux - - os: macOS-15-intel + - os: macOS-26-intel pocl: local - os: windows-2022 pocl: local @@ -125,6 +125,16 @@ jobs: echo '[pocl_jll]' >> test/LocalPreferences.toml echo 'libpocl_path="${{ github.workspace }}/target/lib/libpocl.so"' >> test/LocalPreferences.toml + - name: "Set test arguments and other environment variables" + shell: bash + run: | + if [[ ${{ runner.os }} == "macOS" ]]; then + JULIA_TEST_MAXRSS_MB=1800 + echo "JULIA_TEST_MAXRSS_MB=${JULIA_TEST_MAXRSS_MB}" | tee -a "${GITHUB_ENV}" + JULIA_CPU_THREADS=2 + echo "JULIA_CPU_THREADS=${JULIA_CPU_THREADS}" | tee -a "${GITHUB_ENV}" + fi + - name: Setup OpenCL.jl run: | echo '[OpenCL]' >> test/LocalPreferences.toml @@ -137,7 +147,7 @@ jobs: uses: julia-actions/julia-runtest@v1 if: runner.os != 'Windows' with: - test_args: '--quickfail --platform=pocl' + test_args: '--quickfail --verbose --platform=pocl' - name: Setup BusyBox if: runner.os == 'Windows' @@ -149,7 +159,7 @@ jobs: run: | using Pkg Pkg.activate(".") - Pkg.test(; test_args=`--quickfail --platform=pocl`) + Pkg.test(; test_args=`--quickfail --verbose --platform=pocl`) - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v6 diff --git a/test/Project.toml b/test/Project.toml index 455dc2dd..24acaeeb 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -9,6 +9,7 @@ JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" OpenCL = "08131aa3-fb12-5dee-8b74-c09406e224a2" +ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc" Preferences = "21216c6a-2e73-6563-6e65-726566657250" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" @@ -26,3 +27,4 @@ pocl_jll = "627d6b7a-bbe6-5189-83e7-98cc0a5aeadd" [compat] pocl_jll = "7.0" +ParallelTestRunner = "2.2" diff --git a/test/execution.jl b/test/execution.jl index 2900c04f..1fd69d7a 100644 --- a/test/execution.jl +++ b/test/execution.jl @@ -1,4 +1,5 @@ using SPIRV_LLVM_Translator_jll +using IOCapture @testset "@opencl" begin diff --git a/test/kernelabstractions.jl b/test/kernelabstractions.jl index debf5dec..97e54154 100644 --- a/test/kernelabstractions.jl +++ b/test/kernelabstractions.jl @@ -1,3 +1,17 @@ +# KernelAbstractions has a testsuite that isn't part of the main package. +# Include it directly. + +const KATestSuite = let + mod = @eval module $(gensym()) + using ..Test + import KernelAbstractions + kernelabstractions = pathof(KernelAbstractions) + kernelabstractions_root = dirname(dirname(kernelabstractions)) + include(joinpath(kernelabstractions_root, "test", "testsuite.jl")) + end + mod.Testsuite +end + skip_tests=Set([ "sparse", "Convert", # Need to opt out of i128 diff --git a/test/runtests.jl b/test/runtests.jl index 6fd437f2..fe3e6e86 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,413 +1,160 @@ -using Distributed -using Dates -import REPL -using Printf: @sprintf -using Base.Filesystem: path_separator +using ParallelTestRunner using Preferences +import OpenCL, pocl_jll +import Test -# parse some command-line arguments -function extract_flag!(args, flag, default=nothing) - for f in args - if startswith(f, flag) - # Check if it's just `--flag` or if it's `--flag=foo` - if f != flag - val = split(f, '=')[2] - if default !== nothing && !(typeof(default) <: AbstractString) - val = parse(typeof(default), val) - end - else - val = default - end - - # Drop this value from our args - filter!(x -> x != f, args) - return (true, val) - end - end - return (false, default) -end -do_help, _ = extract_flag!(ARGS, "--help") -if do_help - println(""" - Usage: runtests.jl [--help] [--list] [--jobs=N] [TESTS...] - - --help Show this text. - --list List all available tests. - --verbose Print more information during testing. - --quickfail Fail the entire run as soon as a single test errored. - --jobs=N Launch `N` processes to perform tests (default: Sys.CPU_THREADS). - --platform=NAME Run tests on the platform named `NAME` (default: all platforms). - - Remaining arguments filter the tests that will be executed.""") - exit(0) -end -_, jobs = extract_flag!(ARGS, "--jobs", Sys.CPU_THREADS) -do_verbose, _ = extract_flag!(ARGS, "--verbose") -do_quickfail, _ = extract_flag!(ARGS, "--quickfail") - -include("setup.jl") # make sure everything is precompiled @info "System information:\n" * sprint(io->OpenCL.versioninfo(io)) -@info "Running $jobs tests in parallel. If this is too many, specify the `--jobs` argument to the tests, or set the JULIA_CPU_THREADS environment variable." - -# choose tests -const tests = [] -const test_runners = Dict() -## files in the test folder -for (rootpath, dirs, files) in walkdir(@__DIR__) - # find Julia files - filter!(files) do file - endswith(file, ".jl") && file !== "setup.jl" && file !== "runtests.jl" - end - isempty(files) && continue - - # strip extension - files = map(files) do file - file[1:end-3] - end - - # prepend subdir - subdir = relpath(rootpath, @__DIR__) - if subdir != "." - files = map(files) do file - joinpath(subdir, file) +## custom arguments +args = parse_args(ARGS; custom=["platform"]) + +# determine tests to run +const testsuite = find_tests(pwd()) +## GPUArrays test suite: not part of the main package +const GPUArraysTestSuite = let + mod = @eval module $(gensym()) + using ..Test + import GPUArrays + gpuarrays = pathof(GPUArrays) + gpuarrays_root = dirname(dirname(gpuarrays)) + include(joinpath(gpuarrays_root, "test", "testsuite.jl")) end - end - - # unify path separators - files = map(files) do file - replace(file, path_separator => '/') - end - - append!(tests, files) - for file in files - test_runners[file] = ()->include("$(@__DIR__)/$file.jl") - end + mod.TestSuite end -sort!(tests; by=(file)->stat("$(@__DIR__)/$file.jl").size, rev=true) -## GPUArrays testsuite for name in keys(GPUArraysTestSuite.tests) - push!(tests, "gpuarrays/$name") - test_runners["gpuarrays/$name"] = ()->GPUArraysTestSuite.tests[name](CLArray) + test = "gpuarrays/$name" + testsuite[test] = :(GPUArraysTestSuite.tests[$name](CLArray)) end -## finalize -unique!(tests) - -# parse some more command-line arguments -## --list to list all available tests -do_list, _ = extract_flag!(ARGS, "--list") -if do_list - println("Available tests:") - for test in sort(tests) - println(" - $test") - end - exit(0) -end -## --platform selector -do_platform, platform = extract_flag!(ARGS, "--platform", nothing) -## no options should remain -optlike_args = filter(startswith("-"), ARGS) -if !isempty(optlike_args) - error("Unknown test options `$(join(optlike_args, " "))` (try `--help` for usage instructions)") -end -## the remaining args filter tests -if isempty(ARGS) - # default to running all tests, except: - filter!(tests) do test - if load_preference(OpenCL, "default_memory_backend") == "svm" && - test == "gpuarrays/indexing scalar" +## filter +if filter_tests!(testsuite, args) + if load_preference(OpenCL, "default_memory_backend") == "svm" # GPUArrays' scalar indexing tests assume that indexing is not supported + delete!(testsuite, "gpuarrays/indexing scalar") return false end - - return true - end -else - filter!(tests) do test - any(arg->startswith(test, arg), ARGS) - end end -# add workers -const test_exeflags = Base.julia_cmd() -filter!(test_exeflags.exec) do c - return !(startswith(c, "--depwarn") || startswith(c, "--check-bounds")) -end -push!(test_exeflags.exec, "--check-bounds=yes") -push!(test_exeflags.exec, "--startup-file=no") -push!(test_exeflags.exec, "--depwarn=yes") -push!(test_exeflags.exec, "--project=$(Base.active_project())") -const test_exename = popfirst!(test_exeflags.exec) -function addworker(X; kwargs...) - withenv("JULIA_NUM_THREADS" => 1, "OPENBLAS_NUM_THREADS" => 1) do - procs = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) - @everywhere procs include($(joinpath(@__DIR__, "setup.jl"))) - procs +# wrap tests in device loops +function generate_test(test, expr) + # some tests require native execution capabilities + requires_il = test in ["atomics", "execution", "intrinsics", "kernelabstractions", + "statistics", "linalg", ] || + startswith(test, "gpuarrays/") || startswith(test, "device/") + + # targets is a global variable that is defined in init_code + return quote + if isempty(targets) + platform_filter = $(args.custom["platform"]) + for platform in cl.platforms(), + device in cl.devices(platform) + if platform_filter !== nothing + # filter on the name or vendor + names = lowercase.([platform.name, platform.vendor]) + if !any(contains(platform_filter.value), names) + continue + end + end + push!(targets, (; platform, device)) + end + if isempty(targets) + if platform_filter !== nothing + throw(ArgumentError("No OpenCL platforms found")) + else + throw(ArgumentError("No OpenCL platforms found matching $(platform_filter.value)")) + end + end + end + + @testset "$(device.name)" for (; platform, device) in targets + cl.platform!(platform) + cl.device!(device) + + if !$(requires_il) || "cl_khr_il_program" in device.extensions + $(expr) + end + end end end -addworker(min(jobs, length(tests))) - -# pretty print information about gc and mem usage -testgroupheader = "Test" -workerheader = "(Worker)" -name_align = maximum([textwidth(testgroupheader) + textwidth(" ") + - textwidth(workerheader); map(x -> textwidth(x) + - 3 + ndigits(nworkers()), tests)]) -elapsed_align = textwidth("Time (s)") -gc_align = textwidth("GC (s)") -percent_align = textwidth("GC %") -alloc_align = textwidth("Alloc (MB)") -rss_align = textwidth("RSS (MB)") -printstyled(" "^(name_align + textwidth(testgroupheader) - 3), " | ") -printstyled(" | ---------------- CPU ---------------- |\n", color=:white) -printstyled(testgroupheader, color=:white) -printstyled(lpad(workerheader, name_align - textwidth(testgroupheader) + 1), " | ", color=:white) -printstyled("Time (s) | GC (s) | GC % | Alloc (MB) | RSS (MB) |\n", color=:white) -print_lock = stdout isa Base.LibuvStream ? stdout.lock : ReentrantLock() -if stderr isa Base.LibuvStream - stderr.lock = print_lock +for test in keys(testsuite) + testsuite[test] = generate_test(test, testsuite[test]) end -function print_testworker_stats(test, wrkr, resp) - @nospecialize resp - lock(print_lock) - try - printstyled(test, color=:white) - printstyled(lpad("($wrkr)", name_align - textwidth(test) + 1, " "), " | ", color=:white) - time_str = @sprintf("%7.2f",resp[2]) - printstyled(lpad(time_str, elapsed_align, " "), " | ", color=:white) - cpu_gc_str = @sprintf("%5.2f", resp[4]) - printstyled(lpad(cpu_gc_str, gc_align, " "), " | ", color=:white) - # since there may be quite a few digits in the percentage, - # the left-padding here is less to make sure everything fits - cpu_percent_str = @sprintf("%4.1f", 100 * resp[4] / resp[2]) - printstyled(lpad(cpu_percent_str, percent_align, " "), " | ", color=:white) - cpu_alloc_str = @sprintf("%5.2f", resp[3] / 2^20) - printstyled(lpad(cpu_alloc_str, alloc_align, " "), " | ", color=:white) +const init_worker_code = quote + using OpenCL, pocl_jll - cpu_rss_str = @sprintf("%5.2f", resp[6] / 2^20) - printstyled(lpad(cpu_rss_str, rss_align, " "), " |\n", color=:white) - finally - unlock(print_lock) - end -end -global print_testworker_started = (name, wrkr)->begin - if do_verbose - lock(print_lock) - try - printstyled(name, color=:white) - printstyled(lpad("($wrkr)", name_align - textwidth(name) + 1, " "), " |", - " "^elapsed_align, "started at $(now())\n", color=:white) - finally - unlock(print_lock) + OpenCL.allowscalar(false) + const targets = [] + + # GPUArrays has a testsuite that isn't part of the main package. + # Include it directly. + const GPUArraysTestSuite = let + mod = @eval module $(gensym()) + using Test + import GPUArrays + gpuarrays = pathof(GPUArrays) + gpuarrays_root = dirname(dirname(gpuarrays)) + include(joinpath(gpuarrays_root, "test", "testsuite.jl")) end + mod.TestSuite end -end -function print_testworker_errored(name, wrkr) - lock(print_lock) - try - printstyled(name, color=:red) - printstyled(lpad("($wrkr)", name_align - textwidth(name) + 1, " "), " |", - " "^elapsed_align, " failed at $(now())\n", color=:red) - finally - unlock(print_lock) - end -end -# run tasks -t0 = now() -results = [] -all_tasks = Task[] -all_tests = copy(tests) -try - # Monitor stdin and kill this task on ^C - # but don't do this on Windows, because it may deadlock in the kernel - t = current_task() - running_tests = Dict{String, DateTime}() - if !Sys.iswindows() && isa(stdin, Base.TTY) - stdin_monitor = @async begin - term = REPL.Terminals.TTYTerminal("xterm", stdin, stdout, stderr) - try - REPL.Terminals.raw!(term, true) - while true - c = read(term, Char) - if c == '\x3' - Base.throwto(t, InterruptException()) - break - elseif c == '?' - println("Currently running: ") - tests = sort(collect(running_tests), by=x->x[2]) - foreach(tests) do (test, date) - println(test, " (running for ", round(now()-date, Minute), ")") - end - end - end - catch e - isa(e, InterruptException) || rethrow() - finally - REPL.Terminals.raw!(term, false) + const device_eltypes = Dict() + function GPUArraysTestSuite.supported_eltypes(::Type{<:CLArray}) + get!(device_eltypes, cl.device()) do + types = [Int16, Int32, Int64, + Complex{Int16}, Complex{Int32}, Complex{Int64}, + Float32, ComplexF32] + if "cl_khr_fp64" in cl.device().extensions + push!(types, Float64) + push!(types, ComplexF64) end + if "cl_khr_fp16" in cl.device().extensions + push!(types, Float16) + push!(types, ComplexF16) + end + return types end end - @sync begin - function recycle_worker(p) - rmprocs(p, waitfor=30) - return nothing - end - for p in workers() - @async begin - push!(all_tasks, current_task()) - while length(tests) > 0 - test = popfirst!(tests) + testf(f, xs...; kwargs...) = GPUArraysTestSuite.compare(f, CLArray, xs...; kwargs...) - # sometimes a worker failed, and we need to spawn a new one - if p === nothing - p = addworker(1)[1] - end - wrkr = p - - local resp - - # run the test - running_tests[test] = now() - try - resp = remotecall_fetch(runtests, wrkr, - test_runners[test], test, - platform) - catch e - isa(e, InterruptException) && return - resp = Any[e] - end - delete!(running_tests, test) - push!(results, (test, resp)) + ## auxiliary stuff - # act on the results - if resp[1] isa Exception - print_testworker_errored(test, wrkr) - do_quickfail && Base.throwto(t, InterruptException()) + # Run some code on-device + macro on_device(ex...) + code = ex[end] + kwargs = ex[1:end-1] - # the worker encountered some failure, recycle it - # so future tests get a fresh environment - p = recycle_worker(p) - else - print_testworker_stats(test, wrkr, resp) - - compilations = resp[7] - if Sys.iswindows() && compilations > 100 - # XXX: restart to avoid handle exhaustion - # (see pocl/pocl#1941) - @warn "Restarting worker $wrkr to avoid handle exhaustion" - p = recycle_worker(p) - end - end + @gensym kernel + esc(quote + let + function $kernel() + $code + return end - if p !== nothing - recycle_worker(p) - end + @opencl $(kwargs...) $kernel() + cl.finish(cl.queue()) end - end - end -catch e - isa(e, InterruptException) || rethrow() - # If the test suite was merely interrupted, still print the - # summary, which can be useful to diagnose what's going on - foreach(task -> begin - istaskstarted(task) || return - istaskdone(task) && return - try - schedule(task, InterruptException(); error=true) - catch ex - @error "InterruptException" exception=ex,catch_backtrace() - end - end, all_tasks) - for t in all_tasks - # NOTE: we can't just wait, but need to discard the exception, - # because the throwto for --quickfail also kills the worker. - try - wait(t) - catch e - showerror(stderr, e) - end - end -finally - if @isdefined stdin_monitor - schedule(stdin_monitor, InterruptException(); error=true) + end) end end -t1 = now() -elapsed = canonicalize(Dates.CompoundPeriod(t1-t0)) -println("Testing finished in $elapsed") -# construct a testset to render the test results -o_ts = Test.DefaultTestSet("Overall") -Test.push_testset(o_ts) -completed_tests = Set{String}() -for (testname, (resp,)) in results - push!(completed_tests, testname) - if isa(resp, Test.DefaultTestSet) - Test.push_testset(resp) - Test.record(o_ts, resp) - Test.pop_testset() - elseif isa(resp, Tuple{Int,Int}) - fake = Test.DefaultTestSet(testname) - for i in 1:resp[1] - Test.record(fake, Test.Pass(:test, nothing, nothing, nothing, nothing)) - end - for i in 1:resp[2] - Test.record(fake, Test.Broken(:test, nothing)) - end - Test.push_testset(fake) - Test.record(o_ts, fake) - Test.pop_testset() - elseif isa(resp, RemoteException) && isa(resp.captured.ex, Test.TestSetException) - println("Worker $(resp.pid) failed running test $(testname):") - Base.showerror(stdout, resp.captured) - println() - fake = Test.DefaultTestSet(testname) - for i in 1:resp.captured.ex.pass - Test.record(fake, Test.Pass(:test, nothing, nothing, nothing, nothing)) - end - for i in 1:resp.captured.ex.broken - Test.record(fake, Test.Broken(:test, nothing)) - end - for t in resp.captured.ex.errors_and_fails - Test.record(fake, t) - end - Test.push_testset(fake) - Test.record(o_ts, fake) - Test.pop_testset() +const init_code = quote + using OpenCL, pocl_jll + + # bring used symbols into the temporary module + import ..GPUArraysTestSuite, ..testf + import ..@on_device, ..targets +end + +# avoid handle exhaustion on Windows by running each test in a separate process (pocl/pocl#1941) +function test_worker(_, init_worker_code) + if Sys.iswindows() + addworker(; init_worker_code) else - if !isa(resp, Exception) - resp = ErrorException(string("Unknown result type : ", typeof(resp))) - end - # If this test raised an exception that is not a remote testset exception, - # i.e. not a RemoteException capturing a TestSetException that means - # the test runner itself had some problem, so we may have hit a segfault, - # deserialization errors or something similar. Record this testset as Errored. - fake = Test.DefaultTestSet(testname) - Test.record(fake, Test.Error(:nontest_error, testname, nothing, Any[(resp, [])], LineNumberNode(1))) - Test.push_testset(fake) - Test.record(o_ts, fake) - Test.pop_testset() + nothing end end -for test in all_tests - (test in completed_tests) && continue - fake = Test.DefaultTestSet(test) - Test.record(fake, Test.Error(:test_interrupted, test, nothing, - [("skipped", [])], LineNumberNode(1))) - Test.push_testset(fake) - Test.record(o_ts, fake) - Test.pop_testset() -end -println() -Test.print_test_results(o_ts, 1) -if !o_ts.anynonpass - println(" \033[32;1mSUCCESS\033[0m") -else - println(" \033[31;1mFAILURE\033[0m\n") - Test.print_test_errors(o_ts) - throw(Test.FallbackTestSetException("Test run finished with errors")) -end + +runtests(OpenCL, args; testsuite, init_code, init_worker_code, test_worker) diff --git a/test/setup.jl b/test/setup.jl deleted file mode 100644 index 90337d36..00000000 --- a/test/setup.jl +++ /dev/null @@ -1,166 +0,0 @@ -using Distributed, Test -using OpenCL, pocl_jll -using IOCapture - -# KernelAbstractions has a testsuite that isn't part of the main package. -# Include it directly. -const KATestSuite = let - mod = @eval module $(gensym()) - using ..Test - import KernelAbstractions - kernelabstractions = pathof(KernelAbstractions) - kernelabstractions_root = dirname(dirname(kernelabstractions)) - include(joinpath(kernelabstractions_root, "test", "testsuite.jl")) - end - mod.Testsuite -end - -# GPUArrays has a testsuite that isn't part of the main package. -# Include it directly. -const GPUArraysTestSuite = let - mod = @eval module $(gensym()) - using ..Test - import GPUArrays - gpuarrays = pathof(GPUArrays) - gpuarrays_root = dirname(dirname(gpuarrays)) - include(joinpath(gpuarrays_root, "test", "testsuite.jl")) - end - mod.TestSuite -end -testf(f, xs...; kwargs...) = GPUArraysTestSuite.compare(f, CLArray, xs...; kwargs...) - -const device_eltypes = Dict() -function GPUArraysTestSuite.supported_eltypes(::Type{<:CLArray}) - get!(device_eltypes, cl.device()) do - types = [Int16, Int32, Int64, - Complex{Int16}, Complex{Int32}, Complex{Int64}, - Float32, ComplexF32] - if "cl_khr_fp64" in cl.device().extensions - push!(types, Float64) - push!(types, ComplexF64) - end - if "cl_khr_fp16" in cl.device().extensions - push!(types, Float16) - push!(types, ComplexF16) - end - return types - end -end - -using Random - - -## entry point - -const targets = [] - -function runtests(f, name, platform_filter) - old_print_setting = Test.TESTSET_PRINT_ENABLE[] - Test.TESTSET_PRINT_ENABLE[] = false - - if isempty(targets) - for platform in cl.platforms(), - device in cl.devices(platform) - if platform_filter !== nothing - # filter on the name or vendor - names = lowercase.([platform.name, platform.vendor]) - if !any(contains(platform_filter), names) - continue - end - end - push!(targets, (; platform, device)) - end - if isempty(targets) - if platform_filter === nothing - throw(ArgumentError("No OpenCL platforms found")) - else - throw(ArgumentError("No OpenCL platforms found matching $platform_filter")) - end - end - end - - try - # generate a temporary module to execute the tests in - mod_name = Symbol("Test", rand(1:100), "Main_", replace(name, '/' => '_')) - mod = @eval(Main, module $mod_name end) - @eval(mod, using Test, Random, OpenCL) - - let id = myid() - wait(@spawnat 1 print_testworker_started(name, id)) - end - - # some tests require native execution capabilities - requires_il = name in ["atomics", "execution", "intrinsics", "kernelabstractions"] || - startswith(name, "gpuarrays/") || startswith(name, "device/") - - ex = quote - GC.gc(true) - Random.seed!(1) - OpenCL.allowscalar(false) - - @timed @testset $"$name" begin - @testset "\$(device.name)" for (; platform, device) in $targets - cl.platform!(platform) - cl.device!(device) - - if !$requires_il || "cl_khr_il_program" in device.extensions - $f() - end - end - end - end - data = Core.eval(mod, ex) - #data[1] is the testset - - # process results - cpu_rss = Sys.maxrss() - compilations = OpenCL.compilations[] - if VERSION >= v"1.11.0-DEV.1529" - tc = Test.get_test_counts(data[1]) - passes,fails,error,broken,c_passes,c_fails,c_errors,c_broken = - tc.passes, tc.fails, tc.errors, tc.broken, tc.cumulative_passes, - tc.cumulative_fails, tc.cumulative_errors, tc.cumulative_broken - else - passes,fails,errors,broken,c_passes,c_fails,c_errors,c_broken = - Test.get_test_counts(data[1]) - end - if data[1].anynonpass == false - data = ((passes+c_passes,broken+c_broken), - data[2], - data[3], - data[4], - data[5]) - end - res = vcat(collect(data), cpu_rss, compilations) - - GC.gc(true) - res - finally - Test.TESTSET_PRINT_ENABLE[] = old_print_setting - end -end - - -## auxiliary stuff - -# Run some code on-device -macro on_device(ex...) - code = ex[end] - kwargs = ex[1:end-1] - - @gensym kernel - esc(quote - let - function $kernel() - $code - return - end - - @opencl $(kwargs...) $kernel() - cl.finish(cl.queue()) - end - end) -end - - -nothing # File is loaded via a remotecall to "include". Ensure it returns "nothing".