LUMIERA.clone/tests/library/test/test-event-log-test.cpp
Ichthyostega 33f7fe116a implement refinement filter on log entry's arguments.
Whew! functional programming is such a powerful concept.
You get additional refinement and lazy backtracking
basically for free....
2015-12-12 03:13:32 +01:00

395 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
TestEventLog(Test) - helper for event registration and verification
Copyright (C) Lumiera.org
2015, Hermann Vosseler <Ichthyostega@web.de>
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 "lib/test/run.hpp"
//#include "lib/test/test-helper.hpp"
#include "lib/format-util.hpp"
#include "lib/test/event-log.hpp"
#include "lib/error.hpp"
#include "lib/util.hpp"
#include <iostream>
#include <string>
using util::join;
using util::isnil;
using lumiera::error::LUMIERA_ERROR_ASSERTION;
using std::string;
using std::cout;
using std::endl;
namespace lib {
namespace test{
namespace test{
template<class T>
class Wrmrmpft
{
T tt_;
};
struct Murpf { };
/***********************************************************//**
* @test verify a logging facility, which can be used to ensure
* some events happened while running test code.
*
* @see event-log.hpp
*/
class TestEventLog_test : public Test
{
void
run (Arg)
{
verify_simpleUsage();
verify_backwardMatch();
verify_negatedMatch();
verify_logJoining();
verify_callLogging();
verify_eventLogging();
}
void
verify_simpleUsage ()
{
EventLog log(this);
CHECK (isnil (log));
log.event("α");
log.event("β");
CHECK (!isnil(log));
CHECK (log.verify("α"));
CHECK (log.verify("β"));
CHECK (not log.verify("γ"));
CHECK (log.verify("α").before("β"));
CHECK (not log.verify("β").before("α"));
CHECK (join(log) == "Rec(EventLogHeader| ID = "+idi::instanceTypeID(this)+" ), "
+ "Rec(event|{α}), "
+ "Rec(event|{β})");
}
void
verify_backwardMatch ()
{
EventLog log("baked beans");
log.event("spam");
log.event("ham");
CHECK (log.verify("ham").after("spam").after("beans"));
CHECK (log.verify("ham").after("beans").before("spam").before("ham"));
CHECK (not log.verify("spam").after("beans").after("ham"));
}
void
verify_negatedMatch ()
{
EventLog log("eggs");
log.event("spam");
log.event("ham");
log.event("spam");
CHECK (log.ensureNot("baked beans"));
CHECK (log.ensureNot("ham").before("eggs"));
CHECK (log.ensureNot("spam").after("spam").before("eggs"));
CHECK (not log.ensureNot("spam").before("spam").after("eggs").before("ham"));
}
void
verify_logJoining ()
{
EventLog log1("spam");
EventLog log2("ham");
log1.event("baked beans");
log2.event("eggs");
CHECK (log1.verify("spam").before("baked beans"));
CHECK (log2.verify("ham").before("eggs"));
CHECK (log1.ensureNot("ham"));
CHECK (log1.ensureNot("eggs"));
CHECK (log2.ensureNot("spam"));
CHECK (log2.ensureNot("baked beans"));
EventLog copy(log2);
copy.event("bacon");
CHECK (copy.verify("ham").before("eggs").before("bacon"));
CHECK (log2.verify("ham").before("eggs").before("bacon"));
CHECK (log1.ensureNot("bacon"));
CHECK (log1 != log2);
CHECK (copy == log2);
log2.joinInto(log1);
CHECK (log1 == log2);
CHECK (copy != log2);
CHECK (log1.verify("logJoin|{ham}").after("baked beans"));
CHECK (log1.verify("logJoin|{ham}").after("EventLogHeader| ID = ham").before("eggs").before("bacon").before("logJoin"));
log2.event("sausage");
CHECK (log1.verify("sausage").after("logJoin").after("spam"));
CHECK (copy.ensureNot("logJoin"));
CHECK (copy.ensureNot("sausage"));
CHECK (copy.verify("joined|{spam}").after("EventLogHeader"));
copy.event("spam tomato");
CHECK (log1.ensureNot("spam tomato"));
CHECK (log2.ensureNot("spam tomato"));
CHECK (copy.verify("joined|{spam}").before("spam tomato"));
CHECK (join(log1) == string(
"Rec(EventLogHeader| ID = spam ), "
"Rec(event|{baked beans}), "
"Rec(EventLogHeader| ID = ham ), "
"Rec(event|{eggs}), "
"Rec(event|{bacon}), "
"Rec(logJoin|{ham}), "
"Rec(event|{sausage})"));
CHECK (join(copy) == string(
"Rec(EventLogHeader| ID = ham ), "
"Rec(joined|{spam}), "
"Rec(event|{spam tomato})"));
}
void
verify_callLogging ()
{
EventLog log("funCall");
log.call (this, "fun1");
log.call ("some", "fun2");
log.call ("more", "fun3", "facts", 3.2,1);
CHECK(log.verify("fun1").before("fun2").before("fun3"));
CHECK (join(log) == string(
"Rec(EventLogHeader| ID = funCall ), "
"Rec(call| fun = fun1, this = "+idi::instanceTypeID(this)+" ), "
"Rec(call| fun = fun2, this = some ), "
"Rec(call| fun = fun3, this = more |{facts, 3.2, 1})"));
CHECK (log.verifyCall("fun1"));
CHECK (log.verifyCall("fun2"));
CHECK (log.verifyCall("fun3"));
CHECK (log.verifyCall("fun"));
CHECK (log.verifyCall("fun").after("fun").after("fun"));
CHECK (log.ensureNot("fun").after("fun").after("fun2"));
CHECK (log.verifyCall("fun3").arg("facts", 3.2, 1));
CHECK (log.verifyCall("fun3").arg(string("facts"), 3.2f, int64_t(1)));
CHECK (log.verifyCall("fun3").arg("facts", "3.2", "1"));
CHECK (log.ensureNot("fun").arg(" facts ","3.2", "1"));
CHECK (log.ensureNot("fun").arg("facts", "3.20","1"));
CHECK (log.ensureNot("fun").arg("facts", "3.2", "1L"));
CHECK (log.verifyCall("fun1").arg());
CHECK (log.verifyCall("fun2").arg());
CHECK (log.verify("fun").arg().before("fun").arg("facts", 3.2, 1));
CHECK (log.verify("fun").on(this));
CHECK (log.verify("fun").on("some"));
CHECK (log.verify("fun").on("more"));
CHECK (log.verify("fun").on("more").on("more"));
CHECK (log.ensureNot("fun").on("some").on("more"));
CHECK (log.verify("fun").on("some").arg());
CHECK (log.ensureNot("fun").arg().on("more"));
CHECK (log.ensureNot("fun").on("some").arg("facts", "3.2", "1"));
CHECK (log.verifyCall("fun").arg("facts", "3.2", "1").on("more"));
}
void
verify_eventLogging ()
{
EventLog log("event trace");
log.event("no","fun");
log.call("some","fun");
CHECK (log.verify("fun").before("fun"));
CHECK (log.verify("no").before("some"));
CHECK (log.verifyEvent("fun").beforeCall("fun").on("some"));
CHECK (!log.verifyEvent("fun").after("some"));
CHECK (log.verifyEvent("no","fun"));
CHECK (log.verifyEvent("fun").id("no"));
CHECK (log.verify("no").arg("fun"));
CHECK (join(log) == string(
"Rec(EventLogHeader| ID = event trace ), "
"Rec(event| ID = no |{fun}), "
"Rec(call| fun = fun, this = some |{})"));
}
void
verify_genericLogging ()
{
EventLog log("theHog");
log.note ("type=some","ID=weird","stuff");
log.warn ("danger");
log.error ("horrible");
log.fatal ("destiny");
log.create ("something");
log.destroy ("everything");
CHECK (log.verify("theHog")
.before("stuff")
.before("danger")
.before("horrible")
.before("destiny")
.before("something")
.before("everything"));
CHECK (log.verify("ID").type("EventLogHeader")
.before("weird").type("some")
.before("danger").type("warn")
.before("horrible").type("error")
.before("destiny").type("fatal")
.before("something").type("create")
.before("everything").type("destroy"));
CHECK (log.verify("some").attrib("ID","weird").arg("stuff"));
// NOTE: there is some built-in leeway in event-matching...
CHECK (log.verifyEvent("horrible").beforeEvent("something").beforeEvent("everything"));
CHECK (!log.verifyEvent("stuff")); // not every entry type is an event by default
CHECK (!log.verifyEvent("danger")); // warning is not an event by default
CHECK (log.verifyEvent("some","stuff")); // but the classifier-param matches on the type
CHECK (log.verifyEvent("weird","stuff"));
CHECK (log.verifyEvent("warn","danger"));
CHECK (log.verifyEvent("fatal","destiny"));
CHECK (log.verifyEvent("destroy","everything"));
CHECK (join(log) == string(
"Rec(EventLogHeader| ID = theHog ), "
"Rec(some| ID = weird |{struff}), "
"Rec(warn|{danger}), "
"Rec(error|{horrible}), "
"Rec(fatal|{destiny}), "
"Rec(create|{something}), "
"Rec(destroy|{everything})"));
}
/** @test prints TODO */
void
checkTODO ()
{
#if false ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #975
log.verifyEvent("ctor");
log.verify("ctor").arg("dummy");
CHECK ("dummy" == log.getID().getSym());
CHECK ("ID<gui::model::test::MockElm>-dummy" = string(log.getID()));
VERIFY_ERROR (ASSERTION, log.verifyCall("reset"));
log.reset();
log.verify("reset");
log.verifyCall("reset");
log.verifyEvent("reset");
log.verify("reset").after("ctor");
log.verify("ctor").before("reset");
VERIFY_ERROR (ASSERTION, log.verify("reset").before("ctor"));
VERIFY_ERROR (ASSERTION, log.verify("ctor").after("reset"));
log.verify("reset").before("reset");
log.verify("reset").beforeEvent("reset");
log.verifyCall("reset").before("reset");
log.verifyCall("reset").beforeEvent("reset");
VERIFY_ERROR (ASSERTION, log.verifyCall("reset").afterCall("reset"));
VERIFY_ERROR (ASSERTION, log.verifyCall("reset").afterEvent("reset"));
VERIFY_ERROR (ASSERTION, log.verifyEvent("reset").afterEvent("reset"));
CHECK (!log.isTouched());
CHECK (!log.isExpanded());
log.noteMsg("dolorem ipsum quia dolor sit amet consectetur adipisci velit.");
log.verifyNote("Msg");
log.verifyCall("noteMsg");
log.verifyCall("noteMsg").arg("lorem ipsum");
log.verifyCall("noteMsg").argMatch("dolor.+dolor\\s+");
log.verifyMatch("Rec\\(note.+kind = Msg.+msg = dolorem ipsum");
EventLog log = log.getLog();
log.verify("ctor")
.before("reset")
.before("lorem ipsum");
MockElm foo("foo"), bar;
foo.verify("ctor").arg("foo");
bar.verify("ctor").arg();
bar.ensureNot("foo");
log.ensureNot("foo");
log.ensureNot("foo");
VERIFY_ERROR (ASSERTION, foo.ensureNot("foo"));
log.joinInto(bar).joinInto(foo);
log.verifyEvent("logJoin").arg(bar.getID())
.beforeEvent("logJoin").arg("foo");
log.verifyEvent("logJoin").arg(bar.getID())
.beforeEvent("logJoin").arg("foo");
log.verify("ctor").arg("foo");
log.verify("ctor").arg("foo");
log.verify("ctor").arg("dummy")
.before("ctor").arg(bar.getID())
.before("ctor").arg("foo");
log.kill();
foo.noteMsg("dummy killed");
log.verifyEvent("dtor").on("dummy")
.beforeCall("noteMsg").on("foo");
// and when actually no exception is raised, this is an ASSERTION failure
VERIFY_ERROR (ASSERTION, VERIFY_ERROR (EXCEPTION, dontThrow() ));
#endif ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #975
}
};
LAUNCHER (TestEventLog_test, "unit common");
}}} // namespace lib::test::test