Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions test/plugins/autobutcher.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
config.mode = 'fortress'
config.target = 'autobutcher'

local autobutcher = require('plugins.autobutcher')

local function parse(args)
-- emulate the autobutcher_options struct passed by the C++ command handler
local opts = {races={insert=function(self, pos, v) table.insert(self, v) end}}
autobutcher.parse_commandline(opts, args)
return opts
end

function test.help()
expect.true_(parse{'help'}.help)
expect.true_(parse{'-h'}.help)
expect.true_(parse{'--help'}.help)
end

function test.simple_commands()
for _,cmd in ipairs{'now', 'autowatch', 'noautowatch', 'list',
'list_export'} do
expect.eq(cmd, parse{cmd}.command)
end
end

function test.watch_races()
local opts = parse{'watch', 'CAT', 'BIRD_CROW'}
expect.eq('watch', opts.command)
expect.eq(2, #opts.races)
expect.eq('CAT', opts.races[1].value)
expect.eq('BIRD_CROW', opts.races[2].value)
end

function test.watch_all_and_new()
expect.true_(parse{'watch', 'all'}.races_all)
expect.true_(parse{'unwatch', 'new'}.races_new)
expect.true_(parse{'forget', 'all'}.races_all)
end

function test.watch_requires_races()
expect.error_match('missing list of races', function()
parse{'watch'} end)
end

function test.target()
local opts = parse{'target', '1', '2', '3', '4', 'CAT'}
expect.eq('target', opts.command)
expect.eq(1, opts.fk)
expect.eq(2, opts.mk)
expect.eq(3, opts.fa)
expect.eq(4, opts.ma)
expect.eq(1, #opts.races)
expect.eq('CAT', opts.races[1].value)
end

function test.target_zero_allowed()
local opts = parse{'target', '0', '0', '0', '0', 'all'}
expect.eq(0, opts.fk)
expect.true_(opts.races_all)
end

function test.target_rejects_bad_numbers()
expect.error_match('non%-negative integer', function()
parse{'target', '-1', '0', '0', '0', 'all'} end)
expect.error_match('non%-negative integer', function()
parse{'target', '1.5', '0', '0', '0', 'all'} end)
expect.error_match('non%-negative integer', function()
parse{'target', 'x', '0', '0', '0', 'all'} end)
end

function test.target_requires_all_counts()
expect.error(function() parse{'target', '1', '2', '3'} end)
end

function test.target_requires_races()
expect.error_match('missing list of races', function()
parse{'target', '1', '2', '3', '4'} end)
end

function test.unrecognized_command()
expect.error_match('unrecognized command', function()
parse{'bogus'} end)
end
125 changes: 125 additions & 0 deletions test/plugins/logistics.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
config.mode = 'fortress'
config.target = 'logistics'

local logistics = require('plugins.logistics')

local saved_autoretrain = logistics.logistics_getFeature('autoretrain')
local saved_configs = {}

config.wrapper = function(test_fn)
return dfhack.with_finalize(function()
logistics.logistics_setFeature(saved_autoretrain, 'autoretrain')
for sp_number, configs in pairs(saved_configs) do
for _,c in ipairs(configs) do
logistics.logistics_setStockpileConfig(
c.stockpile_number, c.melt == 1, c.trade == 1,
c.dump == 1, c.train == 1, c.forbid,
c.melt_masterworks == 1)
end
end
end, test_fn)
end

local function snapshot_config(sp_number)
if saved_configs[sp_number] then return end
saved_configs[sp_number] =
logistics.logistics_getStockpileConfigs(sp_number) or {}
end

local function get_first_stockpile()
local stockpiles = df.global.world.buildings.other.STOCKPILE
if #stockpiles == 0 then return nil end
return stockpiles[0].stockpile_number
end

local function get_stats_for(sp_number)
for _,sp in ipairs(logistics.getStockpileData().sp_stats) do
if sp.sp_number == sp_number then return sp end
end
end

function test.help()
expect.false_(logistics.parse_commandline{'help'})
expect.false_(logistics.parse_commandline{'-h'})
end

function test.status()
expect.true_(logistics.parse_commandline{})
expect.true_(logistics.parse_commandline{'status'})
end

function test.unrecognized_command()
expect.false_(logistics.parse_commandline{'bogus'})
end

function test.autoretrain_toggle()
expect.true_(logistics.parse_commandline{'enable', 'autoretrain'})
expect.true_(logistics.logistics_getFeature('autoretrain'))
expect.true_(logistics.parse_commandline{'disable', 'autoretrain'})
expect.false_(logistics.logistics_getFeature('autoretrain'))
end

function test.unknown_feature()
expect.error_match('unknown feature', function()
logistics.parse_commandline{'enable', 'bogus_feature'} end)
end

function test.missing_feature()
expect.error(function()
logistics.parse_commandline{'enable'} end)
end

function test.getStockpileData()
local data = logistics.getStockpileData()
expect.eq(#df.global.world.buildings.other.STOCKPILE,
#data.sp_stats)
-- totals are the sum of the per-stockpile stats
for _,desig in ipairs{'melt', 'trade', 'dump', 'train', 'forbid'} do
local designated, designatable = 0, 0
for _,sp in ipairs(data.sp_stats) do
designated = designated + sp[desig].designated
designatable = designatable + sp[desig].designatable
end
expect.eq(designated, data.sp_totals[desig].designated)
expect.eq(designatable, data.sp_totals[desig].designatable)
end
end

function test.add_and_clear_config()
local sp_number = get_first_stockpile()
if not sp_number then return end
snapshot_config(sp_number)
expect.true_(logistics.parse_commandline{
'add', 'melt', '-s', tostring(sp_number)})
local sp = get_stats_for(sp_number)
expect.true_(sp.melt.enabled)
expect.false_(sp.trade.enabled)
expect.true_(logistics.parse_commandline{
'add', 'trade', 'dump', '-s', tostring(sp_number)})
sp = get_stats_for(sp_number)
expect.true_(sp.melt.enabled)
expect.true_(sp.trade.enabled)
expect.true_(sp.dump.enabled)
expect.true_(logistics.parse_commandline{
'clear', '-s', tostring(sp_number)})
sp = get_stats_for(sp_number)
expect.false_(sp.melt.enabled)
expect.false_(sp.trade.enabled)
expect.false_(sp.dump.enabled)
end

function test.add_invalid_stockpile()
expect.printerr_match('invalid stockpile', function()
logistics.parse_commandline{'add', 'melt', '-s', '999999'} end)
end

function test.cycle()
-- a cycle can designate items if any stockpile configs are enabled;
-- only run it when the fort has none so no state is mutated
for _,desig in ipairs{'melt', 'trade', 'dump', 'train', 'forbid', 'claim'} do
if logistics.getStockpileData().sp_totals[desig].enabled_count > 0 then
return
end
end
expect.true_(logistics.parse_commandline{'now'})
end
60 changes: 60 additions & 0 deletions test/plugins/misery.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
config.mode = 'fortress'
config.target = 'misery'

local misery = require('plugins.misery')

local saved_factor = misery.misery_getFactor()

config.wrapper = function(test_fn)
return dfhack.with_finalize(function()
if saved_factor >= 2 then
misery.misery_setFactor(saved_factor)
end
end, test_fn)
end

function test.status()
expect.true_(misery.parse_commandline('status'))
expect.true_(misery.parse_commandline())
end

function test.help()
expect.false_(misery.parse_commandline('help'))
expect.false_(misery.parse_commandline('-h'))
expect.false_(misery.parse_commandline('--help'))
end

function test.set_factor()
expect.true_(misery.parse_commandline('5'))
expect.eq(5, misery.misery_getFactor())
expect.true_(misery.parse_commandline('2'))
expect.eq(2, misery.misery_getFactor())
end

function test.set_factor_below_minimum()
misery.misery_setFactor(5)
-- the C++ layer rejects the value with a console error message rather
-- than failing the command
misery.misery_setFactor(1)
expect.eq(5, misery.misery_getFactor())
expect.true_(misery.parse_commandline('1'))
expect.eq(5, misery.misery_getFactor())
end

function test.clear()
expect.true_(misery.parse_commandline('clear'))
end

function test.unrecognized_command()
expect.false_(misery.parse_commandline('bogus'))
end

function test.status_output()
misery.misery_setFactor(5)
local lines = {}
mock.patch({{misery, 'print', function(line)
table.insert(lines, line) end}}, function()
misery.status()
end)
expect.str_find('misery factor is: 5', table.concat(lines, '\n'))
end
111 changes: 111 additions & 0 deletions test/plugins/seedwatch.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
config.mode = 'fortress'
config.target = 'seedwatch'

local seedwatch = require('plugins.seedwatch')

local saved_targets = {}
do
local watch_map = seedwatch.seedwatch_getData()
for k, v in pairs(watch_map) do
saved_targets[k] = v
end
end

config.wrapper = function(test_fn)
return dfhack.with_finalize(function()
-- restore original targets and zero out any watch entries that the
-- test created for previously unwatched plants (there is no API to
-- remove a watch entry entirely)
local watch_map = seedwatch.seedwatch_getData()
for k in pairs(watch_map) do
if saved_targets[k] == nil then saved_targets[k] = 0 end
end
for k, v in pairs(saved_targets) do
local plant = df.global.world.raws.plants.all[k]
if plant then
seedwatch.seedwatch_setTarget(plant.id, v)
end
end
end, test_fn)
end

-- finds a seed-bearing non-tree plant, matching the set of plant ids that
-- seedwatch manages (see plugin_load_world_data in seedwatch.cpp)
local function get_seed_plant()
local plants = df.global.world.raws.plants.all
for i = 0, #plants - 1 do
local plant = plants[i]
if plant.material_defs.type[df.plant_material_def.seed] ~= -1 and
not plant.flags.TREE then
return i, plant.id
end
end
end

local function all_targets()
local watch_map = seedwatch.seedwatch_getData()
return watch_map
end

function test.status()
expect.true_(seedwatch.parse_commandline('status'))
expect.true_(seedwatch.parse_commandline())
end

function test.help()
expect.false_(seedwatch.parse_commandline('help'))
expect.false_(seedwatch.parse_commandline('-h'))
end

function test.set_all_targets()
expect.true_(seedwatch.parse_commandline('all', '50'))
local targets = all_targets()
local count = 0
for _ in pairs(targets) do count = count + 1 end
expect.gt(count, 0)
for _, v in pairs(targets) do
expect.eq(50, v)
end
end

function test.clear()
expect.true_(seedwatch.parse_commandline('clear'))
for _, v in pairs(all_targets()) do
expect.eq(0, v)
end
end

function test.set_single_plant()
local idx, id = get_seed_plant()
if not idx then return end
expect.true_(seedwatch.parse_commandline(id, '17'))
expect.eq(17, all_targets()[idx])
end

function test.target_floored()
local idx, id = get_seed_plant()
if not idx then return end
expect.true_(seedwatch.parse_commandline(id, '9.9'))
expect.eq(9, all_targets()[idx])
end

function test.unknown_plant()
local idx = get_seed_plant()
-- the C++ layer prints an error message but the command does not fail
expect.true_(seedwatch.parse_commandline(
'THIS_PLANT_DOES_NOT_EXIST', '5'))
if idx then
expect.ne(5, all_targets()[idx])
end
end

function test.negative_target()
local _, id = get_seed_plant()
if not id then return end
expect.error_match('non%-negative integer', function()
seedwatch.parse_commandline(id, '-5') end)
end

function test.missing_target()
expect.false_(seedwatch.parse_commandline('all'))
end
Loading
Loading