diff --git a/src/core/output.jl b/src/core/output.jl index 8bf8dcce92e97ab1436044fd0d35846bff9daa79..b6437ec42c02190c8c7dd9439f5a2cc2b67cbe47 100644 --- a/src/core/output.jl +++ b/src/core/output.jl @@ -166,7 +166,8 @@ Cycle through all registered data outputs and activate them according to their configured frequency. """ function outputdata(model::AgentBasedModel) - #XXX all output functions are run on the first update (regardless of frequency) + #TODO enable output every X days + #XXX all output functions except for "end" are run on the first update # -> should they all be run on the last update, too? startdate = @param(core.startdate) isnextmonth = d -> (day(d) == day(startdate)) diff --git a/test/io_tests.jl b/test/io_tests.jl index 2180c599d5018eec8dc290c876f3251270ef350a..2fb71c9f13ef9bcf127680216c362b3efd03eefd 100644 --- a/test/io_tests.jl +++ b/test/io_tests.jl @@ -18,10 +18,7 @@ end @testset "Output functions" begin - properties = Dict{Symbol,Any}(:settings=>TESTSETTINGS, - :dataoutputs=>Vector{DataOutput}()) - space = GridSpace((10,10), periodic=false) - model = AgentBasedModel(Animal, space, properties=properties, warn=false) + model = smalltestlandscape() # test that the output directory is created with all files outdir = @param(core.outdir) Ps.createdatadir(outdir, @param(core.overwrite)) @@ -35,9 +32,29 @@ end @test isfile(joinpath(outdir, @param(core.configfile))) @test isfile(joinpath(outdir, Ps.LOGFILE)) # check whether the overwrite warning/protection works - logstring = "Overwriting existing output directory $(outdir)." - #TODO test overwrite protection - @test_logs (:warn, logstring) match_mode=:any Ps.createdatadir(outdir, @param(core.overwrite)) + @test_logs((:warn, "Overwriting existing output directory $(outdir)."), + match_mode=:any, + Ps.createdatadir(outdir, @param(core.overwrite))) + @test_throws ErrorException Ps.createdatadir(outdir, false) + # test that creating a DataOutput works, and outputs data with the required frequency + testoutput(model) = string(model.date)*"\n" + Ps.newdataoutput!(model, "never.csv", "Date", testoutput, "never") + Ps.newdataoutput!(model, "daily.csv", "Date", testoutput, "daily") + Ps.newdataoutput!(model, "monthly.csv", "Date", testoutput, "monthly") + Ps.newdataoutput!(model, "yearly.csv", "Date", testoutput, "yearly") + Ps.newdataoutput!(model, "end.csv", "Date", testoutput, "end") + @param(core.enddate) = Date(2023,2,1) + @test_logs((:info, "Simulated 366 days."), + match_mode=:any, + simulate!(Ps.withtestlogger(model))) + @test !isfile(joinpath(outdir, "never.csv")) + @test isfile(joinpath(outdir, "daily.csv")) + @test countlines(joinpath(outdir, "daily.csv")) == 367 + @test isfile(joinpath(outdir, "monthly.csv")) + @test countlines(joinpath(outdir, "monthly.csv")) == 14 + @test isfile(joinpath(outdir, "yearly.csv")) + @test countlines(joinpath(outdir, "yearly.csv")) == 3 + @test isfile(joinpath(outdir, "end.csv")) + @test countlines(joinpath(outdir, "end.csv")) == 2 rm(outdir, force=true, recursive=true) - #TODO test that creating a DataOutput works, and outputs data with the required frequency end diff --git a/test/landscape_tests.jl b/test/landscape_tests.jl index 7e338e9469a4641cf40d2eaa8590181f74ca83f3..e989fdb41eea1ad201b1f2a96cf9965fdd06e5e0 100644 --- a/test/landscape_tests.jl +++ b/test/landscape_tests.jl @@ -3,38 +3,6 @@ ### These are the tests for the core landscape functions. ### -""" - smalltestlandscape() - -Create a 6x6 landscape with three land cover types for testing: - - F F F F F F - F F F F F F - F F F F F F - F F F F F W - F F G G G G - F F G G G G -""" -function smalltestlandscape() - landscape = Matrix{Pixel}(undef, 6, 6) - for x in 1:6 - for y in 1:6 - (x in (1:2) || y in (1:4)) ? lc = Ps.forest : lc = Ps.grass - landscape[x,y] = Pixel(lc, missing, []) - end - end - landscape[6,4] = Pixel(Ps.water, 0, []) - space = GridSpace(size(landscape), periodic=false) - properties = Dict{Symbol,Any}(:date=>TESTSETTINGS["core.startdate"], - :landscape=>landscape, - :events=>Vector{FarmEvent}(), - :logger=>global_logger(), - :dataoutputs=>Vector{DataOutput}(), - :settings=>TESTSETTINGS) - return AgentBasedModel(Union{Farmer,Animal,FarmPlot}, space, properties=properties, - rng=StableRNG(TESTSETTINGS["core.seed"]), warn=false) -end - @testset "Landscape initialisation" begin # initialise the landscape part of the model landscape = Ps.initlandscape(TESTSETTINGS["core.landcovermap"], diff --git a/test/paramscan.toml b/test/paramscan.toml index cd3f513d8499f869b43bdd104e6a83073992502d..ec44c3e14e7b53c6640e6882d8721591a3c54be1 100644 --- a/test/paramscan.toml +++ b/test/paramscan.toml @@ -3,6 +3,8 @@ ### This configuration file is intended to test the parameter scanning feature. ### +#XXX remember that changes here may break tests! + [core] configfile = "test/paramscan.toml" # location of the configuration file landcovermap = "landcover_jena.tif" # location of the landcover map diff --git a/test/runtests.jl b/test/runtests.jl index 1542cc2dcbb68c77b7ef78a64a4ac4e7d8aa4a2c..24aea56a16c6c8c40e7cadb762f8dae290a823ba 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,6 +20,38 @@ const Ps = Persephone const TESTPARAMETERS = joinpath(pkgdir(Persephone), "test/test_parameters.toml") const TESTSETTINGS = Ps.getsettings(TESTPARAMETERS) +""" + smalltestlandscape() + +Create a 6x6 landscape with three land cover types for testing: + + F F F F F F + F F F F F F + F F F F F F + F F F F F W + F F G G G G + F F G G G G +""" +function smalltestlandscape() + landscape = Matrix{Pixel}(undef, 6, 6) + for x in 1:6 + for y in 1:6 + (x in (1:2) || y in (1:4)) ? lc = Ps.forest : lc = Ps.grass + landscape[x,y] = Pixel(lc, missing, []) + end + end + landscape[6,4] = Pixel(Ps.water, 0, []) + space = GridSpace(size(landscape), periodic=false) + properties = Dict{Symbol,Any}(:date=>TESTSETTINGS["core.startdate"], + :landscape=>landscape, + :events=>Vector{FarmEvent}(), + :logger=>global_logger(), + :dataoutputs=>Vector{DataOutput}(), + :settings=>TESTSETTINGS) + return AgentBasedModel(Union{Farmer,Animal,FarmPlot}, space, properties=properties, + rng=StableRNG(TESTSETTINGS["core.seed"]), warn=false) +end + @testset "Persephone Tests" begin @testset "Core model" begin include("io_tests.jl") @@ -40,5 +72,5 @@ end # NOTE: Due to an issue with Julia (https://github.com/JuliaLang/julia/issues/48456), # whenever we are using `@test_logs` with a function that takes a model object, we have -# to wrap that model object in `withtestlogger()`. (For an example, see the "Model +# to wrap that model object in `Ps.withtestlogger()`. (For an example, see the "Model # simulation" testset in simulation_tests.jl.) diff --git a/test/simulation_tests.jl b/test/simulation_tests.jl index 7701033638bbe8fc870ea2c9560dfb0e90ef485e..678bf3f86a3064c434b3438305deb7b60754dd28 100644 --- a/test/simulation_tests.jl +++ b/test/simulation_tests.jl @@ -17,22 +17,25 @@ end @testset "Parameter scanning" begin config = "paramscan.toml" - testdirs = ["results_test_paramscan/seed_1_loglevel_debug_overwrite_ask", - "results_test_paramscan/seed_1_loglevel_debug_overwrite_true", + testdirs = ["results_test_paramscan/seed_1_loglevel_warn_overwrite_ask", + "results_test_paramscan/seed_1_loglevel_warn_overwrite_true", "results_test_paramscan/seed_2_loglevel_info_overwrite_true"] settings = Ps.getsettings(config) scanparams = settings["internal.scanparams"] @test length(scanparams) == 3 @test sort(["core.overwrite", "core.loglevel", "core.seed"]) == sort(scanparams) scan = Ps.paramscan(settings, scanparams) - outdirs = (s["core.outdir"] for s in scan) + outdirs = map(s -> s["core.outdir"], scan) @test length(outdirs) == 12 - @test length(initialise(config)) == 12 #XXX This takes a long time + #TODO while parallelisation doesn't work yet, initialising 12 models takes too + # long to do every time the test suite is run. Therefore, I'm commenting out + # some tests here, to be reinstated once parallelisation is implemented. + #@test length(initialise(config)) == 12 for dir in testdirs @test dir in outdirs - @test isdir(dir) + #@test isdir(dir) end - rm("results_test_paramscan", force=true, recursive=true) + #rm("results_test_paramscan", force=true, recursive=true) end @testset "Model simulation" begin diff --git a/test/test_parameters.toml b/test/test_parameters.toml index 7c8891dbac73c8bc10726165771bdfb07fdc46c4..45f37a310536899ca646a93ca61e0761eacc7609 100644 --- a/test/test_parameters.toml +++ b/test/test_parameters.toml @@ -3,6 +3,8 @@ ### This configuration file is used for the test suite. ### +#XXX remember that changes here may break tests! + [core] configfile = "test_parameters.toml" # location of the configuration file landcovermap = "landcover_jena.tif" # location of the landcover map