Arcane  v3.15.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
TestDependencyInjection.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7
8#include <gtest/gtest.h>
9
10#include "arcane/utils/internal/DependencyInjection.h"
11#include "arcane/utils/FatalErrorException.h"
12
13#include "arcane/utils/ITraceMng.h"
14
15/*---------------------------------------------------------------------------*/
16/*---------------------------------------------------------------------------*/
17
18using namespace Arcane;
19
20namespace DI_Test
21{
22using namespace Arcane::DependencyInjection;
23
24class IA
25{
26 public:
27 virtual ~IA() = default;
28 virtual int value() const = 0;
29};
30
31class IB
32{
33 public:
34 virtual ~IB() = default;
35 virtual int value() const = 0;
36};
37
38class IA2
39{
40 public:
41 virtual ~IA2() = default;
42 virtual int value() const = 0;
43 virtual IB* bValue() const = 0;
44};
45
46class IB2
47{
48 public:
49 virtual ~IB2() = default;
50 virtual int value() const = 0;
51 virtual String stringValue() const = 0;
52};
53
54class IC
55{
56 public:
57 virtual ~IC() = default;
58 virtual int value() const = 0;
59};
60
61class ID
62{
63 public:
64 virtual ~ID() = default;
65};
66
67class IE
68{
69 public:
70 virtual ~IE() = default;
71 virtual int intValue() const = 0;
72 virtual String stringValue() const = 0;
73};
74
75class INone
76{
77 public:
78
79 virtual ~INone() = default;
80};
81
82class AImpl
83: public IA
84{
85 public:
86 AImpl() {}
87 int value() const override { return 5; }
88};
89
90class BImpl
91: public IB
92{
93 public:
94 BImpl() {}
95 int value() const override { return 12; }
96};
97
98class B2Impl
99: public IB2
100{
101 public:
102 B2Impl(const String& x)
103 : m_test(x)
104 {}
105 int value() const override { return 32; }
106 String stringValue() const override { return m_test; }
107
108 private:
109 String m_test;
110};
111
112class EImpl
113: public IE
114{
115 public:
117 : m_string_value(string_value)
118 , m_int_value(int_value)
119 {
120 }
121 int intValue() const override { return m_int_value; }
122 String stringValue() const override { return m_string_value; }
123
124 private:
125 String m_string_value;
126 Int32 m_int_value;
127};
128
130: public ID
131, public IC
132{
133 public:
134 CDImpl(int a,double b) : m_int_value(a+(int)b){}
135 CDImpl(int a) : m_int_value(a){}
136 CDImpl() : m_int_value(2){}
137 int value() const override { return m_int_value; }
138 private:
139 int m_int_value;
140};
141
143: public IA2
144{
145 public:
146 A2Impl(int a,IB* ib,IA*) : m_a(a), m_ib(ib) {}
147 A2Impl(int a, IB* ib)
148 : m_a(a)
149 , m_ib(ib)
150 {}
151
152 public:
153 int value() const override { return m_a; }
154 IB* bValue() const override { return m_ib; }
155
156 private:
157 int m_a;
158 IB* m_ib;
159};
160
161ARCANE_DI_REGISTER_PROVIDER(AImpl,
162 ProviderProperty("AImplProvider"),
163 ARCANE_DI_INTERFACES(IA),
164 ARCANE_DI_EMPTY_CONSTRUCTOR());
165
166ARCANE_DI_REGISTER_PROVIDER(BImpl,
167 ProviderProperty("BImplProvider"),
168 ARCANE_DI_INTERFACES(IB),
169 ARCANE_DI_EMPTY_CONSTRUCTOR());
170
171ARCANE_DI_REGISTER_PROVIDER(B2Impl,
172 ProviderProperty("B2ImplProvider"),
173 ARCANE_DI_INTERFACES(IB2),
174 ARCANE_DI_CONSTRUCTOR(String));
175
176ARCANE_DI_REGISTER_PROVIDER(EImpl,
177 ProviderProperty("EImplProvider"),
178 ARCANE_DI_INTERFACES(IE),
179 ARCANE_DI_CONSTRUCTOR(Int32, String));
180
181ARCANE_DI_REGISTER_PROVIDER(A2Impl,
182 ProviderProperty("A2ImplProvider"),
183 ARCANE_DI_INTERFACES(IA2),
184 ARCANE_DI_CONSTRUCTOR(int, IB*));
185
186ARCANE_DI_REGISTER_PROVIDER(CDImpl,
187 ProviderProperty("CDImplProvider2"),
188 ARCANE_DI_INTERFACES(IC, ID),
189 ARCANE_DI_CONSTRUCTOR(int));
190
191ARCANE_DI_REGISTER_PROVIDER(CDImpl,
192 ProviderProperty("CDImplProvider3"),
193 ARCANE_DI_INTERFACES(IC),
194 ARCANE_DI_EMPTY_CONSTRUCTOR());
195
196ARCANE_DI_REGISTER_PROVIDER(CDImpl,
197 ProviderProperty("CDImplProvider4"),
198 ARCANE_DI_INTERFACES(IC, ID),
199 ARCANE_DI_CONSTRUCTOR(int),
200 ARCANE_DI_CONSTRUCTOR(int, double),
201 ARCANE_DI_EMPTY_CONSTRUCTOR());
202} // namespace DI_Test
203
204TEST(DependencyInjection,TestPrintFactories)
205{
206 using namespace Arcane::DependencyInjection;
208 injector.fillWithGlobalFactories();
209
210 std::cout << "FACTORIES=" << injector.printFactories() << "\n";
211}
212
213namespace
214{
215template <typename T> void
217{
218 try {
219 Ref<T> ic = injector.createInstance<T>("Test1");
220 FAIL() << "Expected FatalErrorException";
221 }
222 catch (const FatalErrorException& ex) {
223 std::cout << "EX=" << ex << "\n";
224 }
225 catch (...) {
226 FAIL() << "Expected FatalErrorException";
227 }
228}
229} // namespace
230
231TEST(DependencyInjection, TestNotFound)
232{
233 using namespace Arcane::DependencyInjection;
234 using namespace DI_Test;
236 injector.fillWithGlobalFactories();
237
241 Ref<IC> ic2 = injector.createInstance<IC>("Test1", true);
242 ASSERT_EQ(ic2.get(), nullptr);
243}
244
245TEST(DependencyInjection,TestBind1)
246{
247 using namespace Arcane::DependencyInjection;
248 std::cout << "INJECTOR TEST\n";
250 ITraceMng* tm = Arccore::arccoreCreateDefaultTraceMng();
252 injector.bind(ref_tm);
254 std::cout << "TM=" << tm << "TM2=" << tm2.get() << "\n";
255 ASSERT_EQ(tm,tm2.get()) << "Bad Get Reference";
256}
257
258TEST(DependencyInjection,ProcessGlobalProviders)
259{
260 using namespace Arcane::DependencyInjection;
261 using namespace DI_Test;
262
264 injector.fillWithGlobalFactories();
265
266 Ref<IA> ia = injector.createInstance<IA>({});
267 EXPECT_TRUE(ia.get());
268 ASSERT_EQ(ia->value(),5);
269
270 Ref<IA> ia2 = injector.createInstance<IA>("AImplProvider");
271 EXPECT_TRUE(ia2.get());
272 ASSERT_EQ(ia2->value(),5);
273
274 Ref<IB> ib = injector.createInstance<IB>({});
275 EXPECT_TRUE(ib.get());
276 ASSERT_EQ(ib->value(),12);
277}
278
279void _TestBindValue()
280{
281 using namespace Arcane::DependencyInjection;
282 using namespace DI_Test;
283
284 {
286 injector.fillWithGlobalFactories();
287 String wanted_string("Toto");
288
290
291 Ref<IB2> ib = injector.createInstance<IB2>({});
292 EXPECT_TRUE(ib.get());
293 ASSERT_EQ(ib->value(), 32);
294 ASSERT_EQ(ib->stringValue(), wanted_string);
295 }
296
297 {
299 injector.fillWithGlobalFactories();
300 String wanted_string{ "Tata" };
301 Int32 wanted_int{ 25 };
302
304 injector.bind(wanted_string, "Name");
305 injector.bind(wanted_int, "Value");
306
308 //injector.bind("FalseString","AnyName");
309 //injector.bind(38,"SomeName");
310 //injector.bind(3.2,"DoubleName");
311
312 Ref<IE> ie = injector.createInstance<IE>("EImplProvider");
313 EXPECT_TRUE(ie.get());
314 ASSERT_EQ(ie->intValue(), wanted_int);
315 ASSERT_EQ(ie->stringValue(), wanted_string);
316 }
317}
318
319TEST(DependencyInjection,TestBindValue)
320{
321 try{
322 _TestBindValue();
323 }
324 catch(const Exception& ex){
325 std::cerr << "ERROR=" << ex << "\n";
326 throw;
327 }
328}
329
330TEST(DependencyInjection, ConstructorCall)
331{
332 using namespace DI_Test;
333 namespace di = Arcane::DependencyInjection;
334 using ConstructorType = di::impl::ConstructorRegisterer<int, IB*>;
335
336 di::impl::ConcreteFactory<IA2, A2Impl, ConstructorType> c2f;
337
338 int x = 3;
339
340 try {
342 IB* ib{ new BImpl() };
343 injector.bind(ib);
344 injector.bind(x);
345 Ref<IA2> a2 = c2f.createReference(injector);
347 ASSERT_EQ(a2->value(), 3);
348 ASSERT_EQ(a2->bValue(), ib);
349 }
350 catch (const Exception& ex) {
351 std::cerr << "ERROR=" << ex << "\n";
352 throw;
353 }
354}
355
356TEST(DependencyInjection,Impl2)
357{
358 using namespace DI_Test;
359 namespace di = Arcane::DependencyInjection;
360
361 try{
362 {
363 // Test avec le constructeur CDImpl(int)
365 injector.fillWithGlobalFactories();
366
367 injector.bind<int>(25);
368 Ref<IC> ic = injector.createInstance<IC>("CDImplProvider2");
370 ASSERT_EQ(ic->value(),25);
371 }
372 {
373 // Test avec le constructeur sans arguments (CDImpl())
374 // Dans ce cas la valeur IC::value() doit valoir 2
375 // (voir constructeur de CDImpl)
377 injector.fillWithGlobalFactories();
378 Ref<IC> ic = injector.createInstance<IC>("CDImplProvider3");
380 ASSERT_EQ(ic->value(),2);
381 }
382 {
383 // Test avec le constructeur avec 2 arguments (CDImpl(int,double))
384 // Dans ce cas la valeur IC::value() doit valoir 25+12
385 // (voir constructeur de CDImpl)
387 injector.fillWithGlobalFactories();
388 injector.bind<int>(25);
389 injector.bind<double>(12.0);
390 Ref<IC> ic = injector.createInstance<IC>("CDImplProvider4");
392 ASSERT_EQ(ic->value(),37);
393 }
394 }
395 catch(const Exception& ex){
396 std::cerr << "ERROR=" << ex << "\n";
397 throw;
398 }
399}
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Classe de base d'une exception.
Exception lorsqu'une erreur fatale est survenue.
Interface du gestionnaire de traces.
Chaîne de caractères unicode.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-