Lumiera  0.pre.03
»edit your freedom«
iter-chain-search-test.cpp
Go to the documentation of this file.
1 /*
2  IterChainSearch(Test) - verify chained search operations with backtracking
3 
4  Copyright (C)
5  2018, 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 
20 #include "lib/test/run.hpp"
21 #include "lib/test/test-helper.hpp"
22 #include "lib/format-util.hpp"
24 #include "lib/iter-cursor.hpp"
25 #include "lib/util.hpp"
26 
27 #include <vector>
28 #include <string>
29 
30 
31 
32 namespace lib {
33 namespace iter{
34 namespace test{
35 
36  using ::Test;
37  using util::join;
38  using util::isnil;
39  using util::startsWith;
40  using util::isSameObject;
41  using std::vector;
42  using std::string;
43 
44  using LERR_(ITER_EXHAUST);
45 
46 
47  namespace { // test fixture
48 
49  using Spam = vector<string>;
50 
51  const Spam SPAM{"spam"
52  ,"sausage"
53  ,"spam"
54  ,"spam"
55  ,"bacon"
56  ,"spam"
57  ,"tomato"
58  ,"and"
59  ,"spam"
60  };
61 
62 
64  template<class II>
65  inline string
66  materialise (II&& ii)
67  {
68  return util::join (std::forward<II> (ii), "-");
69  }
70  }// (END)fixture
71 
72 
73 
74 
75 
76 
77 
78  /*****************************************************************/
95  class IterChainSearch_test : public Test
96  {
97 
98  virtual void
99  run (Arg)
100  {
101  simpleSearch();
103  backtracking();
104  }
105 
106 
108  void
110  {
111  auto search = chainSearch(SPAM)
112  .search("bacon")
113  .search("tomato");
114 
115  CHECK (search);
116  CHECK (not isnil(search));
117  CHECK ("tomato" == *search);
118  CHECK (isSameObject (*search, SPAM[6]));
119 
120  search.clearFilter();
121  CHECK ("tomato" == *search);
122  ++search;
123  CHECK ("and" == *search);
124  search.search("spam");
125  CHECK ("spam" == *search);
126  CHECK (isSameObject (*search, SPAM[8]));
127 
128  ++search;
129  CHECK (not search);
130  CHECK (isnil (search));
131  VERIFY_ERROR (ITER_EXHAUST, *search);
132  }
133 
134 
135 
143  void
145  {
146  auto search = chainSearch(SPAM) // Note: 1st filter step picks all s-words
147  .search([](string const& str){ return startsWith (str, "s"); });
148 
149  CHECK (materialise (search) =="spam-sausage-spam-spam-spam-spam");
150  CHECK ("spam" == *search);
151 
152  search.addStep([](auto& filter)
153  { // Note: pick the current value at the point
154  string currVal = *filter; // where the 2nd filter step is (re)applied
155  filter.setNewFilter ([=](string const& val) // ...and bake this value into the lambda closure
156  {
157  return val != currVal;
158  });
159  });
160 
161  CHECK ("sausage" == *search);
162  CHECK (materialise (search)
163  == "sausage-bacon-tomato-and-" // everything in the rest, which is not "spam"
164  "spam-spam-bacon-spam-tomato-and-spam-" // everything starting at "sausage" which is not "sausage"
165  "bacon-tomato-and-" // any non-spam behind the 2nd spam
166  "bacon-tomato-and-" // any non-spam behind the 3rd spam
167  "tomato-and" // any non-spam behind the 4th spam
168  ""); // and any non-spam behind the final spam
169  }
170 
171 
172 
181  void
183  {
184  using Cursor = IterCursor<decltype(SPAM.begin())>;
185 
186  auto search = chainSearch(Cursor{SPAM.begin(), SPAM.end()})
187  .search("spam")
188  .addStep([](auto& filter)
189  {
190  filter.switchBackwards(); // switch search direction without moving the cursor
191  filter.flipFilter(); // flip from match on "spam" to match on non-spam
192  })
193  .addStep([](auto& filter)
194  { // filter is still configured to search non-spam backwards
195  ++filter; // just "advance" this filter by one step (backward)
196  });
197 
198  CHECK (materialise (search) // Layer-0: 1-3 spam fail altogether, too greedy. Try 4rd spam....
199  // Layer-1: turn back, toggle to non-spam, find bacon
200  == "sausage-" // Layer-2: non-spam and one step further backwards yields sausage
201  //
202  // BACKTRACK to Layer-0: pick 5th (and last) spam...
203  // Layer-1: turn back, toggle to non-spam, find "and"
204  "tomato-bacon-sausage-" // Layer-2: non-spam and one step back yields tomato, next bacon, next sausage.
205  // BACKTRACK to Layer-1: take previous one, which is tomato
206  "bacon-sausage-" // Layer-2: non-spam and one step further back yields bacon, then next sausage.
207  // BACKTRACK to Layer-1: take previous non-spam, which is bacon
208  "sausage" // Layer-2: non-spam and one step further back yields sausage.
209  ""); // BACKTRACK to Layer-1: exhausted, BACKTRACK to Layer-0: exhausted. Done.
210  }
211  };
212 
213  LAUNCHER (IterChainSearch_test, "unit common");
214 
215 
216 }}} // namespace lib::iter::test
auto chainSearch(SRC &&srcData)
setup a chain search configuration by suitably wrapping the given container.
bool filter(Placement< DummyMO > const &candidate)
a filter predicate to pick some objects from a resultset.
Definition: run.hpp:40
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
An iterator with the ability to switch direction.
Implementation namespace for support and library code.
Evaluation mechanism to apply a sequence of conditions onto a linear search.
Simplistic test class runner.
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.
A cursor-like iterator with the ability to switch iteration direction.
string materialise(II &&ii)
Diagnostic helper: join all the elements from a copy of the iterator.
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
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