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 import pytest
     16 
     17 from fruit_test_common import *
     18 
     19 COMMON_DEFINITIONS = '''
     20     #include "test_common.h"
     21 
     22     struct X;
     23 
     24     struct Annotation1 {};
     25     using XAnnot1 = fruit::Annotated<Annotation1, X>;
     26 
     27     struct Annotation2 {};
     28     using XAnnot2 = fruit::Annotated<Annotation2, X>;
     29     '''
     30 
     31 @pytest.mark.parametrize('XAnnot', [
     32     'X',
     33     'fruit::Annotated<Annotation1, X>',
     34 ])
     35 def test_move(XAnnot):
     36     source = '''
     37         struct X {
     38           using Inject = X();
     39         };
     40 
     41         fruit::Component<XAnnot> getComponent() {
     42           fruit::Component<XAnnot> c = fruit::createComponent();
     43           fruit::Component<XAnnot> c2 = std::move(c);
     44           return fruit::Component<XAnnot>(std::move(c2));
     45         }
     46 
     47         int main() {
     48           fruit::Injector<XAnnot> injector(getComponent);
     49           injector.get<XAnnot>();
     50         }
     51         '''
     52     expect_success(
     53         COMMON_DEFINITIONS,
     54         source,
     55         locals())
     56 
     57 @pytest.mark.parametrize('XAnnot', [
     58     'X',
     59     'fruit::Annotated<Annotation1, X>',
     60 ])
     61 def test_move_partial_component(XAnnot):
     62     source = '''
     63         struct X {
     64           using Inject = X();
     65         };
     66 
     67         fruit::Component<XAnnot> getComponent() {
     68           auto c = fruit::createComponent();
     69           auto c1 = std::move(c);
     70           return std::move(c1);
     71         }
     72 
     73         int main() {
     74           fruit::Injector<XAnnot> injector(getComponent);
     75           injector.get<XAnnot>();
     76         }
     77         '''
     78     expect_generic_compile_error(
     79         'error: use of deleted function .fruit::PartialComponent<Bindings>::PartialComponent\(fruit::PartialComponent<Bindings>&&\).'
     80             + '|error: call to deleted constructor of .fruit::PartialComponent<>.'
     81             # MSVC 2017
     82             + '|error C2280: .fruit::PartialComponent<>::PartialComponent\(fruit::PartialComponent<> &&\).: attempting to reference a deleted function'
     83             # MSVC 2015
     84             + '|error C2248: .fruit::PartialComponent<>::PartialComponent.: cannot access private member declared in class .fruit::PartialComponent<>.',
     85         COMMON_DEFINITIONS,
     86         source,
     87         locals())
     88 
     89 @pytest.mark.parametrize('XAnnot,ConstXAnnot', [
     90     ('X', 'X'),
     91     ('X', 'const X'),
     92     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
     93     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
     94 ])
     95 def test_error_no_binding_found(XAnnot, ConstXAnnot):
     96     source = '''
     97         struct X {};
     98 
     99         fruit::Component<ConstXAnnot> getComponent() {
    100           return fruit::createComponent();
    101         }
    102         '''
    103     expect_compile_error(
    104         'NoBindingFoundError<XAnnot>',
    105         'No explicit binding nor C::Inject definition was found for T.',
    106         COMMON_DEFINITIONS,
    107         source,
    108         locals())
    109 
    110 @pytest.mark.parametrize('XAnnot,ConstXAnnot', [
    111     ('X', 'X'),
    112     ('X', 'const X'),
    113     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, X>'),
    114     ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'),
    115 ])
    116 def test_error_no_binding_found_abstract_class(XAnnot, ConstXAnnot):
    117     source = '''
    118         struct X {
    119           virtual void f() = 0;
    120         };
    121 
    122         fruit::Component<ConstXAnnot> getComponent() {
    123           return fruit::createComponent();
    124         }
    125         '''
    126     expect_compile_error(
    127         'NoBindingFoundForAbstractClassError<XAnnot,X>',
    128         'No explicit binding was found for T, and note that C is an abstract class',
    129         COMMON_DEFINITIONS,
    130         source,
    131         locals())
    132 
    133 @pytest.mark.parametrize('MaybeConst', [
    134     '',
    135     'const',
    136 ])
    137 def test_error_no_factory_binding_found(MaybeConst):
    138     source = '''
    139         struct X {};
    140 
    141         fruit::Component<MaybeConst std::function<std::unique_ptr<X>()>> getComponent() {
    142           return fruit::createComponent();
    143         }
    144         '''
    145     expect_compile_error(
    146         'NoBindingFoundError<std::function<std::unique_ptr<X(,std::default_delete<X>)?>\((void)?\)>',
    147         'No explicit binding nor C::Inject definition was found for T.',
    148         COMMON_DEFINITIONS,
    149         source,
    150         locals())
    151 
    152 @pytest.mark.parametrize('MaybeConst', [
    153     '',
    154     'const',
    155 ])
    156 def test_error_no_factory_binding_found_with_annotation(MaybeConst):
    157     source = '''
    158         struct X {};
    159 
    160         fruit::Component<fruit::Annotated<Annotation1, MaybeConst std::function<std::unique_ptr<X>()>>> getComponent() {
    161           return fruit::createComponent();
    162         }
    163         '''
    164     expect_compile_error(
    165         'NoBindingFoundError<fruit::Annotated<Annotation1,std::function<std::unique_ptr<X(,std::default_delete<X>)?>\((void)?\)>>',
    166         'No explicit binding nor C::Inject definition was found for T.',
    167         COMMON_DEFINITIONS,
    168         source,
    169         locals())
    170 
    171 if __name__== '__main__':
    172     main(__file__)
    173