diff --git a/test/jobenvs/job-dist/Manifest.toml b/test/jobenvs/job-dist/Manifest.toml index 59624d98a..d3f477ffb 100644 --- a/test/jobenvs/job-dist/Manifest.toml +++ b/test/jobenvs/job-dist/Manifest.toml @@ -1,16 +1,45 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.9.4" +julia_version = "1.11.7" manifest_format = "2.0" -project_hash = "15b8400de0ed6d0aa5f96c6341a036f45951aee0" +project_hash = "0d521bbd8bb6739e51557d680232c96ed350e3a1" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.2" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +version = "1.11.0" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +version = "1.11.0" [[deps.Dates]] deps = ["Printf"] uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +version = "1.11.0" [[deps.Distributed]] deps = ["Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" +version = "1.11.0" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.ElasticClusterManager]] +deps = ["Distributed", "Logging", "MbedTLS", "Pkg", "Serialization", "Sockets", "TLSStreams"] +git-tree-sha1 = "cb58f5f1424daf58c02df426decdd0b8d468a3fc" +uuid = "5d47888a-328e-4da2-b0ad-c7c2d6e59f6b" +version = "0.2.2" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +version = "1.11.0" [[deps.JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] @@ -18,34 +47,111 @@ git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" version = "0.21.4" +[[deps.JuliaHubDistributed]] +deps = ["Distributed", "Downloads", "ElasticClusterManager", "Sockets", "TLSStreams"] +git-tree-sha1 = "8928ce5a1febee2edbe5635fe03e74705e809a98" +uuid = "ac0873db-f1c6-408a-a97a-f3c80a675215" +version = "0.2.0" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.6.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +version = "1.11.0" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.7.2+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +version = "1.11.0" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" +version = "1.11.0" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +version = "1.11.0" + +[[deps.MbedTLS]] +deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] +git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" +uuid = "739be429-bea8-5141-9913-cc70e7f3736d" +version = "1.1.9" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.6+0" + [[deps.Mmap]] uuid = "a63ad114-7e13-5084-954f-fe012c677804" +version = "1.11.0" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.12.12" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" [[deps.Parsers]] deps = ["Dates", "PrecompileTools", "UUIDs"] -git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821" +git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.8.1" +version = "2.8.3" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.11.0" + + [deps.Pkg.extensions] + REPLExt = "REPL" + + [deps.Pkg.weakdeps] + REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[deps.PrecompileTools]] deps = ["Preferences"] -git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.2.0" +version = "1.2.1" [[deps.Preferences]] deps = ["TOML"] -git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e" +git-tree-sha1 = "0f27480397253da18fe2c12a4ba4eb9eb208bf3d" uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.1" +version = "1.5.0" [[deps.Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +version = "1.11.0" [[deps.Random]] -deps = ["SHA", "Serialization"] +deps = ["SHA"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" [[deps.SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" @@ -53,18 +159,48 @@ version = "0.7.0" [[deps.Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +version = "1.11.0" [[deps.Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" +version = "1.11.0" + +[[deps.TLSStreams]] +deps = ["MbedTLS", "Sockets"] +git-tree-sha1 = "d338ed421b802cc65a44e0bac4be8192537ab0d2" +uuid = "94274baf-45e9-4e40-af20-2f884efab5aa" +version = "0.1.1" [[deps.TOML]] deps = ["Dates"] uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" version = "1.0.3" +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + [[deps.UUIDs]] deps = ["Random", "SHA"] uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +version = "1.11.0" [[deps.Unicode]] uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.59.0+0" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" diff --git a/test/jobenvs/job-dist/Project.toml b/test/jobenvs/job-dist/Project.toml index 8b9f6b10f..01f12d4df 100644 --- a/test/jobenvs/job-dist/Project.toml +++ b/test/jobenvs/job-dist/Project.toml @@ -1,3 +1,4 @@ [deps] -Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +JuliaHubDistributed = "ac0873db-f1c6-408a-a97a-f3c80a675215" +Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" diff --git a/test/jobenvs/job-dist/script.jl b/test/jobenvs/job-dist/script.jl index f0f154d54..b56192899 100644 --- a/test/jobenvs/job-dist/script.jl +++ b/test/jobenvs/job-dist/script.jl @@ -1,4 +1,8 @@ -using Distributed, JSON +using Distributed, JSON, JuliaHubDistributed + +JuliaHubDistributed.start() +JuliaHubDistributed.wait_for_workers() + @everywhere using Distributed @everywhere fn() = (myid(), strip(read(`hostname`, String))) fs = [i => remotecall(fn, i) for i in workers()] @@ -8,3 +12,8 @@ vs = map(fs) do (i, future) (; myid, hostname) end ENV["RESULTS"] = JSON.json((; vs)) +if haskey(ENV, "JULIAHUB_RESULTS_SUMMARY_FILE") + open(ENV["JULIAHUB_RESULTS_SUMMARY_FILE"], "w") do io + write(io, ENV["RESULTS"]) + end +end diff --git a/test/jobenvs/job-exposed-port/server.jl b/test/jobenvs/job-exposed-port/server.jl index f88d444a4..d4d20836d 100644 --- a/test/jobenvs/job-exposed-port/server.jl +++ b/test/jobenvs/job-exposed-port/server.jl @@ -30,4 +30,9 @@ serve(; host="0.0.0.0", port=PORT) @info "Exiting the server" ENV["RESULTS"] = results_json() +if haskey(ENV, "JULIAHUB_RESULTS_SUMMARY_FILE") + open(ENV["JULIAHUB_RESULTS_SUMMARY_FILE"], "w") do io + write(io, ENV["RESULTS"]) + end +end println(ENV["RESULTS"]) diff --git a/test/jobenvs/job1/script.jl b/test/jobenvs/job1/script.jl index 7a4b32d3e..605512041 100644 --- a/test/jobenvs/job1/script.jl +++ b/test/jobenvs/job1/script.jl @@ -34,3 +34,8 @@ results = Dict( @info "Storing RESULTS:\n$(results)" ENV["RESULTS"] = JSON.json(results) +if haskey(ENV, "JULIAHUB_RESULTS_SUMMARY_FILE") + open(ENV["JULIAHUB_RESULTS_SUMMARY_FILE"], "w") do io + write(io, ENV["RESULTS"]) + end +end diff --git a/test/jobenvs/sysimage/script.jl b/test/jobenvs/sysimage/script.jl index d6a5f526a..b346d179f 100644 --- a/test/jobenvs/sysimage/script.jl +++ b/test/jobenvs/sysimage/script.jl @@ -16,4 +16,9 @@ ENV["RESULTS"] = """ "hello": "$(hello)" } """ +if haskey(ENV, "JULIAHUB_RESULTS_SUMMARY_FILE") + open(ENV["JULIAHUB_RESULTS_SUMMARY_FILE"], "w") do io + write(io, ENV["RESULTS"]) + end +end @info ENV["RESULTS"] diff --git a/test/jobs-applications-live.jl b/test/jobs-applications-live.jl index f63a6139e..d6530be04 100644 --- a/test/jobs-applications-live.jl +++ b/test/jobs-applications-live.jl @@ -10,5 +10,5 @@ DEFAULT_IDE_NAME = get(ENV, "JULIAHUBJL_LIVE_IDE_NAME", "Julia IDE") @test job.status == "Running" job = JuliaHub.kill_job(job) job = JuliaHub.wait_job(job) - @test job.status == "Stopped" + @test test_job_done_and_not_failed(job, "Stopped") end diff --git a/test/jobs-live.jl b/test/jobs-live.jl index 23ab5bfb3..c29618baf 100644 --- a/test/jobs-live.jl +++ b/test/jobs-live.jl @@ -158,7 +158,7 @@ end end end job_killed = JuliaHub.job(job_killed) # test default auth= - @test job_killed.status == "Stopped" + @test test_job_done_and_not_failed(job_killed, "Stopped") # wait for the logger task to finish, if hasn't already JuliaHub.interrupt!(logbuffer; wait=true) @@ -185,6 +185,11 @@ end job, _ = submit_test_job( JuliaHub.script""" ENV["RESULTS"] = "{\\"x\\":42}" + if haskey(ENV, "JULIAHUB_RESULTS_SUMMARY_FILE") + open(ENV["JULIAHUB_RESULTS_SUMMARY_FILE"], "w") do io + write(io, "{\\"x\\":42}") + end + end error("fail") """noenv; auth, alias="script-fail", timelimit=JuliaHub.Unlimited(), @@ -202,13 +207,18 @@ end end @testset "[LIVE] JuliaHub.submit_job / distributed" begin + script_path = joinpath(@__DIR__, "jobenvs", "job-dist") job, _ = submit_test_job( - JuliaHub.appbundle(joinpath(@__DIR__, "jobenvs", "job-dist"), "script.jl"); + JuliaHub.script(; + code=read(joinpath(script_path, "script.jl"), String), + project=read(joinpath(script_path, "Project.toml"), String), + manifest=read(joinpath(script_path, "Manifest.toml"), String), + ); nnodes=3, auth, alias="distributed", ) job = JuliaHub.wait_job(job) - @test job.status == "Completed" + @test test_job_done_and_not_failed(job, "Completed") @test !isempty(job.results) let results = JSON.parse(job.results) @test results isa AbstractDict @@ -219,8 +229,13 @@ end end @testset "[LIVE] JuliaHub.submit_job / distributed-per-core" begin + script_path = joinpath(@__DIR__, "jobenvs", "job-dist") job, full_alias = submit_test_job( - JuliaHub.appbundle(joinpath(@__DIR__, "jobenvs", "job-dist"), "script.jl"); + JuliaHub.script(; + code=read(joinpath(script_path, "script.jl"), String), + project=read(joinpath(script_path, "Project.toml"), String), + manifest=read(joinpath(script_path, "Manifest.toml"), String), + ); ncpu=2, nnodes=3, process_per_node=false, env=Dict("FOO" => "bar"), auth, alias="distributed-percore", @@ -229,7 +244,7 @@ end @test job.alias == full_alias @test job.env["FOO"] == "bar" job = JuliaHub.wait_job(job) - @test job.status == "Completed" + @test test_job_done_and_not_failed(job, "Completed") @test !isempty(job.results) let results = JSON.parse(job.results) @test results isa AbstractDict @@ -251,7 +266,7 @@ end auth, alias="scripts-1", ) job = JuliaHub.wait_job(job) - @test job.status == "Completed" + @test test_job_done_and_not_failed(job, "Completed") @test !isempty(job.results) let results = JSON.parse(job.results) @test results isa AbstractDict @@ -271,7 +286,7 @@ end auth, alias="scripts-2", ) job = JuliaHub.wait_job(job) - @test job.status == "Completed" + @test test_job_done_and_not_failed(job, "Completed") @test !isempty(job.results) let results = JSON.parse(job.results) @test results isa AbstractDict @@ -282,37 +297,41 @@ end end end -@testset "[LIVE] JuliaHub.submit_job / appbundle" begin - job1_dir = joinpath(@__DIR__, "jobenvs", "job1") - # Note: the exact hash of the file may change if Git decides to change line endings - # on e.g. Windows. - datafile_hash = bytes2hex(open(SHA.sha1, joinpath(job1_dir, "datafile.txt"))) - job, _ = submit_test_job( - JuliaHub.appbundle(job1_dir, "script.jl"); - auth, alias="appbundle", - ) - job = JuliaHub.wait_job(job) - @test job.status == "Completed" - # Check input and output files - @test length(JuliaHub.job_files(job, :input)) >= 2 - @test JuliaHub.job_file(job, :input, "code.jl") isa JuliaHub.JobFile - @test JuliaHub.job_file(job, :input, "appbundle.tar") isa JuliaHub.JobFile - # Test the results values - @test !isempty(job.results) - let results = JSON.parse(job.results) - @test results isa AbstractDict - @test haskey(results, "datastructures_version") - @test VersionNumber(results["datastructures_version"]) == v"0.17.0" - @test haskey(results, "datafile_hash") - @test results["datafile_hash"] == datafile_hash - @test haskey(results, "scripts") - let s = results["scripts"] - @test s isa AbstractDict - @test get(s, "include_success", nothing) === true - @test get(s, "script_1", nothing) === true - @test get(s, "script_2", nothing) === true +if v"1.10" <= Base.VERSION < v"1.12" + @testset "[LIVE] JuliaHub.submit_job / appbundle" begin + job1_dir = joinpath(@__DIR__, "jobenvs", "job1") + # Note: the exact hash of the file may change if Git decides to change line endings + # on e.g. Windows. + datafile_hash = bytes2hex(open(SHA.sha1, joinpath(job1_dir, "datafile.txt"))) + job, _ = submit_test_job( + JuliaHub.appbundle(job1_dir, "script.jl"); + auth, alias="appbundle", + ) + job = JuliaHub.wait_job(job) + @test test_job_done_and_not_failed(job, "Completed") + # Check input and output files + @test length(JuliaHub.job_files(job, :input)) >= 2 + @test JuliaHub.job_file(job, :input, "code.jl") isa JuliaHub.JobFile + @test JuliaHub.job_file(job, :input, "appbundle.tar") isa JuliaHub.JobFile + # Test the results values + @test !isempty(job.results) + let results = JSON.parse(job.results) + @test results isa AbstractDict + @test haskey(results, "datastructures_version") + @test VersionNumber(results["datastructures_version"]) == v"0.17.0" + @test haskey(results, "datafile_hash") + @test results["datafile_hash"] == datafile_hash + @test haskey(results, "scripts") + let s = results["scripts"] + @test s isa AbstractDict + @test get(s, "include_success", nothing) === true + @test get(s, "script_1", nothing) === true + @test get(s, "script_2", nothing) === true + end end end +else + @info("Skipping appbundle tests for Julia version $(Base.VERSION)") end @testset "[LIVE] Job output file access" begin @@ -322,10 +341,15 @@ end ENV["RESULTS_FILE"] = joinpath(@__DIR__, "output.txt") n = write(ENV["RESULTS_FILE"], "output-txt-content") @info "Wrote $(n) bytes" + if haskey(ENV, "JULIAHUB_RESULTS_UPLOAD_DIR") + open(joinpath(ENV["JULIAHUB_RESULTS_UPLOAD_DIR"], "output.txt"), "w") do io + write(io, "output-txt-content") + end + end """noenv; alias="output-file" ) job = JuliaHub.wait_job(job) - @test job.status == "Completed" + @test test_job_done_and_not_failed(job, "Completed") # Project.toml, Manifest.toml, code.jl @test length(JuliaHub.job_files(job, :input)) >= 1 @test JuliaHub.job_file(job, :input, "code.jl") isa JuliaHub.JobFile @@ -346,8 +370,13 @@ end # Job output with a tarball: job, _ = submit_test_job( JuliaHub.script""" - odir = joinpath(@__DIR__, "output_files") - mkdir(odir) + odir = if haskey(ENV, "JULIAHUB_RESULTS_UPLOAD_DIR") + ENV["JULIAHUB_RESULTS_UPLOAD_DIR"] + else + d = joinpath(@__DIR__, "output_files") + mkdir(d) + d + end write(joinpath(odir, "foo.txt"), "output-txt-content-1") write(joinpath(odir, "bar.txt"), "output-txt-content-2") @info "Wrote: odir" @@ -355,7 +384,7 @@ end """noenv; alias="output-file-tarball" ) job = JuliaHub.wait_job(job) - @test job.status == "Completed" + @test test_job_done_and_not_failed(job, "Completed") @test length(JuliaHub.job_files(job, :project)) >= 1 result_tarball = only(JuliaHub.job_files(job, :result)) buf = IOBuffer() @@ -388,15 +417,19 @@ end end @testset "[LIVE] JuliaHub.submit_job / sysimage" begin + script_path = joinpath(@__DIR__, "jobenvs", "sysimage") job, _ = submit_test_job( - JuliaHub.appbundle( - joinpath(@__DIR__, "jobenvs", "sysimage"), - "script.jl"; + JuliaHub.script(; + code=read(joinpath(script_path, "script.jl"), String), + project=read(joinpath(script_path, "Project.toml"), String), + manifest=read(joinpath(script_path, "Manifest.toml"), String), sysimage=true, - ); auth, alias="sysimage" + ); + auth, + alias="sysimage", ) job = JuliaHub.wait_job(job) - @test job.status == "Completed" + @test test_job_done_and_not_failed(job, "Completed") @test job._json["sysimage_build"] === true @test !isempty(job.results) let results = JSON.parse(job.results) diff --git a/test/runtests.jl b/test/runtests.jl index 8f4d138e2..4a33cc921 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -95,6 +95,13 @@ function list_datasets_prefix(prefix, args...; kwargs...) end end +function test_job_done_and_not_failed(job, ideal_status) + if job.status != ideal_status + @warn("ideal job status expected $(ideal_status), found $(job.status)") + end + job.status in ("Completed", "Stopped") +end + @testset "JuliaHub.jl" begin # JuliaHub.jl's behavior can be influenced by these two environment # variables, so we explicitly unset them, just in case, to ensure that the