Lumiera  0.pre.03
»edit your freedom«
dependency-factory-test.cpp
Go to the documentation of this file.
1 /*
2  DependencyFactory(Test) - verify modes of creating singletons and dependencies
3 
4  Copyright (C)
5  2013, 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-obj.hpp"
25 #include "lib/util.hpp"
26 
27 #include "lib/depend.hpp"
28 #include "lib/depend-inject.hpp"
29 #include "test-target-obj.hpp"
30 
31 
32 
33 namespace lib {
34 namespace test{
35 
36  using ::Test;
37  using util::isSameObject;
38 
39  namespace {
40 
41  const uint MAX_ID = 1000;
42 
43  struct Sub
45  {
46  static uint created;
47  uint instanceID_;
48 
49  Sub()
50  : TestTargetObj(created++)
51  ,instanceID_(rani(MAX_ID))
52  { }
53 
54  virtual operator string() const
55  {
56  return util::typeStr(this)
57  + TestTargetObj::operator string();
58  }
59  };
60  uint Sub::created = 0;
61 
62 
63  struct SubSub
64  : Sub
65  { };
66 
67  struct SubSubSub
68  : SubSub
69  { };
70 
71  struct SubSubDub
72  : SubSub
73  { };
74  }
75 
76 
77 
78 
79 
80  /***************************************************************************/
91  class DependencyFactory_test : public Test
92  {
93 
94 
95  virtual void
96  run (Arg)
97  {
98  seedRand();
99  verify_defaultSingletonCreation();
100  verify_SubclassCreation();
101  verify_FactoryDefinition_is_sticky();
102  verify_customFactory();
103  verify_automaticReplacement();
104  }
105 
106 
107  void
108  verify_defaultSingletonCreation()
109  {
110  Depend<Sub> accessor1;
111  Depend<Sub> accessor2;
112 
113  Sub & o1 = accessor1();
114  Sub & o2 = accessor2();
115  CHECK (isSameObject (o1, o2));
116  }
117 
118 
119  void
120  verify_SubclassCreation()
121  {
122  Depend<SubSub> specialAccessor;
123  Depend<Sub> genericAccessor;
124 
125  // configure singleton subclass (prior to first use)
127 
128  SubSub& oSub = specialAccessor();
129  Sub& o = genericAccessor();
130 
131  CHECK (!isSameObject (oSub, o));
132  CHECK ( INSTANCEOF (SubSubSub, &oSub));
133  CHECK (!INSTANCEOF (SubSubSub, &o));
134  }
135 
136 
137  void
138  verify_FactoryDefinition_is_sticky()
139  {
140  Depend<SubSub> otherSpecialAccessor;
141 
142  SubSub& oSub = otherSpecialAccessor();
143  CHECK ( INSTANCEOF (SubSubSub, &oSub));
144 
145  Depend<SubSubSub> yetAnotherSpecialAccessor;
146 
147  SubSub& yetAnotherInstance = yetAnotherSpecialAccessor();
148  CHECK ( INSTANCEOF (SubSubSub, &yetAnotherInstance));
149 
150  // both refer to the same configuration and thus access the singleton
151  CHECK (isSameObject (oSub, yetAnotherInstance));
152  }
153 
154 
155  void
156  verify_customFactory()
157  {
158  DependInject<SubSubDub>::useSingleton (customFactoryFunction);
159 
160  Depend<SubSubDub> customised;
161 
162  CHECK ( INSTANCEOF (SubSubDub, &customised()));
163  CHECK (MAX_ID + 10 == customised().instanceID_);
164  }
165 
166  static SubSubDub*
167  customFactoryFunction (void)
168  {
169  SubSubDub* specialInstance = new SubSubDub;
170  specialInstance->instanceID_ = MAX_ID + 10;
171  return specialInstance;
172  }
173 
174 
175 
176  void
177  verify_automaticReplacement()
178  {
179  Depend<Sub> genericAccessor;
180  Sub& original = genericAccessor();
181  uint oID = original.instanceID_;
182 
183  {
184  DependInject<Sub>::Local<SubSubSub> mockObject;
185 
186  Sub& replacement = genericAccessor();
187  CHECK ( isSameObject (replacement, *mockObject));
188  CHECK (!isSameObject (original, replacement));
189 
190  Depend<SubSub> special;
191  Depend<SubSubSub> custom;
192 
193  CHECK(!isSameObject (replacement, special() ));
194  CHECK(!isSameObject (replacement, custom() ));
195  }
196 
197  Sub& nextFetch = genericAccessor();
198  CHECK (isSameObject (original, nextFetch));
199  CHECK (oID == nextFetch.instanceID_);
200 
201  {
202  DependInject<Sub>::Local<SubSub> otherMock;
203 
204  Sub& replacement = genericAccessor();
205  uint repID = replacement.instanceID_;
206 
207  CHECK (!INSTANCEOF (SubSub, &original));
208  CHECK ( INSTANCEOF (SubSub, &replacement));
209  CHECK (!INSTANCEOF (SubSubSub, &replacement));
210  CHECK (!isSameObject (original, replacement));
211 
212  Depend<Sub> anotherAccessor;
213  Sub& otherAccess = anotherAccessor();
214  CHECK (isSameObject (replacement, otherAccess));
215  CHECK (repID == otherAccess.instanceID_);
216  CHECK (repID == replacement.instanceID_);
217  CHECK ( oID == original.instanceID_);
218 
219  // verify the instrumentation indeed targeted the generic accessor,
220  // and *not* an accessor of the sub type, i.e Depend<SubSub>
221  Depend<SubSub> genericSubTypeAccessor;
222  SubSub& subTypeAccess = genericSubTypeAccessor();
223  CHECK ( INSTANCEOF (SubSub, &subTypeAccess));
224  CHECK (!isSameObject (replacement, subTypeAccess));
225  CHECK (!isSameObject (original, subTypeAccess));
226  CHECK (repID != subTypeAccess.instanceID_);
227  CHECK ( oID != subTypeAccess.instanceID_);
228  }
229 
230  CHECK (isSameObject (original, genericAccessor()));
231  CHECK (oID == genericAccessor().instanceID_);
232  }
233  };
234 
235 
236 
237  LAUNCHER (DependencyFactory_test, "unit common");
238 
239 
240 }} // namespace lib::test
Dummy target object to be created by factory for unit tests Used to verify sane memory management and...
Definition: run.hpp:40
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:514
Per type specific configuration of instances created as service dependencies.
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
static void useSingleton()
configure dependency-injection for type SRV to build a subclass singleton.
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:280
Implementation namespace for support and library code.
Target object to be created by Test-Factories or as Singleton.
This framework allows to (re)configure the lib::Depend front-end for dependency-injection.
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Singleton services and Dependency Injection.
Simple functions to represent objects, for debugging and diagnostics.
Configuration handle for temporarily shadowing a dependency by a test mock instance.
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