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 28class TestInstallComponentFunctions(parameterized.TestCase): 29 def test_install_component_functions_deduped_against_previous_install_no_args(self): 30 source = ''' 31 int num_executions = 0; 32 33 fruit::Component<int> getChildComponent() { 34 static int n = 5; 35 ++num_executions; 36 return fruit::createComponent() 37 .bindInstance(n); 38 } 39 40 fruit::Component<> getMiddleComponent() { 41 return fruit::createComponent() 42 .install(getChildComponent); 43 } 44 45 fruit::Component<int> getMainComponent() { 46 return fruit::createComponent() 47 .install(getMiddleComponent) 48 .installComponentFunctions(fruit::componentFunction(getChildComponent)); 49 } 50 51 int main() { 52 fruit::Injector<int> injector(getMainComponent); 53 int n = injector.get<int>(); 54 Assert(n == 5); 55 Assert(num_executions == 1); 56 } 57 ''' 58 expect_success( 59 COMMON_DEFINITIONS, 60 source, 61 locals()) 62 63 def test_install_component_functions_deduped_against_following_install_no_args(self): 64 source = ''' 65 int num_executions = 0; 66 67 fruit::Component<int> getChildComponent() { 68 static int n = 5; 69 ++num_executions; 70 return fruit::createComponent() 71 .bindInstance(n); 72 } 73 74 fruit::Component<> getMiddleComponent() { 75 return fruit::createComponent() 76 .installComponentFunctions(fruit::componentFunction(getChildComponent)); 77 } 78 79 fruit::Component<int> getMainComponent() { 80 return fruit::createComponent() 81 .install(getMiddleComponent) 82 .install(getChildComponent); 83 } 84 85 int main() { 86 fruit::Injector<int> injector(getMainComponent); 87 int n = injector.get<int>(); 88 Assert(n == 5); 89 Assert(num_executions == 1); 90 } 91 ''' 92 expect_success( 93 COMMON_DEFINITIONS, 94 source, 95 locals()) 96 97 def test_install_component_functions_deduped_against_previous_install_with_args(self): 98 source = ''' 99 int num_executions = 0; 100 101 fruit::Component<int> getChildComponent(int) { 102 static int n = 5; 103 ++num_executions; 104 return fruit::createComponent() 105 .bindInstance(n); 106 } 107 108 fruit::Component<> getMiddleComponent() { 109 return fruit::createComponent() 110 .install(getChildComponent, 42); 111 } 112 113 fruit::Component<int> getMainComponent() { 114 return fruit::createComponent() 115 .install(getMiddleComponent) 116 .installComponentFunctions(fruit::componentFunction(getChildComponent, 42)); 117 } 118 119 int main() { 120 fruit::Injector<int> injector(getMainComponent); 121 int n = injector.get<int>(); 122 Assert(n == 5); 123 Assert(num_executions == 1); 124 } 125 ''' 126 expect_success( 127 COMMON_DEFINITIONS, 128 source, 129 locals()) 130 131 def test_install_component_functions_deduped_against_following_install_with_args(self): 132 source = ''' 133 int num_executions = 0; 134 135 fruit::Component<int> getChildComponent(int) { 136 static int n = 5; 137 ++num_executions; 138 return fruit::createComponent() 139 .bindInstance(n); 140 } 141 142 fruit::Component<> getMiddleComponent() { 143 return fruit::createComponent() 144 .installComponentFunctions(fruit::componentFunction(getChildComponent, 42)); 145 } 146 147 fruit::Component<int> getMainComponent() { 148 return fruit::createComponent() 149 .install(getMiddleComponent) 150 .install(getChildComponent, 42); 151 } 152 153 int main() { 154 fruit::Injector<int> injector(getMainComponent); 155 int n = injector.get<int>(); 156 Assert(n == 5); 157 Assert(num_executions == 1); 158 } 159 ''' 160 expect_success( 161 COMMON_DEFINITIONS, 162 source, 163 locals()) 164 165 def test_install_component_functions_same_as_with_previous_install_with_different_args(self): 166 source = ''' 167 int num_executions = 0; 168 169 fruit::Component<int> getChildComponent(int) { 170 static int n = 5; 171 ++num_executions; 172 return fruit::createComponent() 173 .bindInstance(n); 174 } 175 176 fruit::Component<> getMiddleComponent() { 177 return fruit::createComponent() 178 .install(getChildComponent, 42); 179 } 180 181 fruit::Component<int> getMainComponent() { 182 return fruit::createComponent() 183 .install(getMiddleComponent) 184 .installComponentFunctions(fruit::componentFunction(getChildComponent, 2)); 185 } 186 187 int main() { 188 fruit::Injector<int> injector(getMainComponent); 189 int n = injector.get<int>(); 190 Assert(n == 5); 191 Assert(num_executions == 2); 192 } 193 ''' 194 expect_success( 195 COMMON_DEFINITIONS, 196 source, 197 locals()) 198 199 def test_install_component_functions_same_as_following_install_with_different_args(self): 200 source = ''' 201 int num_executions = 0; 202 203 fruit::Component<int> getChildComponent(int) { 204 static int n = 5; 205 ++num_executions; 206 return fruit::createComponent() 207 .bindInstance(n); 208 } 209 210 fruit::Component<> getMiddleComponent() { 211 return fruit::createComponent() 212 .installComponentFunctions(fruit::componentFunction(getChildComponent, 42)); 213 } 214 215 fruit::Component<int> getMainComponent() { 216 return fruit::createComponent() 217 .install(getMiddleComponent) 218 .install(getChildComponent, 2); 219 } 220 221 int main() { 222 fruit::Injector<int> injector(getMainComponent); 223 (void)injector; 224 Assert(num_executions == 2); 225 } 226 ''' 227 expect_success( 228 COMMON_DEFINITIONS, 229 source, 230 locals()) 231 232 def test_install_component_functions_no_component_functions(self): 233 source = ''' 234 fruit::Component<> getComponent() { 235 return fruit::createComponent() 236 .installComponentFunctions(); 237 } 238 239 int main() { 240 fruit::Injector<> injector(getComponent); 241 (void)injector; 242 } 243 ''' 244 expect_success(COMMON_DEFINITIONS, source) 245 246 def test_install_component_functions_one_component_function(self): 247 source = ''' 248 struct X { 249 int n; 250 X(int n) : n(n) {} 251 }; 252 253 fruit::Component<X> getParentComponent(std::string) { 254 return fruit::createComponent() 255 .registerProvider([]() { return X(5); }); 256 } 257 258 fruit::Component<X> getComponent() { 259 return fruit::createComponent() 260 .installComponentFunctions(fruit::componentFunction(getParentComponent, std::string("Hello"))); 261 } 262 263 int main() { 264 fruit::Injector<X> injector(getComponent); 265 X x = injector.get<X>(); 266 Assert(x.n == 5); 267 } 268 ''' 269 expect_success(COMMON_DEFINITIONS, source) 270 271 def test_install_component_functions_two_component_functions(self): 272 source = ''' 273 struct X { 274 int n; 275 X(int n) : n(n) {} 276 }; 277 278 struct Y { 279 int n; 280 Y(int n) : n(n) {} 281 }; 282 283 fruit::Component<X> getParentComponent1(std::string) { 284 return fruit::createComponent() 285 .registerProvider([]() { return X(5); }); 286 } 287 288 fruit::Component<Y> getParentComponent2(std::string) { 289 return fruit::createComponent() 290 .registerProvider([]() { return Y(42); }); 291 } 292 293 fruit::Component<X, Y> getComponent() { 294 return fruit::createComponent() 295 .installComponentFunctions( 296 fruit::componentFunction(getParentComponent1, std::string("Hello")), 297 fruit::componentFunction(getParentComponent2, std::string("World"))); 298 } 299 300 int main() { 301 fruit::Injector<X, Y> injector(getComponent); 302 X x = injector.get<X>(); 303 Y y = injector.get<Y>(); 304 Assert(x.n == 5); 305 Assert(y.n == 42); 306 } 307 ''' 308 expect_success(COMMON_DEFINITIONS, source) 309 310 def test_install_component_functions_with_template_parameter_pack_unpacking(self): 311 source = ''' 312 template <typename T> 313 struct GetComponentHolder; 314 315 struct X { 316 int n; 317 X(int n) : n(n) {} 318 }; 319 320 struct Y { 321 int n; 322 Y(int n) : n(n) {} 323 }; 324 325 template <> 326 struct GetComponentHolder<X> { 327 static fruit::Component<X> getComponent(std::string) { 328 return fruit::createComponent() 329 .registerProvider([]() { return X(5); }); 330 } 331 }; 332 333 template <> 334 struct GetComponentHolder<Y> { 335 static fruit::Component<Y> getComponent(std::string) { 336 return fruit::createComponent() 337 .registerProvider([]() { return Y(42); }); 338 } 339 }; 340 341 template <typename... Ts> 342 fruit::Component<Ts...> getComponent() { 343 return fruit::createComponent() 344 .installComponentFunctions( 345 fruit::componentFunction(GetComponentHolder<Ts>::getComponent, std::string("Hello"))...); 346 } 347 348 int main() { 349 fruit::Injector<X, Y> injector(getComponent<X, Y>); 350 X x = injector.get<X>(); 351 Y y = injector.get<Y>(); 352 Assert(x.n == 5); 353 Assert(y.n == 42); 354 } 355 ''' 356 expect_success(COMMON_DEFINITIONS, source) 357 358 def test_install_component_functions_wrong_argument_type(self): 359 source = ''' 360 fruit::Component<> getMainComponent() { 361 return fruit::createComponent() 362 .installComponentFunctions(42); 363 } 364 ''' 365 expect_compile_error( 366 'IncorrectArgTypePassedToInstallComponentFuntionsError<int>', 367 'All arguments passed to installComponentFunctions.. must be fruit::ComponentFunction<...> objects but an ' 368 'argument with type Arg was passed instead.', 369 COMMON_DEFINITIONS, 370 source, 371 locals()) 372 373if __name__ == '__main__': 374 absltest.main() 375