Basic unit tests for the failure management framework
Includes a simple automated testing framework for Nasal (Aircraft/Generic/Systems/Tests/test.nas) and a collection of unit tests for the failure manager, mostly for the different triggers.
This commit is contained in:
parent
5df7a784e5
commit
081602633a
7 changed files with 739 additions and 0 deletions
7
Aircraft/Generic/Systems/Tests/FailureMgr/test_all.nas
Normal file
7
Aircraft/Generic/Systems/Tests/FailureMgr/test_all.nas
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Aggregation of all tests for the Failure Manager
|
||||
|
||||
io.include("Aircraft/Generic/Systems/Tests/FailureMgr/test_cycle_counter.nas");
|
||||
io.include("Aircraft/Generic/Systems/Tests/FailureMgr/test_altitude_trigger.nas");
|
||||
io.include("Aircraft/Generic/Systems/Tests/FailureMgr/test_mcbf_trigger.nas");
|
||||
io.include("Aircraft/Generic/Systems/Tests/FailureMgr/test_mtbf_trigger.nas");
|
||||
io.include("Aircraft/Generic/Systems/Tests/FailureMgr/test_failure_mode.nas");
|
|
@ -0,0 +1,155 @@
|
|||
# AltitudeTrigger unit tests
|
||||
#
|
||||
# Copyright (C) 2014 Anton Gomez Alvedro
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
io.include("Aircraft/Generic/Systems/Tests/test.nas");
|
||||
io.include("Aircraft/Generic/Systems/failures.nas");
|
||||
|
||||
var TestAltitudeTrigger = {
|
||||
|
||||
parents: [TestSuite],
|
||||
|
||||
setup: func {
|
||||
props.globals.initNode("/test");
|
||||
},
|
||||
|
||||
cleanup: func {
|
||||
me.trigger = nil;
|
||||
props.globals.getNode("/test").remove();
|
||||
},
|
||||
|
||||
test_binding: func {
|
||||
|
||||
setprop("/test/foreign-property", 25);
|
||||
|
||||
me.trigger = AltitudeTrigger.new(100, 200);
|
||||
me.trigger.bind("/test/");
|
||||
|
||||
assert_prop_exists("/test/reset");
|
||||
assert_prop_exists("/test/min-altitude-ft");
|
||||
assert_prop_exists("/test/min-altitude-ft");
|
||||
|
||||
me.trigger.unbind();
|
||||
|
||||
fail_if_prop_exists("/test/reset");
|
||||
fail_if_prop_exists("/test/min-altitude-ft");
|
||||
fail_if_prop_exists("/test/min-altitude-ft");
|
||||
|
||||
assert_prop_exists("/test/foreign-property");
|
||||
},
|
||||
|
||||
test_props_are_read_on_reset: func {
|
||||
|
||||
me.trigger = AltitudeTrigger.new(100, 200);
|
||||
me.trigger.bind("/test/");
|
||||
|
||||
assert(me.trigger.params["min-altitude-ft"] == 100);
|
||||
assert(me.trigger.params["max-altitude-ft"] == 200);
|
||||
|
||||
setprop("/test/min-altitude-ft", 1000);
|
||||
setprop("/test/max-altitude-ft", 2000);
|
||||
|
||||
assert(me.trigger.params["min-altitude-ft"] == 100);
|
||||
assert(me.trigger.params["max-altitude-ft"] == 200);
|
||||
|
||||
me.trigger.reset();
|
||||
|
||||
assert(me.trigger.params["min-altitude-ft"] == 1000);
|
||||
assert(me.trigger.params["max-altitude-ft"] == 2000);
|
||||
},
|
||||
|
||||
test_trigger_fires_within_min_and_max: func {
|
||||
|
||||
me.trigger = AltitudeTrigger.new(100, 200);
|
||||
|
||||
me.trigger._altitude_prop = "/test/fake-altitude-ft";
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 0);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 300);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 150);
|
||||
assert(me.trigger.update() == 1);
|
||||
assert(me.trigger.fired);
|
||||
},
|
||||
|
||||
test_trigger_accepts_nil_max: func {
|
||||
|
||||
me.trigger = AltitudeTrigger.new(500, nil);
|
||||
me.trigger._altitude_prop = "/test/fake-altitude-ft";
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", -250);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 0);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 250);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 750);
|
||||
assert(me.trigger.update() == 1);
|
||||
assert(me.trigger.fired);
|
||||
},
|
||||
|
||||
test_trigger_accepts_nil_min: func {
|
||||
|
||||
me.trigger = AltitudeTrigger.new(nil, 500);
|
||||
me.trigger._altitude_prop = "/test/fake-altitude-ft";
|
||||
me.trigger.bind("/test/trigger/");
|
||||
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 750);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 500);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-altitude-ft", 250);
|
||||
assert(me.trigger.update() == 1);
|
||||
assert(me.trigger.fired);
|
||||
|
||||
me.trigger.reset();
|
||||
|
||||
setprop("/test/fake-altitude-ft", -250);
|
||||
assert(me.trigger.update() == 1);
|
||||
assert(me.trigger.fired);
|
||||
},
|
||||
|
||||
test_trigger_dies_if_both_params_are_nil: func {
|
||||
call(AltitudeTrigger.new, [nil, nil], AltitudeTrigger, var err = []);
|
||||
assert(size(err) > 0);
|
||||
},
|
||||
|
||||
test_to_str: func {
|
||||
me.trigger = AltitudeTrigger.new(100, 200);
|
||||
call(me.trigger.to_str, [], me.trigger, var err = []);
|
||||
assert(size(err) == 0);
|
||||
}
|
||||
};
|
124
Aircraft/Generic/Systems/Tests/FailureMgr/test_cycle_counter.nas
Normal file
124
Aircraft/Generic/Systems/Tests/FailureMgr/test_cycle_counter.nas
Normal file
|
@ -0,0 +1,124 @@
|
|||
# CycleCounter unit tests
|
||||
#
|
||||
# Copyright (C) 2014 Anton Gomez Alvedro
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
io.include("Aircraft/Generic/Systems/Tests/test.nas");
|
||||
io.include("Aircraft/Generic/Systems/failures.nas");
|
||||
|
||||
var TestCycleCounter = {
|
||||
|
||||
parents: [TestSuite],
|
||||
|
||||
setup: func {
|
||||
props.globals.initNode("/test");
|
||||
},
|
||||
|
||||
cleanup: func {
|
||||
props.globals.getNode("/test").remove();
|
||||
me.counter = nil;
|
||||
},
|
||||
|
||||
_shake_that_prop: func (pattern=nil) {
|
||||
|
||||
if (pattern == nil)
|
||||
pattern = [0, -10, 10, -10, 10, -10, 10, 0];
|
||||
|
||||
setprop("/test/property", pattern[0]);
|
||||
me.counter.reset();
|
||||
|
||||
var i = 0;
|
||||
var value = pattern[0];
|
||||
var target = pattern[1];
|
||||
var delta = 0;
|
||||
|
||||
while(i < size(pattern) - 1) {
|
||||
|
||||
target = pattern[i+1];
|
||||
delta = pattern[i+1] > pattern[i] ? 1 : -1;
|
||||
|
||||
while(value != target) {
|
||||
value += delta;
|
||||
setprop("/test/property", value);
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
},
|
||||
|
||||
test_cycles_dont_grow_while_disabled: func {
|
||||
me.counter = CycleCounter.new("/test/property");
|
||||
me._shake_that_prop();
|
||||
assert(me.counter.cycles == 0);
|
||||
},
|
||||
|
||||
test_cycles_grow_while_enabled: func {
|
||||
me.counter = CycleCounter.new("/test/property");
|
||||
|
||||
me._shake_that_prop();
|
||||
assert(me.counter.cycles == 0);
|
||||
|
||||
me.counter.enable();
|
||||
|
||||
me._shake_that_prop();
|
||||
assert(me.counter.cycles == 3);
|
||||
},
|
||||
|
||||
test_reset: func {
|
||||
me.counter = CycleCounter.new("/test/property");
|
||||
me.counter.enable();
|
||||
|
||||
me._shake_that_prop();
|
||||
assert(me.counter.cycles > 0);
|
||||
|
||||
me.counter.reset();
|
||||
assert(me.counter.cycles == 0);
|
||||
},
|
||||
|
||||
test_callback_every_half_cycle: func {
|
||||
var count = 0;
|
||||
|
||||
me.counter = CycleCounter.new(
|
||||
property: "/test/property",
|
||||
on_update: func (cycles) { count += 1 });
|
||||
|
||||
me.counter.enable();
|
||||
me._shake_that_prop();
|
||||
|
||||
assert(count == 6);
|
||||
},
|
||||
|
||||
test_callback_reports_cycle_count: func {
|
||||
var count = 0;
|
||||
var cb = func (cycles) {
|
||||
count += 1;
|
||||
assert(cycles == count * 0.5);
|
||||
};
|
||||
|
||||
me.counter = CycleCounter.new(
|
||||
property: "/test/property", on_update: cb);
|
||||
|
||||
me.counter.enable();
|
||||
me._shake_that_prop();
|
||||
},
|
||||
|
||||
test_counter_works_for_binary_props: func {
|
||||
me.counter = CycleCounter.new("/test/property");
|
||||
me.counter.enable();
|
||||
me._shake_that_prop([0, 1, 0, 1, 0, 1]);
|
||||
assert(me.counter.cycles == 2);
|
||||
}
|
||||
};
|
113
Aircraft/Generic/Systems/Tests/FailureMgr/test_failure_mode.nas
Normal file
113
Aircraft/Generic/Systems/Tests/FailureMgr/test_failure_mode.nas
Normal file
|
@ -0,0 +1,113 @@
|
|||
# AltitudeTrigger unit tests
|
||||
#
|
||||
# Copyright (C) 2014 Anton Gomez Alvedro
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
io.include("Aircraft/Generic/Systems/Tests/test.nas");
|
||||
io.include("Aircraft/Generic/Systems/failures.nas");
|
||||
|
||||
var TestFailureMode = {
|
||||
|
||||
parents: [TestSuite],
|
||||
|
||||
setup: func {
|
||||
props.globals.initNode("/test");
|
||||
},
|
||||
|
||||
cleanup: func {
|
||||
me.mode = nil;
|
||||
props.globals.getNode("/test").remove();
|
||||
},
|
||||
|
||||
test_binding: func {
|
||||
var actuator = { parents: [FailureMgr.FailureActuator] };
|
||||
setprop("/test/foreign-property", 25);
|
||||
|
||||
me.mode = FailureMgr.FailureMode.new(
|
||||
id: "instruments/compass",
|
||||
description: "a description",
|
||||
actuator: actuator);
|
||||
|
||||
me.mode.bind("/test/");
|
||||
assert_prop_exists("/test/instruments/compass/failure-level");
|
||||
|
||||
me.mode.unbind();
|
||||
fail_if_prop_exists("/test/instruments/compass/failure-level");
|
||||
fail_if_prop_exists("/test/instruments/compass");
|
||||
assert_prop_exists("/test/foreign-property");
|
||||
},
|
||||
|
||||
test_set_failure_level_calls_actuator: func {
|
||||
var level = 0;
|
||||
var actuator = {
|
||||
parents: [FailureMgr.FailureActuator],
|
||||
set_failure_level: func (l) { level = l },
|
||||
};
|
||||
|
||||
me.mode = FailureMgr.FailureMode.new(
|
||||
id: "instruments/compass",
|
||||
description: "a description",
|
||||
actuator: actuator);
|
||||
me.mode.bind("/test/");
|
||||
|
||||
me.mode.set_failure_level(1);
|
||||
assert(level == 1);
|
||||
},
|
||||
|
||||
test_actuator_gets_called_from_prop: func {
|
||||
var level = 0;
|
||||
var actuator = {
|
||||
parents: [FailureMgr.FailureActuator],
|
||||
set_failure_level: func (l) { level = l },
|
||||
};
|
||||
|
||||
me.mode = FailureMgr.FailureMode.new(
|
||||
id: "instruments/compass",
|
||||
description: "a description",
|
||||
actuator: actuator);
|
||||
|
||||
me.mode.bind("/test/");
|
||||
setprop("/test/instruments/compass/failure-level", 1);
|
||||
assert(level == 1);
|
||||
},
|
||||
|
||||
test_setting_level_from_nasal_is_shown_in_prop: func {
|
||||
var level = 0;
|
||||
var actuator = {
|
||||
parents: [FailureMgr.FailureActuator],
|
||||
set_failure_level: func (l) { level = l },
|
||||
};
|
||||
|
||||
me.mode = FailureMgr.FailureMode.new(
|
||||
id: "instruments/compass",
|
||||
description: "a description",
|
||||
actuator: actuator);
|
||||
|
||||
me.mode.bind("/test/");
|
||||
|
||||
me.mode.set_failure_level(1);
|
||||
assert(level == 1);
|
||||
|
||||
var prop_value = getprop("/test/instruments/compass/failure-level");
|
||||
assert(prop_value == 1);
|
||||
|
||||
me.mode.set_failure_level(0.5);
|
||||
assert(level == 0.5);
|
||||
|
||||
prop_value = getprop("/test/instruments/compass/failure-level");
|
||||
assert(prop_value == 0.5);
|
||||
}
|
||||
};
|
116
Aircraft/Generic/Systems/Tests/FailureMgr/test_mcbf_trigger.nas
Normal file
116
Aircraft/Generic/Systems/Tests/FailureMgr/test_mcbf_trigger.nas
Normal file
|
@ -0,0 +1,116 @@
|
|||
# McbfTrigger unit tests
|
||||
#
|
||||
# Copyright (C) 2014 Anton Gomez Alvedro
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
io.include("Aircraft/Generic/Systems/Tests/test.nas");
|
||||
io.include("Aircraft/Generic/Systems/failures.nas");
|
||||
|
||||
var TestMcbfTrigger = {
|
||||
|
||||
parents: [TestSuite],
|
||||
|
||||
setup: func {
|
||||
props.globals.initNode("/test");
|
||||
},
|
||||
|
||||
cleanup: func {
|
||||
me.trigger = nil;
|
||||
props.globals.getNode("/test").remove();
|
||||
},
|
||||
|
||||
_do_one_cycle: func (prop) {
|
||||
setprop(prop, 10);
|
||||
setprop(prop, -10);
|
||||
setprop(prop, 0);
|
||||
},
|
||||
|
||||
test_binding: func {
|
||||
setprop("/test/property", 0);
|
||||
|
||||
me.trigger = McbfTrigger.new("/test/property", 3);
|
||||
me.trigger.bind("/test/");
|
||||
|
||||
assert_prop_exists("/test/reset");
|
||||
assert_prop_exists("/test/mcbf");
|
||||
|
||||
me.trigger.unbind();
|
||||
fail_if_prop_exists("/test/reset");
|
||||
fail_if_prop_exists("/test/mcbf");
|
||||
assert_prop_exists("/test/property");
|
||||
},
|
||||
|
||||
test_trigger_fires_after_activation_cycles: func {
|
||||
setprop("/test/property", 25);
|
||||
me.trigger = McbfTrigger.new("/test/property", 3);
|
||||
me.trigger.activation_cycles = 3;
|
||||
me.trigger.enable();
|
||||
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
for (var i = 1; i < 5; i += 1) {
|
||||
me._do_one_cycle("/test/property");
|
||||
assert(me.trigger.fired == (i > 3));
|
||||
}
|
||||
},
|
||||
|
||||
test_trigger_notifies_observer_once: func {
|
||||
var observer_called = 0;
|
||||
var on_fire = func observer_called += 1;
|
||||
|
||||
setprop("/test/property", 25);
|
||||
me.trigger = McbfTrigger.new("/test/property", 3);
|
||||
me.trigger.activation_cycles = 3;
|
||||
me.trigger.on_fire = on_fire;
|
||||
me.trigger.enable();
|
||||
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
for (var i = 1; i < 5; i += 1)
|
||||
me._do_one_cycle("/test/property");
|
||||
|
||||
assert(observer_called == 1);
|
||||
},
|
||||
|
||||
test_reset: func {
|
||||
setprop("/test/property", 25);
|
||||
me.trigger = McbfTrigger.new("/test/property", 3);
|
||||
me.trigger.activation_cycles = 3;
|
||||
me.trigger.bind("/test");
|
||||
me.trigger.enable();
|
||||
|
||||
for (var i = 1; i < 5; i += 1)
|
||||
me._do_one_cycle("/test/property");
|
||||
|
||||
assert(me.trigger.fired);
|
||||
|
||||
me.trigger.reset();
|
||||
me.trigger.activation_cycles = 3;
|
||||
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
for (var i = 1; i < 5; i += 1) {
|
||||
me._do_one_cycle("/test/property");
|
||||
assert(me.trigger.fired == (i > 3));
|
||||
}
|
||||
},
|
||||
|
||||
test_to_str: func {
|
||||
me.trigger = McbfTrigger.new("/test/property", 3);
|
||||
call(me.trigger.to_str, [], me.trigger, var err = []);
|
||||
assert(size(err) == 0);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,87 @@
|
|||
# MtbfTrigger unit tests
|
||||
#
|
||||
# Copyright (C) 2014 Anton Gomez Alvedro
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
io.include("Aircraft/Generic/Systems/Tests/test.nas");
|
||||
io.include("Aircraft/Generic/Systems/failures.nas");
|
||||
|
||||
var TestMtbfTrigger = {
|
||||
|
||||
parents: [TestSuite],
|
||||
|
||||
setup: func {
|
||||
props.globals.initNode("/test");
|
||||
},
|
||||
|
||||
cleanup: func {
|
||||
me.trigger = nil;
|
||||
props.globals.getNode("/test").remove();
|
||||
},
|
||||
|
||||
test_binding: func {
|
||||
|
||||
setprop("/test/foreign-property", 25);
|
||||
|
||||
me.trigger = MtbfTrigger.new(60);
|
||||
me.trigger.bind("/test/");
|
||||
|
||||
assert_prop_exists("/test/reset");
|
||||
assert_prop_exists("/test/mtbf");
|
||||
|
||||
me.trigger.unbind();
|
||||
|
||||
fail_if_prop_exists("/test/reset");
|
||||
fail_if_prop_exists("/test/mtbf");
|
||||
|
||||
assert_prop_exists("/test/foreign-property");
|
||||
},
|
||||
|
||||
test_props_are_read_on_reset: func {
|
||||
|
||||
me.trigger = MtbfTrigger.new(60);
|
||||
me.trigger.bind("/test/");
|
||||
assert(me.trigger.params["mtbf"] == 60);
|
||||
|
||||
setprop("/test/mtbf", 120);
|
||||
assert(me.trigger.params["mtbf"] == 60);
|
||||
|
||||
me.trigger.reset();
|
||||
assert(me.trigger.params["mtbf"] == 120);
|
||||
},
|
||||
|
||||
test_trigger_fires_after_fire_time: func {
|
||||
|
||||
me.trigger = MtbfTrigger.new(60);
|
||||
me.trigger._time_prop = "/test/fake-time-sec";
|
||||
me.trigger.fire_time = 60;
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-time-sec", 50);
|
||||
assert(me.trigger.update() == 0);
|
||||
assert(!me.trigger.fired);
|
||||
|
||||
setprop("/test/fake-time-sec", 70);
|
||||
assert(me.trigger.update() == 1);
|
||||
assert(me.trigger.fired);
|
||||
},
|
||||
|
||||
test_to_str: func {
|
||||
me.trigger = MtbfTrigger.new(60);
|
||||
call(me.trigger.to_str, [], me.trigger, var err = []);
|
||||
assert(size(err) == 0);
|
||||
}
|
||||
};
|
137
Aircraft/Generic/Systems/Tests/test.nas
Normal file
137
Aircraft/Generic/Systems/Tests/test.nas
Normal file
|
@ -0,0 +1,137 @@
|
|||
# Minimalistic framework for automated testing in Nasal
|
||||
#
|
||||
# Copyright (C) 2014 Anton Gomez Alvedro
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
# TestSuite
|
||||
#
|
||||
# Tests are organized in test suites. Each test suite contains an arbitrary
|
||||
# number of tests, and two special methods "setup" and "cleanup". Setup is
|
||||
# called before every test, and cleanup is called after every test.
|
||||
#
|
||||
# In order to define a test suite, you have to create an object parented to
|
||||
# TestSuite. The testing framework will identify any method in your object whose
|
||||
# name starts with "test_" as a test case to be run.
|
||||
#
|
||||
# Important: The order in which test cases and test suites are executed
|
||||
# is undefined!
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# var MyTestSuite = {
|
||||
#
|
||||
# parents: [TestSuite],
|
||||
#
|
||||
# setup: func {
|
||||
# Stuff to do before every test...
|
||||
# This is optional. You don't need to provide it if you don't use it.
|
||||
# },
|
||||
#
|
||||
# cleanup: func {
|
||||
# Stuff to do after every test...
|
||||
# Also optional.
|
||||
# },
|
||||
#
|
||||
# my_auxiliary_function: func {
|
||||
# Methods that do not start with "test_" will not be executed by the
|
||||
# test runner. You can define as many auxiliary functions in the test
|
||||
# suite as you wish.
|
||||
# },
|
||||
#
|
||||
# test_trivial_test: func {
|
||||
# This is a real test (starts with "test_"), and it will be run by the
|
||||
# framework when test_run() is called.#
|
||||
# }
|
||||
# };
|
||||
|
||||
var TestSuite = {
|
||||
setup: func 0,
|
||||
cleanup: func 0
|
||||
};
|
||||
|
||||
# run_tests()
|
||||
#
|
||||
# Executes all test suites found in the namespace where run_tests is defined.
|
||||
# An effective way to work with the framework is to just include the framework
|
||||
# from your test files:
|
||||
#
|
||||
# io.include(".../test.nas");
|
||||
#
|
||||
# and then execute a script like this in the Nasal Console:
|
||||
#
|
||||
# delete(globals, "test");
|
||||
# io.load_nasal(".../my_test_suite.nas", "test");
|
||||
# test.run_tests();
|
||||
#
|
||||
# What this script does is: it empties the "test" namespace and then loads your
|
||||
# script into that namespace. The test framework will be loaded in there as
|
||||
# well if it was io.include'd in my_test_suite.nas. Finally, all test suites
|
||||
# in the "test" namespace are executed.
|
||||
|
||||
var run_tests = func () {
|
||||
|
||||
var ns = closure(run_tests, 1);
|
||||
|
||||
var passed = 0;
|
||||
var failed = 0;
|
||||
var err = [];
|
||||
|
||||
foreach(var suite_name; keys(ns)) {
|
||||
var suite = ns[suite_name];
|
||||
|
||||
if (!isa(suite, TestSuite))
|
||||
continue;
|
||||
|
||||
print("Running test suite ", suite_name);
|
||||
|
||||
foreach (var test_name; keys(suite)) {
|
||||
|
||||
if (find("test_", test_name) != 0)
|
||||
continue;
|
||||
|
||||
# Run the test case
|
||||
setsize(err, 0);
|
||||
contains(suite, "setup") and call(suite.setup, [], suite, err);
|
||||
size(err) == 0 and call(suite[test_name], [], suite, err);
|
||||
size(err) == 0 and contains(suite, "cleanup") and call(suite.cleanup, [], suite, err);
|
||||
|
||||
if (size(err) == 0) {
|
||||
passed += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
failed += 1;
|
||||
print("Test ", test_name, " FAILED\n");
|
||||
debug.printerror(err);
|
||||
}
|
||||
}
|
||||
|
||||
print(sprintf("\n%d tests run. %d passed, %d failed",
|
||||
passed + failed, passed, failed));
|
||||
}
|
||||
|
||||
|
||||
var assert_prop_exists = func (prop) {
|
||||
assert(props.globals.getNode(prop) != nil,
|
||||
sprintf("Property %s does not exist", prop));
|
||||
}
|
||||
|
||||
|
||||
var fail_if_prop_exists = func (prop) {
|
||||
assert(props.globals.getNode(prop) == nil,
|
||||
sprintf("Property %s exists", prop));
|
||||
}
|
Loading…
Add table
Reference in a new issue