Lumiera  0.pre.03
»edit your freedom«
diagnostic-context-test.cpp
Go to the documentation of this file.
1 /*
2  DiagnosticContext(Test) - verify thread local stack for collecting diagnostics
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/test/run.hpp"
20 #include "lib/test/test-helper.hpp"
21 
23 #include "lib/iter-explorer.hpp"
24 #include "lib/thread.hpp"
25 
26 #include <vector>
27 #include <chrono>
28 #include <array>
29 
30 using std::this_thread::sleep_for;
31 using std::chrono_literals::operator ""us;
32 
33 
34 
35 
36 namespace lib {
37 namespace test{
38 
39  namespace error = lumiera::error;
40 
41  namespace { // private test setup...
42 
43  /* WARNING: memory hungry */
44  const uint NUM_THREADS = 75;
45  const uint MAX_RAND = 100*1000;
46 
47  auto isOdd = [](auto val) { return bool (val % 2); };
48 
49  } // (End) test setup....
50 
51  using lib::ThreadJoinable;
52  using LERR_(LOGIC);
53  using std::rand;
54 
55 
61 
62  typedef std::vector<uint> VecI;
63 
64 
65 
66 
67 
68  /******************************************************************************/
79  class DiagnosticContext_test : public Test
80  {
81 
82  virtual void
83  run (Arg)
84  {
85  verify_simpleAccess();
86  verify_heavilyParallelUsage();
87  }
88 
89 
90 
95  void
97  {
98  VERIFY_ERROR (LOGIC, Marker::access());
99 
100  VecI loggedValues;
101 
102  Marker zero(0);
103  CHECK (0 == zero);
104  CHECK (0 == Marker::access());
105 
106  { // nested scope
107  CHECK (0 == Marker::access());
108 
109  Marker one(1);
110  CHECK (1 == Marker::access());
111  CHECK (1 == one);
112  CHECK (0 == zero);
113 
114  { // nested scope
115  CHECK (1 == Marker::access());
116 
117  Marker two(2);
118  CHECK (2 == Marker::access());
119  CHECK (2 == two);
120  CHECK (1 == one);
121  CHECK (0 == zero);
122 
123  loggedValues = Marker::extractStack();
124  }
125  CHECK (1 == Marker::access());
126  }
127  CHECK (0 == Marker::access());
128 
129  CHECK (3 == loggedValues.size());
130  CHECK (2 == loggedValues[0]);
131  CHECK (1 == loggedValues[1]);
132  CHECK (0 == loggedValues[2]);
133  }
134 
135 
136 
137 
153  void
155  {
156  seedRand();
157  auto verifyResult = [](VecI sequence)
158  {
159  uint prev = 0;
160  for (uint val : sequence)
161  {
162  CHECK (isOdd(val) and val > prev);
163  prev = val;
164  }
165  };
166 
167  std::array<TestThread, NUM_THREADS> testcases;
168 
169  auto results = lib::explore(testcases)
170  .transform([](TestThread& t){ return t.join(); })
171  .effuse();
172 
173  for (auto& res : results)
174  verifyResult (res);
175  }
176 
177 
183  struct TestThread
184  : ThreadJoinable<VecI>
185  {
186  TestThread()
187  : ThreadJoinable{"test context stack"
188  ,[seed = 1+rani(MAX_RAND)]
189  { return descend (seed); }}
190  { }
191  };
192 
193  static VecI
194  descend (uint current)
195  {
196  if (current < 2)
197  return Marker::extractStack();
198 
199  sleep_for (500us);
200 
201  if (isOdd (current))
202  {
203  Marker remember(current);
204  return descend (current+1);
205  }
206  else
207  return descend (current/2);
208  }
209  };
210 
211 
212 
214  LAUNCHER (DiagnosticContext_test, "function common");
215 
216 
217 
218 }} // namespace vault::test
Variant of the standard case, requiring to wait and join() on the termination of this thread...
Definition: thread.hpp:668
Build a call stack within separate thread and capture diagnostics.
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
Definition: run.hpp:40
Facility for collecting diagnostic context information explicitly.
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Implementation namespace for support and library code.
ThreadJoinable(string const &, FUN &&, ARGS &&...) -> ThreadJoinable< std::invoke_result_t< FUN, ARGS... >>
deduction guide: find out about result value to capture from a generic callable.
Simplistic test class runner.
lib::Result< RES > join()
put the caller into a blocking wait until this thread has terminated
Definition: thread.hpp:685
Convenience front-end to simplify and codify basic thread handling.
A collection of frequently used helper functions to support unit testing.
Diagnostic data frame to collect specific information concerning a scope.
ExampleStrategy::Qualifier two(string additionalArg)
definition of another qualifier two(arg), accepting an additional argument
static DiagnosticContext & access()
accessing the innermost diagnostic context created
Building tree expanding and backtracking evaluations within hierarchical scopes.
ExampleStrategy::Qualifier one()
definition of a qualifier one()
static ValSequence extractStack()
snapshot of the current stack of diagnostic frames