• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/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.
15import pytest
16
17from fruit_test_common import *
18from fruit_test_config import CXX_COMPILER_NAME
19
20COMMON_DEFINITIONS = '''
21    #include "test_common.h"
22
23    struct Scaler;
24    struct ScalerImpl;
25
26    struct Annotation1 {};
27    using ScalerAnnot1 = fruit::Annotated<Annotation1, Scaler>;
28    using ScalerImplAnnot1 = fruit::Annotated<Annotation1, ScalerImpl>;
29
30    struct Annotation2 {};
31    using ScalerAnnot2 = fruit::Annotated<Annotation2, Scaler>;
32    using ScalerImplAnnot2 = fruit::Annotated<Annotation2, ScalerImpl>;
33
34    template <typename T>
35    using WithNoAnnotation = T;
36
37    template <typename T>
38    using WithAnnotation1 = fruit::Annotated<Annotation1, T>;
39    '''
40
41@pytest.mark.parametrize('XFactoryAnnot', [
42    'std::function<X()>',
43    'fruit::Annotated<Annotation1, std::function<X()>>',
44])
45def test_register_factory_success_no_params_autoinject(XFactoryAnnot):
46    source = '''
47        struct X {
48          INJECT(X()) = default;
49        };
50
51        fruit::Component<XFactoryAnnot> getComponent() {
52          return fruit::createComponent();
53        }
54
55        int main() {
56          fruit::Injector<XFactoryAnnot> injector(getComponent);
57          injector.get<XFactoryAnnot>()();
58        }
59        '''
60    expect_success(
61        COMMON_DEFINITIONS,
62        source,
63        locals())
64
65@pytest.mark.parametrize('ConstructX,XPtrAnnot,XPtrFactoryAnnot', [
66    ('X()', 'X', 'std::function<X()>'),
67    ('X()', 'fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, std::function<X()>>'),
68    ('std::unique_ptr<X>()', 'std::unique_ptr<X>', 'std::function<std::unique_ptr<X>()>'),
69    ('std::unique_ptr<X>()', 'fruit::Annotated<Annotation1, std::unique_ptr<X>>', 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>'),
70])
71def test_register_factory_success_no_params(ConstructX, XPtrAnnot, XPtrFactoryAnnot):
72    source = '''
73        struct X {};
74
75        fruit::Component<XPtrFactoryAnnot> getComponent() {
76          return fruit::createComponent()
77            .registerFactory<XPtrAnnot()>([](){return ConstructX;});
78        }
79
80        int main() {
81          fruit::Injector<XPtrFactoryAnnot> injector(getComponent);
82          injector.get<XPtrFactoryAnnot>()();
83        }
84        '''
85    expect_success(
86        COMMON_DEFINITIONS,
87        source,
88        locals())
89
90@pytest.mark.parametrize('MaybeConst', [
91    '',
92    'const',
93])
94def test_register_factory_autoinject_success(MaybeConst):
95    source = '''
96        struct Scaler {
97          virtual double scale(double x) = 0;
98          virtual ~Scaler() = default;
99        };
100
101        struct ScalerImpl : public Scaler {
102        private:
103          double factor;
104
105        public:
106          INJECT(ScalerImpl(ASSISTED(double) factor))
107            : factor(factor) {
108          }
109
110          double scale(double x) override {
111            return x * factor;
112          }
113        };
114
115        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
116
117        fruit::Component<MaybeConst ScalerFactory> getScalerComponent() {
118          return fruit::createComponent()
119            .bind<Scaler, ScalerImpl>();
120        }
121
122        int main() {
123          fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent);
124          ScalerFactory scalerFactory(injector);
125          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
126          std::cout << scaler->scale(3) << std::endl;
127        }
128        '''
129    expect_success(
130        COMMON_DEFINITIONS,
131        source,
132        locals())
133
134def test_register_factory_autoinject_abstract_class_with_no_virtual_destructor_error():
135    source = '''
136        struct Scaler {
137          virtual double scale(double x) = 0;
138        };
139
140        struct ScalerImpl : public Scaler {
141        public:
142          INJECT(ScalerImpl(ASSISTED(double))) {
143          }
144
145          double scale(double x) override {
146            return x;
147          }
148        };
149
150        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
151
152        fruit::Component<ScalerFactory> getScalerComponent() {
153          return fruit::createComponent()
154            .bind<Scaler, ScalerImpl>();
155        }
156        '''
157    expect_compile_error(
158        'FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError<std::function<std::unique_ptr<Scaler(,std::default_delete<Scaler>)?>\(double\)>,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>',
159        'Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr of a class with no virtual destructor',
160        COMMON_DEFINITIONS,
161        source,
162        locals())
163
164def test_register_factory_autoinject_non_abstract_class_with_no_virtual_destructor_error():
165    source = '''
166        struct Scaler {
167        };
168
169        struct ScalerImpl : public Scaler {
170        public:
171          INJECT(ScalerImpl(ASSISTED(double))) {
172          }
173        };
174
175        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
176
177        fruit::Component<ScalerFactory> getScalerComponent() {
178          return fruit::createComponent()
179            .bind<Scaler, ScalerImpl>();
180        }
181        '''
182    expect_compile_error(
183        'FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError<std::function<std::unique_ptr<Scaler(,std::default_delete<Scaler>)?>\(double\)>,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>',
184        'Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr of a class with no virtual destructor',
185        COMMON_DEFINITIONS,
186        source,
187        locals())
188
189@pytest.mark.parametrize('ScalerAnnot,ScalerFactoryAnnot,MaybeConstScalerFactoryAnnot', [
190    ('Scaler',
191     'std::function<std::unique_ptr<Scaler>(double)>',
192     'std::function<std::unique_ptr<Scaler>(double)>'),
193    ('Scaler',
194     'std::function<std::unique_ptr<Scaler>(double)>',
195     'const std::function<std::unique_ptr<Scaler>(double)>'),
196    ('fruit::Annotated<Annotation1, Scaler>',
197     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>',
198     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'),
199    ('fruit::Annotated<Annotation1, Scaler>',
200     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>',
201     'fruit::Annotated<Annotation1, const std::function<std::unique_ptr<Scaler>(double)>>'),
202])
203def test_autoinject(ScalerAnnot, ScalerFactoryAnnot, MaybeConstScalerFactoryAnnot):
204    source = '''
205        struct Scaler {
206          virtual double scale(double x) = 0;
207          virtual ~Scaler() = default;
208        };
209
210        struct ScalerImpl : public Scaler {
211        private:
212          double factor;
213
214        public:
215          INJECT(ScalerImpl(ASSISTED(double) factor))
216            : factor(factor) {
217          }
218
219          double scale(double x) override {
220            return x * factor;
221          }
222        };
223
224        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
225
226        fruit::Component<MaybeConstScalerFactoryAnnot> getScalerComponent() {
227          return fruit::createComponent()
228            .bind<ScalerAnnot, ScalerImpl>();
229        }
230
231        int main() {
232          fruit::Injector<MaybeConstScalerFactoryAnnot> injector(getScalerComponent);
233          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
234          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
235          std::cout << scaler->scale(3) << std::endl;
236        }
237        '''
238    expect_success(
239        COMMON_DEFINITIONS,
240        source,
241        locals())
242
243@pytest.mark.parametrize('MaybeConst', [
244    '',
245    'const',
246])
247def test_autoinject_returning_value(MaybeConst):
248    source = '''
249        struct X {
250          INJECT(X()) = default;
251        };
252
253        struct Scaler {
254        private:
255          double factor;
256
257        public:
258          INJECT(Scaler(ASSISTED(double) factor, X))
259            : factor(factor) {
260          }
261
262          double scale(double x) {
263            return x * factor;
264          }
265        };
266
267        using ScalerFactory = std::function<Scaler(double)>;
268
269        fruit::Component<MaybeConst ScalerFactory> getScalerComponent() {
270          return fruit::createComponent();
271        }
272
273        int main() {
274          fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent);
275          ScalerFactory scalerFactory(injector);
276          Scaler scaler = scalerFactory(12.1);
277          std::cout << scaler.scale(3) << std::endl;
278        }
279        '''
280    expect_success(
281        COMMON_DEFINITIONS,
282        source,
283        locals())
284
285@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerFactoryAnnot,ScalerImplFactoryAnnotRegex', [
286    ('Scaler',
287     'ScalerImpl',
288     'std::function<std::unique_ptr<Scaler>(double)>',
289     'std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>',
290    ),
291    ('fruit::Annotated<Annotation1, Scaler>',
292     'fruit::Annotated<Annotation2, ScalerImpl>',
293     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>',
294     'fruit::Annotated<Annotation2,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>',
295    ),
296])
297def test_autoinject_error_abstract_class(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot, ScalerImplFactoryAnnotRegex):
298    source = '''
299        struct Scaler {
300          virtual double scale(double x) = 0;
301        };
302
303        struct ScalerImpl : public Scaler {
304        private:
305          double factor;
306
307        public:
308          ScalerImpl(double factor)
309            : factor(factor) {
310          }
311
312          // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class.
313        };
314
315        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
316          return fruit::createComponent()
317            .bind<ScalerAnnot, ScalerImplAnnot>();
318        }
319        '''
320    expect_compile_error(
321        'NoBindingFoundForAbstractClassError<ScalerImplFactoryAnnotRegex,ScalerImpl>',
322        'No explicit binding was found for T, and note that C is an abstract class',
323        COMMON_DEFINITIONS,
324        source,
325        locals())
326
327def test_autoinject_nonmovable_ok():
328    source = '''
329        struct I {
330          virtual ~I() = default;
331        };
332
333        struct C : public I {
334          INJECT(C()) = default;
335
336          C(const C&) = delete;
337          C(C&&) = delete;
338          C& operator=(const C&) = delete;
339          C& operator=(C&&) = delete;
340        };
341
342        using IFactory = std::function<std::unique_ptr<I>()>;
343
344        fruit::Component<IFactory> getIFactory() {
345          return fruit::createComponent()
346              .bind<I, C>();
347        }
348
349        int main() {
350          fruit::Injector<IFactory> injector(getIFactory);
351          IFactory iFactory(injector);
352          std::unique_ptr<I> i = iFactory();
353          (void)i;
354        }
355        '''
356    expect_success(
357        COMMON_DEFINITIONS,
358        source)
359
360def test_autoinject_2_assisted_params():
361    source = '''
362        struct Foo {
363          Foo(int x, float y) {
364            (void)x;
365            (void)y;
366          }
367        };
368
369        using FooFactory = std::function<Foo(int, float)>;
370
371        fruit::Component<FooFactory> getComponent() {
372          return fruit::createComponent()
373              .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>)>(
374                  [](int x, float y) {
375                    return Foo(x, y);
376                  });
377        }
378
379        int main() {
380          fruit::Injector<FooFactory> injector(getComponent);
381          FooFactory fooFactory(injector);
382          Foo foo = fooFactory(1, 2.3f);
383          (void)foo;
384        }
385        '''
386    expect_success(
387        COMMON_DEFINITIONS,
388        source)
389
390def test_autoinject_2_assisted_params_returning_value():
391    source = '''
392        struct Foo {
393          Foo(int x, float y) {
394            (void)x;
395            (void)y;
396          }
397        };
398
399        using FooFactory = std::function<Foo(int, float)>;
400
401        fruit::Component<FooFactory> getComponent() {
402          return fruit::createComponent()
403              .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>)>(
404                  [](int x, float y) {
405                    return Foo(x, y);
406                  });
407        }
408
409        int main() {
410          fruit::Injector<FooFactory> injector(getComponent);
411          FooFactory fooFactory(injector);
412          Foo foo = fooFactory(1, 2.3f);
413          (void)foo;
414        }
415        '''
416    expect_success(
417        COMMON_DEFINITIONS,
418        source)
419
420def test_autoinject_instances_bound_to_assisted_params():
421    source = '''
422        struct X {};
423        struct Y {};
424
425        struct Foo {
426          Foo(X x, Y y) {
427            (void)x;
428            (void)y;
429          }
430        };
431
432        using FooFactory = std::function<Foo()>;
433
434        fruit::Component<FooFactory> getComponent() {
435          static X x = X();
436          static Y y = Y();
437          return fruit::createComponent()
438              .bindInstance(x)
439              .bindInstance(y)
440              .registerFactory<Foo(X, Y)>(
441                  [](X x, Y y) {
442                    return Foo(x, y);
443                  });
444        }
445
446
447        int main() {
448          fruit::Injector<FooFactory> injector(getComponent);
449          FooFactory fooFactory(injector);
450          Foo foo = fooFactory();
451          (void)foo;
452        }
453        '''
454    expect_success(
455        COMMON_DEFINITIONS,
456        source)
457
458def test_autoinject_2_assisted_params_plus_nonassisted_params():
459    source = '''
460        struct X {};
461        struct Y {};
462        struct Z {};
463
464        struct Foo {
465          Foo(X, Y, int, float, Z) {
466          }
467        };
468
469        using FooPtrFactory = std::function<std::unique_ptr<Foo>(int, float)>;
470
471        fruit::Component<FooPtrFactory> getComponent() {
472          static X x = X();
473          static Y y = Y();
474          static Z z = Z();
475          return fruit::createComponent()
476              .bindInstance(x)
477              .bindInstance(y)
478              .bindInstance(z)
479              .registerFactory<std::unique_ptr<Foo>(X, Y, fruit::Assisted<int>, fruit::Assisted<float>, Z)>(
480                  [](X x, Y y, int n, float a, Z z) {
481                    return std::unique_ptr<Foo>(new Foo(x, y, n, a, z));
482                  });
483        }
484
485        int main() {
486          fruit::Injector<FooPtrFactory> injector(getComponent);
487          FooPtrFactory fooPtrFactory(injector);
488          std::unique_ptr<Foo> foo = fooPtrFactory(1, 3.4f);
489          (void)foo;
490        }
491        '''
492    expect_success(
493        COMMON_DEFINITIONS,
494        source)
495
496def test_autoinject_2_assisted_params_plus_nonassisted_params_returning_value():
497    source = '''
498        struct X {};
499        struct Y {};
500        struct Z {};
501
502        struct Foo {
503          Foo(X, Y, int, float, Z) {
504          }
505        };
506
507        using FooFactory = std::function<Foo(int, float)>;
508
509        fruit::Component<FooFactory> getComponent() {
510          static X x = X();
511          static Y y = Y();
512          static Z z = Z();
513          return fruit::createComponent()
514              .bindInstance(x)
515              .bindInstance(y)
516              .bindInstance(z)
517              .registerFactory<Foo(X, Y, fruit::Assisted<int>, fruit::Assisted<float>, Z)>(
518                  [](X x, Y y, int n, float a, Z z) {
519                    return Foo(x, y, n, a, z);
520                  });
521        }
522
523        int main() {
524          fruit::Injector<FooFactory> injector(getComponent);
525          FooFactory fooFactory(injector);
526          Foo foo = fooFactory(1, 3.4f);
527          (void)foo;
528        }
529        '''
530    expect_success(
531        COMMON_DEFINITIONS,
532        source)
533
534def test_autoinject_mixed_assisted_and_injected_params():
535    source = '''
536        struct X {};
537        struct Y {};
538
539        struct Foo {
540          Foo(int, float, X, Y, double) {
541          }
542        };
543
544        using FooFactory = std::function<Foo(int, float, double)>;
545
546        fruit::Component<FooFactory> getComponent() {
547          static X x = X();
548          static Y y = Y();
549          return fruit::createComponent()
550              .bindInstance(x)
551              .bindInstance(y)
552              .registerFactory<Foo(fruit::Assisted<int>, fruit::Assisted<float>, X, Y, fruit::Assisted<double>)>(
553                  [](int n, float a, X x, Y y, double d) {
554                    return Foo(n, a, x, y, d);
555                  });
556        }
557
558        int main() {
559          fruit::Injector<FooFactory> injector(getComponent);
560          FooFactory fooFactory(injector);
561          Foo foo = fooFactory(1, 3.4f, 3.456);
562          (void)foo;
563        }
564        '''
565    expect_success(
566        COMMON_DEFINITIONS,
567        source)
568
569def test_autoinject_annotation_in_signature_return_type():
570    source = '''
571        struct X {
572          using Inject = fruit::Annotated<Annotation1, X>();
573        };
574
575        fruit::Component<fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>> getComponent() {
576          return fruit::createComponent();
577        }
578        '''
579    expect_compile_error(
580        'InjectTypedefWithAnnotationError<X>',
581        'C::Inject is a signature that returns an annotated type',
582        COMMON_DEFINITIONS,
583        source)
584
585def test_autoinject_annotation_in_signature_return_type_returning_value():
586    source = '''
587        struct X {
588          using Inject = fruit::Annotated<Annotation1, X>();
589        };
590
591        fruit::Component<fruit::Annotated<Annotation1, std::function<X()>>> getComponent() {
592          return fruit::createComponent();
593        }
594        '''
595    expect_compile_error(
596        'InjectTypedefWithAnnotationError<X>',
597        'C::Inject is a signature that returns an annotated type',
598        COMMON_DEFINITIONS,
599        source)
600
601def test_autoinject_from_provider_simple():
602    source = '''
603        struct X {
604          INJECT(X()) = default;
605        };
606
607        struct Scaler {
608          virtual double scale(double x) = 0;
609          virtual ~Scaler() = default;
610        };
611
612        struct ScalerImpl : public Scaler {
613        private:
614          double factor;
615
616        public:
617          ScalerImpl(double factor, X)
618            : factor(factor) {
619          }
620
621          double scale(double x) override {
622            return x * factor;
623          }
624        };
625
626        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
627
628        fruit::Component<ScalerFactory> getScalerComponent() {
629          return fruit::createComponent()
630            .registerProvider([](X x) {
631              return std::function<std::unique_ptr<ScalerImpl>(double)>([x](double n){
632                return std::unique_ptr<ScalerImpl>(new ScalerImpl(n, x));
633              });
634            })
635            .bind<Scaler, ScalerImpl>();
636        }
637
638        int main() {
639          fruit::Injector<ScalerFactory> injector(getScalerComponent);
640          ScalerFactory scalerFactory(injector);
641          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
642          std::cout << scaler->scale(3) << std::endl;
643        }
644        '''
645    expect_success(
646        COMMON_DEFINITIONS,
647        source)
648
649@pytest.mark.parametrize('ScalerAnnot,ScalerFactoryAnnot,MaybeConstScalerFactoryAnnot,ScalerImplAnnot,ScalerImplFactoryAnnot', [
650    ('Scaler',
651     'std::function<std::unique_ptr<Scaler>(double)>',
652     'std::function<std::unique_ptr<Scaler>(double)>',
653     'ScalerImpl',
654     'std::function<std::unique_ptr<ScalerImpl>(double)>'),
655    ('Scaler',
656     'std::function<std::unique_ptr<Scaler>(double)>',
657     'const std::function<std::unique_ptr<Scaler>(double)>',
658     'ScalerImpl',
659     'std::function<std::unique_ptr<ScalerImpl>(double)>'),
660    ('fruit::Annotated<Annotation1, Scaler>',
661     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>',
662     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>',
663     'fruit::Annotated<Annotation2, ScalerImpl>',
664     'fruit::Annotated<Annotation2, std::function<std::unique_ptr<ScalerImpl>(double)>>'),
665    ('fruit::Annotated<Annotation1, Scaler>',
666     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>',
667     'fruit::Annotated<Annotation1, const std::function<std::unique_ptr<Scaler>(double)>>',
668     'fruit::Annotated<Annotation2, ScalerImpl>',
669     'fruit::Annotated<Annotation2, std::function<std::unique_ptr<ScalerImpl>(double)>>'),
670])
671def test_autoinject_from_provider(ScalerAnnot, ScalerFactoryAnnot, MaybeConstScalerFactoryAnnot, ScalerImplAnnot, ScalerImplFactoryAnnot):
672    source = '''
673        struct X {
674          INJECT(X()) = default;
675        };
676
677        struct Scaler {
678          virtual double scale(double x) = 0;
679          virtual ~Scaler() = default;
680        };
681
682        struct ScalerImpl : public Scaler {
683        private:
684          double factor;
685
686        public:
687          ScalerImpl(double factor, X)
688            : factor(factor) {
689          }
690
691          double scale(double x) override {
692            return x * factor;
693          }
694        };
695
696        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
697        using ScalerImplFactory = std::function<std::unique_ptr<ScalerImpl>(double)>;
698
699        fruit::Component<MaybeConstScalerFactoryAnnot> getScalerComponent() {
700          return fruit::createComponent()
701            .registerProvider<ScalerImplFactoryAnnot(X)>([](X x) {
702              return std::function<std::unique_ptr<ScalerImpl>(double)>([x](double n){
703                return std::unique_ptr<ScalerImpl>(new ScalerImpl(n, x));
704              });
705            })
706            .bind<ScalerAnnot, ScalerImplAnnot>();
707        }
708
709        int main() {
710          fruit::Injector<MaybeConstScalerFactoryAnnot> injector(getScalerComponent);
711          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
712          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
713          std::cout << scaler->scale(3) << std::endl;
714        }
715        '''
716    expect_success(
717        COMMON_DEFINITIONS,
718        source,
719        locals())
720
721@pytest.mark.parametrize('ScalerFactoryAnnot', [
722    'ScalerFactory',
723    'fruit::Annotated<Annotation1, ScalerFactory>',
724])
725def test_autoinject_from_provider_returning_value(ScalerFactoryAnnot):
726    source = '''
727        struct X {
728          INJECT(X()) = default;
729        };
730
731        struct Scaler {
732        private:
733          double factor;
734
735        public:
736          Scaler(double factor, X)
737            : factor(factor) {
738          }
739
740          double scale(double x) {
741            return x * factor;
742          }
743        };
744
745        using ScalerFactory = std::function<Scaler(double)>;
746
747        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
748          return fruit::createComponent()
749            .registerProvider<ScalerFactoryAnnot(X)>([](X x) {
750              return std::function<Scaler(double)>([x](double n){
751                return Scaler(n, x);
752              });
753            });
754        }
755
756        int main() {
757          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
758          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
759          Scaler scaler = scalerFactory(12.1);
760          std::cout << scaler.scale(3) << std::endl;
761        }
762        '''
763    expect_success(
764        COMMON_DEFINITIONS,
765        source,
766        locals())
767
768@pytest.mark.parametrize('MaybeConst', [
769    '',
770    'const',
771])
772@pytest.mark.parametrize('X_ANNOT', [
773    'X',
774    'ANNOTATED(Annotation1, X)',
775])
776def test_autoinject_with_binding(MaybeConst, X_ANNOT):
777    source = '''
778        struct X {
779          using Inject = X();
780        };
781
782        struct Scaler {
783          virtual double scale(double x) = 0;
784          virtual ~Scaler() = default;
785        };
786
787        struct ScalerImpl : public Scaler {
788        private:
789          double factor;
790
791        public:
792          INJECT(ScalerImpl(ASSISTED(double) factor, X_ANNOT x))
793            : factor(factor) {
794              (void)x;
795          }
796
797          double scale(double x) override {
798            return x * factor;
799          }
800        };
801
802        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
803
804        fruit::Component<MaybeConst ScalerFactory> getScalerComponent() {
805          return fruit::createComponent()
806            .bind<Scaler, ScalerImpl>();
807        }
808
809        int main() {
810          fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent);
811          ScalerFactory scalerFactory(injector);
812          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
813          std::cout << scaler->scale(3) << std::endl;
814        }
815        '''
816    expect_success(
817        COMMON_DEFINITIONS,
818        source,
819        locals())
820
821@pytest.mark.parametrize('MaybeConst', [
822    '',
823    'const',
824])
825@pytest.mark.parametrize('X_ANNOT', [
826    'X',
827    'ANNOTATED(Annotation1, X)',
828])
829def test_autoinject_with_binding_returning_value(MaybeConst, X_ANNOT):
830    source = '''
831        struct X {
832          using Inject = X();
833        };
834
835        struct Scaler {
836        private:
837          double factor;
838
839        public:
840          INJECT(Scaler(ASSISTED(double) factor, X_ANNOT x))
841            : factor(factor) {
842              (void)x;
843          }
844
845          double scale(double x) {
846            return x * factor;
847          }
848        };
849
850        using ScalerFactory = std::function<Scaler(double)>;
851
852        fruit::Component<MaybeConst ScalerFactory> getScalerComponent() {
853          return fruit::createComponent();
854        }
855
856        int main() {
857          fruit::Injector<MaybeConst ScalerFactory> injector(getScalerComponent);
858          ScalerFactory scalerFactory(injector);
859          Scaler scaler = scalerFactory(12.1);
860          std::cout << scaler.scale(3) << std::endl;
861        }
862        '''
863    expect_success(
864        COMMON_DEFINITIONS,
865        source,
866        locals())
867
868def test_autoinject_with_binding2():
869    source = '''
870        struct X {
871          INJECT(X()) = default;
872        };
873
874        struct Scaler {
875          virtual double scale(double x) = 0;
876          virtual ~Scaler() = default;
877        };
878
879        struct ScalerImpl : public Scaler {
880        private:
881          double factor;
882
883        public:
884          INJECT(ScalerImpl(X, ASSISTED(double) factor))
885            : factor(factor) {
886          }
887
888          double scale(double x) override {
889            return x * factor;
890          }
891        };
892
893        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
894
895        fruit::Component<ScalerFactory> getScalerComponent() {
896          return fruit::createComponent()
897            .bind<Scaler, ScalerImpl>();
898        }
899
900        int main() {
901          fruit::Injector<ScalerFactory> injector(getScalerComponent);
902          ScalerFactory scalerFactory(injector);
903          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
904          std::cout << scaler->scale(3) << std::endl;
905        }
906        '''
907    expect_success(
908        COMMON_DEFINITIONS,
909        source)
910
911def test_autoinject_with_binding2_returning_value():
912    source = '''
913        struct X {
914          INJECT(X()) = default;
915        };
916
917        struct Scaler {
918        private:
919          double factor;
920
921        public:
922          INJECT(Scaler(X, ASSISTED(double) factor))
923            : factor(factor) {
924          }
925
926          double scale(double x) {
927            return x * factor;
928          }
929        };
930
931        using ScalerFactory = std::function<Scaler(double)>;
932
933        fruit::Component<ScalerFactory> getScalerComponent() {
934          return fruit::createComponent();
935        }
936
937        int main() {
938          fruit::Injector<ScalerFactory> injector(getScalerComponent);
939          ScalerFactory scalerFactory(injector);
940          Scaler scaler = scalerFactory(12.1);
941          std::cout << scaler.scale(3) << std::endl;
942        }
943        '''
944    expect_success(
945        COMMON_DEFINITIONS,
946        source)
947
948@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerFactoryAnnot', [
949    ('Scaler',
950     'ScalerImpl',
951     'std::function<std::unique_ptr<Scaler>(double)>'),
952    ('fruit::Annotated<Annotation1, Scaler>',
953     'fruit::Annotated<Annotation2, ScalerImpl>',
954     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'),
955])
956def test_register_factory_success(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot):
957    source = '''
958        struct Scaler {
959          virtual double scale(double x) = 0;
960          virtual ~Scaler() = default;
961        };
962
963        struct ScalerImpl : public Scaler {
964        private:
965          double factor;
966
967        public:
968          ScalerImpl(double factor)
969            : factor(factor) {
970          }
971
972          double scale(double x) override {
973            return x * factor;
974          }
975        };
976
977        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
978
979        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
980          return fruit::createComponent()
981            .bind<ScalerAnnot, ScalerImplAnnot>()
982            .registerFactory<ScalerImplAnnot(fruit::Assisted<double>)>([](double factor) { return ScalerImpl(factor); });
983        }
984
985        int main() {
986          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
987          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
988          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
989          std::cout << scaler->scale(3) << std::endl;
990        }
991        '''
992    expect_success(
993        COMMON_DEFINITIONS,
994        source,
995        locals())
996
997def test_register_factory_with_annotation_returning_value():
998    source = '''
999        struct Scaler {
1000        private:
1001          double factor;
1002
1003        public:
1004          Scaler(double factor)
1005            : factor(factor) {
1006          }
1007
1008          double scale(double x) {
1009            return x * factor;
1010          }
1011        };
1012
1013        using ScalerFactory = std::function<Scaler(double)>;
1014        using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>;
1015
1016        fruit::Component<ScalerFactoryAnnot1> getScalerComponent() {
1017          return fruit::createComponent()
1018            .registerFactory<ScalerAnnot1(fruit::Assisted<double>)>(
1019              [](double factor) {
1020                  return Scaler(factor);
1021              });
1022        }
1023
1024        int main() {
1025          fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent);
1026          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>();
1027          Scaler scaler = scalerFactory(12.1);
1028          std::cout << scaler.scale(3) << std::endl;
1029        }
1030        '''
1031    expect_success(
1032        COMMON_DEFINITIONS,
1033        source)
1034
1035def test_register_factory_with_different_annotation():
1036    source = '''
1037        struct Scaler {
1038          virtual double scale(double x) = 0;
1039          virtual ~Scaler() = default;
1040        };
1041
1042        struct ScalerImpl : public Scaler {
1043        private:
1044          double factor;
1045
1046        public:
1047          ScalerImpl(double factor)
1048            : factor(factor) {
1049          }
1050
1051          double scale(double x) override {
1052            return x * factor;
1053          }
1054        };
1055
1056        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1057        using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>;
1058
1059        fruit::Component<ScalerFactoryAnnot1> getScalerComponent() {
1060          return fruit::createComponent()
1061            .bind<ScalerAnnot1, ScalerImplAnnot2>()
1062            .registerFactory<ScalerImplAnnot2(fruit::Assisted<double>)>(
1063                [](double factor) {
1064                    return ScalerImpl(factor);
1065                });
1066        }
1067
1068        int main() {
1069          fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent);
1070          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>();
1071          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1072          std::cout << scaler->scale(3) << std::endl;
1073        }
1074        '''
1075    expect_success(
1076        COMMON_DEFINITIONS,
1077        source)
1078
1079
1080@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerFactoryAnnot', [
1081    ('Scaler',
1082     'ScalerImpl',
1083     'std::function<std::unique_ptr<Scaler>(double, double)>'),
1084    ('fruit::Annotated<Annotation1, Scaler>',
1085     'fruit::Annotated<Annotation2, ScalerImpl>',
1086     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double, double)>>'),
1087])
1088def test_register_factory_2arg_success(ScalerAnnot, ScalerImplAnnot, ScalerFactoryAnnot):
1089    source = '''
1090        struct Scaler {
1091          virtual double scale(double x) = 0;
1092          virtual ~Scaler() = default;
1093        };
1094
1095        struct ScalerImpl : public Scaler {
1096        private:
1097          double factor;
1098
1099        public:
1100          ScalerImpl(double factor)
1101            : factor(factor) {
1102          }
1103
1104          double scale(double x) override {
1105            return x * factor;
1106          }
1107        };
1108
1109        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double, double)>;
1110
1111        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
1112          return fruit::createComponent()
1113            .bind<ScalerAnnot, ScalerImplAnnot>()
1114            .registerFactory<ScalerImplAnnot(fruit::Assisted<double>, fruit::Assisted<double>)>(
1115                [](double factor, double) {
1116                    return ScalerImpl(factor);
1117                });
1118        }
1119
1120        int main() {
1121          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
1122          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
1123          std::unique_ptr<Scaler> scaler = scalerFactory(12.1, 34.2);
1124          std::cout << scaler->scale(3) << std::endl;
1125        }
1126        '''
1127    expect_success(
1128        COMMON_DEFINITIONS,
1129        source,
1130        locals())
1131
1132def test_register_factory_with_different_annotation_error():
1133    source = '''
1134        struct Scaler {
1135          virtual double scale(double x) = 0;
1136        };
1137
1138        struct ScalerImpl : public Scaler {
1139        private:
1140          double factor;
1141
1142        public:
1143          ScalerImpl(double factor)
1144            : factor(factor) {
1145          }
1146
1147          double scale(double x) override {
1148            return x * factor;
1149          }
1150        };
1151
1152        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1153        using ScalerFactoryAnnot1 = fruit::Annotated<Annotation1, ScalerFactory>;
1154
1155        fruit::Component<ScalerFactoryAnnot1> getScalerComponent() {
1156          return fruit::createComponent()
1157            .bind<ScalerAnnot1, ScalerImplAnnot1>()
1158            .registerFactory<ScalerImplAnnot2(fruit::Assisted<double>)>([](double factor) { return ScalerImpl(factor); });
1159        }
1160
1161        int main() {
1162          fruit::Injector<ScalerFactoryAnnot1> injector(getScalerComponent);
1163          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot1>();
1164          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1165          std::cout << scaler->scale(3) << std::endl;
1166        }
1167        '''
1168    expect_compile_error(
1169        'NoBindingFoundError<fruit::Annotated<Annotation1,std::function<std::unique_ptr<ScalerImpl(,std::default_delete<ScalerImpl>)?>\(double\)>>>',
1170        '',
1171        COMMON_DEFINITIONS,
1172        source)
1173
1174
1175def test_register_factory_dep_on_provider():
1176    source = '''
1177        struct Scaler {
1178          virtual double scale(double x) = 0;
1179          virtual ~Scaler() = default;
1180        };
1181
1182        struct ScalerImpl : public Scaler {
1183        private:
1184          double factor;
1185
1186        public:
1187          ScalerImpl(double factor)
1188            : factor(factor) {
1189          }
1190
1191          double scale(double x) override {
1192            return x * factor;
1193          }
1194        };
1195
1196        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1197
1198        fruit::Component<ScalerFactory> getScalerComponent() {
1199          return fruit::createComponent()
1200            .bind<Scaler, ScalerImpl>()
1201            .registerProvider([](){return 23;})
1202            .registerFactory<ScalerImpl(fruit::Assisted<double>, fruit::Provider<int>)>(
1203                [](double factor, fruit::Provider<int> provider) {
1204                    return ScalerImpl(factor * provider.get<int>());
1205                });
1206        }
1207
1208        int main() {
1209          fruit::Injector<ScalerFactory> injector(getScalerComponent);
1210          ScalerFactory scalerFactory(injector);
1211          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1212          std::cout << scaler->scale(3) << std::endl;
1213        }
1214        '''
1215    expect_success(
1216        COMMON_DEFINITIONS,
1217        source)
1218
1219def test_register_factory_dep_on_provider_returning_value():
1220    source = '''
1221        struct Scaler {
1222        private:
1223          double factor;
1224
1225        public:
1226          Scaler(double factor)
1227            : factor(factor) {
1228          }
1229
1230          double scale(double x) {
1231            return x * factor;
1232          }
1233        };
1234
1235        using ScalerFactory = std::function<Scaler(double)>;
1236
1237        fruit::Component<ScalerFactory> getScalerComponent() {
1238          return fruit::createComponent()
1239            .registerProvider([](){return 23;})
1240            .registerFactory<Scaler(fruit::Assisted<double>, fruit::Provider<int>)>(
1241                [](double factor, fruit::Provider<int> provider) {
1242                    return Scaler(factor * provider.get<int>());
1243                });
1244        }
1245
1246        int main() {
1247          fruit::Injector<ScalerFactory> injector(getScalerComponent);
1248          ScalerFactory scalerFactory(injector);
1249          Scaler scaler = scalerFactory(12.1);
1250          std::cout << scaler.scale(3) << std::endl;
1251        }
1252        '''
1253    expect_success(
1254        COMMON_DEFINITIONS,
1255        source)
1256
1257def test_register_factory_error_abstract_class():
1258    source = '''
1259        struct Scaler {
1260          virtual double scale(double x) = 0;
1261        };
1262
1263        struct ScalerImpl : public Scaler {
1264        private:
1265          double factor;
1266
1267        public:
1268          ScalerImpl(double factor)
1269            : factor(factor) {
1270          }
1271
1272          // Note: here we "forgot" to implement scale() (on purpose, for this test) so ScalerImpl is an abstract class.
1273        };
1274
1275        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1276
1277        fruit::Component<ScalerFactory> getScalerComponent() {
1278          return fruit::createComponent()
1279            .bind<Scaler, ScalerImpl>()
1280            .registerFactory<fruit::Annotated<Annotation1, ScalerImpl>(fruit::Assisted<double>)>([](double) { return (ScalerImpl*)nullptr; });
1281        }
1282        '''
1283    expect_compile_error(
1284        'CannotConstructAbstractClassError<ScalerImpl>',
1285        'The specified class can.t be constructed because it.s an abstract class.',
1286        COMMON_DEFINITIONS,
1287        source)
1288
1289def test_register_factory_error_not_function():
1290    source = '''
1291        struct X {
1292          X(int) {}
1293        };
1294
1295        fruit::Component<std::function<X()>> getComponent() {
1296          int n = 3;
1297          return fruit::createComponent()
1298            .registerFactory<X()>([=]{return X(n);});
1299        }
1300        '''
1301    expect_compile_error(
1302        'LambdaWithCapturesError<.*>',
1303        'Only lambdas with no captures are supported',
1304        COMMON_DEFINITIONS,
1305        source)
1306
1307@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerImplPtrAnnot,ScalerFactoryAnnot,ScalerImplFactorySignatureAnnotRegex', [
1308    ('Scaler',
1309     'ScalerImpl',
1310     'ScalerImpl*',
1311     'std::function<std::unique_ptr<Scaler>(double)>',
1312     'ScalerImpl\*\(fruit::Assisted<double>\)'),
1313    ('fruit::Annotated<Annotation1, Scaler>',
1314     'fruit::Annotated<Annotation2, ScalerImpl>',
1315     'fruit::Annotated<Annotation2, ScalerImpl*>',
1316     'fruit::Annotated<Annotation2, std::function<std::unique_ptr<Scaler>(double)>>',
1317     'fruit::Annotated<Annotation2,ScalerImpl\*>\(fruit::Assisted<double>\)')
1318])
1319def test_register_factory_for_pointer(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot, ScalerImplFactorySignatureAnnotRegex):
1320    source = '''
1321        struct Scaler {
1322          virtual double scale(double x) = 0;
1323        };
1324
1325        struct ScalerImpl : public Scaler {
1326        private:
1327          double factor;
1328
1329        public:
1330          ScalerImpl(double factor)
1331            : factor(factor) {
1332          }
1333
1334          double scale(double x) override {
1335            return x * factor;
1336          }
1337        };
1338
1339        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1340
1341        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
1342          return fruit::createComponent()
1343            .bind<ScalerAnnot, ScalerImplAnnot>()
1344            .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>([](double factor) { return new ScalerImpl(factor); });
1345        }
1346
1347        int main() {
1348          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
1349          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
1350          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1351          std::cout << scaler->scale(3) << std::endl;
1352        }
1353        '''
1354    expect_compile_error(
1355        'FactoryReturningPointerError<ScalerImplFactorySignatureAnnotRegex>',
1356        'The specified factory returns a pointer. This is not supported',
1357        COMMON_DEFINITIONS,
1358        source,
1359        locals())
1360
1361@pytest.mark.parametrize('ScalerPtrAnnot,ScalerFactoryAnnot,ScalerFactorySignatureAnnotRegex', [
1362    ('Scaler*',
1363     'std::function<Scaler(double)>',
1364     'Scaler\*\(fruit::Assisted<double>\)'),
1365    ('fruit::Annotated<Annotation1, Scaler*>',
1366     'fruit::Annotated<Annotation1, std::function<Scaler(double)>>',
1367     'fruit::Annotated<Annotation1,Scaler\*>\(fruit::Assisted<double>\)'),
1368])
1369def test_register_factory_for_pointer_returning_value(ScalerPtrAnnot, ScalerFactoryAnnot, ScalerFactorySignatureAnnotRegex):
1370    source = '''
1371        struct Scaler {
1372        private:
1373          double factor;
1374
1375        public:
1376          Scaler(double factor)
1377            : factor(factor) {
1378          }
1379
1380          double scale(double x) {
1381            return x * factor;
1382          }
1383        };
1384
1385        using ScalerFactory = std::function<Scaler(double)>;
1386
1387        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
1388          return fruit::createComponent()
1389            .registerFactory<ScalerPtrAnnot(fruit::Assisted<double>)>([](double factor) { return new Scaler(factor); });
1390        }
1391
1392        int main() {
1393          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
1394          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
1395          Scaler scaler = scalerFactory(12.1);
1396          std::cout << scaler.scale(3) << std::endl;
1397        }
1398        '''
1399    expect_compile_error(
1400        'FactoryReturningPointerError<ScalerFactorySignatureAnnotRegex>',
1401        'The specified factory returns a pointer. This is not supported',
1402        COMMON_DEFINITIONS,
1403        source,
1404        locals())
1405
1406@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerImplPtrAnnot,ScalerFactoryAnnot', [
1407    ('Scaler',
1408     'ScalerImpl',
1409     'std::unique_ptr<ScalerImpl>',
1410     'std::function<std::unique_ptr<Scaler>(double)>'),
1411    ('fruit::Annotated<Annotation1, Scaler>',
1412     'fruit::Annotated<Annotation2, ScalerImpl>',
1413     'fruit::Annotated<Annotation2, std::unique_ptr<ScalerImpl>>',
1414     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'),
1415])
1416def test_register_factory_for_unique_pointer(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot):
1417    source = '''
1418        struct Scaler {
1419          virtual double scale(double x) = 0;
1420          virtual ~Scaler() = default;
1421        };
1422
1423        struct ScalerImpl : public Scaler {
1424        private:
1425          double factor;
1426
1427        public:
1428          ScalerImpl(double factor)
1429            : factor(factor) {
1430          }
1431
1432          double scale(double x) override {
1433            return x * factor;
1434          }
1435        };
1436
1437        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1438
1439        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
1440          return fruit::createComponent()
1441            .bind<ScalerAnnot, ScalerImplAnnot>()
1442            .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>(
1443                [](double factor) {
1444                    return std::unique_ptr<ScalerImpl>(new ScalerImpl(factor));
1445                });
1446        }
1447
1448        int main() {
1449          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
1450          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
1451          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1452          std::cout << scaler->scale(3) << std::endl;
1453        }
1454        '''
1455    expect_success(
1456        COMMON_DEFINITIONS,
1457        source,
1458        locals())
1459
1460@pytest.mark.parametrize('ScalerAnnot,ScalerImplAnnot,ScalerImplPtrAnnot,ScalerFactoryAnnot', [
1461    ('Scaler',
1462     'ScalerImpl',
1463     'std::unique_ptr<ScalerImpl>',
1464     'std::function<std::unique_ptr<Scaler>(double)>'),
1465    ('fruit::Annotated<Annotation1, Scaler>',
1466     'fruit::Annotated<Annotation2, ScalerImpl>',
1467     'fruit::Annotated<Annotation2, std::unique_ptr<ScalerImpl>>',
1468     'fruit::Annotated<Annotation1, std::function<std::unique_ptr<Scaler>(double)>>'),
1469])
1470def test_register_factory_for_unique_pointer_returning_invalid_unique_ptr_ok(ScalerAnnot, ScalerImplAnnot, ScalerImplPtrAnnot, ScalerFactoryAnnot):
1471    source = '''
1472        struct Scaler {
1473          virtual double scale(double x) = 0;
1474          virtual ~Scaler() = default;
1475        };
1476
1477        struct ScalerImpl : public Scaler {
1478        private:
1479          double factor;
1480
1481        public:
1482          ScalerImpl(double factor)
1483            : factor(factor) {
1484          }
1485
1486          double scale(double x) override {
1487            return x * factor;
1488          }
1489        };
1490
1491        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1492
1493        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
1494          return fruit::createComponent()
1495            .bind<ScalerAnnot, ScalerImplAnnot>()
1496            .registerFactory<ScalerImplPtrAnnot(fruit::Assisted<double>)>(
1497                [](double) {
1498                    return std::unique_ptr<ScalerImpl>(nullptr);
1499                });
1500        }
1501
1502        int main() {
1503          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
1504          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
1505          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1506          Assert(scaler.get() == nullptr);
1507        }
1508        '''
1509    expect_success(
1510        COMMON_DEFINITIONS,
1511        source,
1512        locals())
1513
1514@pytest.mark.parametrize('ScalerAnnot,ScalerFactoryAnnot', [
1515    ('Scaler',
1516     'std::function<Scaler(double)>'),
1517    ('fruit::Annotated<Annotation1, Scaler>',
1518     'fruit::Annotated<Annotation1, std::function<Scaler(double)>>'),
1519])
1520def test_register_factory_for_unique_pointer_returning_value(ScalerAnnot, ScalerFactoryAnnot):
1521    source = '''
1522        struct Scaler {
1523        private:
1524          double factor;
1525
1526        public:
1527          Scaler(double factor)
1528            : factor(factor) {
1529          }
1530
1531          double scale(double x) {
1532            return x * factor;
1533          }
1534        };
1535
1536        using ScalerFactory = std::function<Scaler(double)>;
1537
1538        fruit::Component<ScalerFactoryAnnot> getScalerComponent() {
1539          return fruit::createComponent()
1540            .registerFactory<ScalerAnnot(fruit::Assisted<double>)>(
1541                [](double factor) {
1542                    return Scaler(factor);
1543                });
1544        }
1545
1546        int main() {
1547          fruit::Injector<ScalerFactoryAnnot> injector(getScalerComponent);
1548          ScalerFactory scalerFactory = injector.get<ScalerFactoryAnnot>();
1549          Scaler scaler = scalerFactory(12.1);
1550          std::cout << scaler.scale(3) << std::endl;
1551        }
1552        '''
1553    expect_success(
1554        COMMON_DEFINITIONS,
1555        source,
1556        locals())
1557
1558@pytest.mark.parametrize('ScalerImplAnnot', [
1559    'ScalerImpl',
1560    'fruit::Annotated<Annotation1, ScalerImpl>',
1561])
1562def test_register_factory_inconsistent_signature(ScalerImplAnnot):
1563    source = '''
1564        struct Scaler {
1565          virtual double scale(double x) = 0;
1566        };
1567
1568        struct ScalerImpl : public Scaler {
1569        private:
1570          double factor;
1571
1572        public:
1573          ScalerImpl(double factor)
1574            : factor(factor) {
1575          }
1576
1577          double scale(double x) override {
1578            return x * factor;
1579          }
1580        };
1581
1582        using ScalerFactory = std::function<std::unique_ptr<Scaler>(double)>;
1583
1584        fruit::Component<ScalerFactory> getScalerComponent() {
1585          return fruit::createComponent()
1586            .bind<Scaler, ScalerImplAnnot>()
1587            .registerFactory<ScalerImplAnnot(fruit::Assisted<double>)>([](float factor) { return ScalerImpl(factor); });
1588        }
1589
1590        int main() {
1591          fruit::Injector<ScalerFactory> injector(getScalerComponent);
1592          ScalerFactory scalerFactory(injector);
1593          std::unique_ptr<Scaler> scaler = scalerFactory(12.1);
1594          std::cout << scaler->scale(3) << std::endl;
1595        }
1596        '''
1597    expect_compile_error(
1598        'FunctorSignatureDoesNotMatchError<ScalerImpl\(double\),ScalerImpl\(float\)>',
1599        'Unexpected functor signature',
1600        COMMON_DEFINITIONS,
1601        source,
1602        locals())
1603
1604def test_register_factory_inconsistent_signature_returning_value():
1605    source = '''
1606        struct Scaler {
1607        private:
1608          double factor;
1609
1610        public:
1611          Scaler(double factor)
1612            : factor(factor) {
1613          }
1614
1615          double scale(double x) {
1616            return x * factor;
1617          }
1618        };
1619
1620        using ScalerFactory = std::function<Scaler(double)>;
1621
1622        fruit::Component<ScalerFactory> getScalerComponent() {
1623          return fruit::createComponent()
1624            .registerFactory<Scaler(fruit::Assisted<double>)>([](float factor) { return Scaler(factor); });
1625        }
1626
1627        int main() {
1628          fruit::Injector<ScalerFactory> injector(getScalerComponent);
1629          ScalerFactory scalerFactory(injector);
1630          Scaler scaler = scalerFactory(12.1);
1631          std::cout << scaler.scale(3) << std::endl;
1632        }
1633        '''
1634    expect_compile_error(
1635        'FunctorSignatureDoesNotMatchError<Scaler\(double\),Scaler\(float\)>',
1636        'Unexpected functor signature',
1637        COMMON_DEFINITIONS,
1638        source)
1639
1640def test_register_factory_nonmovable_ok():
1641    source = '''
1642        struct C {
1643          INJECT(C()) = default;
1644
1645          C(const C&) = delete;
1646          C(C&&) = delete;
1647          C& operator=(const C&) = delete;
1648          C& operator=(C&&) = delete;
1649        };
1650
1651        using CFactory = std::function<std::unique_ptr<C>()>;
1652
1653        fruit::Component<CFactory> getCFactory() {
1654          return fruit::createComponent();
1655        }
1656
1657        int main() {
1658          fruit::Injector<CFactory> injector(getCFactory);
1659          CFactory cFactory(injector);
1660          std::unique_ptr<C> c = cFactory();
1661          (void)c;
1662        }
1663        '''
1664    expect_success(
1665        COMMON_DEFINITIONS,
1666        source)
1667
1668# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message,
1669# or mention that there are other ways to satisfy that dependency.
1670@pytest.mark.parametrize('XAnnot,XFactoryAnnot', [
1671    ('X',
1672     'std::function<X(int)>'),
1673    ('fruit::Annotated<Annotation1, X>',
1674     'fruit::Annotated<Annotation1, std::function<X(int)>>'),
1675])
1676def test_register_factory_not_existing_constructor1(XAnnot, XFactoryAnnot):
1677    source = '''
1678        struct X {
1679          INJECT(X()) = default;
1680        };
1681
1682        fruit::Component<XFactoryAnnot> getComponent() {
1683          return fruit::createComponent();
1684        }
1685        '''
1686    expect_compile_error(
1687        'FunctorSignatureDoesNotMatchError<XAnnot\(int\),XAnnot\((void)?\)>',
1688        'Unexpected functor signature',
1689        COMMON_DEFINITIONS,
1690        source,
1691        locals())
1692
1693# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message,
1694# or mention that there are other ways to satisfy that dependency.
1695@pytest.mark.parametrize('XIntFactoryAnnot,XIntFactoryAnnotRegex,XVoidFactoryAnnotRegex', [
1696    ('std::function<std::unique_ptr<X>(int)>',
1697     'std::unique_ptr<X(,std::default_delete<X>)?>\(int\)',
1698     'std::unique_ptr<X(,std::default_delete<X>)?>\((void)?\)'),
1699    ('fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>(int)>>',
1700     'fruit::Annotated<Annotation1,std::unique_ptr<X(,std::default_delete<X>)?>>\(int\)',
1701     'fruit::Annotated<Annotation1,std::unique_ptr<X(,std::default_delete<X>)?>>\((void)?\)')
1702])
1703def test_register_factory_not_existing_constructor2(XIntFactoryAnnot, XIntFactoryAnnotRegex, XVoidFactoryAnnotRegex):
1704    source = '''
1705        struct X {
1706          using Inject = X();
1707        };
1708
1709        fruit::Component<XIntFactoryAnnot> getComponent() {
1710          return fruit::createComponent();
1711        }
1712        '''
1713    expect_compile_error(
1714        'FunctorSignatureDoesNotMatchError<XIntFactoryAnnotRegex,XVoidFactoryAnnotRegex>',
1715        'Unexpected functor signature',
1716        COMMON_DEFINITIONS,
1717        source,
1718        locals())
1719
1720# TODO: this might not be the best error message, maybe we should ignore the constructor entirely in the message,
1721# or mention that there are other ways to satisfy that dependency.
1722@pytest.mark.parametrize('XAnnot,XFactoryAnnot', [
1723    ('X',
1724     'std::function<X(int)>'),
1725    ('fruit::Annotated<Annotation1, X>',
1726     'fruit::Annotated<Annotation1, std::function<X(int)>>'),
1727])
1728def test_register_factory_not_existing_constructor2_returning_value(XAnnot, XFactoryAnnot):
1729    source = '''
1730        struct X {
1731          using Inject = X();
1732        };
1733
1734        fruit::Component<XFactoryAnnot> getComponent() {
1735          return fruit::createComponent();
1736        }
1737        '''
1738    expect_compile_error(
1739        'FunctorSignatureDoesNotMatchError<XAnnot\(int\), XAnnot\((void)?\)>',
1740        'Unexpected functor signature',
1741        COMMON_DEFINITIONS,
1742        source,
1743        locals())
1744
1745
1746@pytest.mark.parametrize('XFactoryAnnot', [
1747    'std::function<X()>',
1748    'fruit::Annotated<Annotation1, std::function<X()>>',
1749])
1750def test_register_factory_success_factory_movable_only_implicit(XFactoryAnnot):
1751    source = '''
1752        struct X {
1753          INJECT(X()) = default;
1754          X(X&&) = default;
1755          X(const X&) = delete;
1756        };
1757
1758        fruit::Component<XFactoryAnnot> getComponent() {
1759          return fruit::createComponent();
1760        }
1761
1762        int main() {
1763          fruit::Injector<XFactoryAnnot> injector(getComponent);
1764          injector.get<XFactoryAnnot>()();
1765        }
1766        '''
1767    expect_success(
1768        COMMON_DEFINITIONS,
1769        source,
1770        locals())
1771
1772@pytest.mark.parametrize('XPtrAnnot,ConstructX,XPtrFactoryAnnot', [
1773    ('X', 'X()', 'std::function<X()>'),
1774    ('fruit::Annotated<Annotation1, X>', 'X()', 'fruit::Annotated<Annotation1, std::function<X()>>'),
1775    ('std::unique_ptr<X>', 'std::unique_ptr<X>(new X())', 'std::function<std::unique_ptr<X>()>'),
1776    ('fruit::Annotated<Annotation1, std::unique_ptr<X>>', 'std::unique_ptr<X>(new X())', 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>'),
1777])
1778def test_register_factory_success_factory_movable_only_explicit(XPtrAnnot, ConstructX, XPtrFactoryAnnot):
1779    source = '''
1780        struct X {
1781          X() = default;
1782          X(X&&) = default;
1783          X(const X&) = delete;
1784        };
1785
1786        fruit::Component<XPtrFactoryAnnot> getComponent() {
1787          return fruit::createComponent()
1788            .registerFactory<XPtrAnnot()>([](){return ConstructX;});
1789        }
1790
1791        int main() {
1792          fruit::Injector<XPtrFactoryAnnot> injector(getComponent);
1793          injector.get<XPtrFactoryAnnot>()();
1794        }
1795        '''
1796    expect_success(
1797        COMMON_DEFINITIONS,
1798        source,
1799        locals())
1800
1801@pytest.mark.parametrize('XPtrFactoryAnnot', [
1802    'std::function<std::unique_ptr<X>()>',
1803    'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>',
1804])
1805def test_register_factory_success_factory_not_movable_implicit(XPtrFactoryAnnot):
1806    source = '''
1807        struct X {
1808          INJECT(X()) = default;
1809          X(X&&) = delete;
1810          X(const X&) = delete;
1811        };
1812
1813        fruit::Component<XPtrFactoryAnnot> getComponent() {
1814          return fruit::createComponent();
1815        }
1816
1817        int main() {
1818          fruit::Injector<XPtrFactoryAnnot> injector(getComponent);
1819          injector.get<XPtrFactoryAnnot>()();
1820        }
1821        '''
1822    expect_success(
1823        COMMON_DEFINITIONS,
1824        source,
1825        locals())
1826
1827@pytest.mark.parametrize('XPtrAnnot,XPtrFactoryAnnot', [
1828    ('std::unique_ptr<X>', 'std::function<std::unique_ptr<X>()>'),
1829    ('fruit::Annotated<Annotation1, std::unique_ptr<X>>', 'fruit::Annotated<Annotation1, std::function<std::unique_ptr<X>()>>'),
1830])
1831def test_register_factory_success_factory_not_movable_explicit_returning_pointer(XPtrAnnot, XPtrFactoryAnnot):
1832    source = '''
1833        struct X {
1834          X() = default;
1835          X(X&&) = delete;
1836          X(const X&) = delete;
1837        };
1838
1839        fruit::Component<XPtrFactoryAnnot> getComponent() {
1840          return fruit::createComponent()
1841            .registerFactory<XPtrAnnot()>([](){return std::unique_ptr<X>(new X());});
1842        }
1843
1844        int main() {
1845          fruit::Injector<XPtrFactoryAnnot> injector(getComponent);
1846          injector.get<XPtrFactoryAnnot>()();
1847        }
1848        '''
1849    expect_success(
1850        COMMON_DEFINITIONS,
1851        source,
1852        locals())
1853
1854@pytest.mark.parametrize('ConstructX,XPtr', [
1855    ('X()', 'X'),
1856    ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'),
1857])
1858@pytest.mark.parametrize('WithAnnot', [
1859    'WithNoAnnotation',
1860    'WithAnnotation1',
1861])
1862@pytest.mark.parametrize('YVariant', [
1863    'Y',
1864    'Y*',
1865    'const Y*',
1866    'Y&',
1867    'const Y&',
1868    'std::shared_ptr<Y>',
1869    'fruit::Provider<Y>',
1870    'fruit::Provider<const Y>',
1871])
1872def test_register_factory_with_param_success(ConstructX, XPtr, WithAnnot, YVariant):
1873    source = '''
1874        struct Y {};
1875        struct X {};
1876
1877        fruit::Component<WithAnnot<Y>> getYComponent() {
1878          return fruit::createComponent()
1879            .registerConstructor<WithAnnot<Y>()>();
1880        }
1881
1882        fruit::Component<std::function<XPtr()>> getComponent() {
1883          return fruit::createComponent()
1884            .install(getYComponent)
1885            .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
1886        }
1887
1888        int main() {
1889          fruit::Injector<std::function<XPtr()>> injector(getComponent);
1890          XPtr x = injector.get<std::function<XPtr()>>()();
1891          (void) x;
1892        }
1893        '''
1894    expect_success(
1895        COMMON_DEFINITIONS,
1896        source,
1897        locals())
1898
1899@pytest.mark.parametrize('ConstructX,XPtr', [
1900    ('X()', 'X'),
1901    ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'),
1902])
1903@pytest.mark.parametrize('WithAnnot', [
1904    'WithNoAnnotation',
1905    'WithAnnotation1',
1906])
1907@pytest.mark.parametrize('YVariant', [
1908    'Y',
1909    'const Y*',
1910    'const Y&',
1911    'fruit::Provider<const Y>',
1912])
1913def test_register_factory_with_param_const_binding_success(ConstructX, XPtr, WithAnnot, YVariant):
1914    source = '''
1915        struct Y {};
1916        struct X {};
1917
1918        const Y y{};
1919
1920        fruit::Component<WithAnnot<const Y>> getYComponent() {
1921          return fruit::createComponent()
1922            .bindInstance<WithAnnot<Y>, Y>(y);
1923        }
1924
1925        fruit::Component<std::function<XPtr()>> getComponent() {
1926          return fruit::createComponent()
1927            .install(getYComponent)
1928            .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
1929        }
1930
1931        int main() {
1932          fruit::Injector<std::function<XPtr()>> injector(getComponent);
1933          XPtr x = injector.get<std::function<XPtr()>>()();
1934          (void) x;
1935        }
1936        '''
1937    expect_success(
1938        COMMON_DEFINITIONS,
1939        source,
1940        locals())
1941
1942@pytest.mark.parametrize('ConstructX,XPtr', [
1943    ('X()', 'X'),
1944    ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'),
1945])
1946@pytest.mark.parametrize('WithAnnot,YAnnotRegex', [
1947    ('WithNoAnnotation', 'Y'),
1948    ('WithAnnotation1', 'fruit::Annotated<Annotation1, Y>'),
1949])
1950@pytest.mark.parametrize('XFactoryResult', [
1951    'X',
1952    'std::unique_ptr<X>',
1953])
1954@pytest.mark.parametrize('YVariant', [
1955    'Y*',
1956    'Y&',
1957    'std::shared_ptr<Y>',
1958    'fruit::Provider<Y>',
1959])
1960def test_register_factory_with_param_error_nonconst_param_required(ConstructX, XPtr, WithAnnot, YAnnotRegex, XFactoryResult, YVariant):
1961    source = '''
1962        struct Y {};
1963        struct X {};
1964
1965        fruit::Component<WithAnnot<const Y>> getYComponent();
1966
1967        fruit::Component<std::function<XFactoryResult()>> getComponent() {
1968          return fruit::createComponent()
1969            .install(getYComponent)
1970            .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; });
1971        }
1972        '''
1973    expect_compile_error(
1974        'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>',
1975        'The type T was provided as constant, however one of the constructors/providers/factories in this component',
1976        COMMON_DEFINITIONS,
1977        source,
1978        locals())
1979
1980@pytest.mark.parametrize('ConstructX,XPtr', [
1981    ('X()', 'X'),
1982    ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'),
1983])
1984@pytest.mark.parametrize('XFactoryResult', [
1985    'X',
1986    'std::unique_ptr<X>',
1987])
1988@pytest.mark.parametrize('WithAnnot,YAnnotRegex', [
1989    ('WithNoAnnotation', 'Y'),
1990    ('WithAnnotation1', 'fruit::Annotated<Annotation1, Y>'),
1991])
1992@pytest.mark.parametrize('YVariant', [
1993    'Y*',
1994    'Y&',
1995    'std::shared_ptr<Y>',
1996    'fruit::Provider<Y>',
1997])
1998def test_register_factory_with_param_error_nonconst_param_required_install_after(ConstructX, XPtr, XFactoryResult, WithAnnot, YAnnotRegex, YVariant):
1999    source = '''
2000        struct Y {};
2001        struct X {};
2002
2003        fruit::Component<WithAnnot<const Y>> getYComponent();
2004
2005        fruit::Component<std::function<XFactoryResult()>> getComponent() {
2006          return fruit::createComponent()
2007            .registerFactory<XPtr(WithAnnot<YVariant>)>([](YVariant){ return ConstructX; })
2008            .install(getYComponent);
2009        }
2010        '''
2011    expect_compile_error(
2012        'NonConstBindingRequiredButConstBindingProvidedError<YAnnotRegex>',
2013        'The type T was provided as constant, however one of the constructors/providers/factories in this component',
2014        COMMON_DEFINITIONS,
2015        source,
2016        locals())
2017
2018def test_register_factory_requiring_nonconst_then_requiring_const_ok():
2019    source = '''
2020        struct X {};
2021        struct Y {};
2022        struct Z {};
2023
2024        fruit::Component<std::function<Y()>, std::function<Z()>> getRootComponent() {
2025          return fruit::createComponent()
2026            .registerFactory<Y(X&)>([](X&) { return Y();})
2027            .registerFactory<Z(const X&)>([](const X&) { return Z();})
2028            .registerConstructor<X()>();
2029        }
2030
2031        int main() {
2032          fruit::Injector<std::function<Y()>, std::function<Z()>> injector(getRootComponent);
2033          std::function<Y()> yFactory = injector.get<std::function<Y()>>();
2034          yFactory();
2035          std::function<Z()> zFactory = injector.get<std::function<Z()>>();
2036          zFactory();
2037        }
2038        '''
2039    expect_success(
2040        COMMON_DEFINITIONS,
2041        source,
2042        locals())
2043
2044def test_register_factory_requiring_nonconst_then_requiring_const_declaring_const_requirement_error():
2045    source = '''
2046        struct X {};
2047        struct Y {};
2048        struct Z {};
2049
2050        fruit::Component<fruit::Required<const X>, std::function<Y()>, std::function<Z()>> getRootComponent() {
2051          return fruit::createComponent()
2052            .registerFactory<Y(X&)>([](X&) { return Y();})
2053            .registerFactory<Z(const X&)>([](const X&) { return Z();});
2054        }
2055        '''
2056    expect_compile_error(
2057        'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
2058        'The type T was declared as a const Required type in the returned Component, however',
2059        COMMON_DEFINITIONS,
2060        source,
2061        locals())
2062
2063def test_register_factory_requiring_const_then_requiring_nonconst_ok():
2064    source = '''
2065        struct X {};
2066        struct Y {};
2067        struct Z {};
2068
2069        fruit::Component<std::function<Y()>, std::function<Z()>> getRootComponent() {
2070          return fruit::createComponent()
2071            .registerFactory<Y(const X&)>([](const X&) { return Y();})
2072            .registerFactory<Z(X&)>([](X&) { return Z();})
2073            .registerConstructor<X()>();
2074        }
2075
2076        int main() {
2077          fruit::Injector<std::function<Y()>, std::function<Z()>> injector(getRootComponent);
2078          std::function<Y()> yFactory = injector.get<std::function<Y()>>();
2079          yFactory();
2080          std::function<Z()> zFactory = injector.get<std::function<Z()>>();
2081          zFactory();
2082        }
2083        '''
2084    expect_success(
2085        COMMON_DEFINITIONS,
2086        source,
2087        locals())
2088
2089def test_register_factory_requiring_const_then_requiring_nonconst_declaring_const_requirement_error():
2090    source = '''
2091        struct X {};
2092        struct Y {};
2093        struct Z {};
2094
2095        fruit::Component<fruit::Required<const X>, std::function<Y()>, std::function<Z()>> getRootComponent() {
2096          return fruit::createComponent()
2097            .registerFactory<Y(const X&)>([](const X&) { return Y();})
2098            .registerFactory<Z(X&)>([](X&) { return Z();});
2099        }
2100        '''
2101    expect_compile_error(
2102        'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
2103        'The type T was declared as a const Required type in the returned Component, however',
2104        COMMON_DEFINITIONS,
2105        source,
2106        locals())
2107
2108def test_provider_get_error_type_unique_pointer_pointer_not_provided():
2109    source = '''
2110        struct X {};
2111
2112        void f(fruit::Provider<X> provider) {
2113          provider.get<std::unique_ptr<X>*>();
2114        }
2115        '''
2116    expect_compile_error(
2117        'TypeNotProvidedError<std::unique_ptr<X(,std::default_delete<X>)?>\*>',
2118        'Trying to get an instance of T, but it is not provided by this Provider/Injector.',
2119        COMMON_DEFINITIONS,
2120        source)
2121
2122@pytest.mark.parametrize('ConstructX,XPtr', [
2123    ('X()', 'X'),
2124    ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'),
2125])
2126@pytest.mark.parametrize('XFactoryResult', [
2127    'X',
2128    'std::unique_ptr<X>',
2129])
2130@pytest.mark.parametrize('YVariant,YVariantRegex', [
2131    ('Y**', r'Y\*\*'),
2132    ('std::shared_ptr<Y>*', r'std::shared_ptr<Y>\*'),
2133    ('std::nullptr_t', r'(std::)?nullptr(_t)?'),
2134    ('Y*&', r'Y\*&'),
2135    ('Y(*)()', r'Y(\((__cdecl)?\*\))?\((void)?\)'),
2136    ('fruit::Annotated<Annotation1, Y**>', r'Y\*\*'),
2137])
2138def test_register_factory_with_param_error_type_not_injectable(
2139        ConstructX, XPtr, XFactoryResult, YVariant, YVariantRegex):
2140    source = '''
2141        struct Y {};
2142        struct X {};
2143
2144        fruit::Component<> getComponent() {
2145          return fruit::createComponent()
2146            .registerFactory<XPtr(YVariant)>([](YVariant){ return ConstructX; });
2147        }
2148        '''
2149    expect_compile_error(
2150        'NonInjectableTypeError<YVariantRegex>',
2151        'The type T is not injectable.',
2152        COMMON_DEFINITIONS,
2153        source,
2154        locals())
2155
2156def test_register_factory_bind_nonconst_unique_ptr_factory_to_const_value_factory():
2157    source = '''
2158        struct X {
2159          INJECT(X()) = default;
2160        };
2161
2162        fruit::Component<const std::function<X()>> getChildComponent() {
2163          return fruit::createComponent();
2164        }
2165
2166        fruit::Component<std::function<std::unique_ptr<X>()>> getRootComponent() {
2167          return fruit::createComponent()
2168              .install(getChildComponent);
2169        }
2170
2171        int main() {
2172          fruit::Injector<std::function<std::unique_ptr<X>()>> injector(getRootComponent);
2173          std::function<std::unique_ptr<X>()> xFactory(injector);
2174          xFactory();
2175        }
2176        '''
2177    expect_success(
2178        COMMON_DEFINITIONS,
2179        source,
2180        locals())
2181
2182def test_register_factory_bind_const_interface_factory_to_nonconst_implementation_factory():
2183    source = '''
2184        struct X {
2185          virtual void foo() = 0;
2186          virtual ~X() = default;
2187        };
2188
2189        struct Y : public X {
2190          INJECT(Y()) = default;
2191
2192          void foo() override {
2193          }
2194        };
2195
2196        fruit::Component<std::function<std::unique_ptr<Y>()>> getChildComponent() {
2197          return fruit::createComponent();
2198        }
2199
2200        fruit::Component<const std::function<std::unique_ptr<X>()>> getRootComponent() {
2201          return fruit::createComponent()
2202              .install(getChildComponent)
2203              .bind<X, Y>();
2204        }
2205
2206        int main() {
2207          fruit::Injector<const std::function<std::unique_ptr<X>()>> injector(getRootComponent);
2208          std::function<std::unique_ptr<X>()> xFactory(injector);
2209          xFactory();
2210        }
2211        '''
2212    expect_success(
2213        COMMON_DEFINITIONS,
2214        source,
2215        locals())
2216
2217def test_register_factory_bind_nonconst_interface_factory_to_const_implementation_factory():
2218    source = '''
2219        struct X {
2220          virtual void foo() = 0;
2221          virtual ~X() = default;
2222        };
2223
2224        struct Y : public X {
2225          INJECT(Y()) = default;
2226
2227          void foo() override {
2228          }
2229        };
2230
2231        fruit::Component<const std::function<std::unique_ptr<Y>()>> getChildComponent() {
2232          return fruit::createComponent();
2233        }
2234
2235        fruit::Component<std::function<std::unique_ptr<X>()>> getRootComponent() {
2236          return fruit::createComponent()
2237              .install(getChildComponent)
2238              .bind<X, Y>();
2239        }
2240
2241        int main() {
2242          fruit::Injector<std::function<std::unique_ptr<X>()>> injector(getRootComponent);
2243          std::function<std::unique_ptr<X>()> xFactory(injector);
2244          xFactory();
2245        }
2246        '''
2247    expect_success(
2248        COMMON_DEFINITIONS,
2249        source,
2250        locals())
2251
2252@pytest.mark.parametrize('WithAnnot', [
2253    'WithNoAnnotation',
2254    'WithAnnotation1',
2255])
2256def test_register_factory_abstract_class_ok(WithAnnot):
2257    source = '''
2258        struct I {
2259          virtual int foo() = 0;
2260          virtual ~I() = default;
2261        };
2262
2263        struct X : public I {
2264          int foo() override {
2265            return 5;
2266          }
2267        };
2268
2269        fruit::Component<WithAnnot<std::function<std::unique_ptr<I>()>>> getComponent() {
2270          return fruit::createComponent()
2271            .registerFactory<WithAnnot<std::unique_ptr<I>>()>([](){return std::unique_ptr<I>(static_cast<I*>(new X()));});
2272        }
2273
2274        int main() {
2275          fruit::Injector<WithAnnot<std::function<std::unique_ptr<I>()>>> injector(getComponent);
2276
2277          Assert(injector.get<WithAnnot<std::function<std::unique_ptr<I>()>>>()()->foo() == 5);
2278        }
2279        '''
2280    expect_success(
2281        COMMON_DEFINITIONS,
2282        source,
2283        locals())
2284
2285# TODO: investigate why this doesn't fail to compile with MSVC and then re-enable it for MSVC too.
2286@pytest.mark.skipif(
2287    re.search('MSVC', CXX_COMPILER_NAME),
2288    reason = 'This is disabled in MSVC because it compiles cleanly with the latest MSVC.')
2289@pytest.mark.parametrize('WithAnnot', [
2290    'WithNoAnnotation',
2291    'WithAnnotation1',
2292])
2293def test_register_factory_abstract_class_with_no_virtual_destructor_error(WithAnnot):
2294    source = '''
2295        struct I {
2296          virtual int foo() = 0;
2297        };
2298
2299        struct X : public I {
2300          int foo() override {
2301            return 5;
2302          }
2303        };
2304
2305        fruit::Component<WithAnnot<std::function<std::unique_ptr<I>()>>> getComponent() {
2306          return fruit::createComponent()
2307            .registerFactory<WithAnnot<std::unique_ptr<I>>()>([](){return std::unique_ptr<I>(static_cast<I*>(new X()));});
2308        }
2309        '''
2310    expect_compile_error(
2311        'RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError<I>',
2312        'registerFactory\(\) was called with a lambda that returns a std::unique_ptr<T>, but T is an abstract class',
2313        COMMON_DEFINITIONS,
2314        source,
2315        locals(),
2316        ignore_warnings=True,
2317        disable_error_line_number_check=True)
2318
2319if __name__== '__main__':
2320    main(__file__)
2321