source: utilib/trunk/test/any.cpp @ 1513

Revision 1513, 13.2 KB checked in by jdsiiro, 6 years ago (diff)

Moving the PackBuf? support from PackBuf?.h to stl_auxillary.h (see r1511)
broke Any.h. As Anys provide PackBuf? support for std::vector, Any.h
must now include stl_auxillary.h, which in turn includes Ereal.h and
NumArray?.h, which are Serializable (requiring Serialize.h, which
requires Any.h). This circular header dependency breaks the use of
Anys.

As a stopgap, this commit is moving NumArray? and Ereal dependencies out
of stl_auxillary ind into their respective header files (breaking the
dependency loop). Chalk this up to another "good reason" to deprecate
PackBuf? support in Anys (Any.h should really not depend on anything
outside of the STL).

Line 
1/*  _________________________________________________________________________
2 *
3 *  UTILIB: A utility library for developing portable C++ codes.
4 *  Copyright (c) 2001, Sandia National Laboratories.
5 *  This software is distributed under the GNU Lesser General Public License.
6 *  For more information, see the README file in the top UTILIB directory.
7 *  _________________________________________________________________________
8 */
9
10#include <iostream>
11#include <utilib/Any.h>
12
13using std::cout;
14using std::endl;
15using std::setw;
16using std::string;
17using utilib::Any;
18using utilib::AnyRef;
19using utilib::AnyFixedRef;
20
21#define OUT std::cout
22
23namespace {
24
25class FOO
26  {
27  public:
28    FOO()
29      { OUT << "Constructing FOO" << endl; }
30    FOO(const FOO &rhs)
31      {
32      static_cast<void>(rhs);
33      OUT << "Copy Constructing FOO" << endl;
34      }
35
36    // equality test required by Any API
37    //bool operator==(const FOO &rhs) const
38    //  { return true; }
39    // inequality test required by Any API
40    //bool operator<(const FOO &rhs) const
41    //  { return false; }
42  };
43
44}
45
46/// Macro for incorporating macros into string constants
47/** Macro pair to "stringify" any macro (Part 1).  This works by first
48 *  quoting the macro name and then expanding the macro into it's
49 *  actual value. [see _QUOT(x)]
50 */
51#define QUOTE(x) _QUOTE(x)
52/** Macro pair to "stringify" any macro (Part 2).  This works by first
53 *  quoting the macro name and then expanding the macro into it's
54 *  actual value. [see QUOT(x)]
55 */
56#define _QUOTE(x) #x
57
58/** Macro to "demangle" the type stored in the Any to a known (fixed)
59 *  string.  That is, if the Any currently stores an instance of TYPE,
60 *  then "TYPE" is returned, otherwise the mangled typename of the
61 *  stored type is returned.  This prevents false failures caused by
62 *  different platforms using different mangling rules.
63 */
64#define DEMANGLE_TYPE(ANY, TYPE) \
65   ( strcmp( utilib::mangledName(ANY.type()), \
66             utilib::mangledName(typeid(TYPE)) ) == 0   \
67     ? QUOTE(TYPE) : utilib::mangledName(ANY.type()) )
68
69#define PRINT_ANY(ANY, TYPE)      \
70do {                              \
71  int ans;                        \
72  double d_val = 0;               \
73  long   l_val = 0;               \
74  int    i_val = 0;               \
75  short  s_val = 0;               \
76  OUT << QUOTE(ANY) ": type="  << setw(6) << DEMANGLE_TYPE(ANY,TYPE);   \
77  ans = ANY.extract(d_val);       \
78  OUT << ", d = " << setw(3) << d_val << " (" << setw(4) << ans << ")"; \
79  ans = ANY.extract(i_val);       \
80  OUT << ", i = " << setw(3) << i_val << " (" << setw(4) << ans << ")"; \
81  ans = ANY.extract(s_val);       \
82  OUT << ", s = " << setw(3) << s_val << " (" << setw(4) << ans << ")"; \
83  ans = ANY.extract(l_val);       \
84  OUT << ", l = " << setw(3) << l_val << " (" << setw(4) << ans << ")"; \
85  OUT << endl;                   \
86} while (false)
87
88/** Macro to strip off the file name & line number from the exception
89 *  message (so we don't have to edit the reference output
90 *  (anyShallow.qa) every time we do *any* editing to the source code.
91 *  Also strips off anything after and including the first "'" character
92 *  to prevent comparison failures based on differing mangling rules
93 */
94#define CATCH(STR, EXCEPTION)   \
95  catch (EXCEPTION err)         \
96    {                           \
97    string msg(err.what());     \
98    size_t pos = msg.find_last_of("0123456789");  \
99    if ( pos == string::npos )  \
100      { pos = 0; }              \
101    else                        \
102      { ++pos; }                \
103    size_t end = msg.substr(pos).find("'");  \
104    OUT << STR << " failed" << msg.substr(pos, end) << endl;  \
105    }                                        \
106  catch (...)                                \
107    { OUT << STR << " failed: (unexpected exception)" << endl; }  \
108  do {} while (false)
109
110
111void AnyRefTest(const AnyRef& myAny)
112  {
113  double &tmp = const_cast<double&>(myAny.expose<double>());
114  OUT << tmp << " -> ";
115  tmp++;
116  OUT << tmp;
117  }
118
119void AnyFixedRefTest(AnyFixedRef myAny)
120  {
121  double &tmp = const_cast<double&>(myAny.expose<double>());
122  OUT << tmp << " -> ";
123  myAny = tmp + 2;
124  OUT << tmp;
125  }
126
127
128int test_any(int,char**)
129  {
130  Any::throwCastExceptions() = false;
131  utilib::exception_mngr::set_stack_trace(false);
132
133  short s;
134  int i;
135  long l;
136  double d;
137  utilib::Any foo(5);
138  utilib::Any bar = foo;
139  const utilib::Any const_bar = 6.5;
140
141  bar = 5.5;
142
143  PRINT_ANY(foo, int);
144
145  //foo.set(7.7);
146  foo = 7.7;
147  PRINT_ANY(foo, double);
148
149  s = 7;
150  //foo.set(s);
151  foo = s;
152  PRINT_ANY(foo, short);
153
154  l = 8;
155  //foo.set(l);
156  foo = l;
157  PRINT_ANY(foo, long);
158
159  /* no longer valid as Any now stores CONST objects
160  foo.expose<long>() = 9;
161  PRINT_ANY(foo, long);
162  */
163
164  foo = bar;
165  PRINT_ANY(foo, double);
166
167  foo = const_bar;
168  PRINT_ANY(foo, double);
169
170  OUT << "typeof<int> = " << foo.is_type(typeid(int))
171       << "; typeof<double> = " << foo.is_type(typeid(double)) << endl;
172
173  // The following will throw an exception
174  //foo.expose<int>() = 1;
175
176  i = 5;
177  bar &= i;
178  Any bar1(bar, true);
179  Any bar2(i, false);
180  OUT << "reference tests: ";
181  OUT << DEMANGLE_TYPE(bar, int) << "(" << bar.is_reference() << "), ";
182  OUT << DEMANGLE_TYPE(bar1, Any) << "(" << bar1.is_reference() << "), ";
183  OUT << DEMANGLE_TYPE(bar2, int) << "(" << bar2.is_reference() << ")"
184       << endl;
185
186  OUT << "i = " << i << ", ";
187  OUT << "Any(&i) = " << bar.expose<int>() << ", ";
188  OUT << "Any(i) = " << bar2.expose<int>() << endl;
189
190  ++i;
191  OUT << "i = " << i << ", ";
192  OUT << "Any(&i) = " << bar.expose<int>() << ", ";
193  OUT << "Any(i) = " << bar2.expose<int>() << endl;
194
195  ++const_cast<int&>(bar.expose<int>());
196  ++const_cast<int&>(utilib::anyref_cast<int>(bar2));
197  OUT << "i = " << i << ", ";
198  OUT << "Any(&i) = " << bar.expose<int>() << ", ";
199  OUT << "Any(i) = " << bar2.expose<int>() << endl;
200
201  i = utilib::anyval_cast<int>(bar2);
202  OUT << "i = " << i << ", ";
203  OUT << "Any(&i) = " << bar.expose<int>() << ", ";
204  OUT << "Any(i) = " << bar2.expose<int>() << endl;
205
206  // This will call both constructor & copy constructor
207  FOO myFOO;
208  Any anyFoo1(myFOO);
209  // This will only call the constructor
210  Any anyFoo2;
211  anyFoo2.set<FOO>();
212
213  // Test immutable Anys
214  int j = 1;
215  foo.set(j,true,true);
216  OUT << "j = " << j;
217  foo = bar;
218  OUT << "; j = " << j;
219  foo.set(11);
220  OUT << "; j = " << j << endl;
221  try
222    {
223    bar = 10.5;
224    foo = bar;
225    }
226  CATCH("Assignment", utilib::bad_any_typeid);
227
228  try
229    { foo = 10.5; }
230  CATCH("Assignemnt", utilib::bad_any_typeid);
231 
232  try
233    { foo.set<long>(); }
234  CATCH("Assignemnt", utilib::bad_any_typeid);
235
236  Any::throwCastExceptions() = true;
237  try
238    { foo.extract(d); }
239  CATCH("Extraction", utilib::bad_any_cast);
240
241
242  // test implicit casting to reference anys
243  {
244  d = 1;
245  AnyFixedRef tmp(d);
246  OUT << "refcount = " << tmp.anyCount() << endl;
247  AnyRef tmp4(tmp);
248  OUT << "refcount = " << tmp.anyCount() << endl;
249  AnyRef tmp3(tmp4);
250  OUT << "refcount = " << tmp.anyCount() << endl;
251  Any tmp5;
252  tmp5 = tmp4;
253  OUT << "refcount = " << tmp.anyCount() << endl;
254  OUT << "Test AnyRef: (d = " << d << ") ";
255  AnyRefTest(tmp3);
256  OUT << " (d = " << d << ")" << endl;
257
258  d = 5;
259  OUT << "Test cast double -> AnyRef: (d = " << d << ") ";
260  AnyRefTest(d);
261  OUT << " (d = " << d << ")" << endl;
262
263  d = 10;
264  Any tmp2(d, true);
265  OUT << "Test cast Any(is_ref = true) -> AnyRef: (d = " << d << ") ";
266  AnyRefTest(tmp2);
267  OUT << " (d = " << d << ", Any = " << tmp2.expose<double>() << ")" << endl;
268
269  d = 20;
270  tmp2 = d;
271  OUT << "Test cast Any(is_ref = false) -> AnyRef: (d = " << d << ") ";
272  AnyRefTest(tmp2);
273  OUT << " (d = " << d << ", Any = " << tmp2.expose<double>() << ")" << endl;
274  }
275
276  // test implicit casting to immutable anys
277  {
278  d = 1;
279  AnyRef tmp(d);
280  OUT << "refcount = " << tmp.anyCount() << endl;
281  AnyFixedRef tmp4(tmp);
282  OUT << "refcount = " << tmp4.anyCount() << endl;
283  AnyFixedRef tmp3(tmp4);
284  OUT << "refcount = " << tmp4.anyCount() << endl;
285  Any tmp5 = tmp4;
286  OUT << "refcount = " << tmp4.anyCount() << endl;
287  OUT << "Test AnyFixedRef: (d = " << d << ") ";
288  AnyFixedRefTest(tmp3);
289  OUT << " (d = " << d << ")" << endl;
290
291  d = 5;
292  OUT << "Test cast double -> AnyFixedRef: (d = " << d << ") ";
293  AnyFixedRefTest(d);
294  OUT << " (d = " << d << ")" << endl;
295
296  d = 10;
297  Any tmp2(d, true);
298  OUT << "Test cast Any(is_ref = true) -> AnyFixedRef: (d = " << d << ") ";
299  AnyFixedRefTest(tmp2);
300  OUT << " (d = " << d << ", Any = " << tmp2.expose<double>() << ")" << endl;
301
302  d = 20;
303  tmp2 = d;
304  OUT << "Test cast Any(is_ref = false) -> AnyFixedRef: (d = " << d << ") ";
305  AnyFixedRefTest(tmp2);
306  OUT << " (d = " << d << ", Any = " << tmp2.expose<double>() << ")" << endl;
307  }
308
309  // test equality tests
310  {
311     Any tmp_f = std::vector<FOO>(2);
312     Any tmp_f1 = std::vector<FOO>(2);
313     OUT << "Equality tests" << endl;
314
315     Any tmp1 = i;
316     Any tmp1a = tmp1;
317     Any tmp2(i, true);
318     Any tmp3(j, true);
319     Any tmp4(d, true);
320     OUT << "  test i   ref== i:  " << tmp1.references_same_data_as(tmp1a)
321          << endl;
322     OUT << "  test i   ref== &i: " << tmp1.references_same_data_as(tmp2)
323          << endl;
324     OUT << "  test i      == i:  " << (tmp1 == tmp1a) << endl;
325     OUT << "  test i      == &i: " << (tmp1 == tmp2) << endl;
326     OUT << "  test i      == j:  " << (tmp1 == tmp3) << endl;
327     OUT << "  test i      == d:  " << (tmp1 == tmp4) << endl;
328     j = i;
329     OUT << "  test i      == j:  " << (tmp1 == tmp3) << endl;
330
331     Any tmp_v1  = std::vector<int>(5,5);
332     Any tmp_v1a = std::vector<int>(5,5);
333     OUT << "  test v<i>   == v<i>:   " << ( tmp_v1 == tmp_v1a ) << endl;
334     Any tmp_v1b = std::vector<int>(5,6);
335     OUT << "  test v<i>   == v<i>':  " << ( tmp_v1 == tmp_v1b ) << endl;
336     Any tmp_v1c = std::vector<double>(5,5);
337     OUT << "  test v<i>   == v<d>:   " << ( tmp_v1 == tmp_v1c ) << endl;
338     try
339     {
340        OUT << "  test v<FOO> == v<FOO>: ";
341        OUT << ( tmp_f == tmp_f1 );
342        OUT << endl;
343     }
344     catch (utilib::any_not_comparable& err)
345     { OUT << "Comparing (correctly) failed" << endl; }
346     catch (...)
347     { OUT << "Comparing failed: (unexpected exception)" << endl; }
348
349     std::map<int, double> m;
350     m[1] = 4.4;
351     m[3] = 3;
352     Any tmp_m1 = m;
353     Any tmp_m1a = m;
354     OUT << "  test m<i,d> == m<i,d>: " << ( tmp_m1 == tmp_m1a ) << endl;
355     m[4] = 2;
356     Any tmp_m1b = m;
357     OUT << "  test m<i,d> == m<i,d>: " << ( tmp_m1 == tmp_m1b ) << endl;
358
359     std::list<char> l;
360     l.push_back('a');
361     l.push_back('c');
362     l.push_back('b');
363     Any tmp_l1 = l;
364     Any tmp_l1a = l;
365     OUT << "  test l<c>   == l<c>:   " << ( tmp_l1 == tmp_l1a ) << endl;
366
367     Any tmp_d1 = std::deque<int>();
368     Any tmp_d1a = tmp_d1;
369     OUT << "  test d<i>   == d<i>:   " << ( tmp_d1 == tmp_d1a ) << endl;
370
371     Any tmp_s1 = std::set<int>();
372     Any tmp_s1a = tmp_s1;
373     OUT << "  test s<i>   == s<i>:   " << ( tmp_s1 == tmp_s1a ) << endl;
374
375     Any tmp_ms1 = std::multiset<int>();
376     Any tmp_ms1a = tmp_ms1;
377     OUT << "  test S<i>   == S<i>:   " << ( tmp_ms1 == tmp_ms1a ) << endl;
378
379     Any tmp_mm1 = std::multimap<int,double>();
380     Any tmp_mm1a = tmp_ms1;
381     OUT << "  test M<i,d> == M<i,d>: " << ( tmp_mm1 == tmp_mm1a ) << endl;
382
383
384     // test less than tests
385     OUT << "LessThan tests" << endl;
386
387     OUT << "  test i      <  i:  " << (tmp1 < tmp1a) << endl;
388     OUT << "  test i      <  &i: " << (tmp1 < tmp2) << endl;
389     j = i+1;
390     OUT << "  test i      <  j:  " << (tmp1 < tmp3) << endl;
391     OUT << "  test i      <  d:  " << (tmp1 < tmp4) << endl;
392     j = i;
393     OUT << "  test i      <  j:  " << (tmp1 < tmp3) << endl;
394
395     OUT << "  test v<i>   <  v<i>:   " << ( tmp_v1 < tmp_v1a ) << endl;
396     OUT << "  test v<i>   <  v<i>':  " << ( tmp_v1 < tmp_v1b ) << endl;
397     // We test these as a pair because Any::operator<() for different
398     // types is dependent on the (platform-dependent) definition of
399     // std::type_info::before().
400     OUT << "  (test v<i>  <  v<d>) + (test v<d>  <  v<i>):  "
401          << (( tmp_v1c < tmp_v1 ? 1 : 0 ) + ( tmp_v1 < tmp_v1c ? 1 : 0 ))
402          << endl;
403     try
404     {
405        OUT << "  test v<FOO> <  v<FOO>: ";
406        OUT << ( tmp_f < tmp_f1 );
407        OUT << endl;
408     }
409     catch (utilib::any_not_comparable& err)
410     { OUT << "Comparing (correctly) failed" << endl; }
411     catch (...)
412     { OUT << "Comparing failed: (unexpected exception)" << endl; }
413
414     OUT << "  test m<i,d> <  m<i,d>: " << ( tmp_m1 < tmp_m1a ) << endl;
415     OUT << "  test m<i,d> <  m<i,d>: " << ( tmp_m1 < tmp_m1b ) << endl;
416     OUT << "  test l<c>   <  l<c>:   " << ( tmp_l1 < tmp_l1a ) << endl;
417     OUT << "  test d<i>   <  d<i>:   " << ( tmp_d1 < tmp_d1a ) << endl;
418     OUT << "  test s<i>   <  s<i>:   " << ( tmp_s1 < tmp_s1a ) << endl;
419     OUT << "  test S<i>   <  S<i>:   " << ( tmp_ms1 < tmp_ms1a ) << endl;
420     OUT << "  test M<i,d> <  M<i,d>: " << ( tmp_mm1 < tmp_mm1a ) << endl;
421  }
422
423  OUT << "Printing tests" << endl;
424  {
425     Any tmp = 1;
426     OUT << "  (int) = " << tmp << endl;
427     tmp = 5.5;
428     OUT << "  (dbl) = " << tmp << endl;
429     tmp = std::vector<int>(5,5);
430     OUT << "  (vec) = " << tmp << endl;
431     std::map<int,double> &m = tmp.set<std::map<int, double> >();
432     m[2] = 2.2;
433     m[4] = 4.4;
434     m[8] = 8.8;
435     OUT << "  (map) = " << tmp << endl;
436     AnyRef tmp1 = i;
437     OUT << "  (i&)  = " << tmp1 << endl;
438  }
439
440  return 0;
441  }
Note: See TracBrowser for help on using the repository browser.