• 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.
15
16from absl.testing import parameterized
17from fruit_test_common import *
18
19COMMON_DEFINITIONS = '''
20    #include "test_common.h"
21
22    struct Annotation1 {};
23    '''
24
25class TestMultibindingsBindInstance(parameterized.TestCase):
26    @parameterized.parameters([
27        'X',
28        'fruit::Annotated<Annotation1, X>',
29    ])
30    def test_multibindings_bind_instance_ok(self, XAnnot):
31        source = '''
32            struct X {};
33
34            X x;
35
36            fruit::Component<> getComponent() {
37              return fruit::createComponent()
38                .addInstanceMultibinding<XAnnot, X>(x);
39            }
40
41            int main() {
42              fruit::Injector<> injector(getComponent);
43
44              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
45              Assert(multibindings.size() == 1);
46              Assert(multibindings[0] == &x);
47            }
48            '''
49        expect_success(
50            COMMON_DEFINITIONS,
51            source,
52            locals())
53
54    @parameterized.parameters([
55        'X',
56        'fruit::Annotated<Annotation1, X>',
57    ])
58    def test_multibindings_bind_const_instance_error(self, XAnnot):
59        source = '''
60            struct X {};
61
62            const X x{};
63
64            fruit::Component<> getComponent() {
65              return fruit::createComponent()
66                .addInstanceMultibinding<XAnnot, X>(x);
67            }
68            '''
69        expect_generic_compile_error(
70            r'candidate function not viable: 1st argument \(.const X.\) would lose const qualifier'
71            r'|no matching function for call to .fruit::PartialComponent<.*>::addInstanceMultibinding(<XAnnot,X>)?\(const X&\).'
72            r'|error: no matching member function for call to .addInstanceMultibinding.'
73            r'|cannot convert argument 1 from .const X. to .X &.',
74            COMMON_DEFINITIONS,
75            source,
76            locals())
77
78    @parameterized.parameters([
79        'X',
80        'fruit::Annotated<Annotation1, X>',
81    ])
82    def test_multibindings_bind_instance_vector(self, XAnnot):
83        source = '''
84            struct X {};
85
86            std::vector<X> values = {X(), X()};
87
88            fruit::Component<> getComponent() {
89              return fruit::createComponent()
90                .addInstanceMultibindings<XAnnot, X>(values);
91            }
92
93            int main() {
94              fruit::Injector<> injector(getComponent);
95
96              std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
97              Assert(multibindings.size() == 2);
98              Assert(multibindings[0] == &(values[0]));
99              Assert(multibindings[1] == &(values[1]));
100            }
101            '''
102        expect_success(
103            COMMON_DEFINITIONS,
104            source,
105            locals())
106
107    @parameterized.parameters([
108        'X',
109        'fruit::Annotated<Annotation1, X>',
110    ])
111    def test_multibindings_bind_const_instance_vector_error(self, XAnnot):
112        source = '''
113            struct X {};
114
115            const std::vector<X> values{};
116
117            fruit::Component<> getComponent() {
118              return fruit::createComponent()
119                .addInstanceMultibindings<XAnnot, X>(values);
120            }
121            '''
122        expect_generic_compile_error(
123            r'candidate function not viable: 1st argument \(.const std::vector<X>.\) would lose const qualifier'
124            r'|cannot convert .values. \(type .const std::(__debug::)?vector<X>.\) to type .std::(__debug::)?vector<X>&.'
125            r'|no matching .*function for call to .*addInstanceMultibindings'
126            r'|cannot convert argument 1 from .const std::vector<X,std::allocator<.*>>. to .std::vector<X,std::allocator<.*>> &.',
127            COMMON_DEFINITIONS,
128            source,
129            locals())
130
131    @parameterized.parameters([
132        'X',
133        'fruit::Annotated<Annotation1, X>',
134    ])
135    def test_multibindings_bind_instance_vector_of_consts_error(self, XAnnot):
136        source = '''
137            struct X {};
138
139            std::vector<const X> values;
140
141            fruit::Component<> getComponent() {
142              return fruit::createComponent()
143                .addInstanceMultibindings<XAnnot, X>(values);
144            }
145            '''
146        expect_generic_compile_error(
147            '.*',
148            COMMON_DEFINITIONS,
149            source,
150            locals())
151
152    @parameterized.parameters([
153        ('X**', r'X\*\*'),
154        ('std::shared_ptr<X>*', r'std::shared_ptr<X>\*'),
155        ('const std::shared_ptr<X>', r'const std::shared_ptr<X>'),
156        ('X* const', r'X\* const'),
157        ('const X* const', r'const X\* const'),
158        ('X*&', r'X\*&'),
159        ('fruit::Annotated<Annotation1, X**>', r'X\*\*'),
160    ])
161    def test_multibindings_bind_instance_non_class_type_error(self, XVariant, XVariantRegex):
162        source = '''
163            struct X {};
164
165            using XVariantT = XVariant;
166            fruit::Component<> getComponent(XVariantT x) {
167              return fruit::createComponent()
168                .addInstanceMultibinding<XVariant, XVariant>(x);
169            }
170            '''
171        expect_compile_error(
172            'NonClassTypeError<XVariantRegex,X>',
173            'A non-class type T was specified.',
174            COMMON_DEFINITIONS,
175            source,
176            locals())
177
178    @parameterized.parameters([
179        ('std::nullptr_t', r'(std::)?nullptr(_t)?'),
180        ('X(*)()', r'X(\((__cdecl)?\*\))?\((void)?\)'),
181    ])
182    def test_multibindings_bind_instance_non_injectable_type_error(self, XVariant, XVariantRegex):
183        source = '''
184            struct X {};
185
186            using XVariantT = XVariant;
187            fruit::Component<> getComponent(XVariantT x) {
188              return fruit::createComponent()
189                .addInstanceMultibinding<XVariant, XVariant>(x);
190            }
191            '''
192        expect_compile_error(
193            'NonInjectableTypeError<XVariantRegex>',
194            'The type T is not injectable.',
195            COMMON_DEFINITIONS,
196            source,
197            locals())
198
199if __name__ == '__main__':
200    absltest.main()
201