Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
dependency-configuration-test.cpp
Go to the documentation of this file.
1/*
2 DependencyConfiguration(Test) - verify configuration for injecting dependencies
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
23#include "lib/test/run.hpp"
24#include "lib/format-cout.hpp"
26#include "lib/util.hpp"
27
28#include "lib/depend.hpp"
29#include "lib/depend-inject.hpp"
30
31
32
33namespace lib {
34namespace test{
35
36 using ::Test;
38
39 namespace {
40
41 struct Dum
43 {
44 virtual ~Dum() { }
45 virtual int probe() =0;
46 };
47
48
49 int checksum = 0;
50
51 template<int N>
52 struct Dummy
53 : Dum
54 {
55 Dummy() { checksum += N; }
56 ~Dummy() { checksum -= N; }
57
58 virtual int
59 probe() override
60 {
61 return N * checksum;
62 }
63 };
64 }
65
66 using LERR_(LIFECYCLE);
67 using LERR_(FATAL);
68
69
70
71
72
73 /***************************************************************************/
89 : public Test
90 {
91
92
93 virtual void
94 run (Arg)
95 {
96 checksum = 0;
97
103
104 CHECK (9+7+5+1 == checksum); // singletons stay alive until application shutdown
105 }
106
107
109 void
111 {
112 Depend<Dummy<1>> dep11;
113 Depend<Dummy<5>> dep5;
114 Depend<Dummy<1>> dep12;
115
116 CHECK (1 == sizeof(dep11));
117 CHECK (1 == sizeof(dep12));
118 CHECK (1 == sizeof(dep5));
119
120 // no singleton instance created yet
121 CHECK ( 0 == checksum );
122
123 CHECK ( 1*1 == dep11().probe() );
124 CHECK ( 1 == checksum );
125 CHECK ((1+5)*5 == dep5().probe() );
126 CHECK ((1+5) == checksum );
127 CHECK ((1+5)*1 == dep12().probe() );
128 CHECK ((1+5) == checksum );
129
130 CHECK (not isSameObject (dep11, dep12));
131 CHECK ( isSameObject (dep11(), dep12()));
132 }
133
134
136 void
138 {
139 // unable to create singleton instance of abstract baseclass
140 VERIFY_ERROR (FATAL, Depend<Dum>{}() );
141
142 CHECK ((1+5) == checksum );
143
144 Depend<Dum> dumm;
146 CHECK ((1+5) == checksum );
147
148 CHECK ((1+5+7)*7 == dumm().probe() );
149 CHECK ((1+5+7) == checksum );
150
152 CHECK ((1+5+7)*7 == Depend<Dum>{}().probe() );
153 CHECK ((1+5+7)*7 == dumm().probe() );
154 CHECK ((1+5+7) == checksum );
155 }
156
157
159 void
161 {
162 CHECK ((1+5+7) == checksum );
163
164 struct SubDummy
165 : Dummy<3>
166 {
167 virtual int
168 probe() override
169 {
170 return offset - checksum;
171 }
172
173 int offset = 0;
174 };
175
176 Depend<Dummy<3>> dep3;
177 CHECK ((1+5+7) == checksum );
178 {
179 DependInject<Dummy<3>>::ServiceInstance<SubDummy> service{};
180 CHECK (service);
181 CHECK ((1+5+7+3) == checksum );
182 CHECK (-(1+5+7+3) == dep3().probe() );
183 CHECK ((1+5+7+3) == checksum );
184 service->offset = (1+5+7);
185 CHECK ( -3 == dep3().probe() );
186 CHECK ((1+5+7+3) == checksum );
187 }
188 CHECK ((1+5+7) == checksum );
189 VERIFY_ERROR (LIFECYCLE, dep3().probe() );
191 CHECK ((1+5+7) == checksum );
192 }
193
194
195
197 void
199 {
200 Depend<Dum> dumm;
201 Depend<Dummy<3>> depp;
202 CHECK ((1+5+7) == checksum );
203 CHECK ((1+5+7)*7 == dumm().probe() );
204 VERIFY_ERROR (LIFECYCLE, depp().probe() );
205
206 struct Mock
207 : Dummy<3>
208 {
209 virtual int
210 probe() override
211 {
212 return response;
213 }
214
215 int response = -1;
216 };
217
218 {
219 DependInject<Dum>::Local<Mock> mockDumm;
220 DependInject<Dummy<3>>::Local<Mock> mockDummy3;
221 CHECK ((1+5+7) == checksum );
222
223 CHECK (!mockDumm);
224 CHECK (!mockDummy3);
225 CHECK (-1 == dumm().probe() ); // NOTE: now returning the response from the mock instance
226 CHECK ( mockDumm);
227 CHECK (!mockDummy3);
228 CHECK ((1+5+7+3) == checksum );
229 CHECK (-1 == mockDumm->probe() );
230 CHECK ((1+5+7+3) == checksum );
231
232 mockDumm->response = 11;
233 CHECK (11 == dumm().probe() ); // NOTE: now returning the response changed on the mock instance
234
235 CHECK (!mockDummy3); // the second mock is still in not yet created state...
236 CHECK ((1+5+7+3) == checksum );
237 CHECK (-1 == depp().probe() );
238 CHECK ((1+5+7+3+3) == checksum ); // ...and now we got a second mock instance!
239 CHECK ( mockDummy3);
240 CHECK (-1 == mockDummy3->probe() );
241 CHECK ((1+5+7+3+3) == checksum );
242 mockDummy3->response = 22;
243 CHECK (22 == depp().probe() );
244 mockDumm->response = 12;
245 CHECK (22 == depp().probe() ); // these are really two distinct instances
246 CHECK (12 == dumm().probe() );
247 CHECK ((1+5+7+3+3) == checksum );
248 }
249
250 // Back to normal: the Mocks are gone, original behaviour uncovered
251 CHECK ((1+5+7) == checksum );
252 CHECK ((1+5+7)*7 == dumm().probe() );
253 VERIFY_ERROR (LIFECYCLE, depp().probe() );
254 CHECK ((1+5+7) == checksum );
255
256 {
257 DependInject<Dummy<3>>::ServiceInstance<Mock> service{};
258 CHECK ((1+5+7+3) == checksum ); // NOTE: we got a new Dummy<3> service instance
259 CHECK (-1 == depp().probe() ); // ..... which returns the pristine mock response
260 service->response = 33;
261 CHECK (33 == depp().probe() );
262 CHECK ((1+5+7+3) == checksum );
263
264 {
265 DependInject<Dummy<3>>::Local<Mock> mockDummy31;
266 CHECK (!mockDummy31);
267 CHECK ((1+5+7+3) == checksum ); // ...while SerivceInstance is created eagerly
268 CHECK (-1 == depp().probe() ); // the Local mock instance is only created on-demand
269 CHECK ((1+5+7+3+3) == checksum );
270 mockDummy31->response = 44;
271 CHECK (44 == depp().probe() );
272 CHECK (44 == mockDummy31->probe() );
273 CHECK (33 == service->probe() );
274 CHECK (mockDummy31->response != service->response);
275 service->response = 34;
276 CHECK (44 == depp().probe() ); // NOTE: remains shadowed by the mockDummy
277 CHECK (44 == mockDummy31->probe() );
278 CHECK (34 == service->probe() );
279 CHECK ((1+5+7+3+3) == checksum );
280 }
281
282 // Now the mock is gone and the service instance becomes uncovered
283 CHECK ((1+5+7+3) == checksum );
284 CHECK (34 == depp().probe() ); // now reveals the response changed from within the nested test scope
285 CHECK ((1+5+7+3) == checksum );
286 }
287
288 // Back to normal: Mocks is gone, Service is shutdown, original behaviour uncovered
289 CHECK ((1+5+7) == checksum );
290 VERIFY_ERROR (LIFECYCLE, depp().probe() );
291 CHECK ((1+5+7)*7 == dumm().probe() );
292 CHECK ((1+5+7) == checksum );
293 }
294
295
296
306 void
308 {
309 CHECK ((1+5+7) == checksum );
310
311 struct Veryspecial
312 : Dummy<9>
313 {
314 Veryspecial(int& ref)
315 : magic_{ref}
316 { }
317
318 int& magic_;
319
320 virtual int
321 probe() override
322 {
323 return magic_++;
324 }
325 };
326
327 // NOTE: the following is rejected due to missing default ctor
328 DependInject<Dummy<9>>::useSingleton<Veryspecial>();
329 VERIFY_ERROR (FATAL, Depend<Dummy<9>>{}() );
330
331
332 int backdoor = 22;
333
334 DependInject<Dummy<9>>::useSingleton ([&]{ return new Veryspecial{backdoor}; });
335
336 CHECK ((1+5+7) == checksum );
337 CHECK ( 22 == backdoor );
338
339 Depend<Dummy<9>> tricky;
340 CHECK ((1+5+7) == checksum );
341 CHECK (22 == backdoor );
342
343 CHECK (22 == tricky().probe());
344 CHECK (23 == backdoor );
345 CHECK ((1+5+7+9) == checksum ); // Veryspecial Dummy<9> subclass was created on the heap
346 // and will continue to live there until the testsuite terminates
347 backdoor = 41;
348 CHECK (41 == tricky().probe());
349 CHECK (42 == backdoor );
350
351
352 Depend<Dum> dumm;
353 CHECK ((1+5+7+9)*7 == dumm().probe() );
354
355 {
356
358// // since Veryspecial has no default ctor...
359// //
360// DependInject<Dum>::Local<Dum> impossible;
361
362 DependInject<Dum>::Local<Dum> insidious ([&]{ return new Veryspecial{backdoor}; });
363
364 CHECK ((1+5+7+9) == checksum );
365 CHECK (not insidious);
366
367 CHECK (42 == dumm().probe() );
368 CHECK (43 == backdoor );
369 CHECK ((1+5+7+9+9) == checksum );
370
371 CHECK (isSameObject (dumm(), *insidious));
372
373 CHECK (43 == tricky().probe());
374 CHECK (44 == backdoor );
375
376 backdoor = -1;
377 CHECK (-1 == dumm().probe() );
378 CHECK ( 0 == backdoor );
379
380 CHECK ((1+5+7+9+9) == checksum );
381 }
382
383 CHECK ((1+5+7+9) == checksum );
384 CHECK ((1+5+7+9)*7 == dumm().probe() );
385 CHECK ( 0 == tricky().probe());
386 CHECK (+1 == backdoor );
387 } // NOTE: Veryspecial holds a dangling reference into stack memory from now on!
388 };
389
390
391
393
394
395}} // namespace lib::test
Configuration handle for temporarily shadowing a dependency by a test mock instance.
This framework allows to (re)configure the lib::Depend front-end for dependency-injection.
Access point to singletons and other kinds of dependencies designated by type.
Definition depend.hpp:281
A Dummy object for tests.
static long & checksum()
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Per type specific configuration of instances created as service dependencies.
Singleton services and Dependency Injection.
#define LERR_(_NAME_)
Definition error.hpp:45
Automatically use custom string conversion in C++ stream output.
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
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...