Lumiera  0.pre.03
»edit your freedom«
testframe.cpp
Go to the documentation of this file.
1 /*
2  TestFrame - test data frame (stub) for checking Render engine functionality
3 
4  Copyright (C)
5  2011, 2024 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 
34 #include "lib/error.hpp"
35 #include "lib/random.hpp"
36 #include "lib/hash-standard.hpp"
37 #include "lib/hash-combine.hpp"
39 #include "lib/nocopy.hpp"
40 #include "lib/util.hpp"
41 
42 #include <climits>
43 #include <memory>
44 #include <deque>
45 
46 
47 
48 namespace steam {
49 namespace engine{
50 namespace test {
51  namespace err = lumiera::error;
52 
53  using std::deque;
54  using util::unConst;
55 
58 
59 
60  namespace { // hidden local support facilities....
61 
71  const size_t SEQUENCE_SPREAD = 100;
72 
73  HashVal
74  drawSeed (lib::Random& srcGen)
75  {
76  return srcGen.distribute(
77  std::uniform_int_distribution<HashVal>{SEQUENCE_SPREAD
78  ,std::numeric_limits<HashVal>::max()-SEQUENCE_SPREAD});
79  }
80 
83 
93  uint64_t
94  generateDiscriminator(uint seq, uint family)
95  {
96  // use the family as stepping
97  return (seq+1) * (dataSeed+family);
98  }
99 
101  : public lib::SeedNucleus
103  {
104  uint64_t const& distinction_;
105 
106  public:
107  DistinctNucleus(uint64_t const& anchor)
108  : distinction_{anchor}
109  { }
110 
111  uint64_t
112  getSeed() override
113  {
114  return distinction_;
115  }
116  };
117 
119  HashVal
121  {
122  static const HashVal MARK = lib::entropyGen.hash()
123  | 0b1000'1000'1000'1000'1000'1000'1000'1000; //////////////////////////////TICKET #722 : not portable because HashVal ≡ size_t — should it be?
124  return MARK;
125  }
126 
128  auto
129  buildDataGenFrom (uint64_t const& anchor)
130  {
131  DistinctNucleus seed{anchor};
132  return PseudoRandom{seed};
133  }
134 
135 
136  TestFrame&
137  accessAsTestFrame (void* memoryLocation)
138  {
139  REQUIRE (memoryLocation);
140  return *reinterpret_cast<TestFrame*> (memoryLocation);
141  }
142 
143 
144  /* ======= static TestFrame repository ======= */
145 
153  struct TestFrameTable
154  : deque<deque<TestFrame>>
155  {
156  TestFrameTable() = default;
157 
158  TestFrame&
159  getFrame (uint seqNr, uint chanNr)
160  {
161  if (chanNr >= this->size())
162  resize(chanNr+1);
163  ENSURE (chanNr < this->size());
164  deque<TestFrame>& channel = at(chanNr);
165 
166  if (seqNr >= channel.size())
167  {
168  INFO (test, "Growing channel #%d of test frames %d -> %d elements."
169  , chanNr, channel.size(), seqNr+1);
170  for (uint nr=channel.size(); nr<=seqNr; ++nr)
171  channel.emplace_back (nr, chanNr);
172  }
173  ENSURE (seqNr < channel.size());
174  return channel[seqNr];
175  }
176  };
177  //
178  std::unique_ptr<TestFrameTable> testFrames;
179  //
180  }// (End) hidden impl details
181 
182 
183 
184 
185  TestFrame&
186  testData (uint seqNr, uint chanNr)
187  {
188  if (not testFrames)
189  testFrames = std::make_unique<TestFrameTable>();
190  return testFrames->getFrame (seqNr, chanNr);
191  }
192 
193 
203  void
204  TestFrame::reseed()
205  {
206  testFrames.reset(); // discard existing test data repository
207  dataSeed = drawSeed (lib::defaultGen);
208  }
209 
210 
211 
212 
213 
214  /* ======= TestFrame class ======= */
215 
216  TestFrame::Meta::Meta (uint seq, uint family)
217  : _MARK_{stampHeader()}
218  , checksum{0}
219  , distinction{generateDiscriminator (seq,family)}
220  , stage{CREATED}
221  { }
222 
223  TestFrame::~TestFrame()
224  {
225  header_.stage = DISCARDED;
226  }
227 
228 
229  TestFrame::TestFrame (uint seq, uint family)
230  : header_{seq,family}
231  {
232  buildData();
233  ASSERT (0 < header_.distinction);
234  ENSURE (CREATED == header_.stage);
235  ENSURE (isPristine());
236  }
237 
238  TestFrame::TestFrame (TestFrame const& o)
239  : header_{o.header_}
240  {
241  data() = o.data();
242  header_.stage = CREATED;
243  }
244 
245  TestFrame&
246  TestFrame::operator= (TestFrame const& o)
247  {
248  if (not isAlive())
249  throw err::Logic ("target TestFrame already dead or unaccessible");
250  if (not util::isSameAdr (this, o))
251  {
252  data() = o.data();
253  header_ = o.header_;
254  header_.stage = CREATED;
255  }
256  return *this;
257  }
258 
259 
270  bool
271  TestFrame::Meta::isPlausible() const
272  {
273  return _MARK_ == stampHeader()
274  and stage <= DISCARDED;
275  }
276 
277  TestFrame::Meta&
278  TestFrame::accessHeader()
279  {
280  if (not header_.isPlausible())
281  throw err::Invalid{"TestFrame: missing or corrupted metadata"};
282  return header_;
283  }
284  TestFrame::Meta const&
285  TestFrame::accessHeader() const
286  {
287  return unConst(this)->accessHeader();
288  }
289 
290  TestFrame::StageOfLife
291  TestFrame::currStage() const
292  {
293  return header_.isPlausible()? header_.stage
294  : DISCARDED;
295  }
296 
297  bool
298  TestFrame::Meta::operator== (Meta const&o) const
299  {
300  return isPlausible() and o.isPlausible()
301  and stage == o.stage
302  and checksum == o.checksum
303  and distinction == o.distinction;
304  }
305 
306  bool
307  TestFrame::operator== (void* memLocation) const
308  {
309  TestFrame& candidate (accessAsTestFrame (memLocation));
310  return candidate.isSane()
311  && candidate == *this;
312  }
313 
314  bool
315  TestFrame::contentEquals (TestFrame const& o) const
316  {
317  return data() == o.data();
318  }
319 
320 
329  void
330  TestFrame::buildData()
331  {
332  auto gen = buildDataGenFrom (accessHeader().distinction);
333  for (uint64_t& dat : data64())
334  dat = gen.u64();
335  markChecksum();
336  }
337 
341  bool
342  TestFrame::matchDistinction() const
343  {
344  auto gen = buildDataGenFrom (accessHeader().distinction);
345  for (uint64_t const& dat : data64())
346  if (dat != gen.u64())
347  return false;
348  return true;
349  }
350 
352  HashVal
353  TestFrame::computeChecksum() const
354  {
355  HashVal checksum{0};
356  std::hash<char> getHash;
357  for (char const& dat : data())
358  lib::hash::combine (checksum, getHash (dat));
359  return checksum;
360  }
361 
363  HashVal
364  TestFrame::markChecksum()
365  {
366  return accessHeader().checksum = computeChecksum();
367  }
368 
369 
370  bool
371  TestFrame::hasValidChecksum() const
372  {
373  return accessHeader().checksum == computeChecksum();
374  }
375 
376  bool
377  TestFrame::isSane() const
378  {
379  return header_.isPlausible();
380  }
381 
382  bool
383  TestFrame::isValid() const
384  {
385  return isSane()
386  and hasValidChecksum();
387  }
388 
389  bool
390  TestFrame::isPristine() const
391  {
392  return isValid()
393  and matchDistinction();
394  }
395 
396  bool
397  TestFrame::isAlive() const
398  {
399  return isSane()
400  and not isDead();
401  }
402 
403  bool
404  TestFrame::isDead() const
405  {
406  return isSane()
407  and (DISCARDED == currStage());
408  }
409 
415  bool
416  TestFrame::isAlive (void* memLocation)
417  {
418  TestFrame& candidate (accessAsTestFrame (memLocation));
419  return candidate.isAlive();
420  }
421 
422  bool
423  TestFrame::isDead (void* memLocation)
424  {
425  TestFrame& candidate (accessAsTestFrame (memLocation));
426  return candidate.isDead();
427  }
428 
429 
430 }}} // namespace steam::engine::test
Access point to a selection of random number sources.
Definition: random.hpp:64
const size_t SEQUENCE_SPREAD
Offset to set the seed values of »families« apart.
Definition: testframe.cpp:71
Definition: run.hpp:40
Types marked with this mix-in may be moved but not copied.
Definition: nocopy.hpp:49
Random entropyGen
a global RandomSequencer seeded with real entropy
Definition: random.cpp:71
Steam-Layer implementation namespace root.
auto distribute(DIST)
generic adapter: draw next number to use the given distribution
Definition: random.hpp:197
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Helper to use a single extension point for specialised hash functions.
Establishes a seed point for any instance or performance.
Definition: random.hpp:48
HashVal hash()
non-zero hash value from full 64bit range
Definition: random.hpp:253
Lumiera error handling (C++ interface).
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
Generating (pseudo) random numbers with controlled seed.
Unit test helper to generate fake test data frames.
uint64_t generateDiscriminator(uint seq, uint family)
Definition: testframe.cpp:94