DiffMessage: complete test of diagnostic output

This commit is contained in:
Fischlurch 2017-08-12 14:33:26 +02:00
parent efc27fd07b
commit 06ff5c4e71
3 changed files with 55 additions and 7 deletions

View file

@ -157,11 +157,14 @@ namespace diff{
* this operation needs to impose a _side effect:_ it materialises
* the complete diff sequence at once into a heap allocated buffer.
*/
DiffMessage& withDiagnostics();
DiffMessage& updateDiagnostics();
};
namespace {
namespace { // Implementation: take snapshot to enable diagnostics
/** "materialised view" of the diff sequence */
struct DiffSnapshot
: std::vector<DiffStep>
{
@ -176,6 +179,15 @@ namespace diff{
using _RangeIT = RangeIter<_VecIter>;
using _Wrapped = WrappedLumieraIter<_RangeIT>;
/**
* Decorator to be layered transparently on top of DiffMessage.
* Actually, what we do is to discharge the diff generator into
* the DiffSnapshot buffer and then replace the link to the original
* generator to this decorator, which, when iterated, yields the
* contents of the DiffSnapshot one by one. But since all DiffSteps
* are now stored into that DiffSnapshot _buffer we control,_ we're
* able to produce a diagnostic listing of the complete sequence.
*/
class MaterialisedDiffMessageBuffer
: private DiffSnapshot
, public _Wrapped
@ -194,8 +206,18 @@ namespace diff{
};
}
/** @par operational semantics
* Since the underlying generator of the DiffStep sequence is an iterator,
* the "materialised view" can only capture what's left at the point when
* updateDiagnostics() is invoked. The captured rest sequence seamlessly
* becomes the new generator and the old generator object is released,
* since the assignment of the new backend typically removes the last
* reference in the smart-ptr managing the generation backend. This
* process can be repeated and then the [diagnostics](operator string())
* will show the remainder of the sequence _left at that point._
*/
inline DiffMessage&
DiffMessage::withDiagnostics()
DiffMessage::updateDiagnostics()
{
return *this = DiffMessage{new MaterialisedDiffMessageBuffer(*this)};
}

View file

@ -205,6 +205,13 @@ namespace util {
return buffer.str().substr(0, len - delim.length());
}
template<class X>
inline string
join (std::initializer_list<X> const&& ili, string const& delim =", ")
{
return join (ili, delim);
}
} // namespace util
#endif /*LIB_FORMAT_UTIL_H*/

View file

@ -33,7 +33,6 @@
#include "lib/iter-adapter-stl.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/format-util.hpp"
#include "lib/format-cout.hpp" ///////////////TODO remove when done
#include "lib/util.hpp"
#include <string>
@ -42,6 +41,7 @@
using lumiera::error::LUMIERA_ERROR_ITER_EXHAUST;
using lib::iter_stl::IterSnapshot;
using lib::iter_stl::snapshot;
using util::contains;
using util::isnil;
using util::join;
using std::string;
@ -294,16 +294,35 @@ namespace test{
,set(ATTRIB1)
,del(CHILD_T)};
cout << diffMsg <<endl;
// initially only the default diagnostics of IterSource is shown (rendering the element type)
CHECK (string(diffMsg) == "IterSource<DiffLanguage<TreeDiffInterpreter, GenNode>::DiffStep>");
diffMsg.withDiagnostics();
cout << diffMsg <<endl;
// transparently take a snapshot
diffMsg.updateDiagnostics();
// now the whole sequence is rendered explicitly
string expectedRendering = join ({ins(TYPE_X), set(ATTRIB1), del(CHILD_T)});
CHECK (contains (string(diffMsg), expectedRendering));
CHECK (string(set(ATTRIB1)) == "set(GenNode-ID(\"α\")-DataCap|«int»|1)");
// and we can still iterate...
CHECK (!isnil (diffMsg));
CHECK (ins(TYPE_X) == *diffMsg);
CHECK (set(ATTRIB1) == *++diffMsg);
// NOTE: in fact only the remainder of the sequence is captured...
diffMsg.updateDiagnostics();
CHECK (not contains (string(diffMsg), string(ins(TYPE_X))));
CHECK ( contains (string(diffMsg), string(set(ATTRIB1))));
CHECK ( contains (string(diffMsg), string(del(CHILD_T))));
// and we can still continue to iterate...
CHECK (del(CHILD_T) == *++diffMsg);
CHECK (isnil (++diffMsg));
diffMsg.updateDiagnostics();
CHECK (string(diffMsg) == "Diff--{}");
}