Lumiera  0.pre.03
»edit your freedom«
digxel-test.cpp
Go to the documentation of this file.
1 /*
2  Digxel(Test) - cover behaviour of a generic number-element holder
3 
4  Copyright (C)
5  2011, 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/format-cout.hpp"
21 #include "lib/format-string.hpp"
22 #include "lib/test/test-helper.hpp"
23 #include "lib/time/digxel.hpp"
24 #include "lib/random.hpp"
25 #include "lib/util.hpp"
26 
27 using lumiera::error::LUMIERA_ERROR_ASSERTION;
28 using util::isSameObject;
29 using util::isnil;
30 using lib::rani;
31 
32 
33 namespace lib {
34 namespace time{
35 namespace test{
36 
37  namespace { // Test data and setup
38 
39  const uint REPEAT = 40;
40  const uint RAND_RANGE = 100;
41  const uint RAND_DENOM = 3;
42  const uint TIMING_CNT = 10000000;
43 
44  inline double
45  randomFrac()
46  {
47  double arbitrary = 1 + rani(RAND_RANGE);
48  arbitrary /= 1 + rani(RAND_DENOM);
49 
50  static double prevVal;
51  if (arbitrary != prevVal)
52  {
53  prevVal = arbitrary;
54  return arbitrary;
55  }
56  else
57  return randomFrac();
58  }
59 
60  inline uint
61  isOdd (uint i)
62  {
63  return i % 2;
64  }
65 
66 
67 
68  /* === special Digxel configuration for this test === */
69 
71  : digxel::PrintfFormatter<double, 11>
72  {
74  };
75 
77 
78 
79  double sum(0),
80  checksum(0);
81 
82  void
83  sideeffectSum (TestDigxel* digxel, double val)
84  {
85  sum += val;
86  digxel->setValueRaw (val);
87  }
88 
89  double preval(0), newval(0);
90 
91  void
92  protocollingMutator (TestDigxel* digxel, double val)
93  {
94  preval = newval;
95  newval = val;
96  digxel->setValueRaw (val);
97  }
98 
99  void
100  limitingMutator (TestDigxel* digxel, double value2set)
101  {
102  digxel->setValueRaw ((+1 < value2set) ? +1.0
103  : (-1 > value2set) ? -1.0
104  : value2set);
105  }
106 
107  void
108  trivialMutator (TestDigxel* digxel, double value2set)
109  {
110  digxel->setValueRaw (value2set);
111  }
112 
113  void
114  emptyMutator (TestDigxel*, double)
115  {
116  /* do nothing */
117  }
118 
119  }//(End)Test setup
120 
121 
122 
123 
124 
125 
126 
127  /*******************************************************************/
137  class Digxel_test : public Test
138  {
139  virtual void
140  run (Arg arg)
141  {
142  seedRand();
143 
144  checkSimpleUsage();
145  checkMutation ();
146  verifyMutatorInfluence();
147  verifyAssignMutatingOperators();
148  verifyComparisons();
149  checkCopy ();
150  checkDisplayOverrun();
151 
152  if (!isnil (arg))
153  timingMeasurements();
154  }
155 
156 
157  void
158  checkSimpleUsage ()
159  {
160  TestDigxel digi;
161  CHECK (0 == digi);
162  CHECK ("## +0.0 ##" == string(digi));
163  cout << "empty____" << digi << endl;
164 
165  digi = -88.77;
166  CHECK (-88.77 == digi);
167  CHECK ("##-88.8 ##" == string(digi));
168  cout << "value____" << digi << endl;
169  }
170 
171 
172  void
173  checkMutation ()
174  {
175  TestDigxel digi;
176 
177  // configure what the Digxel does on "mutation"
178  digi.installMutator (sideeffectSum, digi);
179 
180  CHECK (0 == digi);
181  sum = checksum = 0;
182  for (uint i=0; i < REPEAT; ++i)
183  {
184  double arbitrary = randomFrac();
185  checksum += arbitrary; // for verification
186  //
187  digi = arbitrary; //...causes invocation of mutation functor
188 
189  CHECK (sum == checksum, "divergence after adding %f in iteration %d", arbitrary, i);
190  CHECK (digi == arbitrary);
191  }
192  CHECK (0 < sum);
193  }
194 
195 
196  void
197  verifyMutatorInfluence ()
198  {
199  TestDigxel digi;
200 
201  // using the default mutator
202  CHECK (0 == digi);
203  digi = 12.3;
204  CHECK (12.3 == digi);
205 
206  // a special mutator to limit the value
207  digi.installMutator (limitingMutator, digi);
208  CHECK (12.3 == digi);
209  digi = 12.3;
210  CHECK (12.3 == digi); // triggered on real change only
211  digi = 12.2;
212  CHECK (1 == digi);
213 
214  digi = 0.5;
215  CHECK (0.5 == digi);
216  digi = -0.678;
217  CHECK (-0.678 == digi);
218  digi = -9.1011;
219  CHECK (-1 == digi);
220 
221  digi.setValueRaw(12.3); // bypassing mutator
222  CHECK (12.3 == digi);
223  }
224 
225 
231  void
233  {
234  TestDigxel digi;
235  digi.installMutator (protocollingMutator, digi);
236 
237  digi = 12.3;
238  CHECK ( 0.0 == preval && 12.3 == newval);
239  digi += 10;
240  CHECK (12.3 == preval && 22.3 == newval);
241  digi -= 5;
242  CHECK (22.3 == preval && 17.3 == newval);
243  ++digi;
244  CHECK (17.3 == preval && 18.3 == newval);
245  digi++;
246  CHECK (18.3 == preval && 19.3 == newval);
247  --digi;
248  CHECK (19.3 == preval && 18.3 == newval);
249  digi--;
250  CHECK (18.3 == preval && 17.3 == newval);
251 
252  double val = ++digi;
253  CHECK (18.3 == digi && 18.3 == val);
254  val = digi++;
255  CHECK (19.3 == digi && 18.3 == val);
256  val = --digi;
257  CHECK (18.3 == digi && 18.3 == val);
258  val = digi--;
259  CHECK (17.3 == digi && 18.3 == val);
260  }
261 
262 
263  void
264  verifyComparisons ()
265  {
266  TestDigxel d1;
267  TestDigxel d2;
268 
269  CHECK (d1 == d2);
270 
271  double someValue = d1 + randomFrac();
272  d1 = someValue;
273 
274  CHECK (d1 == someValue);
275  CHECK (d1 != d2);
276  CHECK (d2 != d1);
277 
278  d2 = d1 + 22;
279  CHECK (d1 < d2);
280  CHECK (d1 <= d2);
281 
282  CHECK (!(d1 > d2));
283  CHECK (!(d1 >= d2));
284  CHECK (!(d1 == d2));
285  }
286 
287 
288  void
289  checkCopy ()
290  {
291  TestDigxel d1;
292 
293  double someValue = randomFrac();
294 
295  d1 = someValue;
296  CHECK (d1 == someValue);
297 
298  TestDigxel d2(d1);
299  CHECK (d2 == someValue);
300  CHECK (not isSameObject (d1, d2));
301 
302  d1 = randomFrac();
303  CHECK (d1 != d2);
304  CHECK (d2 == someValue);
305  }
306 
307 
310  void
312  {
313  TestDigxel digi;
314  digi = 123456789.12345678;
315 
316  string formatted;
317 #if false
318  VERIFY_ERROR (ASSERTION, formatted = digi.show() ); // should trigger assertion
319  formatted = digi.show(); // second time doesn't reformat
320 #endif
321 
322  CHECK (formatted.length() <= digi.maxlen());
323  }
324 
325 
335  void
337  {
338  TestDigxel digi;
339  digi = 1;
340 
341  clock_t start(0), stop(0);
342  util::_Fmt resultDisplay("timings(%s)%|36T.|%4.0fns\n");
343 
344 #define START_TIMINGS start=clock();
345 #define DISPLAY_TIMINGS(ID)\
346  stop = clock(); \
347  uint ID = stop-start;\
348  cout << resultDisplay % STRINGIFY (ID) % (double(ID)/CLOCKS_PER_SEC/TIMING_CNT*1e9) ;
349 
350 
351  START_TIMINGS
352  for (uint i=0; i < TIMING_CNT; ++i)
353  {
354  isOdd (i);
355  }
356  DISPLAY_TIMINGS (empty_loop)
357 
358 
359  START_TIMINGS
360  for (uint i=0; i < TIMING_CNT; ++i)
361  {
362  digi = 1;
363  isOdd (i);
364  }
365  DISPLAY_TIMINGS (without_reformatting)
366 
367 
368  START_TIMINGS
369  for (uint i=0; i < TIMING_CNT; ++i)
370  {
371  digi = isOdd (i);
372  }
373  DISPLAY_TIMINGS (with_reformatting)
374 
375 
376  digi.installMutator (emptyMutator, digi);
377 
378  START_TIMINGS
379  for (uint i=0; i < TIMING_CNT; ++i)
380  {
381  digi = isOdd (i);
382  }
383  DISPLAY_TIMINGS (with_empty_mutator)
384 
385 
386  digi.installMutator (trivialMutator, digi);
387 
388  START_TIMINGS
389  for (uint i=0; i < TIMING_CNT; ++i)
390  {
391  digi = isOdd (i);
392  }
393  DISPLAY_TIMINGS (with_trivial_mutator)
394 
395 
396  digi.installMutator (&TestDigxel::setValueRaw, digi);
397 
398  START_TIMINGS
399  for (uint i=0; i < TIMING_CNT; ++i)
400  {
401  digi = isOdd (i);
402  }
403  DISPLAY_TIMINGS (with_memfun_mutator)
404 
405 
406  CHECK (without_reformatting < with_reformatting);
407  }
408  };
409 
410 
412  LAUNCHER (Digxel_test, "unit common");
413 
414 
415 
416 }}} // namespace lib::time::test
A self-contained numeric element for building structured numeric displays.
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
Front-end for printf-style string template interpolation.
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
Default / base implementation for Digxel formatting.
Definition: digxel.hpp:90
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A number element for building structured numeric displays.
Definition: digxel.hpp:217
A collection of frequently used helper functions to support unit testing.
Generating (pseudo) random numbers with controlled seed.
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