Lumiera  0.pre.03
»edit your freedom«
view-hook-test.cpp
Go to the documentation of this file.
1 /*
2  ViewHook(Test) - verify abstracted presentation attachment
3 
4  Copyright (C)
5  2019, 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"
23 #include "lib/iter-explorer.hpp"
24 #include "lib/iter-adapter-stl.hpp"
25 #include "lib/util.hpp"
26 
27 #include <list>
28 #include <vector>
29 #include <algorithm>
30 #include <random>
31 
32 
33 using util::isnil;
34 using util::contains;
35 using util::isSameObject;
37 using std::shuffle;
38 using std::vector;
39 
40 
41 namespace stage{
42 namespace model{
43 namespace test {
44 
45 
46  namespace { // Test fixture...
47 
48  struct DummyWidget
49  {
50  int i = rani(); // "identity"
51 
52  friend bool
53  operator== (DummyWidget const& wa, DummyWidget const& wb)
54  {
55  return wa.i == wb.i; // compare identity
56  }
57  };
58 
60 
61 
62 
63  class FakeCanvas
64  : public ViewHook<DummyWidget>
65  {
66  std::list<DummyWidget> widgets_;
67 
68  auto
69  allWidgetIDs() const
70  {
71  return lib::explore(widgets_)
72  .transform([](DummyWidget const& entry)
73  {
74  return entry.i;
75  });
76  }
77 
78  auto
79  findEntry (DummyWidget const& someWidget)
80  {
81  return std::find_if (widgets_.begin()
82  ,widgets_.end()
83  , [&](DummyWidget const& widget) { return widget == someWidget; });
84  }
85 
86  public:
87  /* === diagnostic functions for the test === */
88  bool
89  empty() const
90  {
91  return widgets_.empty();
92  }
93 
94  bool
95  testContains (int someWidgetID)
96  {
97  return util::linearSearch (allWidgetIDs(), someWidgetID);
98  }
99 
101  template<class IT>
102  bool
104  {
105  auto ids = allWidgetIDs();
106  for ( ; refSeq and ids; ++refSeq, ++ids)
107  if (refSeq->i != *ids) break;
108  return isnil(refSeq)
109  and isnil(ids);
110  }
111 
112 
113  /* === Interface ViewHook === */
114 
115  void
116  hook (DummyWidget& elm) override
117  {
118  widgets_.push_back (elm);
119  }
120 
121  void
122  remove (DummyWidget& elm) override
123  {
124  widgets_.remove_if ([&](auto const& widget) { return widget == elm; });
125  }
126 
127 
128  void
129  rehook (DummyWidget& existingHook) noexcept override
130  {
131  auto pos = findEntry (existingHook);
132  REQUIRE (pos != widgets_.end(), "the given iterator must yield previously hooked-up elements");
133  DummyWidget& widget{*pos};
134  this->remove (widget);
135  this->hook (widget);
136  }
137  };
138  }
139 
140 
141 
142 
143  /*************************************************************************************/
155  class ViewHook_test : public Test
156  {
157 
158  virtual void
159  run (Arg)
160  {
161  seedRand();
162  verify_standardUsage();
163  verify_multiplicity();
164  reOrderHooked();
165  }
166 
167 
170  void
172  {
173  FakeCanvas canvas;
174  CHECK (canvas.empty());
175  {
176  HookedWidget widget{canvas};
177  CHECK (canvas.testContains (widget.i));
178  CHECK (not canvas.empty());
179  }// hook goes out of scope...
180  CHECK (canvas.empty());
181  }
182 
183 
186  void
188  {
189  FakeCanvas canvas;
190  CHECK (canvas.empty());
191 
192  HookedWidget widget{canvas};
193  CHECK (canvas.testContains (widget.i));
194  CHECK (not canvas.empty());
195 
196  int someID;
197  {
198  HookedWidget otherWidget{canvas};
199  someID = otherWidget.i;
200  CHECK (canvas.testContains (someID));
201  CHECK (canvas.testContains (widget.i));
202  }// hook goes out of scope...
203  CHECK (not canvas.testContains (someID));
204  CHECK (canvas.testContains (widget.i));
205  CHECK (not canvas.empty());
206  }
207 
208 
219  void
221  {
222  using Widgets = lib::ScopedCollection<HookedWidget>;
223  using OrderIdx = vector<HookedWidget*>;
224 
225  FakeCanvas canvas; // WARNING: Canvas must outlive the widgets!
226 
227  // create 20 (random) widgets and hook them onto the canvas
228  Widgets widgets{20};
229  OrderIdx orderIdx;
230  for (uint i=0; i<20; ++i)
231  orderIdx.push_back (& widgets.emplace<HookedWidget>(canvas));
232 
233  // helper: use the orderIdx to generate sequence of widget refs (not pointers)
234  auto orderSequence = [&] { return lib::ptrDeref(eachElm(orderIdx)); };
235 
236  CHECK (canvas.testContainsSequence (eachElm(widgets)));
237  CHECK (canvas.testContainsSequence (orderSequence()));
238 
239  // now lets assume the relevant order of the widgets has been altered
240  shuffle (orderIdx.begin(),orderIdx.end(), std::random_device());
241  CHECK (not canvas.testContainsSequence (orderSequence()));
242 
243  // so we need to re-construct the canvas attachments in the new order
244  canvas.reOrder (orderSequence());
245  CHECK (canvas.testContainsSequence (orderSequence()));
246  }
247  };
248 
249 
251  LAUNCHER (ViewHook_test, "unit gui");
252 
253 
254 }}} // namespace stage::model::test
A widget attached onto a display canvas or similar central presentation context.
Definition: view-hook.hpp:114
A fixed collection of non-copyable polymorphic objects.
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
bool testContainsSequence(IT refSeq)
verify our internal sequence matches the given one
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
Definition: run.hpp:40
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
Interface to represent _"some presentation layout entity",_ with the ability to attach widgets (manag...
Definition: view-hook.hpp:75
Allow widgets to connect to a common shared presentation context.
Managing a collection of non-copyable polymorphic objects in compact storage.
Simplistic test class runner.
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:37
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A collection of frequently used helper functions to support unit testing.
_SeqT< CON >::Range eachElm(CON &coll)
auto ptrDeref(IT iter)
Convenience shortcut to dereference pointers yielded from the wrapped iterator.
Building tree expanding and backtracking evaluations within hierarchical scopes.
Preconfigured adapters for some STL container standard usage situations.
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255
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