Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
diff-tree-application-test.cpp
Go to the documentation of this file.
1/*
2 DiffTreeApplication(Test) - demonstrate the main features of tree diff representation
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
24#include "lib/test/run.hpp"
25#include "lib/format-util.hpp"
29#include "lib/format-util.hpp"
30#include "lib/util.hpp"
31
32#include <string>
33#include <vector>
34
36using util::isnil;
37using util::join;
38using std::string;
39using std::vector;
40using lib::time::Time;
41
42
43namespace lib {
44namespace diff{
45namespace test{
46
47 namespace {//Test fixture....
48
49 // define some GenNode elements
50 // to act as templates within the concrete diff
51 // NOTE: everything in this diff language is by-value
52 const GenNode ATTRIB1("α", 1), // attribute α = 1
53 ATTRIB2("β", int64_t(2)), // attribute α = 2L (int64_t)
54 ATTRIB3("γ", 3.45), // attribute γ = 3.45 (double)
55 TYPE_X("type", "X"), // a "magic" type attribute "X"
56 TYPE_Y("type", "Y"), //
57 CHILD_A("a"), // unnamed string child node
58 CHILD_B('b'), // unnamed char child node
59 CHILD_T(Time(12,34,56,78)), // unnamed time value child
60 SUB_NODE = MakeRec().genNode(), // empty anonymous node used to open a sub scope
61 ATTRIB_NODE = MakeRec().genNode("δ"), // empty named node to be attached as attribute δ
62 CHILD_NODE = SUB_NODE; // yet another child node, same ID as SUB_NODE (!)
63
64 }//(End)Test fixture
65
66
67
68
69
70
71
72
73
74 /***********************************************************************/
105 : public Test
107 {
109
110 DiffSeq
112 {
113 return snapshot({ins(TYPE_X)
114 , ins(ATTRIB1)
115 , ins(ATTRIB2)
116 , ins(ATTRIB3)
117 , ins(CHILD_A)
118 , ins(CHILD_T)
119 , ins(CHILD_T)
120 , ins(SUB_NODE)
121 , mut(SUB_NODE)
122 , ins(CHILD_B)
123 , ins(CHILD_A)
124 , emu(SUB_NODE)
125 });
126 }
127
128
129 DiffSeq
131 {
132 // prepare for direct assignment of new value
133 // NOTE: the target ID will be reconstructed, including hash
134 GenNode childA_upper(CHILD_A.idi.getSym(), "A");
135
136 return snapshot({after(Ref::ATTRIBS) // fast forward to the first child
137 , find(CHILD_T)
138 , pick(CHILD_A)
139 , skip(CHILD_T)
140 , del(CHILD_T)
141 , after(Ref::END) // accept anything beyond as-is
142 , mut(SUB_NODE)
143 , ins(ATTRIB3)
144 , ins(ATTRIB_NODE) // attributes can also be nested objects
145 , find(CHILD_A)
146 , del(CHILD_B)
147 , ins(CHILD_NODE)
148 , ins(CHILD_T)
149 , skip(CHILD_A)
150 , mut(CHILD_NODE)
151 , ins(TYPE_Y)
152 , ins(ATTRIB2)
153 , emu(CHILD_NODE)
154 , set(childA_upper) // direct assignment, target found by ID (out of order)
155 , mut(ATTRIB_NODE) // mutation can be out-of order, target found by ID
156 , ins(CHILD_A)
157 , ins(CHILD_A)
158 , ins(CHILD_A)
159 , emu(ATTRIB_NODE)
160 , emu(SUB_NODE)
161 });
162 }
163
164
165 virtual void
166 run (Arg)
167 {
168 Rec::Mutator target;
169 Rec& subject = target;
170 DiffApplicator<Rec::Mutator> application(target);
171
172 // Part I : apply diff to populate
173 application.consume (populationDiff());
174
175 CHECK (!isnil (subject)); // nonempty -- content has been added
176 CHECK ("X" == subject.getType()); // type was set to "X"
177 CHECK (1 == subject.get("α").data.get<int>()); // has gotten our int attribute "α"
178 CHECK (2L == subject.get("β").data.get<int64_t>()); // ... the long attribute "β"
179 CHECK (3.45 == subject.get("γ").data.get<double>()); // ... and double attribute "γ"
180 auto scope = subject.scope(); // look into the scope contents...
181 CHECK ( *scope == CHILD_A); // there is CHILD_A
182 CHECK (*++scope == CHILD_T); // followed by a copy of CHILD_T
183 CHECK (*++scope == CHILD_T); // and another copy of CHILD_T
184 CHECK (*++scope == MakeRec().appendChild(CHILD_B) // and there is a nested Record
185 .appendChild(CHILD_A) // with CHILD_B
186 .genNode(SUB_NODE.idi.getSym())); // and CHILD_A
187 CHECK (isnil(++scope)); // thats all -- no more children
188
189 // Part II : apply the second diff
190 application.consume (mutationDiff());
191 CHECK (join (subject.keys()) == "α, β, γ"); // the attributes weren't altered
192 scope = subject.scope(); // but the scope was reordered
193 CHECK ( *scope == CHILD_T); // CHILD_T
194 CHECK (*++scope == CHILD_A); // CHILD_A
195 Rec nested = (++scope)->data.get<Rec>(); // and our nested Record, which too has been altered:
196 CHECK (nested.get("γ").data.get<double>() == 3.45); // it carries now an attribute "δ", which is again
197 CHECK (nested.get("δ") == MakeRec().appendChild(CHILD_A) // a nested Record with three children CHILD_A
198 .appendChild(CHILD_A) //
199 .appendChild(CHILD_A) //
200 .genNode("δ")); //
201 auto subScope = nested.scope(); // and within the nested sub-scope we find
202 CHECK ( *subScope != CHILD_A); // CHILD_A has been altered by assignment
203 CHECK (CHILD_A.idi == subScope->idi); // ...: same ID as CHILD_A
204 CHECK ("A" == subScope->data.get<string>()); // ...: but mutated payload
205 CHECK (*++subScope == MakeRec().type("Y") // a yet-again nested sub-Record of type "Y"
206 .set("β", int64_t(2)) // with just an attribute "β" == 2L
207 .genNode(CHILD_NODE.idi.getSym())); // (and an empty child scope)
208 CHECK (*++subScope == CHILD_T); // followed by another copy of CHILD_T
209 CHECK (isnil (++subScope)); //
210 CHECK (isnil (++scope)); // and nothing beyond that.
211 }
212 };
213
214
217
218
219
220}}} // namespace lib::diff::test
generic builder to apply a diff description to a given target data structure.
object-like record of data.
Definition record.hpp:142
Access get(string key) const
Definition record.hpp:245
scopeIter scope() const
Definition record.hpp:319
keyIter keys() const
Definition record.hpp:321
string getType() const
Definition record.hpp:227
string const & getSym() const
Definition entry-id.hpp:169
materialised iterator contents.
Lumiera's internal time value datatype.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Preconfigured adapters for some STL container standard usage situations.
Rec::Mutator MakeRec
Definition gen-node.hpp:135
ContentSnapshot< CON > snapshot(CON const &con)
Take a snapshot of the given STL compliant container.
Implementation namespace for support and library code.
Test runner and basic definitions for tests.
string join(COLL &&coll, string const &delim=", ")
enumerate a collection's contents, separated by delimiter.
bool isnil(lib::time::Duration const &dur)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
generic data element node within a tree
Definition gen-node.hpp:224
static const Ref END
symbolic ID ref "_END_"
Definition gen-node.hpp:863
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition gen-node.hpp:866
a family of time value like entities and their relationships.
Concrete implementation to apply structural changes to hierarchical data structures.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...