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