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....
This commit is contained in:
Fischlurch 2015-12-12 03:13:32 +01:00
parent 5bc6919bdb
commit 33f7fe116a
3 changed files with 61 additions and 10 deletions

View file

@ -73,6 +73,7 @@ namespace util {
// precision for rendering of double values
const auto DIAGNOSTICS_DOUBLE_PRECISION = 8;
const auto DIAGNOSTICS_FLOAT_PRECISION = 5;
template<typename X>
@ -131,6 +132,19 @@ namespace util {
}
catch(...) { return ""; }
};
template<>
struct _InvokeFailsafe<float>
{
static string
toString (float const& val)
try {
std::ostringstream buffer;
buffer.precision(DIAGNOSTICS_FLOAT_PRECISION);
buffer << val;
return buffer.str();
}
catch(...) { return ""; }
};
}//(End) guards/helpers

View file

@ -104,6 +104,9 @@ namespace test{
using Iter = lib::IterCursor<Log::const_iterator>;
using Filter = ExtensibleFilterIter<Iter>;
using ArgSeq = lib::diff::RecordSetup<string>::Storage;
/** match predicate evaluator */
Filter solution_;
@ -225,6 +228,32 @@ namespace test{
};
}
/** this filter functor is for refinement of an existing filter
* @param argSeq perform a substring match consecutively
* for each of the log entry's arguments
* @note the match also fails, when the given log entry
* has more or less arguments, than the number of
* given match expressions in `argSeq`
* @see ExtensibleFilterIter::andFilter()
*/
auto
matchArguments(ArgSeq&& argSeq)
{
return [=](Entry const& entry)
{
auto scope = entry.scope();
for (auto const& match : argSeq)
if (isnil (scope) or not contains(*scope, match))
return false;
else
++scope;
return isnil(scope); // must be exhausted by now
}; // otherwise the sizes do not match...
}
public:
/** final evaluation of the match query,
* usually triggered from the unit test `CHECK()`.
@ -351,17 +380,23 @@ namespace test{
return *this;
}
/** refine filter to additionally require specific arguments
* @remarks the refined filter works on each record qualified by the
* query expression established thus far; it additionally
* looks into the arguments (children list) of the log entry.
* @warning match is processed by comparision of string representation.
*/
template<typename...ARGS>
EventMatch&
arg ()
arg (ARGS const& ...args)
{
UNIMPLEMENTED("process match on no-arg call argument list");
}
template<typename... MORE>
EventMatch&
arg (string match, MORE...args)
{
UNIMPLEMENTED("process match on call argument list");
ArgSeq argSeq;
argSeq.reserve(sizeof...(ARGS));
stringify (argSeq, args...);
solution_.andFilter (matchArguments(std::move(argSeq)));
evaluateQuery ("match-arguments("+util::join(argSeq)+")");
return *this;
}
template<typename... MORE>

View file

@ -217,7 +217,9 @@ namespace test{
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.20", "1L"));
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());