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.
15
16from fruit_test_common import *
17
18COMMON_DEFINITIONS = '''
19    #include "test_common.h"
20
21    struct Listener;
22
23    struct X {};
24
25    struct Annotation {};
26    struct Annotation1 {};
27    using ListenerAnnot = fruit::Annotated<Annotation, Listener>;
28    '''
29
30def test_get_none():
31    source = '''
32        fruit::Component<> getComponent() {
33          return fruit::createComponent();
34        }
35
36        int main() {
37          fruit::Injector<> injector(getComponent);
38
39          std::vector<X*> multibindings = injector.getMultibindings<X>();
40          (void) multibindings;
41          Assert(multibindings.empty());
42        }
43        '''
44    expect_success(
45        COMMON_DEFINITIONS,
46        source)
47
48def test_multiple_various_kinds():
49    source = '''
50        static int numNotificationsToListener1 = 0;
51        static int numNotificationsToListener2 = 0;
52        static int numNotificationsToListener3 = 0;
53
54        struct Listener {
55        public:
56          virtual ~Listener() = default;
57
58          virtual void notify() = 0;
59        };
60
61        struct Listener1 : public Listener {
62        public:
63          INJECT(Listener1()) = default;
64
65          virtual ~Listener1() = default;
66
67          void notify() override {
68            ++numNotificationsToListener1;
69          }
70        };
71
72        struct Writer {
73        public:
74          virtual void write(std::string s) = 0;
75        };
76
77        struct StdoutWriter : public Writer {
78        public:
79          INJECT(StdoutWriter()) = default;
80
81          void write(std::string s) override {
82            std::cout << s << std::endl;
83          }
84        };
85
86        struct Listener2 : public Listener {
87        private:
88          Writer* writer;
89
90        public:
91          INJECT(Listener2(Writer* writer))
92            : writer(writer) {
93          }
94
95          virtual ~Listener2() = default;
96
97          void notify() override {
98            (void) writer;
99            ++numNotificationsToListener2;
100          }
101        };
102
103        struct Listener3 : public Listener {
104        private:
105          Writer* writer;
106
107        public:
108          INJECT(Listener3(Writer* writer))
109            : writer(writer) {
110          }
111
112          virtual ~Listener3() = default;
113
114          void notify() override {
115            (void) writer;
116            ++numNotificationsToListener3;
117          }
118        };
119
120        fruit::Component<> getListenersComponent() {
121          return fruit::createComponent()
122            .bind<Writer, StdoutWriter>()
123            // Note: this is just to exercise the other method, but in real code you should split this in
124            // an addMultibinding<Listener, Listener1> and a registerProvider with the lambda.
125            .addMultibindingProvider([]() {
126              Listener1* listener1 = new Listener1();
127              return static_cast<Listener*>(listener1);
128            })
129            .addMultibinding<Listener, Listener2>()
130            .addMultibinding<ListenerAnnot, Listener3>();
131        }
132
133        int main() {
134          fruit::Injector<> injector(getListenersComponent);
135          std::vector<Listener*> listeners = injector.getMultibindings<Listener>();
136          for (Listener* listener : listeners) {
137            listener->notify();
138          }
139
140          std::vector<Listener*> listeners2 = injector.getMultibindings<Listener>();
141          Assert(listeners == listeners2);
142
143          if (numNotificationsToListener1 != 1 || numNotificationsToListener2 != 1
144            || numNotificationsToListener3 != 0) {
145            abort();
146          }
147
148          std::vector<Listener*> listenersWithAnnotation = injector.getMultibindings<ListenerAnnot>();
149          for (Listener* listener : listenersWithAnnotation) {
150            listener->notify();
151          }
152
153          if (numNotificationsToListener1 != 1 || numNotificationsToListener2 != 1
154            || numNotificationsToListener3 != 1) {
155            abort();
156          }
157        }
158        '''
159    expect_success(
160        COMMON_DEFINITIONS,
161        source)
162
163def test_order():
164    source = '''
165        std::vector<int> numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
166        // *
167        // |-- 0
168        // |-- A
169        // |   |-- 1
170        // |   |-- B
171        // |   |   |-- 2
172        // |   |   `-- 3
173        // |   |-- 4
174        // |   |-- C
175        // |   |   |-- 5
176        // |   |   |-- 6
177        // |   |   |-- D
178        // |   |   |   |-- 7
179        // |   |   |   |-- E
180        // |   |   |   |   |-- 8
181        // |   |   |   |   `-- 9
182        // |   |   |   `-- 10
183        // |   |   |-- 11
184        // |   |   |-- F
185        // |   |   |   |-- 12
186        // |   |   |   `-- 13
187        // |   |   `-- 14
188        // |   |-- 15
189        // |   |-- C (won't be expanded)
190        // |   `-- 16
191        // |-- 17
192        // |-- C (won't be expanded)
193        // `-- 18
194
195        fruit::Component<> getRootComponent();
196        fruit::Component<> getComponentA();
197        fruit::Component<> getComponentB();
198        fruit::Component<> getComponentC();
199        fruit::Component<> getComponentD();
200        fruit::Component<> getComponentE();
201        fruit::Component<> getComponentF();
202
203        fruit::Component<> getRootComponent() {
204          return fruit::createComponent()
205            .addInstanceMultibinding(numbers[0])
206            .install(getComponentA)
207            .addInstanceMultibinding(numbers[17])
208            .install(getComponentC)
209            .addInstanceMultibinding(numbers[18]);
210        }
211
212        fruit::Component<> getComponentA() {
213          return fruit::createComponent()
214            .addInstanceMultibinding(numbers[1])
215            .install(getComponentB)
216            .addInstanceMultibinding(numbers[4])
217            .install(getComponentC)
218            .addInstanceMultibinding(numbers[15])
219            .install(getComponentC)
220            .addInstanceMultibinding(numbers[16]);
221        }
222
223        fruit::Component<> getComponentB() {
224          return fruit::createComponent()
225            .addInstanceMultibinding(numbers[2])
226            .addInstanceMultibinding(numbers[3]);
227        }
228
229        fruit::Component<> getComponentC() {
230          return fruit::createComponent()
231            .addInstanceMultibinding(numbers[5])
232            .addInstanceMultibinding(numbers[6])
233            .install(getComponentD)
234            .addInstanceMultibinding(numbers[11])
235            .install(getComponentF)
236            .addInstanceMultibinding(numbers[14]);
237        }
238
239        fruit::Component<> getComponentD() {
240          return fruit::createComponent()
241            .addInstanceMultibinding(numbers[7])
242            .install(getComponentE)
243            .addInstanceMultibinding(numbers[10]);
244        }
245
246        fruit::Component<> getComponentE() {
247          return fruit::createComponent()
248            .addInstanceMultibinding(numbers[8])
249            .addInstanceMultibinding(numbers[9]);
250        }
251
252        fruit::Component<> getComponentF() {
253          return fruit::createComponent()
254            .addInstanceMultibinding(numbers[12])
255            .addInstanceMultibinding(numbers[13]);
256        }
257
258        int main() {
259          fruit::Injector<> injector(getRootComponent);
260          std::vector<int*> result_ptrs = injector.getMultibindings<int>();
261          std::vector<int> results;
262          std::cout << "Results: ";
263          for (int* result : result_ptrs) {
264            std::cout << *result << ", ";
265            results.push_back(*result);
266          }
267          std::cout << std::endl;
268          Assert(results == numbers);
269        }
270        '''
271    expect_success(
272        COMMON_DEFINITIONS,
273        source)
274
275
276def test_order_with_normalized_component():
277    source = '''
278        std::vector<int> numbers = {
279            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
280            19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
281        // root1
282        // |-- 0
283        // |-- A
284        // |   |-- 1
285        // |   |-- B
286        // |   |   |-- 2
287        // |   |   `-- 3
288        // |   |-- 4
289        // |   |-- C
290        // |   |   |-- 5
291        // |   |   |-- 6
292        // |   |   |-- D
293        // |   |   |   |-- 7
294        // |   |   |   |-- E
295        // |   |   |   |   |-- 8
296        // |   |   |   |   `-- 9
297        // |   |   |   `-- 10
298        // |   |   |-- 11
299        // |   |   |-- F
300        // |   |   |   |-- 12
301        // |   |   |   `-- 13
302        // |   |   `-- 14
303        // |   |-- 15
304        // |   |-- C (won't be expanded)
305        // |   `-- 16
306        // |-- 17
307        // |-- C (won't be expanded)
308        // `-- 18
309
310        // root2
311        // |-- 19
312        // |-- A2
313        // |   |-- 20
314        // |   |-- B2
315        // |   |   |-- 21
316        // |   |   `-- 22
317        // |   |-- 23
318        // |   |-- C2
319        // |   |   |-- 24
320        // |   |   |-- 25
321        // |   |   |-- D2
322        // |   |   |   |-- 26
323        // |   |   |   |-- E2
324        // |   |   |   |   |-- 27
325        // |   |   |   |   `-- 28
326        // |   |   |   `-- 29
327        // |   |   |-- 30
328        // |   |   |-- F2
329        // |   |   |   |-- 31
330        // |   |   |   `-- 32
331        // |   |   `-- 33
332        // |   |-- 34
333        // |   |-- C2 (won't be expanded)
334        // |   `-- 35
335        // |-- 36
336        // |-- C2 (won't be expanded)
337        // `-- 37
338
339        fruit::Component<> getRootComponent();
340        fruit::Component<> getComponentA();
341        fruit::Component<> getComponentB();
342        fruit::Component<> getComponentC();
343        fruit::Component<> getComponentD();
344        fruit::Component<> getComponentE();
345        fruit::Component<> getComponentF();
346
347        fruit::Component<> getRootComponent2();
348        fruit::Component<> getComponentA2();
349        fruit::Component<> getComponentB2();
350        fruit::Component<> getComponentC2();
351        fruit::Component<> getComponentD2();
352        fruit::Component<> getComponentE2();
353        fruit::Component<> getComponentF2();
354
355        fruit::Component<> getRootComponent() {
356          return fruit::createComponent()
357            .addInstanceMultibinding(numbers[0])
358            .install(getComponentA)
359            .addInstanceMultibinding(numbers[17])
360            .install(getComponentC)
361            .addInstanceMultibinding(numbers[18]);
362        }
363
364        fruit::Component<> getComponentA() {
365          return fruit::createComponent()
366            .addInstanceMultibinding(numbers[1])
367            .install(getComponentB)
368            .addInstanceMultibinding(numbers[4])
369            .install(getComponentC)
370            .addInstanceMultibinding(numbers[15])
371            .install(getComponentC)
372            .addInstanceMultibinding(numbers[16]);
373        }
374
375        fruit::Component<> getComponentB() {
376          return fruit::createComponent()
377            .addInstanceMultibinding(numbers[2])
378            .addInstanceMultibinding(numbers[3]);
379        }
380
381        fruit::Component<> getComponentC() {
382          return fruit::createComponent()
383            .addInstanceMultibinding(numbers[5])
384            .addInstanceMultibinding(numbers[6])
385            .install(getComponentD)
386            .addInstanceMultibinding(numbers[11])
387            .install(getComponentF)
388            .addInstanceMultibinding(numbers[14]);
389        }
390
391        fruit::Component<> getComponentD() {
392          return fruit::createComponent()
393            .addInstanceMultibinding(numbers[7])
394            .install(getComponentE)
395            .addInstanceMultibinding(numbers[10]);
396        }
397
398        fruit::Component<> getComponentE() {
399          return fruit::createComponent()
400            .addInstanceMultibinding(numbers[8])
401            .addInstanceMultibinding(numbers[9]);
402        }
403
404        fruit::Component<> getComponentF() {
405          return fruit::createComponent()
406            .addInstanceMultibinding(numbers[12])
407            .addInstanceMultibinding(numbers[13]);
408        }
409
410        fruit::Component<> getRootComponent2() {
411          return fruit::createComponent()
412            .addInstanceMultibinding(numbers[19])
413            .install(getComponentA2)
414            .addInstanceMultibinding(numbers[36])
415            .install(getComponentC2)
416            .addInstanceMultibinding(numbers[37]);
417        }
418
419        fruit::Component<> getComponentA2() {
420          return fruit::createComponent()
421            .addInstanceMultibinding(numbers[20])
422            .install(getComponentB2)
423            .addInstanceMultibinding(numbers[23])
424            .install(getComponentC2)
425            .addInstanceMultibinding(numbers[34])
426            .install(getComponentC2)
427            .addInstanceMultibinding(numbers[35]);
428        }
429
430        fruit::Component<> getComponentB2() {
431          return fruit::createComponent()
432            .addInstanceMultibinding(numbers[21])
433            .addInstanceMultibinding(numbers[22]);
434        }
435
436        fruit::Component<> getComponentC2() {
437          return fruit::createComponent()
438            .addInstanceMultibinding(numbers[24])
439            .addInstanceMultibinding(numbers[25])
440            .install(getComponentD2)
441            .addInstanceMultibinding(numbers[30])
442            .install(getComponentF2)
443            .addInstanceMultibinding(numbers[33]);
444        }
445
446        fruit::Component<> getComponentD2() {
447          return fruit::createComponent()
448            .addInstanceMultibinding(numbers[26])
449            .install(getComponentE2)
450            .addInstanceMultibinding(numbers[29]);
451        }
452
453        fruit::Component<> getComponentE2() {
454          return fruit::createComponent()
455            .addInstanceMultibinding(numbers[27])
456            .addInstanceMultibinding(numbers[28]);
457        }
458
459        fruit::Component<> getComponentF2() {
460          return fruit::createComponent()
461            .addInstanceMultibinding(numbers[31])
462            .addInstanceMultibinding(numbers[32]);
463        }
464
465        int main() {
466          fruit::NormalizedComponent<> normalizedComponent(getRootComponent);
467          fruit::Injector<> injector(normalizedComponent, getRootComponent2);
468          std::vector<int*> result_ptrs = injector.getMultibindings<int>();
469          std::vector<int> results;
470          std::cout << "Results: ";
471          for (int* result : result_ptrs) {
472            std::cout << *result << ", ";
473            results.push_back(*result);
474          }
475          std::cout << std::endl;
476          Assert(results == numbers);
477        }
478        '''
479    expect_success(
480        COMMON_DEFINITIONS,
481        source)
482
483def test_with_normalized_component_lazy_components_not_deduped_across():
484    source = '''
485        std::vector<int> numbers = {0, 1, 2, 3, 4};
486
487        // *
488        // |-- 0
489        // |-- A (lazy)
490        // |   |-- 1
491        // |   `-- 2
492        // |-- 3
493        // |-- A (lazy, won't be expanded)
494        // `-- 4
495
496        fruit::Component<> getRootComponent();
497        fruit::Component<> getComponentA();
498
499        fruit::Component<> getRootComponent() {
500          return fruit::createComponent()
501            .addInstanceMultibinding(numbers[0])
502            .install(getComponentA)
503            .addInstanceMultibinding(numbers[3])
504            .install(getComponentA)
505            .addInstanceMultibinding(numbers[4]);
506        }
507
508        fruit::Component<> getComponentA() {
509          return fruit::createComponent()
510            .addInstanceMultibinding(numbers[1])
511            .addInstanceMultibinding(numbers[2]);
512        }
513
514        int main() {
515          fruit::NormalizedComponent<> normalizedComponent(getRootComponent);
516          fruit::Injector<> injector(normalizedComponent, getRootComponent);
517          std::vector<int*> result_ptrs = injector.getMultibindings<int>();
518          std::vector<int> results;
519          std::cout << "Results: ";
520          for (int* result : result_ptrs) {
521            std::cout << *result << ", ";
522            results.push_back(*result);
523          }
524          std::cout << std::endl;
525          std::vector<int> expected_numbers = {0, 1, 2, 3, 4};
526          Assert(results == expected_numbers);
527        }
528        '''
529    expect_success(
530        COMMON_DEFINITIONS,
531        source)
532
533@pytest.mark.parametrize('XVariantAnnot,XVariantRegexp', [
534    ('const X', 'const X'),
535    ('X*', 'X\*'),
536    ('const X*', 'const X\*'),
537    ('std::shared_ptr<X>', 'std::shared_ptr<X>'),
538    ('fruit::Annotated<Annotation1, const X>', 'const X'),
539    ('fruit::Annotated<Annotation1, X*>', 'X\*'),
540    ('fruit::Annotated<Annotation1, const X*>', 'const X\*'),
541    ('fruit::Annotated<Annotation1, std::shared_ptr<X>>', 'std::shared_ptr<X>'),
542])
543def test_multibindings_get_error_non_class_type(XVariantAnnot, XVariantRegexp):
544    source = '''
545        void f(fruit::Injector<> injector) {
546          injector.getMultibindings<XVariantAnnot>();
547        }
548        '''
549    expect_compile_error(
550        'NonClassTypeError<XVariantRegexp,X>',
551        'A non-class type T was specified. Use C instead.',
552        COMMON_DEFINITIONS,
553        source,
554        locals())
555
556@pytest.mark.parametrize('XVariantAnnot,XVariantRegexp', [
557    ('X&', 'X&'),
558    ('const X&', 'const X&'),
559    ('fruit::Annotated<Annotation1, X&>', 'X&'),
560    ('fruit::Annotated<Annotation1, const X&>', 'const X&'),
561])
562def test_multibindings_get_error_reference_type(XVariantAnnot, XVariantRegexp):
563    source = '''
564        void f(fruit::Injector<> injector) {
565          injector.getMultibindings<XVariantAnnot>();
566        }
567        '''
568    expect_generic_compile_error(
569        'declared as a pointer to a reference of type'
570        '|forming pointer to reference type'
571        '|fruit::Injector<.*>::getMultibindings.: no matching overloaded function found',
572        COMMON_DEFINITIONS,
573        source,
574        locals())
575
576if __name__== '__main__':
577    main(__file__)
578