Lumiera  0.pre.03
»edit your freedom«
event-log.hpp
Go to the documentation of this file.
1 /*
2  EVENT-LOG.hpp - test facility to verify the occurrence of expected events
3 
4  Copyright (C)
5  2015, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
70 #ifndef LIB_TEST_EVENT_LOG_H
71 #define LIB_TEST_EVENT_LOG_H
72 
73 
74 #include "lib/error.hpp"
75 #include "lib/iter-cursor.hpp"
77 #include "lib/format-util.hpp"
78 #include "lib/format-cout.hpp"
79 #include "lib/diff/record.hpp"
80 #include "lib/idi/genfunc.hpp"
81 #include "lib/symbol.hpp"
82 #include "lib/util.hpp"
83 
84 #include <memory>
85 #include <vector>
86 #include <string>
87 #include <regex>
88 
89 
90 
91 namespace lib {
92 namespace test{
93 
94  using lib::Symbol;
95  using std::string;
96  using util::collectStr;
97 
98  namespace {
100  using Log = std::vector<Entry>;
101 
102  auto
103  buildSearchFilter(Log const& srcSeq)
104  {
106  return iter::chainSearch (Cursor{srcSeq.begin(), srcSeq.end()});
107  }
108  }
109 
110 
121  {
122  using Filter = decltype( buildSearchFilter (std::declval<Log const&>()) );
123 
125  using RExSeq = std::vector<std::regex>;
126 
127 
129  Filter solution_;
130 
132  string lastMatch_;
133 
136 
138  string violation_;
139 
140 
141 
143  EventMatch(Log const& srcSeq);
144 
145  friend class EventLog;
146 
147 
148  public:
153  operator bool() const
154  {
155  if (not util::isnil (violation_))
156  {
157  cerr << "__Log_condition_violated__\n"+violation_ <<"\n";
158  return false;
159  }
160  return true;
161  }
162 
163 
164  /* query builders to continue search at current position */
165 
166  EventMatch& locate (string match);
167  EventMatch& locateMatch (string regExp);
168  EventMatch& locateEvent (string match);
169  EventMatch& locateEvent (string classifier, string match);
170  EventMatch& locateCall (string match);
171 
172 
173  /* query builders to find a match stepping forwards */
174 
175  EventMatch& before (string match);
176  EventMatch& beforeMatch (string regExp);
177  EventMatch& beforeEvent (string match);
178  EventMatch& beforeEvent (string classifier, string match);
179  EventMatch& beforeCall (string match);
180 
181 
182  /* query builders to find a match stepping backwards */
183 
184  EventMatch& after (string match);
185  EventMatch& afterMatch (string regExp);
186  EventMatch& afterEvent (string match);
187  EventMatch& afterEvent (string classifier, string match);
188  EventMatch& afterCall (string match);
189 
196  template<typename...ARGS>
197  EventMatch&
198  arg (ARGS const& ...args)
199  {
200  refineSerach_matchArguments (collectStr<ArgSeq> (args...));
201  return *this;
202  }
203 
204 
215  template<typename...ARGS>
216  EventMatch&
217  argMatch (ARGS const& ...regExps)
218  {
219  refineSerach_matchArgsRegExp (collectStr<RExSeq> (regExps...),
220  util::join(collectStr<ArgSeq>(regExps...)));
221  return *this;
222  }
223 
225  template<typename ARG>
226  EventMatch&
227  argPos (size_t idx, ARG const& arg)
228  {
229  refineSerach_matchArgument (idx, util::toString(arg));
230  return *this;
231  }
232 
233 
234  /* query builders to augment and refine the currently defined search condition*/
235 
236  EventMatch& type (string typeID);
237  EventMatch& key (string key);
238  EventMatch& attrib (string key, string valueMatch);
239  EventMatch& id (string classifier);
240  EventMatch& on (string targetID);
241  EventMatch& on (const char* targetID);
242 
243  template<typename X>
244  EventMatch& on (const X *const targetObj)
245  {
246  string targetID = idi::instanceTypeID (targetObj);
247  return this->on(targetID);
248  }
249 
250  private:
251  bool foundSolution();
252  void evaluateQuery (string matchSpec, Literal rel = "after");
253 
254  void refineSerach_matchArgument (size_t idx, string match);
255  void refineSerach_matchArguments (ArgSeq&& argSeq);
256  void refineSerach_matchArgsRegExp (RExSeq&& regExpSeq, string rendered_regExps);
257  };
258 
259 
260 
261 
262 
263 
264 
265 
266  /****************************************************************/
275  class EventLog
276  {
277 
279 
280 
281  void
282  log (std::initializer_list<string> const& ili)
283  {
284  log_->emplace_back(ili);
285  }
286 
287  template<typename ATTR, typename ARGS>
288  void
289  log (Symbol typeID, ATTR&& attribs, ARGS&& args)
290  {
291  log_->emplace_back(typeID, std::forward<ATTR>(attribs)
292  , std::forward<ARGS>(args));
293  }
294 
295 
296  public:
297  explicit
298  EventLog (string logID);
299 
300  explicit
301  EventLog (const char* logID)
302  : EventLog(string(logID))
303  { }
304 
305  template<class X>
306  explicit
307  EventLog (const X *const obj)
309  { }
310 
311 
312  // standard copy operations acceptable
313 
314 
316  string
317  getID() const
318  {
319  return log_->front().get("this");
320  }
321 
322 
328  EventLog& joinInto (EventLog& otherLog);
329 
330 
332  EventLog& clear();
333  EventLog& clear (string alteredLogID);
334  EventLog& clear (const char* alteredLogID);
335 
336  template<class X>
337  EventLog&
338  clear (const X *const obj)
339  {
340  return clear (idi::instanceTypeID (obj));
341  }
342 
343 
344 
345  /* ==== Logging API ==== */
346 
348 
350  EventLog& event (string text);
351 
356  EventLog& event (string classifier, string text);
357 
358  template<typename...ELMS>
359  EventLog&
360  event (string classifier, ELMS const& ...initialiser)
361  {
362  log ("event", ArgSeq{"ID="+classifier}, collectStr<ArgSeq> (initialiser...));
363  return *this;
364  }
365 
370  EventLog& call (string target, string function);
371 
373  EventLog& call (string target, string function, ArgSeq&& args);
374 
375  EventLog& call (const char* target, const char* function, ArgSeq&& args);
376 
378  template<typename...ARGS>
379  EventLog&
380  call (string target, string function, ARGS const& ...args)
381  {
382  return call (target, function, collectStr<ArgSeq>(args...));
383  }
384 
386  template<class X, typename...ARGS>
387  EventLog&
388  call (const X *const targetObj, string function, ARGS const& ...args)
389  {
390  return call (idi::instanceTypeID (targetObj), function, args...);
391  }
392 
393  template<typename...ARGS>
394  EventLog&
395  call (const char* target, string function, ARGS const& ...args)
396  {
397  return call (string(target), function, args...);
398  }
399 
400  template<typename...ELMS>
401  EventLog&
402  note (ELMS const& ...initialiser)
403  {
404  log_->emplace_back (collectStr<ArgSeq> (initialiser...));
405  return *this;
406  }
407 
408 
410  EventLog& warn (string text);
411 
413  EventLog& error (string text);
414 
416  EventLog& fatal (string text);
417 
420  EventLog& create (string text);
421 
422 
425  EventLog& destroy (string text);
426 
427 
429  template<typename X, typename...ARGS>
430  EventLog&
431  addAttrib (string const& key, X&& initialiser, ARGS&& ...args)
432  {
433  REQUIRE (not isnil (*log_));
434  mutateInPlace (log_->back())
435  .attrib(key,initialiser, std::forward<ARGS>(args)...);
436  return *this;
437  }
438 
439 
440 
441 
442  /* ==== Iteration ==== */
443 
444  bool
445  empty() const
446  {
447  return 1 >= log_->size(); // do not count the log header
448  }
449 
450 
452 
453  typedef Iter const_iterator;
454  typedef const Entry value_type;
455 
456  const_iterator begin() const { return Iter(log_->begin(), log_->end()); }
457  const_iterator end() const { return Iter(); }
458 
459  friend const_iterator begin (EventLog const& log) { return log.begin(); }
460  friend const_iterator end (EventLog const& log) { return log.end(); }
461 
462 
463 
464 
465  /* ==== Query/Verification API ==== */
466 
475  EventMatch verify (string match) const;
476 
483  EventMatch verifyMatch (string regExp) const;
484 
492  EventMatch verifyEvent (string match) const;
493 
497  EventMatch verifyEvent (string classifier, string match) const;
498 
499  template<typename X>
500  EventMatch
501  verifyEvent (string classifier, X const& something) const
502  {
503  return verifyEvent (classifier, util::toString (something));
504  }
505 
509  EventMatch verifyCall (string match) const;
510 
512  EventMatch
513  ensureNot (string match) const;
514 
515 
516 
517 
519  friend bool
520  operator== (EventLog const& l1, EventLog const& l2)
521  {
522  return l1.log_ == l2.log_
523  or (l1.log_ and l2.log_
524  and *l1.log_ == *l2.log_);
525  }
526  friend bool
527  operator!= (EventLog const& l1, EventLog const& l2)
528  {
529  return not (l1 == l2);
530  }
531  };
532 
533 
534 
535 }} // namespace lib::test
536 #endif /*LIB_TEST_EVENT_LOG_H*/
void refineSerach_matchArgument(size_t idx, string match)
Definition: event-log.cpp:502
EventMatch & type(string typeID)
refine filter to additionally require a matching log entry type
Definition: event-log.cpp:539
EventMatch & locateCall(string match)
basic search for some specific function invocation
Definition: event-log.cpp:365
string violation_
record when the underlying query has failed
Definition: event-log.hpp:138
Automatically use custom string conversion in C++ stream output.
Filter solution_
match predicate evaluator
Definition: event-log.hpp:129
Definition: run.hpp:40
EventMatch & beforeCall(string match)
find a match for some function invocation after the current point of reference
Definition: event-log.cpp:438
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
CON collectStr(ELMS const &...elms)
convert a sequence of elements to string
Helper to log and verify the occurrence of events.
Definition: event-log.hpp:275
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
EventMatch & beforeMatch(string regExp)
find a match with the given regular expression
Definition: event-log.cpp:395
EventMatch & after(string match)
find a match (substring match) of the given text in an EventLog entry before the current position...
Definition: event-log.cpp:454
An iterator with the ability to switch direction.
EventMatch & arg(ARGS const &...args)
refine filter to additionally require specific arguments
Definition: event-log.hpp:198
EventMatch & locateMatch(string regExp)
basic search like locate() but with the given regular expression
Definition: event-log.cpp:332
EventMatch & afterCall(string match)
find a function invocation backwards, before the current point of reference
Definition: event-log.cpp:489
Implementation namespace for support and library code.
Generic functions to build identification schemes.
void evaluateQuery(string matchSpec, Literal rel="after")
this is actually called after each refinement of the filter and matching conditions.
Definition: event-log.cpp:288
EventMatch & attrib(string key, string valueMatch)
refine filter to additionally match on a specific attribute
Definition: event-log.cpp:561
EventMatch(Log const &srcSeq)
Definition: event-log.cpp:258
Token or Atom with distinct identity.
Definition: symbol.hpp:117
Special collection to represent object-like data.
Evaluation mechanism to apply a sequence of conditions onto a linear search.
bool foundSolution()
core of the evaluation machinery: apply a filter predicate and then pull through the log to find a ac...
Definition: event-log.cpp:272
EventMatch & beforeEvent(string match)
find a match for an "event" after the current point of reference
Definition: event-log.cpp:417
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
EventMatch & argPos(size_t idx, ARG const &arg)
refine filter to additionally require match on a specific positional argument
Definition: event-log.hpp:227
bool look_for_match_
support for positive and negative queries.
Definition: event-log.hpp:135
EventMatch & argMatch(ARGS const &...regExps)
refine filter to additionally cover all arguments with a series of regular expressions.
Definition: event-log.hpp:217
EventMatch & id(string classifier)
refine filter to additionally match on the ID attribute
Definition: event-log.cpp:572
void refineSerach_matchArguments(ArgSeq &&argSeq)
Definition: event-log.cpp:512
Lumiera error handling (C++ interface).
string instanceTypeID(const TY *const obj)
designation of an distinct object instance
Definition: genfunc.hpp:116
EventMatch & locate(string match)
basic search function: continue linear lookup over the elements of the EventLog to find a match (subs...
Definition: event-log.cpp:321
EventLog & addAttrib(string const &key, X &&initialiser, ARGS &&...args)
Qualify the latest entry: set further attribute(s)
Definition: event-log.hpp:431
EventLog & call(const X *const targetObj, string function, ARGS const &...args)
Log a function call on given object ("`this`")...
Definition: event-log.hpp:388
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
void refineSerach_matchArgsRegExp(RExSeq &&regExpSeq, string rendered_regExps)
Definition: event-log.cpp:527
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
EventLog & call(string target, string function, ARGS const &...args)
Log a function call with arbitrary arguments.
Definition: event-log.hpp:380
EventMatch & on(string targetID)
refine filter to additionally match the &#39;this&#39; attribute
Definition: event-log.cpp:583
object-like record of data.
Definition: record.hpp:141
EventMatch & key(string key)
refine filter to additionally require the presence an attribute
Definition: event-log.cpp:550
string lastMatch_
record last match for diagnostics
Definition: event-log.hpp:132
EventMatch & before(string match)
find a match (substring match) of the given text in an EventLog entry after the current position ...
Definition: event-log.cpp:384
string getID() const
Definition: event-log.hpp:317
EventMatch & locateEvent(string match)
basic search for a matching "event"
Definition: event-log.cpp:345