blob: 08ac64adb818e2c9955c988673d47c9e116e97f4 [file] [log] [blame]
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001#!/usr/bin/env python3
2# Copyright 2016 Google Inc. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS-IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
Marco Polettief4bc1f2016-11-19 17:49:14 +000015from nose2.tools import params
Marco Polettif9b2c6f2016-10-08 18:49:04 +010016
17from fruit_test_common import *
18
19COMMON_DEFINITIONS = '''
Marco Poletti83b1ad82016-11-12 11:24:51 +000020#include <fruit/fruit.h>
21#include <vector>
22#include "test_macros.h"
23
Marco Poletti21111b02016-11-12 10:49:02 +000024struct Annotation1 {};
Marco Poletti21111b02016-11-12 10:49:02 +000025struct Annotation2 {};
Marco Polettif9b2c6f2016-10-08 18:49:04 +010026'''
27
Marco Polettief4bc1f2016-11-19 17:49:14 +000028@params(
29 ('Scaler',
30 'ScalerImpl',
31 'std::function<std::unique_ptr<Scaler>(double)>'),
32 ('fruit::Annotated<Annotation1, Scaler>',
33 'fruit::Annotated<Annotation2, ScalerImpl>',
34 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'))
35def test_success(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +010036 expect_success(
37 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +000038struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +010039 virtual double scale(double x) = 0;
40};
41
Marco Poletti6317c252016-11-12 16:26:47 +000042struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +010043private:
44 double factor;
45
46public:
47 ScalerImpl(double factor)
48 : factor(factor) {
49 }
50
51 double scale(double x) override {
52 return x * factor;
53 }
54};
55
Marco Polettief4bc1f2016-11-19 17:49:14 +000056using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
57
58fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +010059 return fruit::createComponent()
Marco Polettief4bc1f2016-11-19 17:49:14 +000060 .bind<ScalerAnnot, ScalerImplAnnot>()
61 .registerFactory<ScalerImplAnnot(fruit::Assisted<double>)>([](double factor) { return ScalerImpl(factor); });
Marco Polettif9b2c6f2016-10-08 18:49:04 +010062}
63
64int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +000065 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
66 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
67 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
68 std::cout << scaler->scale(3) << std::endl;
69}
70''',
71 locals())
72
73def test_with_annotation_returning_value():
74 expect_success(
75 COMMON_DEFINITIONS + '''
76struct Scaler {
77private:
78 double factor;
79
80public:
81 Scaler(double factor)
82 : factor(factor) {
83 }
84
85 double scale(double x) {
86 return x * factor;
87 }
88};
89
90using ScalerAnnot1 = fruit::Annotated<Annotation1, Scaler>;
91using ScalerFactory = std::function<Scaler(double)>;
92using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>;
93
94fruit::Component<ScalerFactoryAnnot1> getScalerComponent() {
95 return fruit::createComponent()
96 .registerFactory<ScalerAnnot1(fruit::Assisted<double>)>(
97 [](double factor) {
98 return Scaler(factor);
99 });
100}
101
102int main() {
103 fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent());
104 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>();
105 Scaler scaler = scalerFactory(12.1);
106 std::cout << scaler.scale(3) << std::endl;
107}
108''')
109
110def test_with_different_annotation():
111 expect_success(
112 COMMON_DEFINITIONS + '''
113struct Scaler {
114 virtual double scale(double x) = 0;
115};
116
117struct ScalerImpl : public Scaler {
118private:
119 double factor;
120
121public:
122 ScalerImpl(double factor)
123 : factor(factor) {
124 }
125
126 double scale(double x) override {
127 return x * factor;
128 }
129};
130
131using ScalerAnnot1 = fruit::Annotated<Annotation1, Scaler>;
132using ScalerImplAnnot2 = fruit::Annotated<Annotation2, ScalerImpl>;
133using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
134using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>;
135
136fruit::Component<ScalerFactoryAnnot1> getScalerComponent() {
137 return fruit::createComponent()
138 .bind<ScalerAnnot1, ScalerImplAnnot2>()
139 .registerFactory<ScalerImplAnnot2(fruit::Assisted<double>)>(
140 [](double factor) {
141 return ScalerImpl(factor);
142 });
143}
144
145int main() {
146 fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent());
147 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100148 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
149 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100150}
151''')
152
Marco Polettief4bc1f2016-11-19 17:49:14 +0000153def test_with_different_annotation_error():
154 expect_compile_error(
155 'NoBindingFoundError<fruit::Annotated<Annotation1,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>>',
156 '',
157 COMMON_DEFINITIONS + '''
158struct Scaler {
159 virtual double scale(double x) = 0;
160};
161
162struct ScalerImpl : public Scaler {
163private:
164 double factor;
165
166public:
167 ScalerImpl(double factor)
168 : factor(factor) {
169 }
170
171 double scale(double x) override {
172 return x * factor;
173 }
174};
175
176using ScalerAnnot1 = fruit::Annotated<Annotation1, Scaler>;
177using ScalerImplAnnot1 = fruit::Annotated<Annotation1, ScalerImpl>;
178using ScalerImplAnnot2 = fruit::Annotated<Annotation2, ScalerImpl>;
179using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
180using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>;
181
182fruit::Component<ScalerFactoryAnnot1> getScalerComponent() {
183 return fruit::createComponent()
184 .bind<ScalerAnnot1, ScalerImplAnnot1>()
185 .registerFactory<ScalerImplAnnot2(fruit::Assisted<double>)>([](double factor) { return ScalerImpl(factor); });
186}
187
188int main() {
189 fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent());
190 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>();
191 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
192 std::cout << scaler->scale(3) << std::endl;
193}
194''')
195
196
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100197def test_autoinject_success():
198 expect_success(
Marco Poletti21111b02016-11-12 10:49:02 +0000199 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +0000200struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100201 virtual double scale(double x) = 0;
202};
203
Marco Poletti6317c252016-11-12 16:26:47 +0000204struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100205private:
206 double factor;
207
208public:
209 INJECT(ScalerImpl(ASSISTED(double) factor))
210 : factor(factor) {
211 }
212
213 double scale(double x) override {
214 return x * factor;
215 }
216};
217
218using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
219
Marco Poletti83b1ad82016-11-12 11:24:51 +0000220fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100221 return fruit::createComponent()
222 .bind<Scaler, ScalerImpl>();
223}
224
225int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000226 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100227 ScalerFactory scalerFactory(injector);
228 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
229 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100230}
231''')
232
Marco Polettief4bc1f2016-11-19 17:49:14 +0000233@params(
234 ('Scaler',
235 'std::function<std::unique_ptr<Scaler>(double)>'),
236 ('fruit::Annotated<Annotation1, Scaler>',
237 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'))
238def test_autoinject(ScalerAnnot, ScalerFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100239 expect_success(
240 COMMON_DEFINITIONS + '''
Marco Polettief4bc1f2016-11-19 17:49:14 +0000241struct Scaler {
242 virtual double scale(double x) = 0;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100243};
244
Marco Polettief4bc1f2016-11-19 17:49:14 +0000245struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100246private:
247 double factor;
248
249public:
Marco Polettief4bc1f2016-11-19 17:49:14 +0000250 INJECT(ScalerImpl(ASSISTED(double) factor))
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100251 : factor(factor) {
252 }
253
Marco Polettief4bc1f2016-11-19 17:49:14 +0000254 double scale(double x) override {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100255 return x * factor;
256 }
257};
258
259using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
260
Marco Polettief4bc1f2016-11-19 17:49:14 +0000261fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
262 return fruit::createComponent()
263 .bind<ScalerAnnot, ScalerImpl>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100264}
265
266int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000267 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
268 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100269 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
270 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100271}
Marco Polettief4bc1f2016-11-19 17:49:14 +0000272''',
273 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100274
275def test_autoinject_returning_value():
276 expect_success(
277 COMMON_DEFINITIONS + '''
278struct X {
279 INJECT(X()) = default;
280};
281
Marco Poletti6317c252016-11-12 16:26:47 +0000282struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100283private:
284 double factor;
285
286public:
287 INJECT(Scaler(ASSISTED(double) factor, X))
288 : factor(factor) {
289 }
290
291 double scale(double x) {
292 return x * factor;
293 }
294};
295
296using ScalerFactory = std::function<Scaler(double)>;
297
Marco Poletti83b1ad82016-11-12 11:24:51 +0000298fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100299 return fruit::createComponent();
300}
301
302int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000303 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100304 ScalerFactory scalerFactory(injector);
305 Scaler scaler = scalerFactory(12.1);
306 std::cout << scaler.scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100307}
308''')
309
Marco Polettief4bc1f2016-11-19 17:49:14 +0000310@params(
311 ('Scaler', 'ScalerImpl', 'std::function<std::unique_ptr<Scaler>(double)>'),
312 ('fruit::Annotated<Annotation1, Scaler>', 'fruit::Annotated<Annotation2, ScalerImpl>', 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'))
313def test_autoinject_error_abstract_class(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100314 expect_compile_error(
315 'NoBindingFoundForAbstractClassError<ScalerImpl>',
316 'No explicit binding was found for C, and C is an abstract class',
Marco Poletti21111b02016-11-12 10:49:02 +0000317 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +0000318struct Scaler {
Marco Poletti21111b02016-11-12 10:49:02 +0000319 virtual double scale(double x) = 0;
320};
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100321
Marco Poletti6317c252016-11-12 16:26:47 +0000322struct ScalerImpl : public Scaler {
Marco Poletti21111b02016-11-12 10:49:02 +0000323private:
324 double factor;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100325
Marco Poletti21111b02016-11-12 10:49:02 +0000326public:
327 ScalerImpl(double factor)
328 : factor(factor) {
329 }
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100330
Marco Poletti21111b02016-11-12 10:49:02 +0000331 // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class.
332};
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100333
Marco Poletti83b1ad82016-11-12 11:24:51 +0000334fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Poletti21111b02016-11-12 10:49:02 +0000335 return fruit::createComponent()
336 .bind<ScalerAnnot, ScalerImplAnnot>();
337}
Marco Polettief4bc1f2016-11-19 17:49:14 +0000338''',
339 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100340
341def test_autoinject_nonmovable_ok():
342 expect_success(
Marco Poletti21111b02016-11-12 10:49:02 +0000343 COMMON_DEFINITIONS + '''
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100344struct I {};
345
346struct C : public I {
347 INJECT(C()) = default;
348
349 C(const C&) = delete;
350 C(C&&) = delete;
351 C& operator=(const C&) = delete;
352 C& operator=(C&&) = delete;
353};
354
355using IFactory = std::function<std::unique_ptr<I>()>;
356
Marco Poletti83b1ad82016-11-12 11:24:51 +0000357fruit::Component<IFactory> getIFactory() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100358 return fruit::createComponent()
359 .bind<I, C>();
360}
361
362int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000363 fruit::Injector<IFactory> injector(getIFactory());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100364 IFactory iFactory(injector);
365 std::unique_ptr<I> i = iFactory();
366 (void)i;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100367}
368''')
369
Marco Polettie7ac9ba2016-11-19 11:33:57 +0000370def test_autoinject_2_assisted_params():
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100371 expect_success(
372 COMMON_DEFINITIONS + '''
373struct Foo {
374 Foo(int x, float y) {
375 (void)x;
376 (void)y;
377 }
378};
379
380using FooFactory = std::function<Foo(int, float)>;
381
382fruit::Component<FooFactory> getComponent() {
383 return fruit::createComponent()
384 .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>)>(
385 [](int x, float y) {
386 return Foo(x, y);
387 });
388}
389
390int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000391 fruit::Injector<FooFactory> injector(getComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100392 FooFactory fooFactory(injector);
393 Foo foo = fooFactory(1, 2.3);
394 (void)foo;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100395}
396''')
397
Marco Polettie7ac9ba2016-11-19 11:33:57 +0000398def test_autoinject_2_assisted_params_returning_value():
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100399 expect_success(
400 COMMON_DEFINITIONS + '''
401struct Foo {
402 Foo(int x, float y) {
403 (void)x;
404 (void)y;
405 }
406};
407
408using FooFactory = std::function<Foo(int, float)>;
409
410fruit::Component<FooFactory> getComponent() {
411 return fruit::createComponent()
412 .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>)>(
413 [](int x, float y) {
414 return Foo(x, y);
415 });
416}
417
418int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000419 fruit::Injector<FooFactory> injector(getComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100420 FooFactory fooFactory(injector);
421 Foo foo = fooFactory(1, 2.3);
422 (void)foo;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100423}
424''')
425
Marco Polettie7ac9ba2016-11-19 11:33:57 +0000426def test_autoinject_instances_bound_to_assisted_params():
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100427 expect_success(
428 COMMON_DEFINITIONS + '''
429struct X {};
430struct Y {};
431
432struct Foo {
433 Foo(X x, Y y) {
434 (void)x;
435 (void)y;
436 }
437};
438
439using FooFactory = std::function<Foo()>;
440
441fruit::Component<FooFactory> getComponent() {
442 static X x = X();
443 static Y y = Y();
444 return fruit::createComponent()
445 .bindInstance(x)
446 .bindInstance(y)
447 .registerFactory<Foo(X, Y)>(
448 [](X x, Y y) {
449 return Foo(x, y);
450 });
451}
452
453
454int main() {
455 fruit::Injector<FooFactory> injector(getComponent());
456 FooFactory fooFactory(injector);
457 Foo foo = fooFactory();
458 (void)foo;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100459}
460''')
461
Marco Polettie7ac9ba2016-11-19 11:33:57 +0000462def test_autoinject_2_assisted_params_plus_nonassisted_params():
463 expect_success(
464 COMMON_DEFINITIONS + '''
465struct X {};
466struct Y {};
467struct Z {};
468
469struct Foo {
470 Foo(X, Y, int, float, Z) {
471 }
472};
473
474using FooPtrFactory = std::function<std::unique_ptr<Foo>(int, float)>;
475
476fruit::Component<FooPtrFactory> getComponent() {
477 static X x = X();
478 static Y y = Y();
479 static Z z = Z();
480 return fruit::createComponent()
481 .bindInstance(x)
482 .bindInstance(y)
483 .bindInstance(z)
484 .registerFactory<std::unique_ptr<Foo>(X, Y, fruit::Assisted<int>, fruit::Assisted<float>, Z)>(
485 [](X x, Y y, int n, float a, Z z) {
486 return std::unique_ptr<Foo>(new Foo(x, y, n, a, z));
487 });
488}
489
490int main() {
491 fruit::Injector<FooPtrFactory> injector(getComponent());
492 FooPtrFactory fooPtrFactory(injector);
493 std::unique_ptr<Foo> foo = fooPtrFactory(1, 3.4);
494 (void)foo;
495}
496''')
497
498def test_autoinject_2_assisted_params_plus_nonassisted_params_returning_value():
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100499 expect_success(
500 COMMON_DEFINITIONS + '''
501struct X {};
502struct Y {};
503struct Z {};
504
505struct Foo {
506 Foo(X, Y, int, float, Z) {
507 }
508};
509
510using FooFactory = std::function<Foo(int, float)>;
511
512fruit::Component<FooFactory> getComponent() {
513 static X x = X();
514 static Y y = Y();
515 static Z z = Z();
516 return fruit::createComponent()
517 .bindInstance(x)
518 .bindInstance(y)
519 .bindInstance(z)
520 .registerFactory<Foo(X, Y, fruit::Assisted<int>, fruit::Assisted<float>, Z)>(
521 [](X x, Y y, int n, float a, Z z) {
522 return Foo(x, y, n, a, z);
523 });
524}
525
526int main() {
527 fruit::Injector<FooFactory> injector(getComponent());
528 FooFactory fooFactory(injector);
529 Foo foo = fooFactory(1, 3.4);
530 (void)foo;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100531}
532''')
533
Marco Polettie7ac9ba2016-11-19 11:33:57 +0000534def test_autoinject_mixed_assisted_and_injected_params():
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100535 expect_success(
536 COMMON_DEFINITIONS + '''
537struct X {};
538struct Y {};
539
540struct Foo {
541 Foo(int, float, X, Y, double) {
542 }
543};
544
545using FooFactory = std::function<Foo(int, float, double)>;
546
547fruit::Component<FooFactory> getComponent() {
548 static X x = X();
549 static Y y = Y();
550 return fruit::createComponent()
551 .bindInstance(x)
552 .bindInstance(y)
553 .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>, X, Y, fruit::Assisted<double>)>(
554 [](int n, float a, X x, Y y, double d) {
555 return Foo(n, a, x, y, d);
556 });
557}
558
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100559int main() {
560 fruit::Injector<FooFactory> injector(getComponent());
561 FooFactory fooFactory(injector);
562 Foo foo = fooFactory(1, 3.4, 3.456);
563 (void)foo;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100564}
565''')
566
567def test_autoinject_annotation_in_signature_return_type():
568 expect_compile_error(
569 'InjectTypedefWithAnnotationError<X>',
570 'C::Inject is a signature that returns an annotated type',
571 COMMON_DEFINITIONS + '''
Marco Poletti21111b02016-11-12 10:49:02 +0000572struct X {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000573 using Inject = fruit::Annotated<Annotation1, X>();
Marco Poletti21111b02016-11-12 10:49:02 +0000574};
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100575
Marco Polettief4bc1f2016-11-19 17:49:14 +0000576fruit::Component<fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>> getComponent() {
Marco Poletti21111b02016-11-12 10:49:02 +0000577 return fruit::createComponent();
578}
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100579''')
580
581def test_autoinject_annotation_in_signature_return_type_returning_value():
582 expect_compile_error(
583 'InjectTypedefWithAnnotationError<X>',
584 'C::Inject is a signature that returns an annotated type',
585 COMMON_DEFINITIONS + '''
Marco Poletti21111b02016-11-12 10:49:02 +0000586struct X {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000587 using Inject = fruit::Annotated<Annotation1, X>();
Marco Poletti21111b02016-11-12 10:49:02 +0000588};
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100589
Marco Polettief4bc1f2016-11-19 17:49:14 +0000590fruit::Component<fruit::Annotated<Annotation1, std::function<X()>>> getComponent() {
Marco Poletti21111b02016-11-12 10:49:02 +0000591 return fruit::createComponent();
592}
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100593''')
594
595def test_autoinject_from_provider():
596 expect_success(
597 COMMON_DEFINITIONS + '''
598struct X {
599 INJECT(X()) = default;
600};
601
Marco Poletti6317c252016-11-12 16:26:47 +0000602struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100603 virtual double scale(double x) = 0;
604};
605
Marco Poletti6317c252016-11-12 16:26:47 +0000606struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100607private:
608 double factor;
609
610public:
611 ScalerImpl(double factor, X)
612 : factor(factor) {
613 }
614
615 double scale(double x) override {
616 return x * factor;
617 }
618};
619
620using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
621
Marco Poletti83b1ad82016-11-12 11:24:51 +0000622fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100623 return fruit::createComponent()
624 .registerProvider([](X x) {
625 return std::function<std::unique_ptr<ScalerImpl>(double)>([x](double n){
626 return std::unique_ptr<ScalerImpl>(new ScalerImpl(n, x));
627 });
628 })
629 .bind<Scaler, ScalerImpl>();
630}
631
632int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000633 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100634 ScalerFactory scalerFactory(injector);
635 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
636 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100637}
638''')
639
Marco Polettief4bc1f2016-11-19 17:49:14 +0000640@params(
641 ('Scaler',
642 'std::function<std::unique_ptr<Scaler>(double)>',
643 'ScalerImpl',
644 'std::function<std::unique_ptr<ScalerImpl>(double)>'),
645 ('fruit::Annotated<Annotation1, Scaler>',
646 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>',
647 'fruit::Annotated<Annotation2, ScalerImpl>',
648 'fruit::Annotated<Annotation2, std::function<std::unique_ptr<ScalerImpl>(double)>>'))
649def test_autoinject_from_provider(ScalerAnnot, ScalerFactoryAnnot, ScalerImplAnnot, ScalerImplFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100650 expect_success(
651 COMMON_DEFINITIONS + '''
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100652struct X {
653 INJECT(X()) = default;
654};
655
Marco Poletti6317c252016-11-12 16:26:47 +0000656struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100657 virtual double scale(double x) = 0;
658};
659
Marco Poletti6317c252016-11-12 16:26:47 +0000660struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100661private:
662 double factor;
663
664public:
665 ScalerImpl(double factor, X)
666 : factor(factor) {
667 }
668
669 double scale(double x) override {
670 return x * factor;
671 }
672};
673
674using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100675using ScalerImplFactory = std::function<std::unique_ptr<ScalerImpl>(double)>;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100676
Marco Polettief4bc1f2016-11-19 17:49:14 +0000677fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100678 return fruit::createComponent()
Marco Polettief4bc1f2016-11-19 17:49:14 +0000679 .registerProvider<ScalerImplFactoryAnnot(X)>([](X x) {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100680 return std::function<std::unique_ptr<ScalerImpl>(double)>([x](double n){
681 return std::unique_ptr<ScalerImpl>(new ScalerImpl(n, x));
682 });
683 })
Marco Polettief4bc1f2016-11-19 17:49:14 +0000684 .bind<ScalerAnnot, ScalerImplAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100685}
686
687int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000688 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
689 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100690 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
691 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100692}
Marco Polettief4bc1f2016-11-19 17:49:14 +0000693''',
694 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100695
Marco Polettief4bc1f2016-11-19 17:49:14 +0000696@params('ScalerFactory', 'fruit::Annotated<Annotation1, ScalerFactory>')
697def test_autoinject_from_provider_returning_value(ScalerFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100698 expect_success(
699 COMMON_DEFINITIONS + '''
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100700struct X {
701 INJECT(X()) = default;
702};
703
Marco Poletti6317c252016-11-12 16:26:47 +0000704struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100705private:
706 double factor;
707
708public:
709 Scaler(double factor, X)
710 : factor(factor) {
711 }
712
713 double scale(double x) {
714 return x * factor;
715 }
716};
717
718using ScalerFactory = std::function<Scaler(double)>;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100719
Marco Polettief4bc1f2016-11-19 17:49:14 +0000720fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100721 return fruit::createComponent()
Marco Polettief4bc1f2016-11-19 17:49:14 +0000722 .registerProvider<ScalerFactoryAnnot(X)>([](X x) {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100723 return std::function<Scaler(double)>([x](double n){
724 return Scaler(n, x);
725 });
726 });
727}
728
729int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000730 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
731 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100732 Scaler scaler = scalerFactory(12.1);
733 std::cout << scaler.scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100734}
Marco Polettief4bc1f2016-11-19 17:49:14 +0000735''',
736 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100737
Marco Polettief4bc1f2016-11-19 17:49:14 +0000738@params('X', 'ANNOTATED(Annotation1, X)')
739def test_autoinject_with_binding(X_ANNOT):
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100740 expect_success(
741 COMMON_DEFINITIONS + '''
742struct X {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000743 using Inject = X();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100744};
745
Marco Poletti6317c252016-11-12 16:26:47 +0000746struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100747 virtual double scale(double x) = 0;
748};
749
Marco Poletti6317c252016-11-12 16:26:47 +0000750struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100751private:
752 double factor;
753
754public:
Marco Polettief4bc1f2016-11-19 17:49:14 +0000755 INJECT(ScalerImpl(ASSISTED(double) factor, X_ANNOT x))
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100756 : factor(factor) {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000757 (void)x;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100758 }
759
760 double scale(double x) override {
761 return x * factor;
762 }
763};
764
765using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
766
Marco Poletti83b1ad82016-11-12 11:24:51 +0000767fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100768 return fruit::createComponent()
769 .bind<Scaler, ScalerImpl>();
770}
771
772int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000773 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100774 ScalerFactory scalerFactory(injector);
775 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
776 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100777}
Marco Polettief4bc1f2016-11-19 17:49:14 +0000778''',
779 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100780
Marco Polettief4bc1f2016-11-19 17:49:14 +0000781@params('X', 'ANNOTATED(Annotation1, X)')
782def test_autoinject_with_binding_returning_value(X_ANNOT):
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100783 expect_success(
784 COMMON_DEFINITIONS + '''
785struct X {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000786 using Inject = X();
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100787};
788
Marco Poletti6317c252016-11-12 16:26:47 +0000789struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100790private:
791 double factor;
792
793public:
Marco Polettief4bc1f2016-11-19 17:49:14 +0000794 INJECT(Scaler(ASSISTED(double) factor, X_ANNOT x))
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100795 : factor(factor) {
Marco Polettief4bc1f2016-11-19 17:49:14 +0000796 (void)x;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100797 }
798
799 double scale(double x) {
800 return x * factor;
801 }
802};
803
804using ScalerFactory = std::function<Scaler(double)>;
805
Marco Poletti83b1ad82016-11-12 11:24:51 +0000806fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100807 return fruit::createComponent();
808}
809
810int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000811 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100812 ScalerFactory scalerFactory(injector);
813 Scaler scaler = scalerFactory(12.1);
814 std::cout << scaler.scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100815}
Marco Polettief4bc1f2016-11-19 17:49:14 +0000816''',
817 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100818
819def test_autoinject_with_binding2():
820 expect_success(
821 COMMON_DEFINITIONS + '''
822struct X {
823 INJECT(X()) = default;
824};
825
Marco Poletti6317c252016-11-12 16:26:47 +0000826struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100827 virtual double scale(double x) = 0;
828};
829
Marco Poletti6317c252016-11-12 16:26:47 +0000830struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100831private:
832 double factor;
833
834public:
835 INJECT(ScalerImpl(X, ASSISTED(double) factor))
836 : factor(factor) {
837 }
838
839 double scale(double x) override {
840 return x * factor;
841 }
842};
843
844using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
845
Marco Poletti83b1ad82016-11-12 11:24:51 +0000846fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100847 return fruit::createComponent()
848 .bind<Scaler, ScalerImpl>();
849}
850
851int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000852 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100853 ScalerFactory scalerFactory(injector);
854 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
855 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100856}
857''')
858
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100859def test_autoinject_with_binding2_returning_value():
860 expect_success(
861 COMMON_DEFINITIONS + '''
862struct X {
863 INJECT(X()) = default;
864};
865
Marco Poletti6317c252016-11-12 16:26:47 +0000866struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100867private:
868 double factor;
869
870public:
871 INJECT(Scaler(X, ASSISTED(double) factor))
872 : factor(factor) {
873 }
874
875 double scale(double x) {
876 return x * factor;
877 }
878};
879
880using ScalerFactory = std::function<Scaler(double)>;
881
Marco Poletti83b1ad82016-11-12 11:24:51 +0000882fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100883 return fruit::createComponent();
884}
885
886int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000887 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100888 ScalerFactory scalerFactory(injector);
889 Scaler scaler = scalerFactory(12.1);
890 std::cout << scaler.scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100891}
892''')
893
894def test_dep_on_provider():
895 expect_success(
896 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +0000897struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100898 virtual double scale(double x) = 0;
899};
900
Marco Poletti6317c252016-11-12 16:26:47 +0000901struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100902private:
903 double factor;
904
905public:
906 ScalerImpl(double factor)
907 : factor(factor) {
908 }
909
910 double scale(double x) override {
911 return x * factor;
912 }
913};
914
915using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
916
Marco Poletti83b1ad82016-11-12 11:24:51 +0000917fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100918 return fruit::createComponent()
919 .bind<Scaler, ScalerImpl>()
920 .registerProvider([](){return 23;})
Marco Poletti83b1ad82016-11-12 11:24:51 +0000921 .registerFactory<ScalerImpl(fruit::Assisted<double>, fruit::Provider<int>)>(
922 [](double factor, fruit::Provider<int> provider) {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100923 return ScalerImpl(factor * provider.get<int>());
924 });
925}
926
927int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000928 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100929 ScalerFactory scalerFactory(injector);
930 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
931 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100932}
933''')
934
935def test_dep_on_provider_returning_value():
936 expect_success(
937 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +0000938struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100939private:
940 double factor;
941
942public:
943 Scaler(double factor)
944 : factor(factor) {
945 }
946
947 double scale(double x) {
948 return x * factor;
949 }
950};
951
952using ScalerFactory = std::function<Scaler(double)>;
953
Marco Poletti83b1ad82016-11-12 11:24:51 +0000954fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100955 return fruit::createComponent()
956 .registerProvider([](){return 23;})
Marco Poletti83b1ad82016-11-12 11:24:51 +0000957 .registerFactory<Scaler(fruit::Assisted<double>, fruit::Provider<int>)>(
958 [](double factor, fruit::Provider<int> provider) {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100959 return Scaler(factor * provider.get<int>());
960 });
961}
962
963int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +0000964 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100965 ScalerFactory scalerFactory(injector);
966 Scaler scaler = scalerFactory(12.1);
967 std::cout << scaler.scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100968}
969''')
970
971def test_error_abstract_class():
972 expect_compile_error(
973 'CannotConstructAbstractClassError<ScalerImpl>',
974 'The specified class can.t be constructed because it.s an abstract class.',
975 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +0000976struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100977 virtual double scale(double x) = 0;
978};
979
Marco Poletti6317c252016-11-12 16:26:47 +0000980struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100981private:
982 double factor;
983
984public:
985 ScalerImpl(double factor)
986 : factor(factor) {
987 }
988
989 // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class.
990};
991
992using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
993
Marco Poletti83b1ad82016-11-12 11:24:51 +0000994fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100995 return fruit::createComponent()
996 .bind<Scaler, ScalerImpl>()
Marco Polettief4bc1f2016-11-19 17:49:14 +0000997 .registerFactory<fruit::Annotated<Annotation1, ScalerImpl>(fruit::Assisted<double>)>([](double) { return (ScalerImpl*)nullptr; });
Marco Polettif9b2c6f2016-10-08 18:49:04 +0100998}
999''')
1000
1001def test_error_not_function():
1002 expect_compile_error(
1003 'LambdaWithCapturesError<.*>',
1004 'Only lambdas with no captures are supported',
1005 COMMON_DEFINITIONS + '''
1006struct X {
1007 X(int) {}
1008};
1009
Marco Poletti83b1ad82016-11-12 11:24:51 +00001010fruit::Component<std::function<X()>> getComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001011 int n = 3;
1012 return fruit::createComponent()
1013 .registerFactory<X()>([=]{return X(n);});
1014}
1015''')
1016
Marco Polettief4bc1f2016-11-19 17:49:14 +00001017@params(
1018 ('Scaler',
1019 'ScalerImpl',
1020 'ScalerImpl*',
1021 'std::function<std::unique_ptr<Scaler>(double)>',
1022 'ScalerImpl\*\(fruit::Assisted<double>\)'),
1023 ('fruit::Annotated<Annotation1, Scaler>',
1024 'fruit::Annotated<Annotation2, ScalerImpl>',
1025 'fruit::Annotated<Annotation2, ScalerImpl*>',
1026 'fruit::Annotated<Annotation2, std::function<std::unique_ptr<Scaler>(double)>>',
1027 'fruit::Annotated<Annotation2,ScalerImpl\*>\(fruit::Assisted<double>\)'))
1028def test_for_pointer(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot, ScalerImplFactorySignatureAnnotRegex):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001029 expect_compile_error(
Marco Polettief4bc1f2016-11-19 17:49:14 +00001030 'FactoryReturningPointerError<ScalerImplFactorySignatureAnnotRegex>',
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001031 'The specified factory returns a pointer. This is not supported',
1032 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +00001033struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001034 virtual double scale(double x) = 0;
1035};
1036
Marco Poletti6317c252016-11-12 16:26:47 +00001037struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001038private:
1039 double factor;
1040
1041public:
1042 ScalerImpl(double factor)
1043 : factor(factor) {
1044 }
1045
1046 double scale(double x) override {
1047 return x * factor;
1048 }
1049};
1050
1051using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1052
Marco Polettief4bc1f2016-11-19 17:49:14 +00001053fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001054 return fruit::createComponent()
Marco Polettief4bc1f2016-11-19 17:49:14 +00001055 .bind<ScalerAnnot, ScalerImplAnnot>()
1056 .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>([](double factor) { return new ScalerImpl(factor); });
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001057}
1058
1059int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +00001060 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
1061 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001062 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1063 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001064}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001065''',
1066 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001067
Marco Polettief4bc1f2016-11-19 17:49:14 +00001068@params(
1069 ('Scaler*',
1070 'std::function<Scaler(double)>',
1071 'Scaler\*\(fruit::Assisted<double>\)'),
1072 ('fruit::Annotated<Annotation1, Scaler*>',
1073 'fruit::Annotated<Annotation1, std::function<Scaler(double)>>',
1074 'fruit::Annotated<Annotation1,Scaler\*>\(fruit::Assisted<double>\)'),
1075)
1076def test_for_pointer_returning_value(ScalerPtrAnnot, ScalerFactoryAnnot, ScalerFactorySignatureAnnotRegex):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001077 expect_compile_error(
Marco Polettief4bc1f2016-11-19 17:49:14 +00001078 'FactoryReturningPointerError<ScalerFactorySignatureAnnotRegex>',
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001079 'The specified factory returns a pointer. This is not supported',
1080 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +00001081struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001082private:
1083 double factor;
1084
1085public:
1086 Scaler(double factor)
1087 : factor(factor) {
1088 }
1089
1090 double scale(double x) {
1091 return x * factor;
1092 }
1093};
1094
1095using ScalerFactory = std::function<Scaler(double)>;
1096
Marco Polettief4bc1f2016-11-19 17:49:14 +00001097fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001098 return fruit::createComponent()
Marco Polettief4bc1f2016-11-19 17:49:14 +00001099 .registerFactory<ScalerPtrAnnot(fruit::Assisted<double>)>([](double factor) { return new Scaler(factor); });
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001100}
1101
1102int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +00001103 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
1104 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001105 Scaler scaler = scalerFactory(12.1);
1106 std::cout << scaler.scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001107}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001108''',
1109 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001110
Marco Polettief4bc1f2016-11-19 17:49:14 +00001111@params(
1112 ('Scaler',
1113 'ScalerImpl',
1114 'std::unique_ptr<ScalerImpl>',
1115 'std::function<std::unique_ptr<Scaler>(double)>'),
1116 ('fruit::Annotated<Annotation1, Scaler>',
1117 'fruit::Annotated<Annotation2, ScalerImpl>',
1118 'fruit::Annotated<Annotation2, std::unique_ptr<ScalerImpl>>',
1119 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'))
1120def test_for_unique_pointer(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001121 expect_success(
1122 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +00001123struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001124 virtual double scale(double x) = 0;
1125};
1126
Marco Poletti6317c252016-11-12 16:26:47 +00001127struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001128private:
1129 double factor;
1130
1131public:
1132 ScalerImpl(double factor)
1133 : factor(factor) {
1134 }
1135
1136 double scale(double x) override {
1137 return x * factor;
1138 }
1139};
1140
1141using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1142
Marco Polettief4bc1f2016-11-19 17:49:14 +00001143fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001144 return fruit::createComponent()
Marco Polettief4bc1f2016-11-19 17:49:14 +00001145 .bind<ScalerAnnot, ScalerImplAnnot>()
1146 .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>(
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001147 [](double factor) {
1148 return std::unique_ptr<ScalerImpl>(new ScalerImpl(factor));
1149 });
1150}
1151
1152int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +00001153 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
1154 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001155 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1156 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001157}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001158''',
1159 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001160
Marco Polettief4bc1f2016-11-19 17:49:14 +00001161@params(
1162 ('Scaler',
1163 'std::function<Scaler(double)>'),
1164 ('fruit::Annotated<Annotation1, Scaler>',
1165 'fruit::Annotated<Annotation1, std::function<Scaler(double)>>'))
1166def test_for_unique_pointer_returning_value(ScalerAnnot, ScalerFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001167 expect_success(
1168 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +00001169struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001170private:
1171 double factor;
1172
1173public:
1174 Scaler(double factor)
1175 : factor(factor) {
1176 }
1177
1178 double scale(double x) {
1179 return x * factor;
1180 }
1181};
1182
1183using ScalerFactory = std::function<Scaler(double)>;
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001184
Marco Polettief4bc1f2016-11-19 17:49:14 +00001185fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001186 return fruit::createComponent()
Marco Polettief4bc1f2016-11-19 17:49:14 +00001187 .registerFactory<ScalerAnnot(fruit::Assisted<double>)>(
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001188 [](double factor) {
1189 return Scaler(factor);
1190 });
1191}
1192
1193int main() {
Marco Polettief4bc1f2016-11-19 17:49:14 +00001194 fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent());
1195 ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001196 Scaler scaler = scalerFactory(12.1);
1197 std::cout << scaler.scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001198}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001199''',
1200 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001201
Marco Polettief4bc1f2016-11-19 17:49:14 +00001202@params('ScalerImpl', 'fruit::Annotated<Annotation1, ScalerImpl>')
1203def test_inconsistent_signature(ScalerImplAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001204 expect_compile_error(
1205 'FunctorSignatureDoesNotMatchError<ScalerImpl\(double\),ScalerImpl\(float\)>',
1206 'Unexpected functor signature',
1207 COMMON_DEFINITIONS + '''
Marco Poletti6317c252016-11-12 16:26:47 +00001208struct Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001209 virtual double scale(double x) = 0;
1210};
1211
Marco Poletti6317c252016-11-12 16:26:47 +00001212struct ScalerImpl : public Scaler {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001213private:
1214 double factor;
1215
1216public:
1217 ScalerImpl(double factor)
1218 : factor(factor) {
1219 }
1220
1221 double scale(double x) override {
1222 return x * factor;
1223 }
1224};
1225
1226using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1227
Marco Poletti83b1ad82016-11-12 11:24:51 +00001228fruit::Component<ScalerFactory> getScalerComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001229 return fruit::createComponent()
Marco Poletti21111b02016-11-12 10:49:02 +00001230 .bind<Scaler, ScalerImplAnnot>()
Marco Poletti83b1ad82016-11-12 11:24:51 +00001231 .registerFactory<ScalerImplAnnot(fruit::Assisted<double>)>([](float factor) { return ScalerImpl(factor); });
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001232}
1233
1234int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +00001235 fruit::Injector<ScalerFactory> injector(getScalerComponent());
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001236 ScalerFactory scalerFactory(injector);
1237 std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1238 std::cout << scaler->scale(3) << std::endl;
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001239}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001240''',
1241 locals())
1242
1243def test_inconsistent_signature_returning_value():
1244 expect_compile_error(
1245 'FunctorSignatureDoesNotMatchError<Scaler\(double\),Scaler\(float\)>',
1246 'Unexpected functor signature',
1247 COMMON_DEFINITIONS + '''
1248struct Scaler {
1249private:
1250 double factor;
1251
1252public:
1253 Scaler(double factor)
1254 : factor(factor) {
1255 }
1256
1257 double scale(double x) {
1258 return x * factor;
1259 }
1260};
1261
1262using ScalerFactory = std::function<Scaler(double)>;
1263
1264fruit::Component<ScalerFactory> getScalerComponent() {
1265 return fruit::createComponent()
1266 .registerFactory<Scaler(fruit::Assisted<double>)>([](float factor) { return Scaler(factor); });
1267}
1268
1269int main() {
1270 fruit::Injector<ScalerFactory> injector(getScalerComponent());
1271 ScalerFactory scalerFactory(injector);
1272 Scaler scaler = scalerFactory(12.1);
1273 std::cout << scaler.scale(3) << std::endl;
1274}
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001275''')
1276
1277def test_nonmovable_ok():
1278 expect_success(
1279 COMMON_DEFINITIONS + '''
1280struct C {
1281 INJECT(C()) = default;
1282
1283 C(const C&) = delete;
1284 C(C&&) = delete;
1285 C& operator=(const C&) = delete;
1286 C& operator=(C&&) = delete;
1287};
1288
1289using CFactory = std::function<std::unique_ptr<C>()>;
1290
Marco Poletti83b1ad82016-11-12 11:24:51 +00001291fruit::Component<CFactory> getCFactory() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001292 return fruit::createComponent();
1293}
1294
1295int main() {
Marco Poletti83b1ad82016-11-12 11:24:51 +00001296 fruit::Injector<CFactory> injector(getCFactory());
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001297 CFactory cFactory(injector);
1298 std::unique_ptr<C> c = cFactory();
1299 (void)c;
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001300}
1301''')
1302
Marco Polettief4bc1f2016-11-19 17:49:14 +00001303# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message,
1304# or mention that there are other ways to satisfy that dependency.
1305@params(
1306 ('X',
1307 'std::function<X(int)>'),
1308 ('fruit::Annotated<Annotation1, X>',
1309 'fruit::Annotated<Annotation1, std::function<X(int)>>'))
1310def test_not_existing_constructor1(XAnnot, XFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001311 expect_compile_error(
Marco Polettief4bc1f2016-11-19 17:49:14 +00001312 'FunctorSignatureDoesNotMatchError<XAnnot\(int\),XAnnot\(\)>',
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001313 'Unexpected functor signature',
1314 COMMON_DEFINITIONS + '''
1315struct X {
1316 INJECT(X()) = default;
1317};
1318
Marco Polettief4bc1f2016-11-19 17:49:14 +00001319fruit::Component<XFactoryAnnot> getComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001320 return fruit::createComponent();
1321}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001322''',
1323 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001324
Marco Polettief4bc1f2016-11-19 17:49:14 +00001325# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message,
1326# or mention that there are other ways to satisfy that dependency.
1327@params(
1328 ('std::function<std::unique_ptr<X>(int)>',
1329 'std::unique_ptr<X(,std::default_delete<X>)?>\(int\)',
1330 'std::unique_ptr<X(,std::default_delete<X>)?>\(\)'),
1331 ('fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>(int)>>',
1332 'fruit::Annotated<Annotation1,std::unique_ptr<X(,std::default_delete<X>)?>>\(int\)',
1333 'fruit::Annotated<Annotation1,std::unique_ptr<X(,std::default_delete<X>)?>>\(\)'))
1334def test_not_existing_constructor2(XIntFactoryAnnot, XIntFactoryAnnotRegex, XVoidFactoryAnnotRegex):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001335 expect_compile_error(
Marco Polettief4bc1f2016-11-19 17:49:14 +00001336 'FunctorSignatureDoesNotMatchError<XIntFactoryAnnotRegex,XVoidFactoryAnnotRegex>',
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001337 'Unexpected functor signature',
1338 COMMON_DEFINITIONS + '''
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001339struct X {
1340 using Inject = X();
1341};
1342
Marco Polettief4bc1f2016-11-19 17:49:14 +00001343fruit::Component<XIntFactoryAnnot> getComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001344 return fruit::createComponent();
1345}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001346''',
1347 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001348
Marco Polettief4bc1f2016-11-19 17:49:14 +00001349# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message,
1350# or mention that there are other ways to satisfy that dependency.
1351@params(
1352 ('X',
1353 'std::function<X(int)>'),
1354 ('fruit::Annotated<Annotation1, X>',
1355 'fruit::Annotated<Annotation1, std::function<X(int)>>'))
1356def test_not_existing_constructor2_returning_value(XAnnot, XFactoryAnnot):
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001357 expect_compile_error(
Marco Polettief4bc1f2016-11-19 17:49:14 +00001358 'FunctorSignatureDoesNotMatchError<XAnnot\(int\), XAnnot\(\)>',
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001359 'Unexpected functor signature',
1360 COMMON_DEFINITIONS + '''
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001361struct X {
1362 using Inject = X();
1363};
1364
Marco Polettief4bc1f2016-11-19 17:49:14 +00001365fruit::Component<XFactoryAnnot> getComponent() {
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001366 return fruit::createComponent();
1367}
Marco Polettief4bc1f2016-11-19 17:49:14 +00001368''',
1369 locals())
Marco Polettif9b2c6f2016-10-08 18:49:04 +01001370
1371if __name__ == '__main__':
1372 import nose2
1373 nose2.main()