* Lumiera source code always was copyrighted by individual contributors * there is no entity "Lumiera.org" which holds any copyrights * Lumiera source code is provided under the GPL Version 2+ == Explanations == Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above. For this to become legally effective, the ''File COPYING in the root directory is sufficient.'' The licensing header in each file is not strictly necessary, yet considered good practice; attaching a licence notice increases the likeliness that this information is retained in case someone extracts individual code files. However, it is not by the presence of some text, that legally binding licensing terms become effective; rather the fact matters that a given piece of code was provably copyrighted and published under a license. Even reformatting the code, renaming some variables or deleting parts of the code will not alter this legal situation, but rather creates a derivative work, which is likewise covered by the GPL! The most relevant information in the file header is the notice regarding the time of the first individual copyright claim. By virtue of this initial copyright, the first author is entitled to choose the terms of licensing. All further modifications are permitted and covered by the License. The specific wording or format of the copyright header is not legally relevant, as long as the intention to publish under the GPL remains clear. The extended wording was based on a recommendation by the FSF. It can be shortened, because the full terms of the license are provided alongside the distribution, in the file COPYING.
284 lines
9.9 KiB
C++
284 lines
9.9 KiB
C++
/*
|
||
SchedulerInvocation(Test) - verify queue processing in the scheduler
|
||
|
||
Copyright (C)
|
||
2023, Hermann Vosseler <Ichthyostega@web.de>
|
||
|
||
**Lumiera** 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. See the file COPYING for further details.
|
||
|
||
* *****************************************************************/
|
||
|
||
/** @file scheduler-invocation-test.cpp
|
||
** unit test \ref SchedulerInvocation_test
|
||
*/
|
||
|
||
|
||
#include "lib/test/run.hpp"
|
||
#include "vault/gear/scheduler-invocation.hpp"
|
||
#include "lib/util.hpp"
|
||
|
||
using test::Test;
|
||
using util::isSameObject;
|
||
|
||
|
||
namespace vault{
|
||
namespace gear {
|
||
namespace test {
|
||
|
||
|
||
|
||
|
||
/********************************************************************//**
|
||
* @test Scheduler Layer-1: queue processing and invocation by priority.
|
||
* @see SchedulerCommutator_test
|
||
* @see SchedulerUsage_test
|
||
*/
|
||
class SchedulerInvocation_test : public Test
|
||
{
|
||
|
||
virtual void
|
||
run (Arg)
|
||
{
|
||
simpleUsage();
|
||
verify_Queuing();
|
||
verify_WaterLevel();
|
||
verify_Significance();
|
||
verify_stability();
|
||
verify_isDue();
|
||
}
|
||
|
||
|
||
/** @test demonstrate a simple usage scenario of data passing
|
||
*/
|
||
void
|
||
simpleUsage()
|
||
{
|
||
SchedulerInvocation sched;
|
||
Activity activity;
|
||
Time when{1,2,3};
|
||
Time dead{2,3,4};
|
||
|
||
CHECK (not sched.peekHead());
|
||
|
||
sched.instruct ({activity, when, dead});
|
||
sched.feedPrioritisation();
|
||
CHECK (sched.peekHead());
|
||
|
||
Activity* head = sched.pullHead();
|
||
CHECK (not sched.peekHead());
|
||
CHECK (isSameObject (*head, activity));
|
||
}
|
||
|
||
|
||
|
||
/** @test verify records are passed properly through the queues
|
||
* - add multiple elements to the instruct queue
|
||
* - after `feedPrioritisation` these appear as output
|
||
*/
|
||
void
|
||
verify_Queuing()
|
||
{
|
||
SchedulerInvocation sched;
|
||
Activity one{1u,1u};
|
||
Activity two{2u,2u};
|
||
Activity wee{3u,3u};
|
||
Time t{5,5};
|
||
|
||
sched.instruct ({one, t});
|
||
sched.instruct ({two, t});
|
||
sched.instruct ({wee, t});
|
||
CHECK (not sched.peekHead());
|
||
|
||
sched.feedPrioritisation();
|
||
CHECK (isSameObject (*sched.pullHead(), one));
|
||
CHECK (isSameObject (*sched.pullHead(), two));
|
||
CHECK (isSameObject (*sched.pullHead(), wee));
|
||
CHECK (not sched.peekHead());
|
||
CHECK (sched.empty());
|
||
}
|
||
|
||
|
||
|
||
/** @test verify the given time point is utilised for prioritisation
|
||
* - order at output is determined by the time spec
|
||
* - even later added elements can push back
|
||
* previously visible elements at head
|
||
*/
|
||
void
|
||
verify_WaterLevel()
|
||
{
|
||
SchedulerInvocation sched;
|
||
Activity a1{1u,1u};
|
||
Activity a2{2u,2u};
|
||
Activity a3{3u,3u};
|
||
Activity a4{4u,4u};
|
||
|
||
sched.instruct ({a2, Time{2,0}});
|
||
sched.instruct ({a4, Time{4,0}});
|
||
sched.feedPrioritisation();
|
||
CHECK (isSameObject (*sched.peekHead(), a2));
|
||
|
||
sched.instruct ({a3, Time{3,0}});
|
||
sched.instruct ({a1, Time{1,0}});
|
||
CHECK (isSameObject (*sched.peekHead(), a2));
|
||
|
||
sched.feedPrioritisation();
|
||
CHECK (isSameObject (*sched.pullHead(), a1));
|
||
CHECK (isSameObject (*sched.pullHead(), a2));
|
||
CHECK (isSameObject (*sched.pullHead(), a3));
|
||
CHECK (isSameObject (*sched.pullHead(), a4));
|
||
}
|
||
|
||
|
||
|
||
/** @test sort order is not necessarily stable
|
||
* if using identical time specs on entrance
|
||
*/
|
||
void
|
||
verify_stability()
|
||
{
|
||
SchedulerInvocation sched;
|
||
Activity a1{1u,1u};
|
||
Activity a2{2u,2u};
|
||
Activity a3{3u,3u};
|
||
Activity a4{4u,4u};
|
||
|
||
sched.feedPrioritisation ({a1, Time{0,5}});
|
||
sched.feedPrioritisation ({a2, Time{0,5}});
|
||
sched.feedPrioritisation ({a3, Time{0,5}});
|
||
sched.feedPrioritisation ({a4, Time{0,4}});
|
||
CHECK (isSameObject (*sched.pullHead(), a4));
|
||
CHECK (isSameObject (*sched.pullHead(), a3));
|
||
CHECK (isSameObject (*sched.pullHead(), a1));
|
||
CHECK (isSameObject (*sched.pullHead(), a2));
|
||
CHECK (not sched.pullHead());
|
||
}
|
||
|
||
|
||
|
||
/** @test the entry appearing at head _is due_
|
||
* when its time is at or before current time.
|
||
*/
|
||
void
|
||
verify_isDue()
|
||
{
|
||
SchedulerInvocation sched;
|
||
Activity a1{1u,1u};
|
||
|
||
sched.feedPrioritisation ({a1, Time{0,5}});
|
||
CHECK (isSameObject (*sched.peekHead(), a1));
|
||
CHECK ( sched.isDue (Time{0,10}));
|
||
CHECK ( sched.isDue (Time{0,5}));
|
||
CHECK (not sched.isDue (Time{0,1}));
|
||
|
||
sched.pullHead();
|
||
CHECK (not sched.peekHead());
|
||
CHECK (not sched.isDue (Time{0,1}));
|
||
CHECK (not sched.isDue (Time{0,10}));
|
||
}
|
||
|
||
|
||
|
||
/** @test verify extended classification data and information functions at scheduler head
|
||
* - add entries providing extra information regarding significance
|
||
* - verify that missing the deadline is detected
|
||
* - entries past deadline are marked _outdated_ (will be dropped by Layer-2)
|
||
* - entries can be tagged with an ManifestationID, allowing to enable
|
||
* or disable visibility for a »family« of schedule entries
|
||
* - use the flag for _compulsory_ entries, allowing to detect
|
||
* a fatal _jammed_ situation where the head entry is
|
||
* out of time, while marked mandatory to process.
|
||
*/
|
||
void
|
||
verify_Significance()
|
||
{
|
||
SchedulerInvocation sched;
|
||
Activity act;
|
||
|
||
sched.feedPrioritisation ({act, Time{2,0}, Time{3,0}});
|
||
CHECK (Time(2,0) == sched.headTime());
|
||
CHECK ( sched.isDue (Time{2,0}));
|
||
CHECK (not sched.isMissed (Time{2,0}));
|
||
CHECK (not sched.isMissed (Time{3,0}));
|
||
CHECK ( sched.isMissed (Time{4,0}));
|
||
|
||
CHECK (not sched.isOutdated (Time{2,0}));
|
||
CHECK (not sched.isOutdated (Time{3,0}));
|
||
CHECK ( sched.isOutdated (Time{4,0}));
|
||
|
||
sched.feedPrioritisation ({act, Time{1,0}, Time{3,0}, ManifestationID{5}});
|
||
CHECK (Time(1,0) == sched.headTime());
|
||
CHECK ( sched.isOutdated (Time{1,0}));
|
||
CHECK (not sched.isMissed (Time{1,0}));
|
||
|
||
sched.activate (ManifestationID{5});
|
||
CHECK (Time(1,0) == sched.headTime());
|
||
CHECK ( sched.isDue (Time{1,0}));
|
||
CHECK (not sched.isOutdated (Time{1,0}));
|
||
CHECK (not sched.isOutdated (Time{3,0}));
|
||
CHECK ( sched.isOutdated (Time{4,0}));
|
||
CHECK ( sched.isMissed (Time{4,0}));
|
||
CHECK ( sched.isDue (Time{4,0}));
|
||
|
||
sched.activate (ManifestationID{23});
|
||
CHECK (not sched.isOutdated (Time{1,0}));
|
||
|
||
sched.drop (ManifestationID{5});
|
||
CHECK (Time(1,0) == sched.headTime());
|
||
CHECK ( sched.isOutdated (Time{1,0}));
|
||
CHECK ( sched.isOutdated (Time{4,0}));
|
||
CHECK ( sched.isMissed (Time{4,0}));
|
||
CHECK (not sched.isMissed (Time{1,0}));
|
||
CHECK ( sched.isDue (Time{1,0}));
|
||
|
||
sched.feedPrioritisation ({act, Time{0,0}, Time{2,0}, ManifestationID{23}, true});
|
||
CHECK (Time(0,0) == sched.headTime()); // ^^^^ marked as compulsory
|
||
CHECK (not sched.isMissed (Time{1,0}));
|
||
CHECK (not sched.isOutdated (Time{1,0}));
|
||
CHECK (not sched.isOutOfTime(Time{2,0})); // still OK /at/ deadline
|
||
CHECK ( sched.isOutOfTime(Time{3,0})); // ↯ past deadline yet marked as compulsory
|
||
CHECK ( sched.isOutdated (Time{3,0}));
|
||
CHECK ( sched.isMissed (Time{3,0}));
|
||
|
||
sched.drop (ManifestationID{5});
|
||
CHECK ( sched.isOutOfTime(Time{3,0})); // Manifestation-5 is altogether irrelevant for this case
|
||
|
||
sched.drop (ManifestationID{23});
|
||
CHECK (Time(0,0) == sched.headTime());
|
||
CHECK ( sched.isOutdated (Time{1,0}));
|
||
CHECK (not sched.isOutOfTime(Time{2,0}));
|
||
CHECK (not sched.isOutOfTime(Time{3,0})); // the disabled manifestation-23 masks the fatal out-of-time state
|
||
CHECK ( sched.isOutdated (Time{3,0}));
|
||
CHECK ( sched.isMissed (Time{3,0}));
|
||
|
||
sched.pullHead();
|
||
CHECK (Time(1,0) == sched.headTime());
|
||
CHECK ( sched.isOutdated (Time{1,0}));
|
||
CHECK ( sched.isDue (Time{1,0}));
|
||
|
||
sched.pullHead();
|
||
CHECK (Time(2,0) == sched.headTime());
|
||
CHECK (not sched.isOutdated (Time{2,0}));
|
||
CHECK ( sched.isOutdated (Time{4,0}));
|
||
CHECK ( sched.isMissed (Time{4,0}));
|
||
CHECK ( sched.isDue (Time{4,0}));
|
||
|
||
sched.pullHead();
|
||
CHECK (Time::NEVER == sched.headTime());
|
||
CHECK (not sched.isMissed (Time{4,0}));
|
||
CHECK (not sched.isOutdated (Time{4,0}));
|
||
CHECK (not sched.isDue (Time{4,0}));
|
||
CHECK (sched.empty());
|
||
}
|
||
};
|
||
|
||
|
||
/** Register this test class... */
|
||
LAUNCHER (SchedulerInvocation_test, "unit engine");
|
||
|
||
|
||
|
||
}}} // namespace vault::gear::test
|