Lumiera  0.pre.03
»edit your freedom«
buffer-metadata-key-test.cpp
Go to the documentation of this file.
1 /*
2  BufferMetadataKey(Test) - calculation of (internal) buffer metadata type keys
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/error.hpp"
20 #include "lib/test/run.hpp"
21 #include "lib/test/test-helper.hpp"
23 
24 #include <cstdlib>
25 #include <cstring>
26 #include <limits>
27 
28 using util::isnil;
29 using util::isSameObject;
30 
31 
32 namespace steam {
33 namespace engine{
34 namespace metadata{
35 namespace test {
36 
37  namespace { // Test fixture
38 
39  const size_t TEST_MAX_SIZE = 1024 * 1024;
40 
41 
52  template<size_t siz>
54  {
55  typedef char Pattern[siz];
56 
57  Pattern pattern_;
58 
60  {
61  for (size_t i=0; i<siz; ++i)
62  pattern_[i] = i % CHAR_MAX;
63  }
64 
65  ~PlacedNumbers()
66  {
67  for (size_t i=0; i<siz; ++i)
68  pattern_[i] = 0;
69  }
70 
71 
72  /* === diagnostics === */
73 
74  static bool
75  verifyFilled (const void* buff)
76  {
77  REQUIRE (buff);
78  const Pattern& patt = *reinterpret_cast<const Pattern*> (buff);
79 
80  for (size_t i=0; i<siz; ++i)
81  if (patt[i] != char(i % CHAR_MAX))
82  return false;
83 
84  return true;
85  }
86 
87  static bool
88  verifyCleared (const void* buff)
89  {
90  REQUIRE (buff);
91  const Pattern& patt = *reinterpret_cast<const Pattern*> (buff);
92 
93  for (size_t i=0; i<siz; ++i)
94  if (patt[i])
95  return false;
96 
97  return true;
98  }
99  };
100 
101 
107  : Key
108  {
109  size_t const& investigateSize() const { return this->storageSize_; }
110  TypeHandler const& investigateHandler() const { return this->instanceFunc_; }
111  LocalTag const& investigateSpecifics() const { return this->specifics_; }
112 
113  KeyTypeSpecialisationDiagnostics (Key const& toInvestigate)
114  : Key(toInvestigate)
115  { }
116  };
117 
118 
119  inline size_t
120  verifySize (Key const& subject)
121  {
122  return KeyTypeSpecialisationDiagnostics(subject).investigateSize();
123  }
124 
125  inline const TypeHandler
126  verifyHandler (Key const& subject)
127  {
128  return KeyTypeSpecialisationDiagnostics(subject).investigateHandler();
129  }
130 
131  inline const LocalTag
132  verifySpecifics (Key const& subject)
133  {
134  return KeyTypeSpecialisationDiagnostics(subject).investigateSpecifics();
135  }
136 
137  }//(End) Test helpers
138 
139 
140 
141 
142 
143  /*******************************************************************/
155  class BufferMetadataKey_test : public Test
156  {
157  size_t SIZE_A{0};
158  size_t SIZE_B{0};
159 
160 
161  virtual void
162  run (Arg)
163  {
164  seedRand();
165  SIZE_A = 1 + rani(TEST_MAX_SIZE);
166  SIZE_B = 1 + rani(TEST_MAX_SIZE);
167 
168  CHECK (ensure_proper_fixture());
169  buildSimpleKeys();
170  verifyChainedHashes();
171  verifyTypeHandler<500>();
172  verifyTypeSpecialisation();
173  }
174 
175 
176  bool
177  ensure_proper_fixture()
178  {
179  return (SIZE_A != SIZE_B);
180  }
181 
182 
183  void
184  buildSimpleKeys()
185  {
186  HashVal family(123);
187  Key k1(family, SIZE_A);
188  Key k12(k1, SIZE_B);
189  Key k123(k12, LocalTag(56));
190 
191  CHECK (HashVal (k1));
192  CHECK (HashVal (k12));
193  CHECK (HashVal (k123));
194  }
195 
196 
197  void
198  verifyChainedHashes()
199  {
200  HashVal family(123);
201  HashVal otherFamily(456);
202 
203  Key k1(family, SIZE_A);
204  Key k1o(otherFamily, SIZE_A);
205  CHECK (HashVal(k1) != HashVal(k1o));
206 
207  // hash is reproducible
208  CHECK (HashVal(k1) == HashVal(Key(family, SIZE_A)));
209 
210  // differentiate on buffer size
211  Key k12(k1, SIZE_B);
212  Key k121(k12, SIZE_A);
213  Key k2(family, SIZE_B);
214 
215  CHECK (HashVal(k1) != HashVal(k121));
216  CHECK (HashVal(k12) != HashVal(k2));
217 
218  // so the specialisation path really matters, but this is reproducible...
219  CHECK (HashVal(k121) == HashVal(Key(Key(Key(family,SIZE_A),SIZE_B),SIZE_A)));
220  }
221 
222 
223  template<size_t SIZ>
224  void
225  verifyTypeHandler()
226  {
227  char buff[SIZ];
228  memset (buff, '\0', SIZ);
229 
230  typedef PlacedNumbers<SIZ> Pattern;
231 
232  TypeHandler attachPattern = TypeHandler::create<Pattern>();
233 
234  CHECK (attachPattern.isValid());
235  CHECK (0 != hash_value(attachPattern));
236 
237  CHECK (Pattern::verifyCleared (buff));
238  attachPattern.createAttached (buff); // invoke the ctor-functor to place an instance of PlacedNumbers
239  CHECK (Pattern::verifyFilled (buff));
240  attachPattern.destroyAttached (buff); // invoke the dtor-functor to clear the attached instance
241  CHECK (Pattern::verifyCleared (buff));
242  }
243 
244 
245  void
246  verifyTypeSpecialisation()
247  {
248  HashVal family(123);
249  Key kb (family, SIZE_A); // "root" key
250 
251  typedef PlacedNumbers<45> Marker;
252  TypeHandler placeMarker = TypeHandler::create<Marker>();
253  TypeHandler noHandler;
254 
255  LocalTag opaque1 (rani(1000));
256  LocalTag opaque2 (1000 + rani(1000));
257 
258  Key k_siz (kb, SIZE_B); // sub-key to "root": use a different buffer size
259  Key k_han0(kb, noHandler); // sub-key to "root": use a locally defined type functor
260  Key k_han1(kb, placeMarker); // sub-key to "root": use yet another type functor
261  Key k_loc1(kb, opaque1); // sub-key to "root": attach an private opaque ID
262  Key k_loc2(kb, opaque2); // sub-key to "root": attach another opaque ID
263 
264  CHECK (kb != k_siz );
265  CHECK (kb != k_han0);
266  CHECK (kb != k_han1);
267  CHECK (kb != k_loc1);
268  CHECK (kb != k_loc2);
269  CHECK (k_siz != k_han0);
270  CHECK (k_siz != k_han1);
271  CHECK (k_siz != k_loc1);
272  CHECK (k_siz != k_loc2);
273  CHECK (k_han0 != k_han1);
274  CHECK (k_han0 != k_loc1);
275  CHECK (k_han0 != k_loc2);
276  CHECK (k_han1 != k_loc1);
277  CHECK (k_han1 != k_loc2);
278  CHECK (k_loc1 != k_loc2);
279 
280  CHECK (HashVal(kb ) != HashVal(k_siz ));
281  CHECK (HashVal(kb ) != HashVal(k_han0));
282  CHECK (HashVal(kb ) != HashVal(k_han1));
283  CHECK (HashVal(kb ) != HashVal(k_loc1));
284  CHECK (HashVal(kb ) != HashVal(k_loc2));
285  CHECK (HashVal(k_siz ) != HashVal(k_han0));
286  CHECK (HashVal(k_siz ) != HashVal(k_han1));
287  CHECK (HashVal(k_siz ) != HashVal(k_loc1));
288  CHECK (HashVal(k_siz ) != HashVal(k_loc2));
289  CHECK (HashVal(k_han0) != HashVal(k_han1));
290  CHECK (HashVal(k_han0) != HashVal(k_loc1));
291  CHECK (HashVal(k_han0) != HashVal(k_loc2));
292  CHECK (HashVal(k_han1) != HashVal(k_loc1));
293  CHECK (HashVal(k_han1) != HashVal(k_loc2));
294  CHECK (HashVal(k_loc1) != HashVal(k_loc2));
295 
296  CHECK (SIZE_A == verifySize(kb ));
297  CHECK (SIZE_B == verifySize(k_siz ));
298  CHECK (SIZE_A == verifySize(k_han0));
299  CHECK (SIZE_A == verifySize(k_han1));
300  CHECK (SIZE_A == verifySize(k_loc1));
301  CHECK (SIZE_A == verifySize(k_loc2));
302 
303  CHECK (TypeHandler::RAW == verifyHandler(kb ));
304  CHECK (TypeHandler::RAW == verifyHandler(k_siz ));
305  CHECK ( noHandler == verifyHandler(k_han0));
306  CHECK ( placeMarker == verifyHandler(k_han1));
307  CHECK (TypeHandler::RAW == verifyHandler(k_loc1));
308  CHECK (TypeHandler::RAW == verifyHandler(k_loc2));
309 
310  CHECK (LocalTag::UNKNOWN == verifySpecifics(kb ));
311  CHECK (LocalTag::UNKNOWN == verifySpecifics(k_siz ));
312  CHECK (LocalTag::UNKNOWN == verifySpecifics(k_han0));
313  CHECK (LocalTag::UNKNOWN == verifySpecifics(k_han1));
314  CHECK ( opaque1 == verifySpecifics(k_loc1));
315  CHECK ( opaque2 == verifySpecifics(k_loc2));
316 
317 
318  // Verify 2nd level specialisation (some examples)
319  Key k_han1_siz (k_han1, SIZE_B); // sub-key deriving from k_han1, but differing buffer size
320  Key k_siz_han1 (k_siz, placeMarker); // sub-key deriving from k_siz, but using another type functor
321 
322  // Verify some 3rd level specialisations
323  Key k_han1_siz_loc2 (k_han1_siz, opaque2);
324  Key k_loc2_han1_siz (Key(k_loc2,placeMarker), SIZE_B);
325 
326  CHECK (SIZE_B == verifySize(k_han1_siz ));
327  CHECK (SIZE_B == verifySize(k_siz_han1 ));
328  CHECK (SIZE_B == verifySize(k_han1_siz_loc2));
329  CHECK (SIZE_B == verifySize(k_loc2_han1_siz));
330 
331  CHECK (placeMarker == verifyHandler(k_han1_siz ));
332  CHECK (placeMarker == verifyHandler(k_siz_han1 ));
333  CHECK (placeMarker == verifyHandler(k_han1_siz_loc2));
334  CHECK (placeMarker == verifyHandler(k_loc2_han1_siz));
335 
336  CHECK (LocalTag::UNKNOWN == verifySpecifics(k_han1_siz ));
337  CHECK (LocalTag::UNKNOWN == verifySpecifics(k_siz_han1 ));
338  CHECK (opaque2 == verifySpecifics(k_han1_siz_loc2));
339  CHECK (opaque2 == verifySpecifics(k_loc2_han1_siz));
340 
341  // for equality, also the order of specialisation matters
342  CHECK (k_han1_siz != k_siz_han1 );
343  CHECK (k_han1_siz_loc2 != k_loc2_han1_siz);
344 
345  CHECK (HashVal(k_han1_siz ) != HashVal(k_siz_han1 ));
346  CHECK (HashVal(k_han1_siz_loc2) != HashVal(k_loc2_han1_siz));
347 
348  // yet this *is* an semantic equality test
349  Key k_again (Key(k_han1,SIZE_B), opaque2);
350  CHECK (k_again == k_han1_siz_loc2);
351  CHECK (HashVal(k_again) == HashVal(k_han1_siz_loc2));
352 
353  // pick just some combinations for cross verification...
354  CHECK (kb != k_han1_siz );
355  CHECK (kb != k_siz_han1 );
356  CHECK (kb != k_han1_siz_loc2);
357  CHECK (kb != k_loc2_han1_siz);
358  CHECK (k_han1 != k_han1_siz );
359  CHECK (k_han1 != k_siz_han1 );
360  CHECK (k_han1 != k_han1_siz_loc2);
361  CHECK (k_han1 != k_loc2_han1_siz);
362  CHECK (k_siz != k_han1_siz );
363  CHECK (k_siz != k_siz_han1 );
364  CHECK (k_siz != k_han1_siz_loc2);
365  CHECK (k_siz != k_loc2_han1_siz);
366  CHECK (k_loc2 != k_han1_siz );
367  CHECK (k_loc2 != k_siz_han1 );
368  CHECK (k_loc2 != k_han1_siz_loc2);
369  CHECK (k_loc2 != k_loc2_han1_siz);
370 
371  CHECK (HashVal(kb ) != HashVal(k_han1_siz ));
372  CHECK (HashVal(kb ) != HashVal(k_siz_han1 ));
373  CHECK (HashVal(kb ) != HashVal(k_han1_siz_loc2));
374  CHECK (HashVal(kb ) != HashVal(k_loc2_han1_siz));
375  CHECK (HashVal(k_han1) != HashVal(k_han1_siz ));
376  CHECK (HashVal(k_han1) != HashVal(k_siz_han1 ));
377  CHECK (HashVal(k_han1) != HashVal(k_han1_siz_loc2));
378  CHECK (HashVal(k_han1) != HashVal(k_loc2_han1_siz));
379  CHECK (HashVal(k_siz ) != HashVal(k_han1_siz ));
380  CHECK (HashVal(k_siz ) != HashVal(k_siz_han1 ));
381  CHECK (HashVal(k_siz ) != HashVal(k_han1_siz_loc2));
382  CHECK (HashVal(k_siz ) != HashVal(k_loc2_han1_siz));
383  CHECK (HashVal(k_loc2) != HashVal(k_han1_siz ));
384  CHECK (HashVal(k_loc2) != HashVal(k_siz_han1 ));
385  CHECK (HashVal(k_loc2) != HashVal(k_han1_siz_loc2));
386  CHECK (HashVal(k_loc2) != HashVal(k_loc2_han1_siz));
387  }
388  };
389 
390 
392  LAUNCHER (BufferMetadataKey_test, "unit player");
393 
394 
395 
396 }}}} // namespace steam::engine::metadata::test
Definition: run.hpp:40
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
an opaque mark to be used by the BufferProvider implementation.
Steam-Layer implementation namespace root.
Metadata for managing and accessing buffers.
Description of a Buffer-"type".
Simplistic test class runner.
static const TypeHandler RAW
Marker for the default case: raw buffer without type handling.
A collection of frequently used helper functions to support unit testing.
Lumiera error handling (C++ interface).
static const LocalTag UNKNOWN
Marker when no distinct local key is given.
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
A pair of functors to maintain a datastructure within a buffer.
HashVal hash_value(ProcID const &procID)
generate registry hash value based on the distinct data in ProcID.
Definition: proc-node.cpp:105
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