Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
multifact-test.cpp
Go to the documentation of this file.
1/*
2 MultiFact(Test) - cover the configurable object-family creating factory
3
4 Copyright (C)
5 2014, 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"
21#include "lib/multifact.hpp"
22#include "lib/util.hpp"
23
24#include <boost/lexical_cast.hpp>
25#include <functional>
26#include <memory>
27#include <string>
28
29
30
31namespace lib {
32namespace test{
33
34 using boost::lexical_cast;
36 using util::isnil;
37
38 using std::shared_ptr;
39 using std::function;
40 using std::string;
41 using std::bind;
42
43 using lumiera::error::LUMIERA_ERROR_INVALID;
44
45
46 namespace { // hierarchy of test dummy objects
47
48 struct Interface
49 {
50 virtual ~Interface() {};
51 virtual operator string () =0;
52 };
53
54
55
56 enum theID
57 { ONE = 1
58 , TWO
59 , THR
60 , FOU
61 };
62
63
64
65 template<theID ii>
67 : public Interface
68 {
70
71 operator string()
72 {
73 return instanceID_ + lexical_cast<string> (ii);
74 }
75
76 public:
77 Implementation(string id = "Impl-")
78 : instanceID_(id)
79 { }
80 };
81
82
83
84 template<typename X>
85 string
86 buildSome (X rawVal)
87 {
88 return lexical_cast<string> (rawVal);
89 }
90
91 string
93 {
94 return buildSome(ONE);
95 }
96 }
97
98
99
100
101
102 /******************************************************************************/
114 class MultiFact_test : public Test
115 {
116 virtual void
124
125 string
126 callMe (string val)
127 {
128 ++invocations_;
129 return val;
130 }
132
133
134 void
136 {
137 using TestFactory = factory::MultiFact<string, theID>;
138
139 TestFactory theFact;
140
141 // the first "production line" is wired to a free function
142 theFact.defineProduction (ONE, buildOne);
143
144 // second "production line" uses a explicit partial closure
145 theFact.defineProduction (TWO, bind (buildSome<theID>, TWO));
146
147 // for the third "production line" we set up a function object
148 auto memberFunction = bind (&MultiFact_test::callMe, this, "lalü");
149 theFact.defineProduction (THR, memberFunction);
150
151 // and the fourth "production line" uses a lambda, closed with a local reference
152 string backdoor("backdoor");
153 theFact.defineProduction (FOU, [&] {
154 return backdoor;
155 });
156
157 CHECK (!isnil (theFact));
158 CHECK (theFact(ONE) == "1");
159 CHECK (theFact(TWO) == "2");
160
161 CHECK (theFact(THR) == "lalü");
162 CHECK (invocations_ == 1);
163
164 CHECK (theFact(FOU) == "backdoor");
165 backdoor = "I am " + backdoor.substr(0,4);
166 CHECK (theFact(FOU) == "I am back");
167
168
169 TestFactory anotherFact;
170 CHECK (isnil (anotherFact));
171 VERIFY_ERROR (INVALID, anotherFact(ONE) );
172
173 anotherFact.defineProduction (ONE, memberFunction);
174 CHECK (anotherFact(ONE) == "lalü");
175 CHECK (invocations_ == 2);
176
177 CHECK (theFact(THR) == "lalü");
178 CHECK (invocations_ == 3);
179
180
181 CHECK ( theFact.contains (FOU));
182 CHECK (!anotherFact.contains (FOU));
183
184 anotherFact = theFact;
185 CHECK (anotherFact.contains (FOU));
186 CHECK (!isSameObject(theFact, anotherFact));
187
188 CHECK (anotherFact(ONE) == "1");
189 CHECK (anotherFact(TWO) == "2");
190 CHECK (anotherFact(THR) == "lalü");
191 CHECK (anotherFact(FOU) == "I am back");
192 CHECK (invocations_ == 4);
193 }
194
195
196 void
198 {
200 using PIfa = shared_ptr<Interface>;
201
202 TestFactory theFact;
203
204 // set up the "production lines" by lambda
205 theFact.defineProduction (ONE, [] { return new Implementation<ONE>; });
206 theFact.defineProduction (TWO, [] { return new Implementation<TWO>; });
207 theFact.defineProduction (THR, [] { return new Implementation<THR>; });
208 theFact.defineProduction (FOU, [] { return new Implementation<FOU>; });
209 CHECK (!isnil (theFact));
210
211 PIfa p1 = theFact(ONE);
212 PIfa p2 = theFact(TWO);
213 PIfa p3 = theFact(THR);
214 PIfa p4 = theFact(FOU);
215
216 PIfa p11 = theFact(ONE);
217
218 CHECK ("Impl-1" == string(*p1));
219 CHECK ("Impl-2" == string(*p2));
220 CHECK ("Impl-3" == string(*p3));
221 CHECK ("Impl-4" == string(*p4));
222
223 CHECK ("Impl-1" == string(*p11));
224 CHECK (!isSameObject(*p1, *p11));
225
226 PIfa p12(p11);
227 CHECK (isSameObject(*p11, *p12));
228 CHECK ("Impl-1" == string(*p12));
229 CHECK (1 == p1.use_count());
230 CHECK (2 == p11.use_count());
231 CHECK (2 == p12.use_count());
232 }
233
234
235 void
237 {
238 using TestFactory = factory::MultiFact<Interface*(string), theID>;
239
240 TestFactory theFact;
241
242 // set up the "production lines"
243 theFact.defineProduction (ONE, [](string ) { return new Implementation<ONE>; });
244 theFact.defineProduction (TWO, [](string ) { return new Implementation<TWO>("X"); });
245 theFact.defineProduction (THR, [](string id) { return new Implementation<THR>(id); });
246 theFact.defineProduction (FOU, [](string id) { return new Implementation<FOU>("Z"+id);});
247
248 Interface *p1 = theFact(ONE, "irrelevant"),
249 *p2 = theFact(TWO, "ignored"),
250 *p3 = theFact(THR, "idiocy"),
251 *p4 = theFact(FOU, "omg"),
252 *p5 = theFact(FOU, "z");
253
254 // does not compile...
255 // theFact(ONE);
256 // theFact(ONE, "foo", bar);
257
258 CHECK ("Impl-1" == string(*p1));
259 CHECK ("X2" == string(*p2));
260 CHECK ("idiocy3"== string(*p3));
261 CHECK ("Zomg4" == string(*p4));
262 CHECK ("Zz4" == string(*p5));
263
264 CHECK (!isSameObject(*p4, *p5));
265 CHECK (INSTANCEOF(Implementation<ONE>, p1));
266 CHECK (INSTANCEOF(Implementation<TWO>, p2));
267 CHECK (INSTANCEOF(Implementation<THR>, p3));
268 CHECK (INSTANCEOF(Implementation<FOU>, p4));
269 CHECK (INSTANCEOF(Implementation<FOU>, p5));
270
271 delete p1;
272 delete p2;
273 delete p3;
274 delete p4;
275 delete p5;
276 }
277
278
279 void
281 {
282 using TestFactory = factory::MultiFact<int(int), theID, factory::Build<long>::Wrapper>;
283
284 TestFactory theFact;
285
286 // Setup(1): each "production line" does a distinct calculation
287 theFact.defineProduction (ONE, [](int par) { return par; });
288 theFact.defineProduction (TWO, [](int par) { return 2 * par; });
289 theFact.defineProduction (THR, [](int par) { return par*par; });
290 theFact.defineProduction (FOU, [](int par) { return 1 << par;});
291
292 // Setup(2): and a common "wrapper functor" finishes
293 // the output of the chosen "production line"
294 theFact.defineFinalWrapper([](int raw) { return raw + 1; });
295
296 CHECK (long(1 + 1) == theFact(ONE, 1));
297 CHECK (long(1 + 2) == theFact(ONE, 2));
298 CHECK (long(1 + 3) == theFact(ONE, 3));
299
300 CHECK (long(1 + 2) == theFact(TWO, 1));
301 CHECK (long(1 + 4) == theFact(TWO, 2));
302 CHECK (long(1 + 6) == theFact(TWO, 3));
303
304 CHECK (long(1 + 1) == theFact(THR, 1));
305 CHECK (long(1 + 4) == theFact(THR, 2));
306 CHECK (long(1 + 9) == theFact(THR, 3));
307
308 CHECK (long(1 + 2) == theFact(FOU, 1));
309 CHECK (long(1 + 4) == theFact(FOU, 2));
310 CHECK (long(1 + 8) == theFact(FOU, 3));
311 }
312 };
313
314
316 LAUNCHER (MultiFact_test, "unit common");
317
318
319
320}} // namespace lib::test
Factory for creating a family of objects by ID.
void defineProduction(ID id, FUNC &&fun)
to set up a production line, associated with a specific ID
bool contains(ID id) const
Target object to be instantiated as Singleton Allocates a variable amount of additional heap memory a...
unsigned int uint
Definition integral.hpp:29
Framework for building a configurable factory, to generate families of related objects.
Implementation namespace for support and library code.
Test runner and basic definitions for tests.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Definition util.hpp:421
bool isnil(lib::time::Duration const &dur)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition util.hpp:514