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) Lumiera.org
5  2019, 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/test/test-helper.hpp"
32 #include "lib/iter-explorer.hpp"
33 #include "lib/iter-adapter-stl.hpp"
34 #include "lib/util.hpp"
35 
36 #include <list>
37 #include <vector>
38 #include <algorithm>
39 #include <random>
40 
41 
42 using util::isnil;
43 using util::contains;
44 using util::isSameObject;
46 using std::shuffle;
47 using std::vector;
48 
49 
50 namespace stage{
51 namespace model{
52 namespace test {
53 
54 
55  namespace { // Test fixture...
56 
57  struct DummyWidget
58  {
59  int i = rand(); // "identity"
60 
61  friend bool
62  operator== (DummyWidget const& wa, DummyWidget const& wb)
63  {
64  return wa.i == wb.i; // compare identity
65  }
66  };
67 
69 
70 
71 
72  class FakeCanvas
73  : public ViewHook<DummyWidget>
74  {
75  std::list<DummyWidget> widgets_;
76 
77  auto
78  allWidgetIDs() const
79  {
80  return lib::explore(widgets_)
81  .transform([](DummyWidget const& entry)
82  {
83  return entry.i;
84  });
85  }
86 
87  auto
88  findEntry (DummyWidget const& someWidget)
89  {
90  return std::find_if (widgets_.begin()
91  ,widgets_.end()
92  , [&](DummyWidget const& widget) { return widget == someWidget; });
93  }
94 
95  public:
96  /* === diagnostic functions for the test === */
97  bool
98  empty() const
99  {
100  return widgets_.empty();
101  }
102 
103  bool
104  testContains (int someWidgetID)
105  {
106  return util::linearSearch (allWidgetIDs(), someWidgetID);
107  }
108 
110  template<class IT>
111  bool
113  {
114  auto ids = allWidgetIDs();
115  for ( ; refSeq and ids; ++refSeq, ++ids)
116  if (refSeq->i != *ids) break;
117  return isnil(refSeq)
118  and isnil(ids);
119  }
120 
121 
122  /* === Interface ViewHook === */
123 
124  void
125  hook (DummyWidget& elm) override
126  {
127  widgets_.push_back (elm);
128  }
129 
130  void
131  remove (DummyWidget& elm) override
132  {
133  widgets_.remove_if ([&](auto const& widget) { return widget == elm; });
134  }
135 
136 
137  void
138  rehook (DummyWidget& existingHook) noexcept override
139  {
140  auto pos = findEntry (existingHook);
141  REQUIRE (pos != widgets_.end(), "the given iterator must yield previously hooked-up elements");
142  DummyWidget& widget{*pos};
143  this->remove (widget);
144  this->hook (widget);
145  }
146  };
147  }
148 
149 
150 
151 
152  /*************************************************************************************/
164  class ViewHook_test : public Test
165  {
166 
167  virtual void
168  run (Arg)
169  {
170  verify_standardUsage();
171  verify_multiplicity();
172  reOrderHooked();
173  }
174 
175 
178  void
180  {
181  FakeCanvas canvas;
182  CHECK (canvas.empty());
183  {
184  HookedWidget widget{canvas};
185  CHECK (canvas.testContains (widget.i));
186  CHECK (not canvas.empty());
187  }// hook goes out of scope...
188  CHECK (canvas.empty());
189  }
190 
191 
194  void
196  {
197  FakeCanvas canvas;
198  CHECK (canvas.empty());
199 
200  HookedWidget widget{canvas};
201  CHECK (canvas.testContains (widget.i));
202  CHECK (not canvas.empty());
203 
204  int someID;
205  {
206  HookedWidget otherWidget{canvas};
207  someID = otherWidget.i;
208  CHECK (canvas.testContains (someID));
209  CHECK (canvas.testContains (widget.i));
210  }// hook goes out of scope...
211  CHECK (not canvas.testContains (someID));
212  CHECK (canvas.testContains (widget.i));
213  CHECK (not canvas.empty());
214  }
215 
216 
227  void
229  {
230  using Widgets = lib::ScopedCollection<HookedWidget>;
231  using OrderIdx = vector<HookedWidget*>;
232 
233  FakeCanvas canvas; // WARNING: Canvas must outlive the widgets!
234 
235  // create 20 (random) widgets and hook them onto the canvas
236  Widgets widgets{20};
237  OrderIdx orderIdx;
238  for (uint i=0; i<20; ++i)
239  orderIdx.push_back (& widgets.emplace<HookedWidget>(canvas));
240 
241  // helper: use the orderIdx to generate sequence of widget refs (not pointers)
242  auto orderSequence = [&] { return lib::ptrDeref(eachElm(orderIdx)); };
243 
244  CHECK (canvas.testContainsSequence (eachElm(widgets)));
245  CHECK (canvas.testContainsSequence (orderSequence()));
246 
247  // now lets assume the relevant order of the widgets has been altered
248  shuffle (orderIdx.begin(),orderIdx.end(), std::random_device());
249  CHECK (not canvas.testContainsSequence (orderSequence()));
250 
251  // so we need to re-construct the canvas attachments in the new order
252  canvas.reOrder (orderSequence());
253  CHECK (canvas.testContainsSequence (orderSequence()));
254  }
255  };
256 
257 
259  LAUNCHER (ViewHook_test, "unit gui");
260 
261 
262 }}} // namespace stage::model::test
A widget attached onto a display canvas or similar central presentation context.
Definition: view-hook.hpp:123
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:49
Interface to represent _"some presentation layout entity",_ with the ability to attach widgets (manag...
Definition: view-hook.hpp:84
Allow widgets to connect to a common shared presentation context.
Managing a collection of non-copyable polymorphic objects in compact storage.
Simple test class runner.
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:46
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, bypassing any custom comparison operators.
Definition: util.hpp:372