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) Lumiera.org
5  2008, 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/util.hpp"
30 
31 #include "lib/ref-array-impl.hpp"
32 
33 #include <vector>
34 
35 using ::test::Test;
36 using std::vector;
37 using std::rand;
38 
39 
40 namespace lib {
41 namespace test{
42 
43 
44  namespace { // test types
45 
46  struct I
47  {
48  virtual int op(int i) const =0;
49  virtual ~I() {}
50  };
51 
52  struct Sub1 : I
53  {
54  int offs_;
55 
56  Sub1 (int o=1) : offs_(o) {}
57 
58  int op (int i) const { return i+offs_; }
59  };
60 
61  struct Sub2 : I
62  {
63  const char* letterz_;
64  Sub2() : letterz_("ABCDEFGHIJKLMNOPQRSTUVWXYZ") {}
65 
66  int op (int i) const { return (int)letterz_[i % 26]; }
67  };
68 
69  struct Sub3 : I
70  {
71  int id_;
72  static long sum;
73  static long trigger;
74 
75  Sub3(int id) : id_(id)
76  {
77  sum +=id_;
78  if ( id_ == trigger )
79  throw trigger; // fail while in construction
80  }
81  ~Sub3()
82  {
83  sum -=id_;
84  }
85 
86  int op (int i) const { return i + id_; }
87  };
88 
89  long Sub3::sum = 0;
90  long Sub3::trigger = -1;
91 
92 
93  } // (END) test types
94 
95 
96 
97 
98 
99 
100 
101  /***************************************************************/
113  class RefArray_test : public Test
114  {
115 
116  virtual void
117  run (Arg)
118  {
119  checkWrapper();
120  checkVector();
121  checkTable();
122  checkTable_inplaceCreation();
123  checkTable_errorHandling();
124  }
125 
126 
127 
128  void
129  checkWrapper()
130  {
131  vector<Sub2> subz(10);
132  RefArrayVectorWrapper<I,Sub2> subWrap (subz);
133 
134  RefArray<I> & rArr (subWrap);
135 
136  CHECK (subWrap.size()==subz.size());
137  CHECK (INSTANCEOF(I, &rArr[0]));
138  for (size_t i=0; i<rArr.size(); ++i)
139  {
140  CHECK (&rArr[i] == &subz[i]);
141  CHECK (rArr[i].op(i) == subz[i].op(i));
142  }
143  }
144 
145  void
146  checkVector()
147  {
148  RefArrayVector<I,Sub2> subz(10);
149 
150  vector<Sub2> & vect (subz);
151  RefArray<I> & rArr (subz);
152 
153  CHECK (vect.size()==subz.size());
154  CHECK (INSTANCEOF(I, &rArr[0]));
155  for (size_t i=0; i<rArr.size(); ++i)
156  {
157  CHECK (&rArr[i] == &vect[i]);
158  CHECK (rArr[i].op(i) == vect[i].op(i));
159  }
160  }
161 
162 
163 #define ADR(OBJ) (ulong)&(OBJ)
164 
165  void
166  checkTable()
167  {
169  // creates 20 Sub1-objects in-place
170  // which are indeed located within the object
171  CHECK (sizeof(tab) >= 20 * sizeof(Sub1));
172  CHECK (ADR(tab) < ADR(tab[19]) && ADR(tab[19]) < ADR(tab) + sizeof(tab));
173 
174  RefArray<I> & rArr (tab);
175 
176  CHECK (20 == tab.size());
177  CHECK (INSTANCEOF(I, &rArr[0]));
178  for (size_t i=0; i<rArr.size(); ++i)
179  {
180  CHECK (i*sizeof(Sub1) == ADR(rArr[i]) - ADR(rArr[0]) ); // indeed array-like storage
181  CHECK (int(i+1) == rArr[i].op(i)); // check the known result
182  }
183  }
184 
185  template<class SUB>
186  struct Fac
187  {
188  int offset_;
189  Fac ( ) : offset_ (0) {}
190 
191  void operator() (void* place)
192  {
193  CHECK (place);
194  new(place) SUB (offset_++); // note: varying ctor parameter
195  }
196  };
197 
198 
199  void
200  checkTable_inplaceCreation()
201  {
203  RefArrayTable<I,30,Sub1> tab (theFact);
204  RefArray<I> & rArr (tab);
205  CHECK (30 == tab.size());
206  for (size_t i=0; i<rArr.size(); ++i)
207  CHECK (int(i+i) == rArr[i].op(i)); // each one has gotten another offset ctor parameter
208  }
209 
210 
211  void
212  checkTable_errorHandling()
213  {
214  for (uint i=0; i<500; ++i)
215  {
216  Sub3::sum = 0;
217  Sub3::trigger = (rand() % 50); // when hitting the trigger Sub3 throws
218  try
219  {
220  {
221  Fac<Sub3> factory;
222  RefArrayTable<I,30,Sub3> table (factory);
223  CHECK (Sub3::sum == (29+1)*29/2);
224  }
225  CHECK (Sub3::sum == 0);
226  }
227 
228  catch(long id)
229  {
230  CHECK (id == Sub3::trigger);
231  CHECK (Sub3::sum == id);
232  // meaning: all objects have been cleaned up,
233  // with the exception of the one hitting the trigger
234  } }
235  }
236  };
237 
238 
239 
241  LAUNCHER (RefArray_test, "unit common");
242 
243 
244 
245 }} // namespace lib::test
Abstraction: Array of const references.
Definition: ref-array.hpp:48
Definition: run.hpp:49
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:492
Implementation namespace for support and library code.
RefArray implementation based on a fixed size array, i.e.
Simple 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...