/* DummyJob - diagnostic job for unit tests Copyright (C) Lumiera.org 2013, Hermann Vosseler 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., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************/ #include "backend/engine/dummy-job.hpp" #include "lib/test/test-helper.hpp" #include "lib/time/timevalue.hpp" #include "backend/real-clock.hpp" #include "lib/null-value.hpp" #include "lib/hash-value.h" #include "lib/util.hpp" #include #include #include namespace backend{ namespace engine { namespace { // DummyJob implementation details... using lib::HashVal; using lib::NullValue; using lib::time::TimeVar; using std::unordered_map; using util::access_or_default; const int MAX_PARAM_A(1000); ///< random test values 0...1000 const int MAX_PARAM_B(10); ///< random test values -10...+10 /** * test dummy jobs are backed by this closure. * DummyJob invocations are recorded in a hashtable * @note as of 9/2013, we use a very simplistic implementation, * causing a consecutive invocation of the same job instance * to overwrite the previous log entry. */ class DummyClosure : public JobClosure { void invokeJobOperation (JobParameter parameter) { invocationLog_[hash_value (parameter)] = Invocation(parameter); } void signalFailure (JobParameter,JobFailureReason) { NOTREACHED ("Job failure is not subject of this test"); } JobKind getJobKind() const { return META_JOB; } bool verify (Time nominalJobTime, InvocationInstanceID invoKey) const { return Time::NEVER < nominalJobTime && 0 <= invoKey.metaInfo.a && invoKey.metaInfo.a < MAX_PARAM_A && -MAX_PARAM_B <= invoKey.metaInfo.b && invoKey.metaInfo.b < MAX_PARAM_B; } size_t hashOfInstance(InvocationInstanceID invoKey) const { return boost::hash_value (invoKey.metaInfo.a); } /* === Logging/Reporting of job invocation === */ struct Invocation { TimeVar nominal; TimeVar real; int a,b; Invocation(JobParameter param) : nominal(TimeValue(param.nominalTime)) , real(RealClock::now()) , a(param.invoKey.metaInfo.a) , b(param.invoKey.metaInfo.b) { } Invocation() : nominal(Time::NEVER) , real(Time::ANYTIME) , a(MAX_PARAM_A), b(0) { } }; /** recording DummyJob invocations */ unordered_map invocationLog_; public: Invocation const& queryInvocation (JobParameter param) const { return access_or_default (invocationLog_, hash_value(param) ,NullValue::get()); } }; /** actual instance of the test dummy job operation */ DummyClosure dummyClosure; }// (End)Implementation details Job DummyJob::build() { InvocationInstanceID invoKey; invoKey.metaInfo.a = rand() % MAX_PARAM_A; invoKey.metaInfo.b = rand() % (2*MAX_PARAM_B) - MAX_PARAM_B; Time nominalTime = lib::test::randTime(); return Job(dummyClosure, invoKey, nominalTime); } Job DummyJob::build (Time nominalTime, int additionalKey) { InvocationInstanceID invoKey; invoKey.metaInfo.a = additionalKey; invoKey.metaInfo.b = rand() % (2*MAX_PARAM_B) - MAX_PARAM_B; return Job(dummyClosure, invoKey, nominalTime); } bool DummyJob::was_invoked (Job const& job) { REQUIRE (job.usesClosure (dummyClosure)); return Time::NEVER != dummyClosure.queryInvocation(job.parameter).nominal; } Time DummyJob::invocationTime (Job const& job) { REQUIRE (job.usesClosure (dummyClosure)); return dummyClosure.queryInvocation(job.parameter).real; } }} // namespace backend::engine