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