Skip to content
Snippets Groups Projects
Commit fd1cfdeb authored by xo30xoqa's avatar xo30xoqa
Browse files

Fixed @test_logs issue, code cleanup

parent 47496d12
Branches
Tags
No related merge requests found
...@@ -20,11 +20,17 @@ using ...@@ -20,11 +20,17 @@ using
GeoArrays, #XXX this is a big dependency - can we get rid of it? GeoArrays, #XXX this is a big dependency - can we get rid of it?
Logging, Logging,
LoggingExtras, LoggingExtras,
#MacroTools, #may be useful: http://fluxml.ai/MacroTools.jl/stable/utilities/
Random, Random,
StableRNGs, StableRNGs,
TOML TOML
## Packages to check out:
# MacroTools, http://fluxml.ai/MacroTools.jl/stable/utilities/
# Debugger, https://github.com/JuliaDebug/Debugger.jl
# Makie, https://docs.makie.org/stable/
# PackageCompiler, https://julialang.github.io/PackageCompiler.jl/stable/
# SpatialEcology, https://github.com/EcoJulia/SpatialEcology.jl
## define exported functions and variables ## define exported functions and variables
export export
#types #types
......
...@@ -64,14 +64,19 @@ function getsettings(configfile::String, seed::Union{Int64,Nothing}=nothing) ...@@ -64,14 +64,19 @@ function getsettings(configfile::String, seed::Union{Int64,Nothing}=nothing)
end end
end end
end end
# pre-process certain parameters !isnothing(seed) && (settings["core.seed"] = seed)
if !isnothing(seed) settings["internal.scanparams"] = scanparams
settings["core.seed"] = seed preprocessparameters(settings, defaults["core.outdir"])
end
if settings["core.seed"] == 0
settings["core.seed"] = abs(rand(RandomDevice(), Int32))
end end
defaultoutdir = defaults["core.outdir"]
"""
preprocessparameters(settings)
Take the raw input parameters and process them (convert types, perform checks, etc.).
This is a helper function for `getsettings()`.
"""
function preprocessparameters(settings::Dict{String,Any}, defaultoutdir::String)
(settings["core.seed"] == 0) && (settings["core.seed"] = abs(rand(RandomDevice(), Int32)))
if settings["core.outdir"] == defaultoutdir if settings["core.outdir"] == defaultoutdir
outdir = defaultoutdir*"_"*string(Dates.today())*"_s"*string(settings["core.seed"]) outdir = defaultoutdir*"_"*string(Dates.today())*"_s"*string(settings["core.seed"])
settings["core.outdir"] = outdir settings["core.outdir"] = outdir
...@@ -79,8 +84,15 @@ function getsettings(configfile::String, seed::Union{Int64,Nothing}=nothing) ...@@ -79,8 +84,15 @@ function getsettings(configfile::String, seed::Union{Int64,Nothing}=nothing)
if settings["core.startdate"] > settings["core.enddate"] if settings["core.startdate"] > settings["core.enddate"]
Base.error("Enddate is earlier than startdate.") #TODO replace with exception Base.error("Enddate is earlier than startdate.") #TODO replace with exception
end end
!isempty(scanparams) && addprocs(settings["core.processors"]) settings["core.loglevel"] == "debug" ? settings["core.loglevel"] = Logging.Debug :
settings["internal.scanparams"] = scanparams settings["core.loglevel"] == "warn" ? settings["core.loglevel"] = Logging.Warn :
settings["core.loglevel"] = Logging.Info
if !isempty(settings["internal.scanparams"])
# https://docs.julialang.org/en/v1/manual/distributed-computing/#code-availability
addprocs(settings["core.processors"])
#addprocs(exeflags="--project") ?
@everywhere include("../Persephone.jl") #FIXME
end
settings settings
end end
...@@ -90,7 +102,7 @@ end ...@@ -90,7 +102,7 @@ end
An internal utility function to convert the two-dimensional dict returned An internal utility function to convert the two-dimensional dict returned
by `TOML.parsefile()` into a one-dimensional dict, so that instead of by `TOML.parsefile()` into a one-dimensional dict, so that instead of
writing `settings["domain"]["param"]` one can use `settings["domain.param"]`. writing `settings["domain"]["param"]` one can use `settings["domain.param"]`.
Can be reversed with `expandTOML()`. Can be reversed with `prepareTOML()`.
""" """
function flattenTOML(tomldict) function flattenTOML(tomldict)
flatdict = Dict{String, Any}() flatdict = Dict{String, Any}()
...@@ -127,7 +139,7 @@ function parsecommandline() ...@@ -127,7 +139,7 @@ function parsecommandline()
arg_type = String arg_type = String
required = false required = false
"--loglevel", "-l" "--loglevel", "-l"
help = "verbosity: \"debug\", \"info\", or \"quiet\"" help = "verbosity: \"debug\", \"info\", or \"warn\""
arg_type = String arg_type = String
required = false required = false
end end
......
...@@ -22,36 +22,43 @@ function createdatadir(outdir::String, overwrite::Union{Bool,String}) ...@@ -22,36 +22,43 @@ function createdatadir(outdir::String, overwrite::Union{Bool,String})
answer = readline() answer = readline()
(answer == "yes") && (overwrite = true) (answer == "yes") && (overwrite = true)
end end
if !overwrite !overwrite ? Base.error("Output directory exists, will not overwrite. Aborting.") :
#TODO replace with exception
Base.error("Output directory exists, will not overwrite. Aborting.")
else
@warn "Overwriting existing output directory $(outdir)." @warn "Overwriting existing output directory $(outdir)."
end #TODO replace with exception
end end
mkpath(outdir) mkpath(outdir)
end end
""" """
modellogger(logsetting, outdir) modellogger(loglevel, outdir)
Create a logger object that writes output both to screen and to a logfile. Create a logger object that writes output both to screen and to a logfile.
This object is stored as `model.logger` and can then be used with `with_logger()`. This object is stored as `model.logger` and can then be used with `with_logger()`.
Note: requires `createdatadir()` to be run first. Note: requires `createdatadir()` to be run first.
""" """
function modellogger(logsetting::String, outdir::String) function modellogger(loglevel::LogLevel, outdir::String)
!isdir(outdir) && #TODO replace with exception
Base.error("$(outdir) does not exist. Call `createdatadir()` before `modellogger()`.")
#XXX If this is a parallel run, should we turn off logging to screen? #XXX If this is a parallel run, should we turn off logging to screen?
loglevel = Logging.Info
if logsetting == "debug"
loglevel = Logging.Debug
elseif logsetting == "warn"
loglevel = Logging.Warn
end
logfile = open(joinpath(outdir, LOGFILE), "w+") logfile = open(joinpath(outdir, LOGFILE), "w+")
TeeLogger(ConsoleLogger(logfile, loglevel), TeeLogger(ConsoleLogger(logfile, loglevel),
ConsoleLogger(stdout, loglevel)) ConsoleLogger(stdout, loglevel))
end end
"""
withtestlogger(model)
Replace the model logger with the currently active logger. This is intended to be
used in the testsuite to circumvent a Julia issue, where @test_logs doesn't work
with local loggers (https://github.com/JuliaLang/julia/issues/48456).
"""
function withtestlogger(model::AgentBasedModel)
# copied together from https://github.com/JuliaLang/julia/blob/master/base/logging.jl
logstate = current_task().logstate
logstate == nothing ? model.logger = global_logger() : model.logger = logstate.logger
model
end
""" """
saveinputfiles(model) saveinputfiles(model)
...@@ -59,6 +66,8 @@ Copy all input files into the output directory, including the actual parameter ...@@ -59,6 +66,8 @@ Copy all input files into the output directory, including the actual parameter
settings used. This allows replicating a run in future. settings used. This allows replicating a run in future.
""" """
function saveinputfiles(model::AgentBasedModel) function saveinputfiles(model::AgentBasedModel)
#XXX If this is a parallel run, we should save the global config to the top-level
# output directory
@debug "Setting up output directory $(@param(core.outdir))." @debug "Setting up output directory $(@param(core.outdir))."
currentcommit = read(`git rev-parse HEAD`, String)[1:8] currentcommit = read(`git rev-parse HEAD`, String)[1:8]
open(joinpath(@param(core.outdir), basename(@param(core.configfile))), "w") do f open(joinpath(@param(core.outdir), basename(@param(core.configfile))), "w") do f
...@@ -72,7 +81,7 @@ function saveinputfiles(model::AgentBasedModel) ...@@ -72,7 +81,7 @@ function saveinputfiles(model::AgentBasedModel)
println(f, "# WARNING: Your repository contains uncommitted changes. This may") println(f, "# WARNING: Your repository contains uncommitted changes. This may")
println(f, "# compromise the reproducibility of this simulation run.\n") println(f, "# compromise the reproducibility of this simulation run.\n")
end end
TOML.print(f, expandTOML(model.settings)) TOML.print(f, prepareTOML(model.settings))
end end
# Copy the map files to the output folder # Copy the map files to the output folder
lcmap = @param(core.landcovermap) lcmap = @param(core.landcovermap)
...@@ -85,17 +94,23 @@ function saveinputfiles(model::AgentBasedModel) ...@@ -85,17 +94,23 @@ function saveinputfiles(model::AgentBasedModel)
end end
""" """
expandTOML(dict) prepareTOML(dict)
An internal utility function to re-convert the one-dimensional dict created An internal utility function to re-convert the one-dimensional dict created
by `flattenTOML()` into the two-dimensional dict needed by `TOML.print()`. by `flattenTOML()` into the two-dimensional dict needed by `TOML.print()`,
and convert any data types into TOML-compatible types where necessary.
""" """
function expandTOML(settingsdict) function prepareTOML(settings)
# convert data types
settings["core.loglevel"] == Logging.Debug ? settings["core.loglevel"] = "debug" :
settings["core.loglevel"] == Logging.Warn ? settings["core.loglevel"] = "warn" :
settings["core.loglevel"] = "info"
# convert dict structure
fulldict = Dict{String, Dict{String, Any}}() fulldict = Dict{String, Dict{String, Any}}()
for parameter in keys(settingsdict) for parameter in keys(settings)
domain, param = split(parameter, ".") domain, param = split(parameter, ".")
!(domain in keys(fulldict)) && (fulldict[domain] = Dict{String,Any}()) !(domain in keys(fulldict)) && (fulldict[domain] = Dict{String,Any}())
fulldict[domain][param] = settingsdict[parameter] fulldict[domain][param] = settings[parameter]
end end
fulldict fulldict
end end
......
...@@ -187,6 +187,7 @@ macro trait(traitname) ...@@ -187,6 +187,7 @@ macro trait(traitname)
# (i.e. outside of a @phase block). Although this is specified in the documentation, # (i.e. outside of a @phase block). Although this is specified in the documentation,
# it is unexpected and liable to be overlooked. Can we add a third clause to # it is unexpected and liable to be overlooked. Can we add a third clause to
# compensate for that? # compensate for that?
#TODO replace with `animal.traitname` syntax using `getproperty()`/`setproperty!()`
if traitname in fieldnames(Animal) if traitname in fieldnames(Animal)
:($(esc(:animal)).$(traitname)) :($(esc(:animal)).$(traitname))
else else
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
### ###
@testset "Model configuration" begin @testset "Model configuration" begin
# Test the configuration file
settings = Ps.getsettings(TESTPARAMETERS) settings = Ps.getsettings(TESTPARAMETERS)
properties = Dict{Symbol,Any}(:settings=>settings) properties = Dict{Symbol,Any}(:settings=>settings)
space = GridSpace((10,10), periodic=false) space = GridSpace((10,10), periodic=false)
...@@ -11,10 +12,20 @@ ...@@ -11,10 +12,20 @@
@test @param(core.configfile) == basename(TESTPARAMETERS) @test @param(core.configfile) == basename(TESTPARAMETERS)
@test @param(core.startdate) == Date(2022, 2, 1) @test @param(core.startdate) == Date(2022, 2, 1)
@test @param(core.loglevel) == Logging.Warn
@test @param(nature.targetspecies) == ["Wolpertinger", "Wyvern"] @test @param(nature.targetspecies) == ["Wolpertinger", "Wyvern"]
@param(core.enddate) = Date(2022,1,3) @param(core.enddate) = Date(2022,1,3)
@test @param(core.enddate) == Date(2022,1,3) @test @param(core.enddate) == Date(2022,1,3)
#TODO test commandline parameters # Test the parsing of commandline parameters
#XXX ARGS not recognised immediately - redefining a constant is problematic anyway
# Base.ARGS = ["--configfile", "test.toml", "-s", "314",
# "--outdir", "random_results", "-l", "info"]
# settings = Ps.getsettings(TESTPARAMETERS)
# @test @param(core.configfile) == "test.toml"
# @test @param(core.seed) == 314
# @test @param(core.outdir) == "random_results"
# @test @param(core.loglevel) == Logging.Info
# Base.ARGS = []
end end
@testset "Output functions" begin @testset "Output functions" begin
...@@ -24,18 +35,20 @@ end ...@@ -24,18 +35,20 @@ end
model = AgentBasedModel(Animal, space, properties=properties, warn=false) model = AgentBasedModel(Animal, space, properties=properties, warn=false)
# test that the output directory is created with all files # test that the output directory is created with all files
outdir = @param(core.outdir) outdir = @param(core.outdir)
Ps.createdatadir(outdir, @param(core.overwrite))
@test isdir(outdir)
logger = Ps.modellogger(@param(core.loglevel), outdir)
@test_logs((:debug, "Setting up output directory results_testsuite."), @test_logs((:debug, "Setting up output directory results_testsuite."),
min_level=Logging.Debug, match_mode=:any, min_level=Logging.Debug, match_mode=:any,
Ps.setupdatadir(model)) Ps.saveinputfiles(model))
@test isdir(outdir)
@test isfile(joinpath(outdir, @param(core.landcovermap))) @test isfile(joinpath(outdir, @param(core.landcovermap)))
@test isfile(joinpath(outdir, @param(core.farmfieldsmap))) @test isfile(joinpath(outdir, @param(core.farmfieldsmap)))
@test isfile(joinpath(outdir, @param(core.configfile))) @test isfile(joinpath(outdir, @param(core.configfile)))
@test isfile(joinpath(outdir, Ps.LOGFILE)) @test isfile(joinpath(outdir, Ps.LOGFILE))
# check whether the overwrite warning/protection works # check whether the overwrite warning/protection works
logstring = "Overwriting existing output directory $(outdir)." logstring = "Overwriting existing output directory $(outdir)."
@test_logs (:warn, logstring) match_mode=:any Ps.setupdatadir(model) #TODO test overwrite protection
#TODO test overwrite protection (requires parameter mutability) @test_logs (:warn, logstring) match_mode=:any Ps.createdatadir(outdir, @param(core.overwrite))
rm(outdir, force=true, recursive=true) rm(outdir, force=true, recursive=true)
#TODO test that creating a DataOutput works, and outputs data with the required frequency #TODO test that creating a DataOutput works, and outputs data with the required frequency
end end
...@@ -15,7 +15,7 @@ Create a 6x6 landscape with three land cover types for testing: ...@@ -15,7 +15,7 @@ Create a 6x6 landscape with three land cover types for testing:
F F G G G G F F G G G G
F F G G G G F F G G G G
""" """
function smalltestlandscape(agenttype::Type=Animal) function smalltestlandscape()
landscape = Matrix{Pixel}(undef, 6, 6) landscape = Matrix{Pixel}(undef, 6, 6)
for x in 1:6 for x in 1:6
for y in 1:6 for y in 1:6
...@@ -28,9 +28,10 @@ function smalltestlandscape(agenttype::Type=Animal) ...@@ -28,9 +28,10 @@ function smalltestlandscape(agenttype::Type=Animal)
properties = Dict{Symbol,Any}(:date=>TESTSETTINGS["core.startdate"], properties = Dict{Symbol,Any}(:date=>TESTSETTINGS["core.startdate"],
:landscape=>landscape, :landscape=>landscape,
:events=>Vector{FarmEvent}(), :events=>Vector{FarmEvent}(),
:logger=>global_logger(),
:dataoutputs=>Vector{DataOutput}(), :dataoutputs=>Vector{DataOutput}(),
:settings=>TESTSETTINGS) :settings=>TESTSETTINGS)
return AgentBasedModel(agenttype, space, properties=properties, return AgentBasedModel(Union{Farmer,Animal,FarmPlot}, space, properties=properties,
rng=StableRNG(TESTSETTINGS["core.seed"]), warn=false) rng=StableRNG(TESTSETTINGS["core.seed"]), warn=false)
end end
...@@ -62,11 +63,15 @@ end ...@@ -62,11 +63,15 @@ end
@test model.landscape[1,1].events == [Ps.tillage, Ps.sowing] @test model.landscape[1,1].events == [Ps.tillage, Ps.sowing]
@test model.landscape[2,1].events == [Ps.tillage] @test model.landscape[2,1].events == [Ps.tillage]
@test model.landscape[2,2].events == [Ps.sowing] @test model.landscape[2,2].events == [Ps.sowing]
@test_logs (:info, "Simulating day 2022-02-01.") match_mode=:any stepsimulation!(model) @test_logs((:info, "Simulating day 2022-02-01."),
match_mode=:any,
stepsimulation!(Ps.withtestlogger(model)))
@test model.landscape[1,1].events == [Ps.sowing] @test model.landscape[1,1].events == [Ps.sowing]
@test model.landscape[2,1].events == [] @test model.landscape[2,1].events == []
@test model.landscape[2,2].events == [Ps.sowing] @test model.landscape[2,2].events == [Ps.sowing]
@test_logs (:info, "Simulating day 2022-02-02.") match_mode=:any stepsimulation!(model) @test_logs((:info, "Simulating day 2022-02-02."),
match_mode=:any,
stepsimulation!(Ps.withtestlogger(model)))
@test model.landscape[1,1].events == [] @test model.landscape[1,1].events == []
@test model.landscape[2,1].events == [] @test model.landscape[2,1].events == []
@test model.landscape[2,2].events == [] @test model.landscape[2,2].events == []
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
@testset "Habitat macros" begin @testset "Habitat macros" begin
# set up the testing landscape # set up the testing landscape
model = smalltestlandscape(Union{Animal,FarmPlot}) model = smalltestlandscape()
model.landscape[6,6] = Pixel(Ps.agriculture, 1, []) model.landscape[6,6] = Pixel(Ps.agriculture, 1, [])
species::Dict{String,Any} = Dict("name"=>"test_animal") species::Dict{String,Any} = Dict("name"=>"test_animal")
add_agent!((6,6), FarmPlot, model, [(6,6)], Ps.wheat, 1.2, 3.4) add_agent!((6,6), FarmPlot, model, [(6,6)], Ps.wheat, 1.2, 3.4)
...@@ -68,7 +68,7 @@ end ...@@ -68,7 +68,7 @@ end
@testset "Species macros" begin @testset "Species macros" begin
# create a model landscape and a test species # create a model landscape and a test species
model = smalltestlandscape(Union{Animal,Farmer,FarmPlot}) model = smalltestlandscape()
@species Mermaid begin @species Mermaid begin
ageofmaturity = 2 ageofmaturity = 2
...@@ -80,7 +80,7 @@ end ...@@ -80,7 +80,7 @@ end
@respond Persephone.harvest @setphase(drought) @respond Persephone.harvest @setphase(drought)
@debug "Animal: $animal" @debug "Animal: $animal"
if @trait(sex) == Persephone.female && @countanimals() < 3 && if @trait(sex) == Persephone.female && @countanimals() < 3 &&
@trait(age) >= @trait(ageofmaturity) && @here(landcover) == Persephone.water @trait(age) >= @trait(ageofmaturity) && @landcover() == Persephone.water
@reproduce() @reproduce()
end end
end end
...@@ -107,19 +107,19 @@ end ...@@ -107,19 +107,19 @@ end
@test_logs((:debug, "Mermaid 1 is swimming happily in its pond."), @test_logs((:debug, "Mermaid 1 is swimming happily in its pond."),
(:debug, "Mermaid 2 is swimming happily in its pond."), (:debug, "Mermaid 2 is swimming happily in its pond."),
min_level=Logging.Debug, match_mode=:any, min_level=Logging.Debug, match_mode=:any,
stepsimulation!(model)) stepsimulation!(Ps.withtestlogger(model)))
@test model[1].age == 1 @test model[1].age == 1
@test model[2].traits["phase"] == "drought" @test model[2].traits["phase"] == "drought"
createevent!(model, [pond], Ps.sowing) createevent!(model, [pond], Ps.sowing)
@test_logs((:debug, "Mermaid 1 is experiencing drought with 1 neighbour(s)."), @test_logs((:debug, "Mermaid 1 is experiencing drought with 1 neighbour(s)."),
(:debug, "Mermaid 2 is experiencing drought with 1 neighbour(s)."), (:debug, "Mermaid 2 is experiencing drought with 1 neighbour(s)."),
min_level=Logging.Debug, match_mode=:any, min_level=Logging.Debug, match_mode=:any,
stepsimulation!(model)) stepsimulation!(Ps.withtestlogger(model)))
@test_logs((:debug, "Mermaid 1 is swimming happily in its pond."), @test_logs((:debug, "Mermaid 1 is swimming happily in its pond."),
(:debug, "Mermaid 1 has reproduced."), (:debug, "Mermaid 1 has reproduced."),
(:debug, "Mermaid 2 is swimming happily in its pond."), (:debug, "Mermaid 2 is swimming happily in its pond."),
min_level=Logging.Debug, match_mode=:any, min_level=Logging.Debug, match_mode=:any,
stepsimulation!(model)) stepsimulation!(Ps.withtestlogger(model)))
@test Ps.countanimals(pond, model) == 3 @test Ps.countanimals(pond, model) == 3
createevent!(model, [pond], Ps.pesticide) createevent!(model, [pond], Ps.pesticide)
@test_logs((:debug, "Mermaid 1 is swimming happily in its pond."), @test_logs((:debug, "Mermaid 1 is swimming happily in its pond."),
...@@ -129,7 +129,7 @@ end ...@@ -129,7 +129,7 @@ end
(:debug, "Mermaid 3 is swimming happily in its pond."), (:debug, "Mermaid 3 is swimming happily in its pond."),
(:debug, "Mermaid 3 has died from poisoning."), (:debug, "Mermaid 3 has died from poisoning."),
min_level=Logging.Debug, match_mode=:any, min_level=Logging.Debug, match_mode=:any,
stepsimulation!(model)) stepsimulation!(Ps.withtestlogger(model)))
@test Ps.countanimals(pond, model) == 0 @test Ps.countanimals(pond, model) == 0
# test @rand (this is done more easily outside of @species) # test @rand (this is done more easily outside of @species)
......
...@@ -9,6 +9,7 @@ Pkg.activate("..") ...@@ -9,6 +9,7 @@ Pkg.activate("..")
using Agents using Agents
using Dates using Dates
using Logging using Logging
using LoggingExtras
using Persephone using Persephone
using Random using Random
using StableRNGs using StableRNGs
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
@test model.date == Date(2022,2,1) @test model.date == Date(2022,2,1)
@test typeof(model.landscape) == Matrix{Pixel} @test typeof(model.landscape) == Matrix{Pixel}
@test typeof(model.dataoutputs) == Vector{DataOutput} @test typeof(model.dataoutputs) == Vector{DataOutput}
@test typeof(model.logger) == TeeLogger{Tuple{ConsoleLogger, ConsoleLogger}}
@test length(model.dataoutputs) == 2 @test length(model.dataoutputs) == 2
@test model.events == Vector{FarmEvent}() @test model.events == Vector{FarmEvent}()
@test nagents(model) == 2092+10+28 @test nagents(model) == 2092+10+28
...@@ -26,6 +27,7 @@ end ...@@ -26,6 +27,7 @@ end
scan = Ps.paramscan(settings, scanparams) scan = Ps.paramscan(settings, scanparams)
outdirs = (s["core.outdir"] for s in scan) outdirs = (s["core.outdir"] for s in scan)
@test length(outdirs) == 12 @test length(outdirs) == 12
#FIXME On worker 2: KeyError: key Persephone [039acd1d-2a07-4b33-b082-83a1ff0fd136] not found
@test length(initialise(config)) == 12 #XXX This takes a long time @test length(initialise(config)) == 12 #XXX This takes a long time
for dir in testdirs for dir in testdirs
@test dir in outdirs @test dir in outdirs
...@@ -51,7 +53,7 @@ end ...@@ -51,7 +53,7 @@ end
@test_logs((:info, "Simulating day 2022-02-01."), @test_logs((:info, "Simulating day 2022-02-01."),
(:info, "Simulated 59 days."), (:info, "Simulated 59 days."),
min_level=Logging.Debug, match_mode=:any, min_level=Logging.Debug, match_mode=:any,
simulate!(model)) simulate!(Ps.withtestlogger(model)))
@test model.date == Date(2022,4,1) @test model.date == Date(2022,4,1)
@test rand() == rand1 @test rand() == rand1
end end
......
...@@ -10,6 +10,7 @@ farmfieldsmap = "fields_jena.tif" # location of the field geometry map ...@@ -10,6 +10,7 @@ farmfieldsmap = "fields_jena.tif" # location of the field geometry map
outdir = "results_testsuite" # location and name of the output folder outdir = "results_testsuite" # location and name of the output folder
overwrite = true # overwrite the output directory? (true/false/"ask") overwrite = true # overwrite the output directory? (true/false/"ask")
loglevel = "warn" # verbosity level: "debug", "info", "warn" loglevel = "warn" # verbosity level: "debug", "info", "warn"
processors = 6 # number of processors to use on parallel runs
seed = 1 # seed value for the RNG (0 -> random value) seed = 1 # seed value for the RNG (0 -> random value)
# dates to start and end the simulation # dates to start and end the simulation
startdate = 2022-02-01 startdate = 2022-02-01
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment