Lumiera  0.pre.03
»edit your freedom«
ref-array-test.cpp
Go to the documentation of this file.
1 /*
2  RefArray(Test) - unittest for wrapping with array-of-refs access
3 
4  Copyright (C)
5  2008, 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 
21 #include "lib/test/run.hpp"
22 #include "lib/util.hpp"
23 
24 #include "lib/ref-array-impl.hpp"
25 
26 #include <vector>
27 
28 using ::test::Test;
29 using std::vector;
30 
31 
32 namespace lib {
33 namespace test{
34 
35  namespace { // test types
36 
37  struct I
38  {
39  virtual int op(int i) const =0;
40  virtual ~I() {}
41  };
42 
43  struct Sub1 : I
44  {
45  int offs_;
46 
47  Sub1 (int o=1) : offs_(o) {}
48 
49  int op (int i) const { return i+offs_; }
50  };
51 
52  struct Sub2 : I
53  {
54  const char* letterz_;
55  Sub2() : letterz_("ABCDEFGHIJKLMNOPQRSTUVWXYZ") {}
56 
57  int op (int i) const { return (int)letterz_[i % 26]; }
58  };
59 
60  struct Sub3 : I
61  {
62  int id_;
63  static long sum;
64  static long trigger;
65 
66  Sub3(int id) : id_(id)
67  {
68  sum +=id_;
69  if ( id_ == trigger )
70  throw trigger; // fail while in construction
71  }
72  ~Sub3()
73  {
74  sum -=id_;
75  }
76 
77  int op (int i) const { return i + id_; }
78  };
79 
80  long Sub3::sum = 0;
81  long Sub3::trigger = -1;
82 
83 
84  } // (END) test types
85 
86 
87 
88 
89 
90 
91 
92  /***************************************************************/
104  class RefArray_test : public Test
105  {
106 
107  virtual void
108  run (Arg)
109  {
110  seedRand();
111 
112  checkWrapper();
113  checkVector();
114  checkTable();
115  checkTable_inplaceCreation();
116  checkTable_errorHandling();
117  }
118 
119 
120 
121  void
122  checkWrapper()
123  {
124  vector<Sub2> subz(10);
125  RefArrayVectorWrapper<I,Sub2> subWrap (subz);
126 
127  RefArray<I> & rArr (subWrap);
128 
129  CHECK (subWrap.size()==subz.size());
130  CHECK (INSTANCEOF(I, &rArr[0]));
131  for (size_t i=0; i<rArr.size(); ++i)
132  {
133  CHECK (&rArr[i] == &subz[i]);
134  CHECK (rArr[i].op(i) == subz[i].op(i));
135  }
136  }
137 
138  void
139  checkVector()
140  {
141  RefArrayVector<I,Sub2> subz(10);
142 
143  vector<Sub2> & vect (subz);
144  RefArray<I> & rArr (subz);
145 
146  CHECK (vect.size()==subz.size());
147  CHECK (INSTANCEOF(I, &rArr[0]));
148  for (size_t i=0; i<rArr.size(); ++i)
149  {
150  CHECK (&rArr[i] == &vect[i]);
151  CHECK (rArr[i].op(i) == vect[i].op(i));
152  }
153  }
154 
155 
156 #define ADR(OBJ) (ulong)&(OBJ)
157 
158  void
159  checkTable()
160  {
162  // creates 20 Sub1-objects in-place
163  // which are indeed located within the object
164  CHECK (sizeof(tab) >= 20 * sizeof(Sub1));
165  CHECK (ADR(tab) < ADR(tab[19]) && ADR(tab[19]) < ADR(tab) + sizeof(tab));
166 
167  RefArray<I> & rArr (tab);
168 
169  CHECK (20 == tab.size());
170  CHECK (INSTANCEOF(I, &rArr[0]));
171  for (size_t i=0; i<rArr.size(); ++i)
172  {
173  CHECK (i*sizeof(Sub1) == ADR(rArr[i]) - ADR(rArr[0]) ); // indeed array-like storage
174  CHECK (int(i+1) == rArr[i].op(i)); // check the known result
175  }
176  }
177 
178  template<class SUB>
179  struct Fac
180  {
181  int offset_;
182  Fac ( ) : offset_ (0) {}
183 
184  void operator() (void* place)
185  {
186  CHECK (place);
187  new(place) SUB (offset_++); // note: varying ctor parameter
188  }
189  };
190 
191 
192  void
193  checkTable_inplaceCreation()
194  {
196  RefArrayTable<I,30,Sub1> tab (theFact);
197  RefArray<I> & rArr (tab);
198  CHECK (30 == tab.size());
199  for (size_t i=0; i<rArr.size(); ++i)
200  CHECK (int(i+i) == rArr[i].op(i)); // each one has gotten another offset ctor parameter
201  }
202 
203 
204  void
205  checkTable_errorHandling()
206  {
207  for (uint i=0; i<500; ++i)
208  {
209  Sub3::sum = 0;
210  Sub3::trigger = rani(50); // when hitting the trigger Sub3 throws
211  try
212  {
213  {
214  Fac<Sub3> factory;
215  RefArrayTable<I,30,Sub3> table (factory);
216  CHECK (Sub3::sum == (29+1)*29/2);
217  }
218  CHECK (Sub3::sum == 0);
219  }
220 
221  catch(long id)
222  {
223  CHECK (id == Sub3::trigger);
224  CHECK (Sub3::sum == id);
225  // meaning: all objects have been cleaned up,
226  // with the exception of the one hitting the trigger
227  } }
228  }
229  };
230 
231 
232 
234  LAUNCHER (RefArray_test, "unit common");
235 
236 
237 
238 }} // namespace lib::test
Abstraction: Array of const references.
Definition: ref-array.hpp:42
Definition: run.hpp:40
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:514
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
Implementation namespace for support and library code.
RefArray implementation based on a fixed size array, i.e.
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Some (library-) implementations of the RefArray interface.
< fabricating a series of subclass instances with varying ctor parameter
This variation of the wrapper actually is a vector, but can act as a RefArray.
Wrap a vector holding objects of a subtype and provide array-like access using the interface type...