Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
generic-record-test.cpp
Go to the documentation of this file.
1/*
2 GenericRecord(Test) - introspective representation of object-like data
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
19#include "lib/test/run.hpp"
21#include "lib/format-cout.hpp"
22#include "lib/format-util.hpp"
23#include "lib/diff/record.hpp"
24#include "lib/itertools.hpp"
25
26#include <string>
27#include <vector>
28
29using std::string;
31using util::isnil;
32using util::join;
33using std::vector;
34using std::swap;
35
36
37namespace lib {
38namespace diff{
39namespace test{
40
41 using LERR_(INVALID);
42 using LERR_(INDEX_BOUNDS);
43 using LERR_(BOTTOM_VALUE);
44
45 namespace {//Test fixture....
46
47 using Seq = vector<string>;
49
50 template<class IT>
51 inline Seq
52 contents (IT const& it)
53 {
54 Seq collected;
55 append_all (it, collected);
56 return collected;
57 }
58
59 inline Seq
60 contents (RecS const& rec_of_strings)
61 {
62 return contents (rec_of_strings.begin());
63 }
64
65 template<class X>
66 inline Seq
67 strings (std::initializer_list<X> const& con)
68 {
69 Seq collected;
70 for (auto elm : con)
71 collected.push_back(elm);
72 return collected;
73 }
74
75
76 }//(End)Test fixture
77
78
79
80
81
82
83
84 /*************************************************************************************/
118 class GenericRecord_test : public Test
119 {
120
121 virtual void
122 run (Arg)
123 {
124 simpleUsage();
128 equality();
129 wrapRef();
130 }
131
132
133 void
135 {
136 RecS enterprise("starship"
137 , strings ({"Name = USS Enterprise"
138 ,"Registry = NCC-1701-D"
139 ,"Class = Galaxy"
140 ,"Owner = United Federation of Planets"
141 ,"Operator= Starfleet"
142 ,"built=2363"
143 })
144 , strings ({"Picard", "Riker", "Data", "Troi", "Worf", "Crusher", "La Forge"})
145 );
146
147 CHECK (enterprise.getType() == "starship");
148 CHECK (enterprise.get("Registry") == "NCC-1701-D");
149 CHECK (enterprise.child(0) == "Picard");
150 CHECK (enterprise.child(2) == "Data");
151
152 CHECK (enterprise.hasAttribute("Owner"));
153 CHECK (!enterprise.hasAttribute("owner"));
154 CHECK (!enterprise.hasAttribute("Owner ")); // no normalisation
155
156 CHECK (enterprise.contains("Data"));
157 CHECK (!enterprise.contains("Woof")); // it is /Worf/, madam
158 CHECK (util::contains (enterprise, "Worf"));
159
160 VERIFY_ERROR (INVALID, enterprise.get("warp10"));
161 VERIFY_ERROR (INDEX_BOUNDS, enterprise.child(12));
162
163 cout << "enterprise = "
164 << enterprise <<endl;
165 for (string elm : enterprise)
166 cout << elm <<endl;
167 cout << "--Attributes--"<<endl;
168 for (string att : enterprise.attribs())
169 cout << att <<endl;
170 cout << "--Keys--->" << join (enterprise.keys(), "<->")<<endl;
171 cout << "--Vals--->" << join (enterprise.vals(), "<->")<<endl;
172 cout << "--Crew--->" << join (enterprise.scope()," | ")<<endl;
173 }
174
175
176 void
178 {
179 RecS nil;
180 CHECK (isnil(nil));
181 CHECK ("NIL" == nil.getType());
182 CHECK (RecS::TYPE_NIL == nil.getType());
183
184 CHECK (!nil.begin());
185 CHECK (nil.begin() == nil.end());
186
187
188 RecS untyped({"x"});
189 CHECK (!isnil(untyped));
190 CHECK ("NIL" == untyped.getType());
191 CHECK (Seq{"x"} == contents(untyped));
192 CHECK (Seq{"x"} == contents(untyped.scope()));
193 CHECK (isnil (untyped.attribs()));
194
195 RecS untyped2({"x=y", "z"});
196 CHECK (!isnil(untyped2));
197 CHECK ("NIL" == untyped2.getType());
198 CHECK (Seq({"x=y", "z"}) == contents(untyped2));
199 CHECK (Seq{"x"} == contents (untyped2.keys()));
200 CHECK (Seq{"y"} == contents (untyped2.vals()));
201 CHECK (Seq{"z"} == contents (untyped2.scope()));
202
203
204 RecS something({"a=1", "type=thing", "b=2", "c", "d"});
205 CHECK (!isnil(something));
206 CHECK ("thing" == something.getType());
207 CHECK (Seq({"a=1", "b=2", "c", "d"}) == contents(something));
208 CHECK (Seq({"a", "b"}) == contents (something.keys()));
209 CHECK (Seq({"1", "2"}) == contents (something.vals()));
210 CHECK (Seq({"c", "d"}) == contents (something.scope()));
211 }
212
213
214 void
216 {
217 RecS a({"a=1", "b=2", "c", "d"});
218 RecS b(a);
219 CHECK (a.getType() == b.getType());
220 CHECK (contents(a) == contents(b));
221 CHECK (contents(a.attribs()) == contents(b.attribs()));
222
223 CHECK (!isSameObject (a.get("a"), b.get("a")));
224 CHECK (!isSameObject (*a.scope(), *b.scope()));
225
226 string const& c = *b.scope();
227 CHECK ("c" == c);
228
229 RecS bb;
230 CHECK (isnil(bb));
231 bb = move(b);
232 CHECK ("2" == bb.get("b"));
233 CHECK (isSameObject(c, *bb.scope()));
234
235 swap (a, bb);
236 CHECK (!isSameObject(c, *bb.scope()));
237 CHECK ( isSameObject(c, *a.scope()));
238
239 CHECK (isnil (b));
240 b = bb;
241 CHECK (!isnil (b));
242 CHECK (!isSameObject(b.get("a"), bb.get("a")));
243 CHECK (!isSameObject(*b.scope(), *bb.scope()));
244 }
245
246
247 void
249 {
250 RecS a({"a"});
251 RecS aa({"a","aa"});
252 RecS aaa({"a","a"});
253 RecS ax({"type=a","a"});
254 RecS ay({"a=a","a"});
255 RecS az({"a =a","a"});
256
257 CHECK (a != aa); CHECK (aa != a);
258 CHECK (aa != aaa); CHECK (aaa != aa);
259 CHECK (a != aaa); CHECK (aaa != a);
260 CHECK (a != ax); CHECK (ax != a);
261 CHECK (a != ay); CHECK (ay != a);
262 CHECK (ax != ay); CHECK (ay != ax);
263 CHECK (aaa != ay); CHECK (ay != aaa);
264 CHECK (ay != az); CHECK (az != ay); // NOTE: attributes are *not* normalised,
265 // rather, they are used as-is,
266 // thus "a=a" != "a =a"
267 RecS a2({"a","aa"});
268 CHECK (aa == a2); CHECK (a2 == aa);
269
270 RecS o1("oo", strings({"a=α", "b=β"}), strings({"γ", "δ", "ε"}));
271 RecS o2({"type=oo", "a=α", "b=β", "γ", "δ", "ε"});
272 RecS o3({"type=oO", "a=α", "b=β", "γ", "δ", "ε"});
273 RecS o4({"type=oo", "a=α", "b=β", "c=γ", "δ", "ε"});
274 RecS o5({"type=oo", "a=α", "b=β", "γ", "ε", "δ"});
275 RecS o6({"type=oo", "a=α", "b=β", "γ", "δ"});
276
277 CHECK (o1 == o2); CHECK (o2 == o1);
278 CHECK (o2 != o3); CHECK (o3 != o2);
279 CHECK (o3 != o4); CHECK (o4 != o3);
280 CHECK (o4 != o5); CHECK (o5 != o4);
281 CHECK (o5 != o6); CHECK (o6 != o5);
282 CHECK (o1 != o3); CHECK (o3 != o1);
283 CHECK (o1 != o4); CHECK (o4 != o1);
284 CHECK (o1 != o5); CHECK (o5 != o1);
285 CHECK (o1 != o6); CHECK (o6 != o1);
286 CHECK (o2 != o4); CHECK (o4 != o2);
287 CHECK (o2 != o5); CHECK (o5 != o2);
288 CHECK (o2 != o6); CHECK (o6 != o2);
289 CHECK (o3 != o5); CHECK (o5 != o3);
290 CHECK (o3 != o6); CHECK (o6 != o3);
291 CHECK (o4 != o6); CHECK (o6 != o4);
292
293 RecS o7({"type=oo", "b = β", "a = α", "γ", "δ", "ε"});
294 CHECK (o2 != o7); CHECK (o7 != o2);
295 // ideally, they would be equal, but this would require
296 // a way more expensive implementation
297 }
298
299
300 void
302 {
303 RecS a;
304 CHECK (isnil (a));
305 CHECK ("NIL" == a.getType());
306
307 RecS::Mutator mut(a);
308 mut.setType("u");
309 mut.appendChild("a");
310 mut.set("a", "1");
311
312 RecS aa(mut);
313 CHECK (a != aa);
314 CHECK ("u" == aa.getType());
315 CHECK (Seq({"a = 1", "a"}) == contents(aa));
316 CHECK (Seq({"a"}) == contents (aa.keys()));
317 CHECK (Seq({"1"}) == contents (aa.vals()));
318 CHECK (Seq({"a"}) == contents (aa.scope()));
319
320 CHECK (mut == aa);
321
322 mut.prependChild("⟂");
323 mut.set("b", "β");
324 mut.set("a", "α");
325
326 CHECK (mut != aa);
327
328 mut.swap (a);
329 CHECK (isnil (mut));
330 CHECK (Seq({"a = α", "b = β", "⟂", "a"}) == contents(a));
331 CHECK (Seq({"a = 1", "a"}) == contents(aa));
332
333 // move out into Mutator and move into target
334 RecS aaa{RecS::Mutator{move(a)}};
335 CHECK (isnil (a));
336 CHECK (not isnil (aaa));
337 CHECK (Seq({"a = α", "b = β", "⟂", "a"}) == contents(aaa));
338 }
339
340
341 void
343 {
344 RecS oo({"type = 🌰", "☿ = mercury", "♀ = venus", "♁ = earth", "♂ = mars", "♃ = jupiter", "♄ = saturn"});
345
346 RecordRef<string> empty;
347 CHECK (bool(empty) == false);
348 CHECK (nullptr == empty.get());
349 VERIFY_ERROR (BOTTOM_VALUE, empty.operator RecS&() );
350
351 RecordRef<string> ref(oo);
352 CHECK (ref);
353 CHECK (ref.get() == &oo);
354
355 RecS& oor = ref;
356 CHECK ("🌰" == oor.getType());
357 CHECK (oor.get("♄") == "saturn");
358
359 // are copyable but not reassignable
360 RecordRef<string> r2 = ref;
361 CHECK (r2);
362 CHECK (r2.get() == ref.get());
363 CHECK (!isSameObject (r2, ref));
364
365 // but references are move-assignable
366 empty = std::move(r2);
367 CHECK (empty);
368 CHECK (!r2);
369 CHECK (nullptr == r2.get());
370 }
371 };
372
373
375 LAUNCHER (GenericRecord_test, "unit common");
376
377
378
379}}} // namespace lib::diff::test
wrapped record reference.
Definition record.hpp:618
Target * get() const noexcept
Definition record.hpp:679
object-like record of data.
Definition record.hpp:142
#define LERR_(_NAME_)
Definition error.hpp:45
Automatically use custom string conversion in C++ stream output.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Helpers for working with iterators based on the pipeline model.
Implementation namespace for support and library code.
void append_all(IT iter, CON &container)
Test runner and basic definitions for tests.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Definition util.hpp:421
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition util.hpp:230
string join(COLL &&coll, string const &delim=", ")
enumerate a collection's contents, separated by delimiter.
bool isnil(lib::time::Duration const &dur)
Special collection to represent object-like data.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.