ServiceUtil_test.cc
Go to the documentation of this file.
1 /**
2  * @file ServiceUtil_test.cc
3  * @brief Tests the utilities in ServiceUtil.h
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date April 28, 2016
6  * @see ServiceUtil.h
7  *
8  * This test takes no command line argument.
9  *
10  */
11 
12 /*
13  * Boost Magic: define the name of the module;
14  * and do that before the inclusion of Boost unit test headers
15  * because it will change what they provide.
16  * Among the those, there is a main() function and some wrapping catching
17  * unhandled exceptions and considering them test failures, and probably more.
18  */
19 #define BOOST_TEST_MODULE ( ServiceUtil_test )
20 
21 // LArSoft libraries
24 
25 // art libraries
28 
29 // Boost libraries
30 #include <boost/test/unit_test.hpp>
31 
32 //------------------------------------------------------------------------------
33 //
34 // here are some services: three of them, all different classes.
35 //
36 struct MyProvider: protected lar::UncopiableAndUnmovableClass {};
37 
39 
41 
42 template <typename Provider>
44  Provider* prov = nullptr;
45 
46  public:
47  MyServiceTemplate(Provider* ptr = nullptr): prov(ptr) {}
48 
49  using provider_type = Provider;
50 
51  provider_type const* provider() const { return prov; }
52 
53 }; // MyServiceTemplate
54 
58 
59 
60 namespace lar {
61  namespace details {
62 
63  template struct ServiceProviderRequirementsChecker<MyProvider>;
64 
65  template struct ServiceRequirementsChecker<MyService>;
66 
67  } // namespace details
68 } // namespace lar
69 
70 
71 //
72 // And this is art. Well, kind of.
73 //
74 // We are actually hijacking `art::ServiceHandle` for a few specific classes.
75 //
76 struct GlobalServicesClass {
77  std::unique_ptr<MyService> myServicePtr;
78  std::unique_ptr<MyOtherService> myOtherServicePtr;
79  std::unique_ptr<YetAnotherService> yetAnotherServicePtr;
80 }; // GlobalServicesClass
82 
83 
84 template <typename Service>
86  public:
87  Service* operator->() const { return instance; }
88  Service& operator*() const { return *instance; }
89  protected:
90  Service* instance = nullptr;
91 }; // ServiceHandleBase<>
92 
93 
94 namespace art {
95 
96  namespace detail {
97  template <>
98  struct ServiceHelper<MyService> {
99  static constexpr art::ServiceScope scope_val
101  };
102  template <>
104  static constexpr art::ServiceScope scope_val
106  };
107  template <>
109  static constexpr art::ServiceScope scope_val
111  };
112 
113  } // namespace detail
114 
115 
116  template <>
119  { ServiceHandle() { instance = GlobalServices.myServicePtr.get(); } };
120 
121  template <>
124  {};
125 
126  template <>
129  { ServiceHandle() { instance = GlobalServices.myOtherServicePtr.get(); } };
130 
131  template <>
134  {};
135 
136  template <>
139  { ServiceHandle() { instance = GlobalServices.yetAnotherServicePtr.get(); } };
140 
141  template <>
144  {};
145 
146 } // namespace art
147 
148 
149 
150 
151 
152 BOOST_AUTO_TEST_CASE(providerFromTest) {
153 
154  // on the first try, there is no service provider.
155 
156  GlobalServices.myServicePtr = std::make_unique<MyService>();
157  BOOST_CHECK_EXCEPTION(lar::providerFrom<MyService>(), art::Exception,
158  [](art::Exception const& e)
159  { return e.categoryCode() == art::errors::NotFound; }
160  );
161 
162  // now let's create a "real" provider
163  MyProvider prov;
164  GlobalServices.myServicePtr = std::make_unique<MyService>(&prov);
165  BOOST_TEST(lar::providerFrom<MyService>() == &prov);
166 
167  // that's enough; let's clean up
168  GlobalServices.myServicePtr.reset();
169 
170 } // BOOST_AUTO_TEST_CASE(providerFromTest)
171 
172 
173 
174 BOOST_AUTO_TEST_CASE(providersFromTest) {
175 
176  // on the first try, there is no "other" service provider.
177 
178  MyProvider prov;
179  GlobalServices.myServicePtr = std::make_unique<MyService>(&prov);
180  GlobalServices.myOtherServicePtr = std::make_unique<MyOtherService>();
181  GlobalServices.yetAnotherServicePtr = std::make_unique<YetAnotherService>();
182 
183  auto provPack1 = lar::providersFrom<MyService>();
184  BOOST_TEST(provPack1.get<MyProvider>() == &prov);
185  BOOST_CHECK_EXCEPTION(lar::providersFrom<MyOtherService>(), art::Exception,
186  [](art::Exception const& e)
187  { return e.categoryCode() == art::errors::NotFound; }
188  );
189  BOOST_CHECK_EXCEPTION(
190  (lar::providersFrom<MyService, MyOtherService>()), art::Exception,
191  [](art::Exception const& e)
192  { return e.categoryCode() == art::errors::NotFound; }
193  );
194 
195  // now let's create a "real" provider
196  MyOtherProvider oprov;
197  YetAnotherProvider yaprov;
198  GlobalServices.myOtherServicePtr = std::make_unique<MyOtherService>(&oprov);
199  GlobalServices.yetAnotherServicePtr
200  = std::make_unique<YetAnotherService>(&yaprov);
201 
202  auto provPack
203  = lar::providersFrom<MyService, MyOtherService, YetAnotherService>();
204 
205  BOOST_TEST((provPack == lar::makeProviderPack(&prov, &oprov, &yaprov)));
206  BOOST_TEST(lar::providerFrom<MyService>() == &prov);
207  BOOST_TEST(lar::providerFrom<MyOtherService>() == &oprov);
208  BOOST_TEST(lar::providerFrom<YetAnotherService>() == &yaprov);
209 
210 
211  // that's enough; let's clean up
212  GlobalServices.myServicePtr.reset();
213 
214 } // BOOST_AUTO_TEST_CASE(providersFromTest)
215 
216 
217 
218 //------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(providerFromTest)
An empty class that can&#39;t be copied nor moved.
ServiceScope
Definition: ServiceScope.h:7
std::unique_ptr< MyService > myServicePtr
Defines classes that can&#39;t be copied nor moved.
const std::string instance
std::unique_ptr< MyOtherService > myOtherServicePtr
std::unique_ptr< YetAnotherService > yetAnotherServicePtr
provider_type const * provider() const
const double e
Service & operator*() const
MyServiceTemplate(Provider *ptr=nullptr)
ProviderPack< Providers... > makeProviderPack(Providers const *...providers)
Function to create a ProviderPack from the function arguments.
Definition: ProviderPack.h:272
GlobalServicesClass GlobalServices
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
LArSoft-specific namespace.
Service * operator->() const