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) Lumiera.org
5  2013, 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 
32 #include "lib/test/run.hpp"
33 #include "lib/format-obj.hpp"
34 #include "lib/util.hpp"
35 
36 #include "lib/depend.hpp"
37 #include "lib/depend-inject.hpp"
38 #include "test-target-obj.hpp"
39 
40 #include <cstdlib>
41 
42 
43 
44 namespace lib {
45 namespace test{
46 
47  using ::Test;
48  using util::isSameObject;
49 
50  namespace {
51 
52  const uint MAX_ID = 1000;
53 
54  struct Sub
56  {
57  static uint created;
58  uint instanceID_;
59 
60  Sub()
61  : TestTargetObj(created++)
62  ,instanceID_(rand() % MAX_ID)
63  { }
64 
65  virtual operator string() const
66  {
67  return util::typeStr(this)
68  + TestTargetObj::operator string();
69  }
70  };
71  uint Sub::created = 0;
72 
73 
74  struct SubSub
75  : Sub
76  { };
77 
78  struct SubSubSub
79  : SubSub
80  { };
81 
82  struct SubSubDub
83  : SubSub
84  { };
85  }
86 
87 
88 
89 
90 
91  /***************************************************************************/
102  class DependencyFactory_test : public Test
103  {
104 
105 
106  virtual void
107  run (Arg)
108  {
109  verify_defaultSingletonCreation();
110  verify_SubclassCreation();
111  verify_FactoryDefinition_is_sticky();
112  verify_customFactory();
113  verify_automaticReplacement();
114  }
115 
116 
117  void
118  verify_defaultSingletonCreation()
119  {
120  Depend<Sub> accessor1;
121  Depend<Sub> accessor2;
122 
123  Sub & o1 = accessor1();
124  Sub & o2 = accessor2();
125  CHECK (isSameObject (o1, o2));
126  }
127 
128 
129  void
130  verify_SubclassCreation()
131  {
132  Depend<SubSub> specialAccessor;
133  Depend<Sub> genericAccessor;
134 
135  // configure singleton subclass (prior to first use)
137 
138  SubSub& oSub = specialAccessor();
139  Sub& o = genericAccessor();
140 
141  CHECK (!isSameObject (oSub, o));
142  CHECK ( INSTANCEOF (SubSubSub, &oSub));
143  CHECK (!INSTANCEOF (SubSubSub, &o));
144  }
145 
146 
147  void
148  verify_FactoryDefinition_is_sticky()
149  {
150  Depend<SubSub> otherSpecialAccessor;
151 
152  SubSub& oSub = otherSpecialAccessor();
153  CHECK ( INSTANCEOF (SubSubSub, &oSub));
154 
155  Depend<SubSubSub> yetAnotherSpecialAccessor;
156 
157  SubSub& yetAnotherInstance = yetAnotherSpecialAccessor();
158  CHECK ( INSTANCEOF (SubSubSub, &yetAnotherInstance));
159 
160  // both refer to the same configuration and thus access the singleton
161  CHECK (isSameObject (oSub, yetAnotherInstance));
162  }
163 
164 
165  void
166  verify_customFactory()
167  {
168  DependInject<SubSubDub>::useSingleton (customFactoryFunction);
169 
170  Depend<SubSubDub> customised;
171 
172  CHECK ( INSTANCEOF (SubSubDub, &customised()));
173  CHECK (MAX_ID + 10 == customised().instanceID_);
174  }
175 
176  static SubSubDub*
177  customFactoryFunction (void)
178  {
179  SubSubDub* specialInstance = new SubSubDub;
180  specialInstance->instanceID_ = MAX_ID + 10;
181  return specialInstance;
182  }
183 
184 
185 
186  void
187  verify_automaticReplacement()
188  {
189  Depend<Sub> genericAccessor;
190  Sub& original = genericAccessor();
191  uint oID = original.instanceID_;
192 
193  {
194  DependInject<Sub>::Local<SubSubSub> mockObject;
195 
196  Sub& replacement = genericAccessor();
197  CHECK ( isSameObject (replacement, *mockObject));
198  CHECK (!isSameObject (original, replacement));
199 
200  Depend<SubSub> special;
201  Depend<SubSubSub> custom;
202 
203  CHECK(!isSameObject (replacement, special() ));
204  CHECK(!isSameObject (replacement, custom() ));
205  }
206 
207  Sub& nextFetch = genericAccessor();
208  CHECK (isSameObject (original, nextFetch));
209  CHECK (oID == nextFetch.instanceID_);
210 
211  {
212  DependInject<Sub>::Local<SubSub> otherMock;
213 
214  Sub& replacement = genericAccessor();
215  uint repID = replacement.instanceID_;
216 
217  CHECK (!INSTANCEOF (SubSub, &original));
218  CHECK ( INSTANCEOF (SubSub, &replacement));
219  CHECK (!INSTANCEOF (SubSubSub, &replacement));
220  CHECK (!isSameObject (original, replacement));
221 
222  Depend<Sub> anotherAccessor;
223  Sub& otherAccess = anotherAccessor();
224  CHECK (isSameObject (replacement, otherAccess));
225  CHECK (repID == otherAccess.instanceID_);
226  CHECK (repID == replacement.instanceID_);
227  CHECK ( oID == original.instanceID_);
228 
229  // verify the instrumentation indeed targeted the generic accessor,
230  // and *not* an accessor of the sub type, i.e Depend<SubSub>
231  Depend<SubSub> genericSubTypeAccessor;
232  SubSub& subTypeAccess = genericSubTypeAccessor();
233  CHECK ( INSTANCEOF (SubSub, &subTypeAccess));
234  CHECK (!isSameObject (replacement, subTypeAccess));
235  CHECK (!isSameObject (original, subTypeAccess));
236  CHECK (repID != subTypeAccess.instanceID_);
237  CHECK ( oID != subTypeAccess.instanceID_);
238  }
239 
240  CHECK (isSameObject (original, genericAccessor()));
241  CHECK (oID == genericAccessor().instanceID_);
242  }
243  };
244 
245 
246 
247  LAUNCHER (DependencyFactory_test, "unit common");
248 
249 
250 }} // namespace lib::test
Dummy target object to be created by factory for unit tests Used to verify sane memory management and...
Definition: run.hpp:49
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:492
Per type specific configuration of instances created as service dependencies.
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:289
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.
Simple 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, bypassing any custom comparison operators.
Definition: util.hpp:372