Lumiera  0.pre.03
»edit your freedom«
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"
20 #include "lib/test/test-helper.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 
29 using std::string;
30 using util::isSameObject;
31 using util::isnil;
32 using util::join;
33 using std::vector;
34 using std::swap;
35 
36 
37 namespace lib {
38 namespace diff{
39 namespace 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>;
48  using RecS = Record<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();
125  verifyCreation();
126  verifyMutations();
127  copy_and_move();
128  equality();
129  wrapRef();
130  }
131 
132 
133  void
134  simpleUsage()
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
177  verifyCreation()
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
215  copy_and_move()
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
248  equality()
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
301  verifyMutations()
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 
334 
335  void
336  wrapRef()
337  {
338  RecS oo({"type = 🌰", "☿ = mercury", "♀ = venus", "♁ = earth", "♂ = mars", "♃ = jupiter", "♄ = saturn"});
339 
340  RecordRef<string> empty;
341  CHECK (bool(empty) == false);
342  CHECK (nullptr == empty.get());
343  VERIFY_ERROR (BOTTOM_VALUE, empty.operator RecS&() );
344 
345  RecordRef<string> ref(oo);
346  CHECK (ref);
347  CHECK (ref.get() == &oo);
348 
349  RecS& oor = ref;
350  CHECK ("🌰" == oor.getType());
351  CHECK (oor.get("♄") == "saturn");
352 
353  // are copyable but not reassignable
354  RecordRef<string> r2 = ref;
355  CHECK (r2);
356  CHECK (r2.get() == ref.get());
357  CHECK (!isSameObject (r2, ref));
358 
359  // but references are move-assignable
360  empty = std::move(r2);
361  CHECK (empty);
362  CHECK (!r2);
363  CHECK (nullptr == r2.get());
364  }
365  };
366 
367 
369  LAUNCHER (GenericRecord_test, "unit common");
370 
371 
372 
373 }}} // namespace lib::diff::test
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
iterator begin() const
default iteration exposes all data within this "object", starting with the attributes ...
Definition: record.hpp:309
Implementation namespace for support and library code.
Special collection to represent object-like data.
Simplistic test class runner.
wrapped record reference.
Definition: record.hpp:612
A collection of frequently used helper functions to support unit testing.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Helpers for working with iterators based on the pipeline model.
object-like record of data.
Definition: record.hpp:141
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee&#39;s memory identities. ...
Definition: util.hpp:421