Diff-Listener: need a really basic test

All of the existing "simple" tests for the »Diff Framework« are way to much low-level;
they might indeed be elementary, but not introductory and simple to grasp.
We need a very simplistic example to show off the idea of mutation by diff,
and this simple example can then be used to build further usage test cases.

My actual goal for #1206 to have such a very basic usage demonstration and then
to attach a listener to this setup, and verify it is actually triggered.

PS: the name "GenNodeBasic_test" is somewhat pathetic, this test covers a lot
of ground and is anything but "basic". GenNode in fact became a widely used
fundamental data structure within Lumiera, and -- admittedly -- the existing
implementation might be somewhat simplistic, while the whole concept as such
is demanding, and we should accept that as the state of affairs
This commit is contained in:
Fischlurch 2019-12-12 23:41:26 +01:00
parent f6a4ee3f89
commit 3321e5bc6b
16 changed files with 230 additions and 42 deletions

View file

@ -36,7 +36,7 @@
** cases actually of interest. All other cases invoke the default handling, which
** returns \c false.
**
** @see gen-node-basic-test.cpp
** @see gen-node-test.cpp
**
*/

View file

@ -92,7 +92,7 @@
** To begin with, for the task of diff detection and application, it is sufficient
** to get the children as traversable collection and to offer a depth-first expansion.
**
** @see GenNodeBasic_test
** @see GenNode_test
** @see diff-list-generation-test.cpp
** @see DiffDetector
**

View file

@ -82,7 +82,7 @@
** of Record entities as tree nodes within a GenNode monad, such a
** more elaborate approach was deemed unnecessary for the time being.
**
** @see GenericRecordRepresentation_test
** @see GenericRecord_test
**
*/

View file

@ -124,7 +124,7 @@
** @see DiffTreeApplication_test
** @see DiffComplexApplication_test
** @see DiffListApplication_test
** @see GenNodeBasic_test
** @see GenNode_test
** @see tree-diff.hpp
**
*/

View file

@ -29,7 +29,7 @@
** In a nutshell, if some private data structure wants to receive
** mutation diff messages...
** - it must either implement the interface DiffMutable
** - or provide the function point `void buildMutator(TreeMutator::Handle)`
** - or provide the extension point `void buildMutator(TreeMutator::Handle)`
** Additionally, when the size of the custom TreeMutator object exceeds some
** hard wired limit (200 bytes), then the target type also needs to define
** the extension point `size_t treeMutatorSize(TargetType)`
@ -41,7 +41,7 @@
** @see DiffComplexApplication_test
** @see DiffTreeApplication_test
** @see DiffListApplication_test
** @see GenNodeBasic_test
** @see GenNode_test
** @see tree-diff.hpp
**
*/

View file

