Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
diff-tree-mutation-listener-test.cpp
Go to the documentation of this file.
1/*
2 DiffTreeMutationListener(Test) - verify notification on structural changes
3
4 Copyright (C)
5 2019, 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
20#include "lib/test/run.hpp"
23#include "lib/format-util.hpp"
24#include "lib/util.hpp"
25
26#include <boost/algorithm/string.hpp>
27#include <string>
28#include <vector>
29
30using util::isnil;
31using std::string;
32using std::vector;
33
34
35namespace lib {
36namespace diff{
37namespace test{
38
39 namespace {//Test fixture....
40
41 // some symbolic values to be used within the diff
42 const GenNode VAL_A{"a"},
43 VAL_B{"b"},
44 VAL_C{"c"},
45 VAL_D{"d"},
46
49
50 string
51 contents (vector<string> const& strings)
52 {
53 return util::join (strings);
54 }
55
56 string
57 lowerCase (string src)
58 {
59 return boost::algorithm::to_lower_copy(src); //WARNING: only works for ASCII
60 }
61
62 bool
63 caseInsensitiveEqual (string a, string b)
64 {
65 return lowerCase (a) == lowerCase (b);
66 }
67 }//(End)Test fixture
68
69
70
71
72
73
74
75
76
77 /****************************************************************************/
106 : public Test
107 , public DiffMutable
109 {
110 std::vector<string> subject_;
113
120 void
122 {
123 buff.emplace (
125 .attach (collection (subject_)
126 .matchElement ([](GenNode const& spec, string const& elm) -> bool
127 { // »Matcher« : what target string "matches" a diff spec?
128 return caseInsensitiveEqual(elm, spec.data.get<string>());
129 })
130 .assignElement ([](string& target, GenNode const& spec) -> bool
131 { // »Setter« : how to assign the value from the spec to the target
132 target = spec.data.get<string>();
133 return true;
134 }))
135 .onSeqChange ([&]()
136 {
137 ++structChanges_; // Note: these lambdas are the key point for this test
138 })
139 .onLocalChange ([&]()
140 {
142 })
143 );
144 }
145
146
147 virtual void
148 run (Arg)
149 {
150 CHECK (isnil (subject_));
151 CHECK (0 == structChanges_);
152 CHECK (0 == localChanges_);
153
155
156 applicator.consume (MutationMessage{{ins (VAL_A)
157 , ins (VAL_C)
158 , ins (VAL_D)
159 , ins (VAL_C)
160 }});
161 CHECK ("a, c, d, c" == contents(subject_));
162 CHECK (1 == structChanges_);
163 CHECK (1 == localChanges_);
164
165 applicator.consume (MutationMessage{{after(Ref::END)
166 , set (VAL_C_UPPER) // Note: the current element is tried first, which happens to match
167 , set (VAL_D_UPPER) // ...while in this case, a linear search finds the "d"
168 }});
169 CHECK ("a, c, D, C" == contents(subject_));
170 CHECK (1 == structChanges_); // Note: the listener has not fired, since this counts as value change.
171 CHECK (2 == localChanges_);
172
173 applicator.consume (MutationMessage{{pick(VAL_A)
174 , ins (VAL_B)
175 , find(VAL_D)
176 , pick(VAL_C)
177 , skip(VAL_D)
178 , del (VAL_C)
179 }});
180 CHECK ("a, b, D, c" == contents(subject_));
181 CHECK (2 == structChanges_); // Note: this obviously is a structure change, so both listeners fired.
182 CHECK (3 == localChanges_);
183
184 applicator.consume (MutationMessage{{after(Ref::END)
185 }});
186 CHECK ("a, b, D, c" == contents(subject_));
187 CHECK (2 == structChanges_); // Note: contents confirmed as-is, none of the listeners is invoked.
188 CHECK (3 == localChanges_);
189 }
190 };
191
192
195
196
197
198}}} // namespace lib::diff::test
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
SUB & emplace(SUB &&implementation)
move-construct an instance of a subclass into the opaque buffer
generic builder to apply a diff description to a given target data structure.
Marker or capability interface: an otherwise not further disclosed data structure,...
static Builder< TreeMutator > build()
DSL: start building a custom adapted tree mutator, where the operations are tied by closures or wrapp...
void buildMutator(TreeMutator::Handle buff) override
rig the test class itself to receive a diff mutation.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Generic Message with an embedded diff, to describe changes to model elements.
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
Opaque message to effect a structural change on a target, which is likewise only known in an abstract...
static const Ref END
symbolic ID ref "_END_"
Definition gen-node.hpp:863
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...