Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
diff-tree-application-test.cpp
Go to the documentation of this file.
1 /*
2  DiffTreeApplication(Test) - demonstrate the basics of tree diff representation
3 
4  Copyright (C) Lumiera.org
5  2015, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
30 #include "lib/test/run.hpp"
31 #include "lib/format-util.hpp"
33 #include "lib/iter-adapter-stl.hpp"
34 #include "lib/time/timevalue.hpp"
35 #include "lib/format-util.hpp"
36 #include "lib/util.hpp"
37 
38 #include <string>
39 #include <vector>
40 
42 using util::isnil;
43 using util::join;
44 using std::string;
45 using std::vector;
46 using lib::time::Time;
47 
48 
49 namespace lib {
50 namespace diff{
51 namespace test{
52 
53  namespace {//Test fixture....
54 
55  // define some GenNode elements
56  // to act as templates within the concrete diff
57  // NOTE: everything in this diff language is by-value
58  const GenNode ATTRIB1("α", 1), // attribute α = 1
59  ATTRIB2("β", int64_t(2)), // attribute α = 2L (int64_t)
60  ATTRIB3("γ", 3.45), // attribute γ = 3.45 (double)
61  TYPE_X("type", "X"), // a "magic" type attribute "X"
62  TYPE_Y("type", "Y"), //
63  CHILD_A("a"), // unnamed string child node
64  CHILD_B('b'), // unnamed char child node
65  CHILD_T(Time(12,34,56,78)), // unnamed time value child
66  SUB_NODE = MakeRec().genNode(), // empty anonymous node used to open a sub scope
67  ATTRIB_NODE = MakeRec().genNode("δ"), // empty named node to be attached as attribute δ
68  CHILD_NODE = SUB_NODE; // yet another child node, same ID as SUB_NODE (!)
69 
70  }//(End)Test fixture
71 
72 
73 
74 
75 
76 
77 
78 
79 
80  /***********************************************************************/
110  : public Test
112  {
114 
115  DiffSeq
117  {
118  return snapshot({ins(TYPE_X)
119  , ins(ATTRIB1)
120  , ins(ATTRIB2)
121  , ins(ATTRIB3)
122  , ins(CHILD_A)
123  , ins(CHILD_T)
124  , ins(CHILD_T)
125  , ins(SUB_NODE)
126  , mut(SUB_NODE)
127  , ins(CHILD_B)
128  , ins(CHILD_A)
129  , emu(SUB_NODE)
130  });
131  }
132 
133 
134  DiffSeq
136  {
137  // prepare for direct assignment of new value
138  // NOTE: the target ID will be reconstructed, including hash
139  GenNode childA_upper(CHILD_A.idi.getSym(), "A");
140 
141  return snapshot({after(Ref::ATTRIBS) // fast forward to the first child
142  , find(CHILD_T)
143  , pick(CHILD_A)
144  , skip(CHILD_T)
145  , del(CHILD_T)
146  , after(Ref::END) // accept anything beyond as-is
147  , mut(SUB_NODE)
148  , ins(ATTRIB3)
149  , ins(ATTRIB_NODE) // attributes can also be nested objects
150  , find(CHILD_A)
151  , del(CHILD_B)
152  , ins(CHILD_NODE)
153  , ins(CHILD_T)
154  , skip(CHILD_A)
155  , mut(CHILD_NODE)
156  , ins(TYPE_Y)
157  , ins(ATTRIB2)
158  , emu(CHILD_NODE)
159  , set(childA_upper) // direct assignment, target found by ID (out of order)
160  , mut(ATTRIB_NODE) // mutation can be out-of order, target found by ID
161  , ins(CHILD_A)
162  , ins(CHILD_A)
163  , ins(CHILD_A)
164  , emu(ATTRIB_NODE)
165  , emu(SUB_NODE)
166  });
167  }
168 
169 
170  virtual void
172  {
173  Rec::Mutator target;
174  Rec& subject = target;
175  DiffApplicator<Rec::Mutator> application(target);
176 
177  // Part I : apply diff to populate
178  application.consume (populationDiff());
179 
180  CHECK (!isnil (subject)); // nonempty -- content has been added
181  CHECK ("X" == subject.getType()); // type was set to "X"
182  CHECK (1 == subject.get("α").data.get<int>()); // has gotten our int attribute "α"
183  CHECK (2L == subject.get("β").data.get<int64_t>()); // ... the long attribute "β"
184  CHECK (3.45 == subject.get("γ").data.get<double>()); // ... and double attribute "γ"
185  auto scope = subject.scope(); // look into the scope contents...
186  CHECK ( *scope == CHILD_A); // there is CHILD_A
187  CHECK (*++scope == CHILD_T); // followed by a copy of CHILD_T
188  CHECK (*++scope == CHILD_T); // and another copy of CHILD_T
189  CHECK (*++scope == MakeRec().appendChild(CHILD_B) // and there is a nested Record
190  .appendChild(CHILD_A) // with CHILD_B
191  .genNode(SUB_NODE.idi.getSym())); // and CHILD_A
192  CHECK (isnil(++scope)); // thats all -- no more children
193 
194  // Part II : apply the second diff
195  application.consume (mutationDiff());
196  CHECK (join (subject.keys()) == "α, β, γ"); // the attributes weren't altered
197  scope = subject.scope(); // but the scope was reordered
198  CHECK ( *scope == CHILD_T); // CHILD_T
199  CHECK (*++scope == CHILD_A); // CHILD_A
200  Rec nested = (++scope)->data.get<Rec>(); // and our nested Record, which too has been altered:
201  CHECK (nested.get("γ").data.get<double>() == 3.45); // it carries now an attribute "δ", which is again
202  CHECK (nested.get("δ") == MakeRec().appendChild(CHILD_A) // a nested Record with three children CHILD_A
203  .appendChild(CHILD_A) //
204  .appendChild(CHILD_A) //
205  .genNode("δ")); //
206  auto subScope = nested.scope(); // and within the nested sub-scope we find
207  CHECK ( *subScope != CHILD_A); // CHILD_A has been altered by assignment
208  CHECK (CHILD_A.idi == subScope->idi); // ...: same ID as CHILD_A
209  CHECK ("A" == subScope->data.get<string>()); // ...: but mutated payload
210  CHECK (*++subScope == MakeRec().type("Y") // a yet-again nested sub-Record of type "Y"
211  .set("β", int64_t(2)) // with just an attribute "β" == 2L
212  .genNode(CHILD_NODE.idi.getSym())); // (and an empty child scope)
213  CHECK (*++subScope == CHILD_T); // followed by another copy of CHILD_T
214  CHECK (isnil (++subScope)); //
215  CHECK (isnil (++scope)); // and nothing beyond that.
216  }
217  };
218 
219 
221  LAUNCHER (DiffTreeApplication_test, "unit common");
222 
223 
224 
225 }}} // namespace lib::diff::test
Concrete implementation to apply structural changes to hierarchical data structures.
Rec::Mutator MakeRec
Definition: gen-node.hpp:135
keyIter keys() const
Definition: record.hpp:316
string getType() const
Definition: record.hpp:225
int data
Definition: test-priqueue.c:84
void consume(DIFF &&diff)
Definition: run.hpp:49
string join(CON &&coll, string const &delim=", ")
enumerate a collection's contents, separated by delimiter.
scopeIter scope() const
Definition: record.hpp:314
ContentSnapshot< CON > snapshot(CON const &con)
Take a snapshot of the given STL compliant container.
Implementation namespace for support and library code.
bool find(Query< Pipe > &q)
shortcut: run just a query without creating new instances
std::vector< string > & Arg
Definition: run.hpp:54
static const Ref END
symbolic ID ref "_END_"
Definition: gen-node.hpp:754
LAUNCHER(DiffComplexApplication_test,"unit common")
Register this test class...
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Mutator & appendChild(VAL const &newChild)
Definition: record.hpp:492
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition: gen-node.hpp:757
Access get(string key) const
Definition: record.hpp:243
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
materialised iterator contents.
Preconfigured adapters for some STL container standard usage situations.
a family of time value like entities and their relationships.
object-like record of data.
Definition: record.hpp:143
generic data element node within a tree
Definition: gen-node.hpp:213
generic builder to apply a diff description to a given target data structure.