Lumiera  0.pre.03
»edit your freedom«
verb-visitor-dispatch-test.cpp
Go to the documentation of this file.
1 /*
2  VerbVisitorDispatch(Test) - Setup to dispatch to arbitrary functions on a receiver interface
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 
29 #include "lib/test/run.hpp"
30 #include "lib/verb-visitor.hpp"
31 #include "lib/format-string.hpp"
32 #include "lib/format-cout.hpp"
33 #include "lib/format-util.hpp"
35 #include "lib/iter-explorer.hpp"
36 
37 #include <string>
38 #include <vector>
39 #include <tuple>
40 
41 using std::string;
42 using util::_Fmt;
43 using util::join;
44 using std::vector;
45 using std::forward;
46 using std::make_tuple;
47 
48 
49 namespace lib {
50 namespace test{
51 
52  namespace { // Test Fixture
53 
55  class Receiver
56  {
57  public:
58  virtual ~Receiver() { }
59 
60  virtual string woof (bool huge, uint cnt) =0;
61  virtual string honk (string) =0;
62  virtual string moo (size_t num) =0;
63  virtual string meh () =0;
64  };
65 
66 
67  using Token = VerbPack<Receiver, string, sizeof(string)>; // the argument list for honk(string) requires the most inline storage
68  using TokenSeq = vector<Token>;
69 
70 
76  : public Receiver
77  {
78  string
79  woof (bool huge, uint cnt) override
80  {
81  string woof;
82  while (0 < cnt--)
83  woof += isnil(woof)? string {huge? "Woof..":"haw-haw"}
84  : woof;
85  return woof;
86  }
87  string
88  honk (string theHonk) override
89  {
90  return theHonk+"-"+theHonk+"!";
91  }
92  string
93  moo (size_t num) override
94  {
95  return join (vector<string>{num, "Moo"}, "__");
96  }
97  string
98  meh() override
99  {
100  return "Meh?";
101  }
102  };
103 
108  : public Receiver
109  {
110  string woof (bool huge, uint cnt) override { return report("woof", huge, cnt); }
111  string honk (string theHonk) override { return report("honk", theHonk); }
112  string moo (size_t num) override { return report("moo", num); }
113  string meh() override { return report("meh"); }
114 
115  template<typename...ARGS>
116  string
117  report (Literal func, ARGS&&...args)
118  {
119  return string(func)
120  + meta::dump (make_tuple (forward<ARGS>(args)...));
121  }
122  };
123 
124  }//(End)Test Fixture
125 
126 
127 
128 
129 
130 
131  /***********************************************************************/
138  class VerbVisitorDispatch_test : public Test
139  {
140 
141  virtual void
142  run (Arg)
143  {
144  TokenSeq tokens = build_and_copy_tokens();
145  apply_VerboseRenderer (tokens);
146  apply_different_receivers (tokens);
147  verify_copy_and_equality (tokens);
148  }
149 
150 
154  TokenSeq
156  {
157  Token littleWoof(&Receiver::woof, "woof", 0, 3); // NOTE: argument type conversion
158  Token bigWoof(&Receiver::woof, "woof", true, 2);
159  Token quack(&Receiver::honk, "honk", "quaack");
160  Token honk(&Receiver::honk, "honk", "Hoonk");
161  Token moo(&Receiver::moo, "moo", 3);
162  Token meh(&Receiver::meh, "meh");
163 
164  CHECK (sizeof(Token) == sizeof(string) // storage size reserved for the arguments (by declaration of type Token)
165  + sizeof(void*) // additional overhead for the VTable for dispatch
166  + sizeof(void(Receiver::*)()) // storage for the function pointer to the interface function
167  + sizeof(Literal) // storage for the verb symbol (for diagnostics and equality comparisions)
168  );
169 
170  // add LVal-copies to result sequence
171  return TokenSeq{{littleWoof, quack, honk, bigWoof, moo, meh}};
172  }
173 
179  void
180  apply_VerboseRenderer (TokenSeq& tokens)
181  {
182  VerboseRenderer receiver;
183  for (Token& tok : tokens)
184  cout << "dispatching " << tok
185  << " -> '"
186  << tok.applyTo(receiver)
187  << "'\n";
188  }
189 
196  void
197  apply_different_receivers (TokenSeq& tokens)
198  {
199  VerboseRenderer verbose;
200  DiagnosticRenderer diagnostic;
201  auto render = [&](Receiver& renderer)
202  {
203  return join (lib::explore(tokens)
204  .transform ([&](Token tok)
205  {
206  return tok.applyTo (renderer);
207  })
208  ,"-");
209  };
210 
211  CHECK (render(diagnostic) == "woof(false,3)-honk(quaack)-honk(Hoonk)-woof(true,2)-moo(3)-meh()");
212  CHECK (render(verbose) == "haw-hawhaw-hawhaw-hawhaw-haw-quaack-quaack!-Hoonk-Hoonk!-Woof..Woof..-Moo__Moo__Moo-Meh?");
213  }
214 
215 
216  void
217  verify_copy_and_equality (TokenSeq& tokens)
218  {
219  Token bigWoof = tokens[3];
220  Token oldWoof{&Receiver::woof, "woof", true, 1};
221  Token oldWolf{&Receiver::woof, "wolf", true, 0};
222 
223  CHECK (bigWoof == oldWoof);
224  CHECK (bigWoof != oldWolf);
225 
226  CHECK (not util::isSameObject (bigWoof, oldWoof));
227  CHECK (string(bigWoof) == "VerbPack(woof)");
228  CHECK (string(oldWoof) == "VerbPack(woof)");
229  CHECK (string(oldWolf) == "VerbPack(wolf)");
230 
231  VerboseRenderer bark;
232  CHECK (bigWoof.applyTo(bark) == "Woof..Woof..");
233  CHECK (oldWoof.applyTo(bark) == "Woof..");
234  CHECK (oldWolf.applyTo(bark) == "");
235  }
236  };
237 
238 
240  LAUNCHER (VerbVisitorDispatch_test, "unit common");
241 
242 
243 
244 }} // namespace lib::test
Automatically use custom string conversion in C++ stream output.
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
a concrete receiver of verb-tokens, which renders them verbosely
Definition: run.hpp:49
A self-contained token to embody a specific yet abstracted operation, together with a concrete set of...
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
Front-end for printf-style string template interpolation.
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Metaprogramming with tuples-of-types and the std::tuple record.
Simple test class runner.
A specific double dispatch variation for function invocation.
another concrete receiver to report any invocation with arguments
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Building tree expanding and backtracking evaluations within hierarchical scopes.
the "visitor" interface used by all VerbPacks in this test