Lumiera  0.pre.03
»edit your freedom«
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) 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 
33 #include "lib/test/run.hpp"
34 #include "lib/format-util.hpp"
36 #include "lib/iter-adapter-stl.hpp"
37 #include "lib/time/timevalue.hpp"
38 #include "lib/format-util.hpp"
39 #include "lib/util.hpp"
40 
41 #include <string>
42 #include <vector>
43 
45 using util::isnil;
46 using util::join;
47 using std::string;
48 using std::vector;
49 using lib::time::Time;
50 
51 
52 namespace lib {
53 namespace diff{
54 namespace test{
55 
56  namespace {//Test fixture....
57 
58  // define some GenNode elements
59  // to act as templates within the concrete diff
60  // NOTE: everything in this diff language is by-value
61  const GenNode ATTRIB1("α", 1), // attribute α = 1
62  ATTRIB2("β", int64_t(2)), // attribute α = 2L (int64_t)
63  ATTRIB3("γ", 3.45), // attribute γ = 3.45 (double)
64  TYPE_X("type", "X"), // a "magic" type attribute "X"
65  TYPE_Y("type", "Y"), //
66  CHILD_A("a"), // unnamed string child node
67  CHILD_B('b'), // unnamed char child node
68  CHILD_T(Time(12,34,56,78)), // unnamed time value child
69  SUB_NODE = MakeRec().genNode(), // empty anonymous node used to open a sub scope
70  ATTRIB_NODE = MakeRec().genNode("δ"), // empty named node to be attached as attribute δ
71  CHILD_NODE = SUB_NODE; // yet another child node, same ID as SUB_NODE (!)
72 
73  }//(End)Test fixture
74 
75 
76 
77 
78 
79 
80 
81 
82 
83  /***********************************************************************/
114  : public Test
116  {
118 
119  DiffSeq
120  populationDiff()
121  {
122  return snapshot({ins(TYPE_X)
123  , ins(ATTRIB1)
124  , ins(ATTRIB2)
125  , ins(ATTRIB3)
126  , ins(CHILD_A)
127  , ins(CHILD_T)
128  , ins(CHILD_T)
129  , ins(SUB_NODE)
130  , mut(SUB_NODE)
131  , ins(CHILD_B)
132  , ins(CHILD_A)
133  , emu(SUB_NODE)
134  });
135  }
136 
137 
138  DiffSeq
139  mutationDiff()
140  {
141  // prepare for direct assignment of new value
142  // NOTE: the target ID will be reconstructed, including hash
143  GenNode childA_upper(CHILD_A.idi.getSym(), "A");
144 
145  return snapshot({after(Ref::ATTRIBS) // fast forward to the first child
146  , find(CHILD_T)
147  , pick(CHILD_A)
148  , skip(CHILD_T)
149  , del(CHILD_T)
150  , after(Ref::END) // accept anything beyond as-is
151  , mut(SUB_NODE)
152  , ins(ATTRIB3)
153  , ins(ATTRIB_NODE) // attributes can also be nested objects
154  , find(CHILD_A)
155  , del(CHILD_B)
156  , ins(CHILD_NODE)
157  , ins(CHILD_T)
158  , skip(CHILD_A)
159  , mut(CHILD_NODE)
160  , ins(TYPE_Y)
161  , ins(ATTRIB2)
162  , emu(CHILD_NODE)
163  , set(childA_upper) // direct assignment, target found by ID (out of order)
164  , mut(ATTRIB_NODE) // mutation can be out-of order, target found by ID
165  , ins(CHILD_A)
166  , ins(CHILD_A)
167  , ins(CHILD_A)
168  , emu(ATTRIB_NODE)
169  , emu(SUB_NODE)
170  });
171  }
172 
173 
174  virtual void
175  run (Arg)
176  {
177  Rec::Mutator target;
178  Rec& subject = target;
179  DiffApplicator<Rec::Mutator> application(target);
180 
181  // Part I : apply diff to populate
182  application.consume (populationDiff());
183 
184  CHECK (!isnil (subject)); // nonempty -- content has been added
185  CHECK ("X" == subject.getType()); // type was set to "X"
186  CHECK (1 == subject.get("α").data.get<int>()); // has gotten our int attribute "α"
187  CHECK (2L == subject.get("β").data.get<int64_t>()); // ... the long attribute "β"
188  CHECK (3.45 == subject.get("γ").data.get<double>()); // ... and double attribute "γ"
189  auto scope = subject.scope(); // look into the scope contents...
190  CHECK ( *scope == CHILD_A); // there is CHILD_A
191  CHECK (*++scope == CHILD_T); // followed by a copy of CHILD_T
192  CHECK (*++scope == CHILD_T); // and another copy of CHILD_T
193  CHECK (*++scope == MakeRec().appendChild(CHILD_B) // and there is a nested Record
194  .appendChild(CHILD_A) // with CHILD_B
195  .genNode(SUB_NODE.idi.getSym())); // and CHILD_A
196  CHECK (isnil(++scope)); // thats all -- no more children
197 
198  // Part II : apply the second diff
199  application.consume (mutationDiff());
200  CHECK (join (subject.keys()) == "α, β, γ"); // the attributes weren't altered
201  scope = subject.scope(); // but the scope was reordered
202  CHECK ( *scope == CHILD_T); // CHILD_T
203  CHECK (*++scope == CHILD_A); // CHILD_A
204  Rec nested = (++scope)->data.get<Rec>(); // and our nested Record, which too has been altered:
205  CHECK (nested.get("γ").data.get<double>() == 3.45); // it carries now an attribute "δ", which is again
206  CHECK (nested.get("δ") == MakeRec().appendChild(CHILD_A) // a nested Record with three children CHILD_A
207  .appendChild(CHILD_A) //
208  .appendChild(CHILD_A) //
209  .genNode("δ")); //
210  auto subScope = nested.scope(); // and within the nested sub-scope we find
211  CHECK ( *subScope != CHILD_A); // CHILD_A has been altered by assignment
212  CHECK (CHILD_A.idi == subScope->idi); // ...: same ID as CHILD_A
213  CHECK ("A" == subScope->data.get<string>()); // ...: but mutated payload
214  CHECK (*++subScope == MakeRec().type("Y") // a yet-again nested sub-Record of type "Y"
215  .set("β", int64_t(2)) // with just an attribute "β" == 2L
216  .genNode(CHILD_NODE.idi.getSym())); // (and an empty child scope)
217  CHECK (*++subScope == CHILD_T); // followed by another copy of CHILD_T
218  CHECK (isnil (++subScope)); //
219  CHECK (isnil (++scope)); // and nothing beyond that.
220  }
221  };
222 
223 
225  LAUNCHER (DiffTreeApplication_test, "unit common");
226 
227 
228 
229 }}} // namespace lib::diff::test
Concrete implementation to apply structural changes to hierarchical data structures.
Definition: run.hpp:49
iter_stl::IterSnapshot< VAL > snapshot(std::initializer_list< VAL > const &&ili)
Take a snapshot of the given std::initializer_list.
Implementation namespace for support and library code.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:308
static const Ref END
symbolic ID ref "_END_"
Definition: gen-node.hpp:871
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition: gen-node.hpp:874
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:150
generic data element node within a tree
Definition: gen-node.hpp:231
generic builder to apply a diff description to a given target data structure.