@ -31,9 +31,9 @@
** Each concrete TreeMutator instance will be configured differently, and this
** adaptation is done by implementing binding templates, in the way of building
** blocks, attached and customised through lambdas. It is possible to layer
** several bindings on top of a single TreeMutator -- and this header defines
** a building block for one such layer, especially for binding to a representation
** of "child objects" managed within a typical STL container.
** several bindings on top of a single TreeMutator -- and especially this header
** defines a building block for one such layer, especially for binding to a
** representation of "child objects" managed within a typical STL container.
**
** As a _special case_, binding to a STL map is supported, while this usage is rather
** discouraged, since it contradicts the diff semantics due to intrinsic ordering.
@ -398,7 +398,7 @@ namespace diff{
binding_.inject (move(*pos_));
++pos_;
}
if (binding_.matches (spec, *pos_))
if (pos_ and binding_.matches (spec, *pos_))
{
binding_.inject (move(*pos_));
++pos_;
@ -681,7 +681,7 @@ namespace diff{
* This function shall be used right within Builder::attach()
* and wrap a language reference to the concrete collection
* implementing the "object children". The result is a default configured
* binding, which should be further adapted with the builder functions,
* binding, which could be further adapted with the builder functions,
* using lambdas as callback into the otherwise opaque implementation code.
*/
template<class COLL>

View file

@ -400,8 +400,8 @@ namespace diff{
* allows to limit applicability of this whole binding (layer) to only some
* diff specs. E.g., we may set up a binding for elements with value semantics
* and another binding layer on top to deal with object like children (sub scopes).
* Please note that this selector also gets to judge the Ref::ATTRIBS spec, which
* means this layer's contents can be considered "attributes".
* Please note that this selector also gets to judge upon the Ref::ATTRIBS spec,
* which indicates if this layer's contents can be considered "attributes".
* - the optional _setter closure_ (CollectionBindingBuilder::assignElement) accepts
* a diff spec (GenNode) and should assign an equivalent value to the internal
* data representation of the corresponding element (typically by constructing

View file

@ -343,7 +343,7 @@ return: 0
END
TEST "Generic Object Record" GenericRecordRepresentation_test <<END
TEST "Generic Object Record" GenericRecord_test <<END
out-lit: enterprise = Rec(starship| Name = USS Enterprise, Registry = NCC-1701-D, Class = Galaxy, Owner = United Federation of Planets, Operator = Starfleet, built = 2363 |{Picard, Riker, Data, Troi, Worf, Crusher, La Forge})
out-lit: Name = USS Enterprise
out-lit: Registry = NCC-1701-D
@ -372,7 +372,7 @@ return: 0
END
TEST "Generic Record data node" GenNodeBasic_test <<END
TEST "Generic Record data node" GenNode_test <<END
out: GenNode.+_CHILD_Record.+Rec.spam..ham = DataCap.+eggs
out-lit: --spam--
out: GenNode.+"baked beans".+Rec...hasSpam = DataCap.«bool».true.+«char».+«string».*«double».+GenNode.+"spam".+«Record<GenNode>».+«string».eggs.+«string».spam.+«string».spam

View file

@ -23,9 +23,10 @@
/** @file diff-complex-application-test.cpp
** unit test \ref DiffComplexApplication_test.
** Demonstrates the concept of tree mutation by diff messages.
** This is an elaborate demonstration setup to highlight some
** of the more intricate, the flexibility and support for
** and complex opaque implementation variations.
** This is an elaborate demonstration setup to show how a binding
** is setup in practice and to highlight some of the more intricate
** implementation corner cases, allowing for much flexibility when
** binding to otherwise opaque target data structures.
*/

View file

@ -0,0 +1,151 @@
/*
DiffTreeApplicationSimple(Test) - demonstrate the basics of tree diff representation
Copyright (C) Lumiera.org
2019, 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.
* *****************************************************/
/** @file diff-tree-application-simple-test.cpp
** unit test \ref DiffTreeApplicationSimple_test.
** Demonstrates the basic concept of reshaping structured data
** through a tree-diff sequence.
*/
#include "lib/test/run.hpp"
#include "lib/format-util.hpp"
#include "lib/diff/mutation-message.hpp"
#include "lib/diff/tree-diff-application.hpp"
#include "lib/format-util.hpp"
#include "lib/format-cout.hpp"
#include "lib/util.hpp"
#include <string>
#include <vector>
//using util::isnil;
using std::string;
using std::vector;
namespace lib {
namespace diff{
namespace test{
namespace {//Test fixture....
// some symbolic values to be used within the diff
const GenNode VAL_A("a"),
VAL_B("b"),
VAL_C("c"),
VAL_D("d");
/** render the child elements as string data for test/verification */
string
contents (Rec const& object)
{
return util::join (transformIterator (object.scope()
,[](GenNode const& n) { return n.data.get<string>(); }
));
}
}//(End)Test fixture
/****************************************************************************//**
* @test Demonstration/Concept: apply a "tree diff" to reshape structured data.
* - the demo_one() constructs a "GenNode object",
* which is then mutated by applying a diff.
* - the demo_two() uses a STL collection (vector) as _opaque data structure,_
* establishes a _diff binding_ to that structure and then applies basically
* the same diff to mutate the target data.
* @remarks This test is meant as introductory example to explain the meaning of
* the terms "diff", "diff verbs", "application", "mutation", "target data"
* and thus to show the basic ideas of Lumiera's »Diff Framework«. As can be
* expected, these examples are somewhat artificial and everything is made
* up as to look simple, while deliberately a lot of technical intricacies
* will be swept under the carpet.
* @see DiffTreeApplication_test extended demonstration of possible diff operations
* @see DiffComplexApplication_test handling arbitrary data structures
* @see GenericRecord_test
* @see GenNode_test
* @see DiffListApplication_test
* @see diff-tree-application.hpp
* @see tree-diff.hpp
* @see tree-diff-traits.hpp
*/
class DiffTreeApplicationSimple_test
: public Test
, TreeDiffLanguage
{
virtual void
run (Arg)
{
demo_one();
// demo_two();
}
/**
* a change represented symbolically as »diff sequence«.
* This is a sequence of _verbs_ to describe what should be done
* in order to mutate the target data. This example can be read as
* - first accept an existing element "a" as-is
* - after that insert a new element "d" into the sequence
* - next delete an existing element "b" from the sequence
* - and finally accept an existing element "c" into the result
*/
MutationMessage
someDiff()
{
return { pick(VAL_A)
, ins (VAL_D)
, del (VAL_B)
, pick(VAL_C)
};
}
/** @test mutate a Record<GenNode> by applying a the sample diff */
void
demo_one()
{
Rec::Mutator subject;
subject.scope(VAL_A, VAL_B, VAL_C);
CHECK ("a, b, c" == contents(subject));
DiffApplicator<Rec::Mutator>{subject}.consume (someDiff());
CHECK ("a, d, c" == contents(subject));
}
};
/** Register this test class... */
LAUNCHER (DiffTreeApplicationSimple_test, "unit common");
}}} // namespace lib::diff::test

View file

@ -1,5 +1,5 @@
/*
DiffTreeApplication(Test) - demonstrate the basics of tree diff representation
DiffTreeApplication(Test) - demonstrate the main features of tree diff representation
Copyright (C) Lumiera.org
2015, Hermann Vosseler <Ichthyostega@web.de>
@ -22,8 +22,11 @@
/** @file diff-tree-application-test.cpp
** unit test \ref DiffTreeApplication_test.
** Demonstrates the basic concept of reshaping structured data
** through a tree-diff sequence.
** Demonstrates the most relevant operations for reshaping structured data
** through a tree-diff sequence. Here, we use a lib::diff:Record<GenNode>
** as target data, and the test focuses on demonstrating the possible operations.
** @see [Introductory demonstration](\ref diff-tree-application-simple-test.cpp)
** @see [More complex setup with opaque data](\ref diff-complex-application-test.cpp)
*/
@ -89,19 +92,20 @@ namespace test{
* and a nested child-Record.
* - the second step demonstrates various diff language constructs
* to alter, reshape and mutate this data structure
* After applying those two diff sequences, we verify the data
* is indeed in the expected shape.
* After applying those two diff sequences, we verify that
* the mutated data is indeed in the reordered shape.
* @remarks to follow this test, you should be familiar both with our
* [generic data record](\ref diff::Record), as well as with the
* [variant data node](\ref diff::GenNode). The key point to note
* is the usage of Record elements as payload within GenNode, which
* allows to represent tree shaped object like data structures.
* allows to represent tree shaped object-like data structures.
* @note literally the same test case is repeated in MutationMessage_test,
* just there the diff is transported in a MutationMessage capsule,
* as is the case in the real application as well.
* as would be the case in the real application.
* @see DiffComplexApplication_test handling arbitrary data structures
* @see GenericRecordRepresentation_test
* @see GenNodeBasic_test
* @see DiffTreeApplicationSimple_test introductory example demonstration
* @see GenericRecord_test
* @see GenNode_test
* @see DiffListApplication_test
* @see diff-tree-application.hpp
* @see tree-diff.hpp

View file

@ -1,5 +1,5 @@
/*
GenNodeBasic(Test) - fundamental properties of a generic tree node element
GenNode(Test) - fundamental properties of a generic tree node element
Copyright (C) Lumiera.org
2015, Hermann Vosseler <Ichthyostega@web.de>
@ -20,8 +20,8 @@
* *****************************************************/
/** @file gen-node-basic-test.cpp
** unit test \ref GenNodeBasic_test
/** @file gen-node-test.cpp
** unit test \ref GenNode_test
*/
@ -88,7 +88,7 @@ namespace test{
* @see IndexTable
* @see DiffListApplication_test
*/
class GenNodeBasic_test : public Test
class GenNode_test : public Test
{
virtual void
@ -951,7 +951,7 @@ namespace test{
/** Register this test class... */
LAUNCHER (GenNodeBasic_test, "unit common");
LAUNCHER (GenNode_test, "unit common");

View file

@ -1,5 +1,5 @@
/*
GenericRecordRepresentation(Test) - introspective representation of object-like data
GenericRecord(Test) - introspective representation of object-like data
Copyright (C) Lumiera.org
2015, Hermann Vosseler <Ichthyostega@web.de>
@ -20,8 +20,8 @@
* *****************************************************/
/** @file generic-record-representation-test.cpp
** unit test \ref GenericRecordRepresentation_test
/** @file generic-record-test.cpp
** unit test \ref GenericRecord_test
*/
@ -121,10 +121,10 @@ namespace test{
* do not normalise the content in any way; content is meant to reflect
* other data structures, which are normalised and maintained by their owner.
*
* @see GenNodeBasic_test
* @see GenNode_test
* @see tree-diff.cpp
*/
class GenericRecordRepresentation_test : public Test
class GenericRecord_test : public Test
{
virtual void
@ -375,7 +375,7 @@ namespace test{
/** Register this test class... */
LAUNCHER (GenericRecordRepresentation_test, "unit common");
LAUNCHER (GenericRecord_test, "unit common");

View file

@ -148,7 +148,7 @@ namespace test{
* @see TreeMutator
* @see TreeMutator_test
* @see DiffTreeApplication_test
* @see GenNodeBasic_test
* @see GenNode_test
* @see AbstractTangible_test::mutate()
*/
class TreeMutatorBinding_test : public Test

View file

@ -62,8 +62,8 @@ namespace test{
*
* @see TreeMutator
* @see DiffComplexApplication_test a way more complex usage scenario
* @see GenNodeBasic_test
* @see GenericRecordRepresentation_test
* @see GenNode_test
* @see GenericRecord_test
*/
class TreeMutator_test : public Test
{

View file

@ -19576,6 +19576,9 @@
</node>
<node CREATED="1575050510878" ID="ID_646844971" MODIFIED="1575577381370" TEXT="Diff bietet automatische Benachrichtigung bei Struktur&#xe4;nderung">
<arrowlink COLOR="#624d7d" DESTINATION="ID_101148427" ENDARROW="Default" ENDINCLINATION="-3637;-782;" ID="Arrow_ID_498364014" STARTARROW="None" STARTINCLINATION="2976;130;"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576168044826" ID="ID_1758473434" MODIFIED="1576168051635" TEXT="#1206 diff structure change listener">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
@ -21635,6 +21638,9 @@
<node CREATED="1575050510878" ID="ID_350484232" MODIFIED="1575580714937" TEXT="Basis ist vom Diff-System zu leisten">
<arrowlink COLOR="#624d7d" DESTINATION="ID_101148427" ENDARROW="Default" ENDINCLINATION="-3637;-782;" ID="Arrow_ID_1277214644" STARTARROW="None" STARTINCLINATION="2973;244;"/>
<linktarget COLOR="#4d81bf" DESTINATION="ID_350484232" ENDARROW="Default" ENDINCLINATION="-77;-68;" ID="Arrow_ID_658076840" SOURCE="ID_932505699" STARTARROW="None" STARTINCLINATION="-201;12;"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576168044826" ID="ID_1912653386" MODIFIED="1576168051635" TEXT="#1206 diff structure change listener">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
@ -39360,11 +39366,37 @@
<linktarget COLOR="#624d7d" DESTINATION="ID_101148427" ENDARROW="Default" ENDINCLINATION="-3637;-782;" ID="Arrow_ID_498364014" SOURCE="ID_646844971" STARTARROW="None" STARTINCLINATION="2976;130;"/>
<linktarget COLOR="#624d7d" DESTINATION="ID_101148427" ENDARROW="Default" ENDINCLINATION="-3637;-782;" ID="Arrow_ID_1277214644" SOURCE="ID_350484232" STARTARROW="None" STARTINCLINATION="2973;244;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576168044826" ID="ID_230800629" MODIFIED="1576168051635" TEXT="#1206 diff structure change listener">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1573837829595" ID="ID_613778773" MODIFIED="1573837833320" TEXT="immer wenn...">
<node CREATED="1573837834482" ID="ID_980057100" MODIFIED="1573837839549" TEXT="ein Element hinzugekommen ist"/>
<node CREATED="1573837840543" ID="ID_749166782" MODIFIED="1573837845620" TEXT="ein Element entfernt wurde"/>
<node CREATED="1573837847552" ID="ID_1255347678" MODIFIED="1573837852995" TEXT="Element umgeordnet wurden"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576189076819" ID="ID_817894648" MODIFIED="1576189085494" TEXT="Implementierung">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1576189086866" ID="ID_99179892" MODIFIED="1576189103864" TEXT="Ansatzpunkt: TreeMutator">
<icon BUILTIN="idea"/>
<node CREATED="1576189115934" ID="ID_1929426370" MODIFIED="1576189130272" TEXT="vermutlich direkt in&apos;s collection-binding"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576189131908" ID="ID_1843660348" MODIFIED="1576189186952" TEXT="brauche Testfall">
<icon BUILTIN="pencil"/>
<node CREATED="1576189189125" ID="ID_791562073" MODIFIED="1576189207107" TEXT="huch... brauche einfachen Diff-Test">
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="smiley-oh"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576189140651" ID="ID_835328626" MODIFIED="1576189143491" TEXT="Test">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576189161697" ID="ID_1786250967" MODIFIED="1576189178606" TEXT="Struktur&#xe4;nderungen triggern Listener">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576189172445" ID="ID_1803915875" MODIFIED="1576189177766" TEXT="andere &#xc4;nderungen triggern nicht">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node>
@ -40389,7 +40421,7 @@
</node>
</node>
<node CREATED="1446356556349" ID="ID_1068649765" MODIFIED="1512926192454" TEXT="offen...">
<node COLOR="#338800" CREATED="1446356765393" ID="ID_293921295" MODIFIED="1473352607814" TEXT="IDs in Testdaten f&#xfc;r GenNodeBasic_test">
<node COLOR="#338800" CREATED="1446356765393" ID="ID_293921295" MODIFIED="1473352607814" TEXT="IDs in Testdaten f&#xfc;r GenNode_test">
<richcontent TYPE="NOTE"><html>
<head>