Home | History | Annotate | Download | only in tests
      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 
     16 from fruit_test_common import *
     17 
     18 COMMON_DEFINITIONS = '''
     19     #include "test_common.h"
     20 
     21     struct X;
     22 
     23     struct Annotation1 {};
     24     using XAnnot1 = fruit::Annotated<Annotation1, X>;
     25     '''
     26 
     27 @pytest.mark.parametrize('XParamInChildComponent,XParamInRootComponent', [
     28     ('X', 'X'),
     29     ('X', 'const X'),
     30     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
     31     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
     32 ])
     33 def test_success(XParamInChildComponent, XParamInRootComponent):
     34     source = '''
     35         struct X {
     36           int n;
     37           X(int n) : n(n) {}
     38         };
     39 
     40         fruit::Component<XParamInChildComponent> getChildComponent() {
     41           return fruit::createComponent()
     42             .registerProvider<XParamInChildComponent()>([]() { return X(5); });
     43         }
     44 
     45         fruit::Component<XParamInRootComponent> getRootComponent() {
     46           return fruit::createComponent()
     47             .install(getChildComponent);
     48         }
     49 
     50         int main() {
     51           fruit::Injector<XParamInRootComponent> injector(getRootComponent);
     52           X x = injector.get<XParamInRootComponent>();
     53           Assert(x.n == 5);
     54         }
     55         '''
     56     expect_success(
     57         COMMON_DEFINITIONS,
     58         source,
     59         locals())
     60 
     61 @pytest.mark.parametrize('XParamInChildComponent,XParamInRootComponent', [
     62     ('const X', 'X'),
     63     ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
     64 ])
     65 def test_install_error_child_component_provides_const(XParamInChildComponent, XParamInRootComponent):
     66     source = '''
     67         struct X {};
     68 
     69         fruit::Component<XParamInChildComponent> getChildComponent();
     70 
     71         fruit::Component<XParamInRootComponent> getRootComponent() {
     72           return fruit::createComponent()
     73             .install(getChildComponent);
     74         }
     75         '''
     76     expect_compile_error(
     77         'NonConstBindingRequiredButConstBindingProvidedError<XParamInRootComponent>',
     78         'The type T was provided as constant, however one of the constructors/providers/factories in this component',
     79         COMMON_DEFINITIONS,
     80         source,
     81         locals())
     82 
     83 @pytest.mark.parametrize('ProvidedXParam,RequiredXParam', [
     84     ('X', 'X'),
     85     ('X', 'const X'),
     86     ('const X', 'const X'),
     87     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
     88     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
     89     ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, const X>'),
     90 ])
     91 def test_with_requirements_success(ProvidedXParam, RequiredXParam):
     92     ProvidedXParamWithoutConst = ProvidedXParam.replace('const ', '')
     93     source = '''
     94         struct X {
     95           int n;
     96           X(int n) : n(n) {}
     97         };
     98 
     99         struct Y {
    100           X x;
    101           Y(X x): x(x) {}
    102         };
    103 
    104         fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1() {
    105           return fruit::createComponent()
    106             .registerProvider<Y(RequiredXParam)>([](X x) { return Y(x); });
    107         }
    108 
    109         fruit::Component<ProvidedXParam> getChildComponent2() {
    110           return fruit::createComponent()
    111             .registerProvider<ProvidedXParamWithoutConst()>([]() { return X(5); });
    112         }
    113 
    114         fruit::Component<Y> getRootComponent() {
    115           return fruit::createComponent()
    116             .install(getChildComponent1)
    117             .install(getChildComponent2);
    118         }
    119 
    120         int main() {
    121           fruit::Injector<Y> injector(getRootComponent);
    122           Y y = injector.get<Y>();
    123           Assert(y.x.n == 5);
    124         }
    125         '''
    126     expect_success(
    127         COMMON_DEFINITIONS,
    128         source,
    129         locals())
    130 
    131 @pytest.mark.parametrize('ProvidedXParam,RequiredXParam', [
    132     ('const X', 'X'),
    133     ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
    134 ])
    135 def test_with_requirements_error_only_nonconst_provided(ProvidedXParam, RequiredXParam):
    136     source = '''
    137         struct X {};
    138         struct Y {};
    139 
    140         fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1();
    141 
    142         fruit::Component<ProvidedXParam> getChildComponent2();
    143 
    144         fruit::Component<Y> getRootComponent() {
    145           return fruit::createComponent()
    146             .install(getChildComponent1)
    147             .install(getChildComponent2);
    148         }
    149         '''
    150     expect_compile_error(
    151         'NonConstBindingRequiredButConstBindingProvidedError<RequiredXParam>',
    152         'The type T was provided as constant, however one of the constructors/providers/factories in this component',
    153         COMMON_DEFINITIONS,
    154         source,
    155         locals())
    156 
    157 @pytest.mark.parametrize('ProvidedXParam,RequiredXParam', [
    158     ('const X', 'X'),
    159     ('fruit::Annotated<Annotation1, const X>', 'fruit::Annotated<Annotation1, X>'),
    160 ])
    161 def test_with_requirements_error_only_nonconst_provided_reversed_install_order(ProvidedXParam, RequiredXParam):
    162     source = '''
    163         struct X {};
    164         struct Y {};
    165 
    166         fruit::Component<fruit::Required<RequiredXParam>, Y> getChildComponent1();
    167 
    168         fruit::Component<ProvidedXParam> getChildComponent2();
    169 
    170         fruit::Component<Y> getRootComponent() {
    171           return fruit::createComponent()
    172             .install(getChildComponent2)
    173             .install(getChildComponent1);
    174         }
    175         '''
    176     expect_compile_error(
    177         'NonConstBindingRequiredButConstBindingProvidedError<RequiredXParam>',
    178         'The type T was provided as constant, however one of the constructors/providers/factories in this component',
    179         COMMON_DEFINITIONS,
    180         source,
    181         locals())
    182 
    183 def test_with_requirements_not_specified_in_child_component_error():
    184     source = '''
    185         struct X {
    186           int n;
    187           X(int n) : n(n) {}
    188         };
    189 
    190         struct Y {
    191           X x;
    192           Y(X x): x(x) {}
    193         };
    194 
    195         fruit::Component<fruit::Required<X>, Y> getParentYComponent() {
    196           return fruit::createComponent()
    197             .registerProvider([](X x) { return Y(x); });
    198         }
    199 
    200         // We intentionally don't have fruit::Required<X> here, we want to test that this results in an error.
    201         fruit::Component<Y> getYComponent() {
    202           return fruit::createComponent()
    203             .install(getParentYComponent);
    204         }
    205         '''
    206     expect_compile_error(
    207         'NoBindingFoundError<X>',
    208         'No explicit binding nor C::Inject definition was found for T',
    209         COMMON_DEFINITIONS,
    210         source)
    211 
    212 @pytest.mark.parametrize('XAnnot,ConstXAnnot', [
    213     ('X', 'const X'),
    214     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
    215 ])
    216 def test_install_requiring_nonconst_then_install_requiring_const_ok(XAnnot, ConstXAnnot):
    217     source = '''
    218         struct X {};
    219         struct Y {};
    220         struct Z {};
    221 
    222         fruit::Component<fruit::Required<XAnnot>, Y> getChildComponent1() {
    223           return fruit::createComponent()
    224               .registerConstructor<Y()>();
    225         }
    226         
    227         fruit::Component<fruit::Required<ConstXAnnot>, Z> getChildComponent2() {
    228           return fruit::createComponent()
    229               .registerConstructor<Z()>();
    230         }
    231 
    232         fruit::Component<Y, Z> getRootComponent() {
    233           return fruit::createComponent()
    234             .install(getChildComponent1)
    235             .install(getChildComponent2)
    236             .registerConstructor<XAnnot()>();
    237         }
    238         
    239         int main() {
    240           fruit::Injector<Y, Z> injector(getRootComponent);
    241           injector.get<Y>();
    242           injector.get<Z>();
    243         }
    244         '''
    245     expect_success(
    246         COMMON_DEFINITIONS,
    247         source,
    248         locals())
    249 
    250 def test_install_requiring_nonconst_then_install_requiring_const_declaring_const_requirement_error():
    251     source = '''
    252         struct X {};
    253         struct Y {};
    254         struct Z {};
    255 
    256         fruit::Component<fruit::Required<X>, Y> getChildComponent1();
    257         fruit::Component<fruit::Required<const X>, Z> getChildComponent2();
    258 
    259         fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() {
    260           return fruit::createComponent()
    261             .install(getChildComponent1)
    262             .install(getChildComponent2);
    263         }
    264         '''
    265     expect_compile_error(
    266         'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
    267         'The type T was declared as a const Required type in the returned Component, however',
    268         COMMON_DEFINITIONS,
    269         source,
    270         locals())
    271 
    272 def test_install_requiring_const_then_install_requiring_nonconst_ok():
    273     source = '''
    274         struct X {};
    275         struct Y {};
    276         struct Z {};
    277 
    278         fruit::Component<fruit::Required<const X>, Y> getChildComponent1() {
    279           return fruit::createComponent()
    280               .registerConstructor<Y()>();
    281         }
    282         
    283         fruit::Component<fruit::Required<X>, Z> getChildComponent2() {
    284           return fruit::createComponent()
    285               .registerConstructor<Z()>();
    286         }
    287 
    288         fruit::Component<Y, Z> getRootComponent() {
    289           return fruit::createComponent()
    290             .install(getChildComponent1)
    291             .install(getChildComponent2)
    292             .registerConstructor<X()>();
    293         }
    294         
    295         int main() {
    296           fruit::Injector<Y, Z> injector(getRootComponent);
    297           injector.get<Y>();
    298           injector.get<Z>();
    299         }
    300         '''
    301     expect_success(
    302         COMMON_DEFINITIONS,
    303         source,
    304         locals())
    305 
    306 def test_install_requiring_const_then_install_requiring_nonconst_declaring_const_requirement_error():
    307     source = '''
    308         struct X {};
    309         struct Y {};
    310         struct Z {};
    311 
    312         fruit::Component<fruit::Required<const X>, Y> getChildComponent1();
    313         fruit::Component<fruit::Required<X>, Z> getChildComponent2();
    314 
    315         fruit::Component<fruit::Required<const X>, Y, Z> getRootComponent() {
    316           return fruit::createComponent()
    317             .install(getChildComponent1)
    318             .install(getChildComponent2);
    319         }
    320         '''
    321     expect_compile_error(
    322         'ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<X>',
    323         'The type T was declared as a const Required type in the returned Component, however',
    324         COMMON_DEFINITIONS,
    325         source,
    326         locals())
    327 
    328 def test_install_with_args_success():
    329     source = '''
    330         struct X {
    331           int n;
    332           X(int n) : n(n) {}
    333         };
    334         
    335         struct Arg {
    336           Arg(int) {}
    337           Arg() = default;
    338           Arg(const Arg&) = default;
    339           Arg(Arg&&) = default;
    340           Arg& operator=(const Arg&) = default;
    341           Arg& operator=(Arg&&) = default;
    342         };
    343         
    344         bool operator==(const Arg&, const Arg&) {
    345           return true;
    346         }
    347         
    348         namespace std {
    349           template <>
    350           struct hash<Arg> {
    351             size_t operator()(const Arg&) {
    352               return 0;
    353             }
    354           };
    355         }
    356 
    357         fruit::Component<X> getParentComponent(int, std::string, Arg, Arg) {
    358           return fruit::createComponent()
    359             .registerProvider([]() { return X(5); });
    360         }
    361 
    362         fruit::Component<X> getComponent() {
    363           return fruit::createComponent()
    364             .install(getParentComponent, 5, std::string("Hello"), Arg{}, 15);
    365         }
    366 
    367         int main() {
    368           fruit::Injector<X> injector(getComponent);
    369           X x = injector.get<X>();
    370           Assert(x.n == 5);
    371         }
    372         '''
    373     expect_success(COMMON_DEFINITIONS, source)
    374 
    375 def test_install_with_args_error_not_move_constructible():
    376     source = '''
    377         struct Arg {
    378           Arg() = default;
    379           Arg(const Arg&) = default;
    380           Arg(Arg&&) = delete;
    381           Arg& operator=(const Arg&) = default;
    382           Arg& operator=(Arg&&) = default;
    383         };
    384         
    385         bool operator==(const Arg&, const Arg&);
    386         
    387         namespace std {
    388           template <>
    389           struct hash<Arg> {
    390             size_t operator()(const Arg&);
    391           };
    392         }
    393 
    394         fruit::Component<X> getParentComponent(int, std::string, Arg);
    395 
    396         fruit::Component<X> getComponent() {
    397           return fruit::createComponent()
    398             .install(getParentComponent, 5, std::string("Hello"), Arg{});
    399         }
    400         '''
    401     expect_generic_compile_error(
    402         'error: use of deleted function .Arg::Arg\(Arg&&\).'
    403             + '|error: call to deleted constructor of .Arg.'
    404             + '|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.',
    405         COMMON_DEFINITIONS,
    406         source)
    407 
    408 def test_install_with_args_error_not_move_constructible_with_conversion():
    409     source = '''
    410         struct Arg {
    411           Arg(int) {}
    412           Arg() = default;
    413           Arg(const Arg&) = default;
    414           Arg(Arg&&) = delete;
    415           Arg& operator=(const Arg&) = default;
    416           Arg& operator=(Arg&&) = default;
    417         };
    418         
    419         bool operator==(const Arg&, const Arg&);
    420         
    421         namespace std {
    422           template <>
    423           struct hash<Arg> {
    424             size_t operator()(const Arg&);
    425           };
    426         }
    427 
    428         fruit::Component<X> getParentComponent(int, std::string, Arg);
    429 
    430         fruit::Component<X> getComponent() {
    431           return fruit::createComponent()
    432             .install(getParentComponent, 5, std::string("Hello"), 15);
    433         }
    434         '''
    435     expect_generic_compile_error(
    436         'error: use of deleted function .Arg::Arg\(Arg&&\).'
    437             + '|error: call to deleted constructor of .Arg.'
    438             + '|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.',
    439         COMMON_DEFINITIONS,
    440         source)
    441 
    442 def test_install_with_args_error_not_copy_constructible():
    443     source = '''
    444         struct X {
    445           int n;
    446           X(int n) : n(n) {}
    447         };
    448         
    449         struct Arg {
    450           Arg() = default;
    451           Arg(const Arg&) = delete;
    452           Arg(Arg&&) = default;
    453           Arg& operator=(const Arg&) = default;
    454           Arg& operator=(Arg&&) = default;
    455         };
    456         
    457         bool operator==(const Arg&, const Arg&);
    458         
    459         namespace std {
    460           template <>
    461           struct hash<Arg> {
    462             size_t operator()(const Arg&);
    463           };
    464         }
    465 
    466         fruit::Component<X> getParentComponent(int, std::string, Arg);
    467 
    468         fruit::Component<X> getComponent() {
    469           return fruit::createComponent()
    470             .install(getParentComponent, 5, std::string("Hello"), Arg{});
    471         }
    472         '''
    473     expect_generic_compile_error(
    474         'error: use of deleted function .Arg::Arg\(const Arg&\).'
    475             + '|error: call to deleted constructor of .Arg.'
    476             + '|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function',
    477         COMMON_DEFINITIONS,
    478         source)
    479 
    480 def test_install_with_args_error_not_copy_constructible_with_conversion():
    481     source = '''
    482         struct X {
    483           int n;
    484           X(int n) : n(n) {}
    485         };
    486         
    487         struct Arg {
    488           Arg(int) {}
    489           Arg() = default;
    490           Arg(const Arg&) = delete;
    491           Arg(Arg&&) = default;
    492           Arg& operator=(const Arg&) = default;
    493           Arg& operator=(Arg&&) = default;
    494         };
    495         
    496         bool operator==(const Arg&, const Arg&);
    497         
    498         namespace std {
    499           template <>
    500           struct hash<Arg> {
    501             size_t operator()(const Arg&);
    502           };
    503         }
    504 
    505         fruit::Component<X> getParentComponent(int, std::string, Arg);
    506 
    507         fruit::Component<X> getComponent() {
    508           return fruit::createComponent()
    509             .install(getParentComponent, 5, std::string("Hello"), 15);
    510         }
    511         '''
    512     expect_generic_compile_error(
    513         'error: use of deleted function .Arg::Arg\(const Arg&\).'
    514             + '|error: call to deleted constructor of .Arg.'
    515             + '|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function',
    516         COMMON_DEFINITIONS,
    517         source)
    518 
    519 def test_install_with_args_error_not_move_assignable():
    520     source = '''
    521         struct Arg {
    522           Arg() = default;
    523           Arg(const Arg&) = default;
    524           Arg(Arg&&) = default;
    525           Arg& operator=(const Arg&) = default;
    526           Arg& operator=(Arg&&) = delete;
    527         };
    528         
    529         bool operator==(const Arg&, const Arg&);
    530         
    531         namespace std {
    532           template <>
    533           struct hash<Arg> {
    534             size_t operator()(const Arg&);
    535           };
    536         }
    537 
    538         fruit::Component<X> getParentComponent(int, std::string, Arg);
    539 
    540         fruit::Component<X> getComponent() {
    541           return fruit::createComponent()
    542             .install(getParentComponent, 5, std::string("Hello"), Arg{});
    543         }
    544         '''
    545     expect_generic_compile_error(
    546         'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
    547             + '|error: overload resolution selected deleted operator .=.'
    548             + '|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
    549         COMMON_DEFINITIONS,
    550         source)
    551 
    552 def test_install_with_args_error_not_move_assignable_with_conversion():
    553     source = '''
    554         struct Arg {
    555           Arg(int) {}
    556           Arg() = default;
    557           Arg(const Arg&) = default;
    558           Arg(Arg&&) = default;
    559           Arg& operator=(const Arg&) = default;
    560           Arg& operator=(Arg&&) = delete;
    561         };
    562         
    563         bool operator==(const Arg&, const Arg&);
    564         
    565         namespace std {
    566           template <>
    567           struct hash<Arg> {
    568             size_t operator()(const Arg&);
    569           };
    570         }
    571 
    572         fruit::Component<X> getParentComponent(int, std::string, Arg);
    573 
    574         fruit::Component<X> getComponent() {
    575           return fruit::createComponent()
    576             .install(getParentComponent, 5, std::string("Hello"), 15);
    577         }
    578         '''
    579     expect_generic_compile_error(
    580         'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).'
    581             + '|error: overload resolution selected deleted operator .=.'
    582             + '|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function',
    583         COMMON_DEFINITIONS,
    584         source)
    585 
    586 def test_install_with_args_error_not_copy_assignable():
    587     source = '''
    588         struct X {
    589           int n;
    590           X(int n) : n(n) {}
    591         };
    592         
    593         struct Arg {
    594           Arg() = default;
    595           Arg(const Arg&) = default;
    596           Arg(Arg&&) = default;
    597           Arg& operator=(const Arg&) = delete;
    598           Arg& operator=(Arg&&) = default;
    599         };
    600         
    601         bool operator==(const Arg&, const Arg&);
    602         
    603         namespace std {
    604           template <>
    605           struct hash<Arg> {
    606             size_t operator()(const Arg&);
    607           };
    608         }
    609 
    610         fruit::Component<X> getParentComponent(int, std::string, Arg);
    611 
    612         fruit::Component<X> getComponent() {
    613           return fruit::createComponent()
    614             .install(getParentComponent, 5, std::string("Hello"), Arg{});
    615         }
    616         '''
    617     expect_generic_compile_error(
    618         'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
    619             + '|error: overload resolution selected deleted operator .=.'
    620             + '|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
    621         COMMON_DEFINITIONS,
    622         source)
    623 
    624 def test_install_with_args_error_not_copy_assignable_with_conversion():
    625     source = '''
    626         struct X {
    627           int n;
    628           X(int n) : n(n) {}
    629         };
    630         
    631         struct Arg {
    632           Arg(int) {}
    633           Arg() = default;
    634           Arg(const Arg&) = default;
    635           Arg(Arg&&) = default;
    636           Arg& operator=(const Arg&) = delete;
    637           Arg& operator=(Arg&&) = default;
    638         };
    639         
    640         bool operator==(const Arg&, const Arg&);
    641         
    642         namespace std {
    643           template <>
    644           struct hash<Arg> {
    645             size_t operator()(const Arg&);
    646           };
    647         }
    648 
    649         fruit::Component<X> getParentComponent(int, std::string, Arg);
    650 
    651         fruit::Component<X> getComponent() {
    652           return fruit::createComponent()
    653             .install(getParentComponent, 5, std::string("Hello"), 15);
    654         }
    655         '''
    656     expect_generic_compile_error(
    657         'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).'
    658             + '|error: overload resolution selected deleted operator .=.'
    659             + '|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function',
    660         COMMON_DEFINITIONS,
    661         source)
    662 
    663 def test_install_with_args_error_not_equality_comparable():
    664     source = '''
    665         struct X {
    666           int n;
    667           X(int n) : n(n) {}
    668         };
    669         
    670         struct Arg {
    671           Arg() = default;
    672           Arg(const Arg&) = default;
    673           Arg(Arg&&) = default;
    674           Arg& operator=(const Arg&) = default;
    675           Arg& operator=(Arg&&) = default;
    676         };
    677         
    678         namespace std {
    679           template <>
    680           struct hash<Arg> {
    681             size_t operator()(const Arg&);
    682           };
    683         }
    684 
    685         fruit::Component<X> getParentComponent(int, std::string, Arg);
    686 
    687         fruit::Component<X> getComponent() {
    688           return fruit::createComponent()
    689             .install(getParentComponent, 5, std::string("Hello"), Arg{});
    690         }
    691         '''
    692     expect_generic_compile_error(
    693         'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
    694             + '|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
    695             + '|error C2676: binary .==.: .const Arg. does not define this operator',
    696         COMMON_DEFINITIONS,
    697         source)
    698 
    699 def test_install_with_args_error_not_equality_comparable_with_conversion():
    700     source = '''
    701         struct X {
    702           int n;
    703           X(int n) : n(n) {}
    704         };
    705         
    706         struct Arg {
    707           Arg(int) {}
    708           Arg() = default;
    709           Arg(const Arg&) = default;
    710           Arg(Arg&&) = default;
    711           Arg& operator=(const Arg&) = default;
    712           Arg& operator=(Arg&&) = default;
    713         };
    714         
    715         namespace std {
    716           template <>
    717           struct hash<Arg> {
    718             size_t operator()(const Arg&);
    719           };
    720         }
    721 
    722         fruit::Component<X> getParentComponent(int, std::string, Arg);
    723 
    724         fruit::Component<X> getComponent() {
    725           return fruit::createComponent()
    726             .install(getParentComponent, 5, std::string("Hello"), 15);
    727         }
    728         '''
    729     expect_generic_compile_error(
    730         'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)'
    731             + '|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)'
    732             + '|error C2676: binary .==.: .const Arg. does not define this operator',
    733         COMMON_DEFINITIONS,
    734         source)
    735 
    736 def test_install_with_args_error_not_hashable():
    737     source = '''
    738         struct Arg {
    739           Arg() = default;
    740           Arg(const Arg&) = default;
    741           Arg(Arg&&) = default;
    742           Arg& operator=(const Arg&) = default;
    743           Arg& operator=(Arg&&) = default;
    744         };
    745         
    746         bool operator==(const Arg&, const Arg&);
    747         
    748         fruit::Component<X> getParentComponent(int, std::string, Arg);
    749 
    750         fruit::Component<X> getComponent() {
    751           return fruit::createComponent()
    752             .install(getParentComponent, 5, std::string("Hello"), Arg{});
    753         }
    754         '''
    755     expect_generic_compile_error(
    756         'error: use of deleted function .std::hash<Arg>::hash\(\).'
    757             + '|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
    758             + '|error: invalid use of incomplete type .struct std::hash<Arg>.'
    759             + '|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
    760             + '|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
    761             + '|error C2064: term does not evaluate to a function taking 1 arguments',
    762         COMMON_DEFINITIONS,
    763         source)
    764 
    765 def test_install_with_args_error_not_hashable_with_conversion():
    766     source = '''
    767         struct Arg {
    768           Arg(int) {}
    769           Arg() = default;
    770           Arg(const Arg&) = default;
    771           Arg(Arg&&) = default;
    772           Arg& operator=(const Arg&) = default;
    773           Arg& operator=(Arg&&) = default;
    774         };
    775         
    776         bool operator==(const Arg&, const Arg&);
    777         
    778         fruit::Component<X> getParentComponent(int, std::string, Arg);
    779 
    780         fruit::Component<X> getComponent() {
    781           return fruit::createComponent()
    782             .install(getParentComponent, 5, std::string("Hello"), 15);
    783         }
    784         '''
    785     expect_generic_compile_error(
    786         'error: use of deleted function .std::hash<Arg>::hash\(\).'
    787             + '|error: call to implicitly-deleted default constructor of .std::hash<Arg>.'
    788             + '|error: invalid use of incomplete type .struct std::hash<Arg>.'
    789             + '|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.'
    790             + '|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.'
    791             + '|error C2064: term does not evaluate to a function taking 1 arguments',
    792         COMMON_DEFINITIONS,
    793         source)
    794 
    795 @pytest.mark.parametrize('XAnnot', [
    796     'X',
    797     'fruit::Annotated<Annotation1, X>',
    798 ])
    799 def test_install_component_functions_deduped(XAnnot):
    800     source = '''
    801         struct X {};
    802 
    803         X x;
    804 
    805         fruit::Component<> getComponent() {
    806           return fruit::createComponent()
    807             .addInstanceMultibinding<XAnnot, X>(x);
    808         }
    809 
    810         fruit::Component<> getComponent2() {
    811           return fruit::createComponent()
    812             .install(getComponent);
    813         }
    814 
    815         fruit::Component<> getComponent3() {
    816           return fruit::createComponent()
    817             .install(getComponent);
    818         }
    819 
    820         fruit::Component<> getComponent4() {
    821           return fruit::createComponent()
    822             .install(getComponent2)
    823             .install(getComponent3);
    824         }
    825 
    826         int main() {
    827           fruit::Injector<> injector(getComponent4);
    828 
    829           // We test multibindings because the effect on other bindings is not user-visible (that only affects
    830           // performance).
    831           std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
    832           Assert(multibindings.size() == 1);
    833           Assert(multibindings[0] == &x);
    834         }
    835         '''
    836     expect_success(
    837         COMMON_DEFINITIONS,
    838         source,
    839         locals())
    840 
    841 @pytest.mark.parametrize('XAnnot', [
    842     'X',
    843     'fruit::Annotated<Annotation1, X>',
    844 ])
    845 def test_install_component_functions_deduped_across_normalized_component(XAnnot):
    846     source = '''
    847         struct X {};
    848 
    849         X x;
    850 
    851         fruit::Component<> getComponent() {
    852           return fruit::createComponent()
    853             .addInstanceMultibinding<XAnnot, X>(x);
    854         }
    855 
    856         fruit::Component<> getComponent2() {
    857           return fruit::createComponent()
    858             .install(getComponent);
    859         }
    860 
    861         fruit::Component<> getComponent3() {
    862           return fruit::createComponent()
    863             .install(getComponent);
    864         }
    865 
    866         int main() {
    867           fruit::NormalizedComponent<> normalizedComponent(getComponent2);
    868           fruit::Injector<> injector(normalizedComponent, getComponent3);
    869 
    870           // We test multibindings because the effect on other bindings is not user-visible (that only affects
    871           // performance).
    872           std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
    873           Assert(multibindings.size() == 1);
    874           Assert(multibindings[0] == &x);
    875         }
    876         '''
    877     expect_success(
    878         COMMON_DEFINITIONS,
    879         source,
    880         locals())
    881 
    882 @pytest.mark.parametrize('XAnnot', [
    883     'X',
    884     'fruit::Annotated<Annotation1, X>',
    885 ])
    886 def test_install_component_functions_with_args_deduped(XAnnot):
    887     source = '''
    888         struct X {};
    889 
    890         X x;
    891 
    892         fruit::Component<> getComponent(int) {
    893           return fruit::createComponent()
    894             .addInstanceMultibinding<XAnnot, X>(x);
    895         }
    896 
    897         fruit::Component<> getComponent2() {
    898           return fruit::createComponent()
    899             .install(getComponent, 1);
    900         }
    901 
    902         fruit::Component<> getComponent3() {
    903           return fruit::createComponent()
    904             .install(getComponent, 1);
    905         }
    906 
    907         fruit::Component<> getComponent4() {
    908           return fruit::createComponent()
    909             .install(getComponent2)
    910             .install(getComponent3);
    911         }
    912 
    913         int main() {
    914           fruit::Injector<> injector(getComponent4);
    915 
    916           // We test multibindings because the effect on other bindings is not user-visible (that only affects
    917           // performance).
    918           std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
    919           Assert(multibindings.size() == 1);
    920           Assert(multibindings[0] == &x);
    921         }
    922         '''
    923     expect_success(
    924         COMMON_DEFINITIONS,
    925         source,
    926         locals())
    927 
    928 @pytest.mark.parametrize('XAnnot', [
    929     'X',
    930     'fruit::Annotated<Annotation1, X>',
    931 ])
    932 def test_install_component_functions_different_args_not_deduped(XAnnot):
    933     source = '''
    934         struct X {};
    935 
    936         X x;
    937 
    938         fruit::Component<> getComponent(int) {
    939           return fruit::createComponent()
    940             .addInstanceMultibinding<XAnnot, X>(x);
    941         }
    942 
    943         fruit::Component<> getComponent2() {
    944           return fruit::createComponent()
    945             .install(getComponent, 1);
    946         }
    947 
    948         fruit::Component<> getComponent3() {
    949           return fruit::createComponent()
    950             .install(getComponent, 2);
    951         }
    952 
    953         fruit::Component<> getComponent4() {
    954           return fruit::createComponent()
    955             .install(getComponent2)
    956             .install(getComponent3);
    957         }
    958 
    959         int main() {
    960           fruit::Injector<> injector(getComponent4);
    961 
    962           // We test multibindings because the effect on other bindings is not user-visible (it only affects
    963           // performance).
    964           std::vector<X*> multibindings = injector.getMultibindings<XAnnot>();
    965           Assert(multibindings.size() == 2);
    966           Assert(multibindings[0] == &x);
    967           Assert(multibindings[1] == &x);
    968         }
    969         '''
    970     expect_success(
    971         COMMON_DEFINITIONS,
    972         source,
    973         locals())
    974 
    975 def test_install_component_functions_loop():
    976     source = '''
    977         struct X {};
    978         struct Y {};
    979         struct Z {};
    980         
    981         // X -> Y -> Z -> Y
    982         
    983         fruit::Component<X> getXComponent();
    984         fruit::Component<Y> getYComponent();
    985         fruit::Component<Z> getZComponent();
    986 
    987         fruit::Component<X> getXComponent() {
    988           return fruit::createComponent()
    989               .registerConstructor<X()>()
    990               .install(getYComponent);
    991         }
    992 
    993         fruit::Component<Y> getYComponent() {
    994           return fruit::createComponent()
    995               .registerConstructor<Y()>()
    996               .install(getZComponent);
    997         }
    998 
    999         fruit::Component<Z> getZComponent() {
   1000           return fruit::createComponent()
   1001               .registerConstructor<Z()>()
   1002               .install(getYComponent);
   1003         }
   1004 
   1005         int main() {
   1006           fruit::Injector<X> injector(getXComponent);
   1007           (void)injector;
   1008         }
   1009         '''
   1010     expect_runtime_error(
   1011         'Component installation trace \(from top-level to the most deeply-nested\):\n'
   1012             + '(class )?fruit::Component<(struct )?X> ?\((__cdecl)?\*\)\((void)?\)\n'
   1013             + '<-- The loop starts here\n'
   1014             + '(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n'
   1015             + '(class )?fruit::Component<(struct )?Z> ?\((__cdecl)?\*\)\((void)?\)\n'
   1016             + '(class )?fruit::Component<(struct )?Y> ?\((__cdecl)?\*\)\((void)?\)\n',
   1017         COMMON_DEFINITIONS,
   1018         source,
   1019         locals())
   1020 
   1021 def test_install_component_functions_different_arguments_loop_not_reported():
   1022     source = '''
   1023         struct X {};
   1024         struct Y {};
   1025         struct Z {};
   1026         
   1027         // X -> Y(1) -> Z -> Y(2)
   1028         
   1029         fruit::Component<X> getXComponent();
   1030         fruit::Component<Y> getYComponent(int);
   1031         fruit::Component<Z> getZComponent();
   1032 
   1033         fruit::Component<X> getXComponent() {
   1034           return fruit::createComponent()
   1035               .registerConstructor<X()>()
   1036               .install(getYComponent, 1);
   1037         }
   1038 
   1039         fruit::Component<Y> getYComponent(int n) {
   1040             if (n == 1) {
   1041                 return fruit::createComponent()
   1042                     .registerConstructor<Y()>()
   1043                     .install(getZComponent);
   1044             } else {
   1045                 return fruit::createComponent()
   1046                     .registerConstructor<Y()>();
   1047             }
   1048         }
   1049 
   1050         fruit::Component<Z> getZComponent() {
   1051           return fruit::createComponent()
   1052               .registerConstructor<Z()>()
   1053               .install(getYComponent, 2);
   1054         }
   1055 
   1056         int main() {
   1057           fruit::Injector<X> injector(getXComponent);
   1058           injector.get<X>();
   1059         }
   1060         '''
   1061     expect_success(
   1062         COMMON_DEFINITIONS,
   1063         source,
   1064         locals())
   1065 
   1066 if __name__== '__main__':
   1067     main(__file__)
   1068