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 23class TestComponentFunctions(parameterized.TestCase): 24 def test_component_function_success(self): 25 source = ''' 26 struct X { 27 int n; 28 X(int n) : n(n) {} 29 }; 30 31 struct Arg { 32 Arg(int) {} 33 Arg() = default; 34 Arg(const Arg&) = default; 35 Arg(Arg&&) = default; 36 Arg& operator=(const Arg&) = default; 37 Arg& operator=(Arg&&) = default; 38 }; 39 40 bool operator==(const Arg&, const Arg&) { 41 return true; 42 } 43 44 namespace std { 45 template <> 46 struct hash<Arg> { 47 size_t operator()(const Arg&) { 48 return 0; 49 } 50 }; 51 } 52 53 fruit::Component<X> getParentComponent(int, std::string, Arg, Arg) { 54 return fruit::createComponent() 55 .registerProvider([]() { return X(5); }); 56 } 57 58 fruit::Component<X> getComponent() { 59 return fruit::createComponent() 60 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{}, 15)); 61 } 62 63 int main() { 64 fruit::Injector<X> injector(getComponent); 65 X x = injector.get<X>(); 66 Assert(x.n == 5); 67 } 68 ''' 69 expect_success(COMMON_DEFINITIONS, source) 70 71 def test_component_function_no_args_success(self): 72 source = ''' 73 struct X { 74 int n; 75 X(int n) : n(n) {} 76 }; 77 78 fruit::Component<X> getParentComponent() { 79 return fruit::createComponent() 80 .registerProvider([]() { return X(5); }); 81 } 82 83 fruit::Component<X> getComponent() { 84 return fruit::createComponent() 85 .installComponentFunctions(fruit::componentFunction(getParentComponent)); 86 } 87 88 int main() { 89 fruit::Injector<X> injector(getComponent); 90 X x = injector.get<X>(); 91 Assert(x.n == 5); 92 } 93 ''' 94 expect_success(COMMON_DEFINITIONS, source) 95 96 def test_component_function_one_arg_success(self): 97 source = ''' 98 struct X { 99 int n; 100 X(int n) : n(n) {} 101 }; 102 103 fruit::Component<X> getParentComponent(std::string) { 104 return fruit::createComponent() 105 .registerProvider([]() { return X(5); }); 106 } 107 108 fruit::Component<X> getComponent() { 109 return fruit::createComponent() 110 .installComponentFunctions(fruit::componentFunction(getParentComponent, std::string("Hello"))); 111 } 112 113 int main() { 114 fruit::Injector<X> injector(getComponent); 115 X x = injector.get<X>(); 116 Assert(x.n == 5); 117 } 118 ''' 119 expect_success(COMMON_DEFINITIONS, source) 120 121 def test_component_function_error_not_move_constructible(self): 122 source = ''' 123 struct X {}; 124 125 struct Arg { 126 Arg() = default; 127 Arg(const Arg&) = default; 128 Arg(Arg&&) = delete; 129 Arg& operator=(const Arg&) = default; 130 Arg& operator=(Arg&&) = default; 131 }; 132 133 bool operator==(const Arg&, const Arg&); 134 135 namespace std { 136 template <> 137 struct hash<Arg> { 138 size_t operator()(const Arg&); 139 }; 140 } 141 142 fruit::Component<X> getParentComponent(int, std::string, Arg); 143 144 fruit::Component<X> getComponent() { 145 return fruit::createComponent() 146 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 147 } 148 ''' 149 expect_generic_compile_error( 150 r'error: use of deleted function .Arg::Arg\(Arg&&\).' 151 r'|error: call to deleted constructor of .Arg.' 152 r'|.Arg::Arg\(const Arg &\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.' 153 r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.' 154 r'|.Arg::Arg\(Arg &&\).: attempting to reference a deleted function', 155 COMMON_DEFINITIONS, 156 source) 157 158 def test_component_function_error_not_move_constructible_with_conversion(self): 159 source = ''' 160 struct X {}; 161 162 struct Arg { 163 Arg(int) {} 164 Arg() = default; 165 Arg(const Arg&) = default; 166 Arg(Arg&&) = delete; 167 Arg& operator=(const Arg&) = default; 168 Arg& operator=(Arg&&) = default; 169 }; 170 171 bool operator==(const Arg&, const Arg&); 172 173 namespace std { 174 template <> 175 struct hash<Arg> { 176 size_t operator()(const Arg&); 177 }; 178 } 179 180 fruit::Component<X> getParentComponent(int, std::string, Arg); 181 182 fruit::Component<X> getComponent() { 183 return fruit::createComponent() 184 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 185 } 186 ''' 187 expect_generic_compile_error( 188 r'error: use of deleted function .Arg::Arg\(Arg&&\).' 189 r'|error: call to deleted constructor of .Arg.' 190 r'|.Arg::Arg\((int|Arg &&)\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.' 191 r'|error: copying parameter of type .Arg. invokes deleted constructor' 192 r'|error C2280: .Arg::Arg\(Arg &&\).: attempting to reference a deleted function', 193 COMMON_DEFINITIONS, 194 source) 195 196 def test_component_function_error_not_copy_constructible(self): 197 source = ''' 198 struct X { 199 int n; 200 X(int n) : n(n) {} 201 }; 202 203 struct Arg { 204 Arg() = default; 205 Arg(const Arg&) = delete; 206 Arg(Arg&&) = default; 207 Arg& operator=(const Arg&) = default; 208 Arg& operator=(Arg&&) = default; 209 }; 210 211 bool operator==(const Arg&, const Arg&); 212 213 namespace std { 214 template <> 215 struct hash<Arg> { 216 size_t operator()(const Arg&); 217 }; 218 } 219 220 fruit::Component<X> getParentComponent(int, std::string, Arg); 221 222 fruit::Component<X> getComponent() { 223 return fruit::createComponent() 224 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 225 } 226 ''' 227 expect_generic_compile_error( 228 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 229 r'|error: call to deleted constructor of .Arg.' 230 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function' 231 r'|.std::tuple<int,std::string,Arg>::tuple.: no overloaded function takes 3 arguments' 232 # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print 233 # a more useful error. 234 r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.', 235 COMMON_DEFINITIONS, 236 source) 237 238 def test_component_function_error_not_copy_constructible_with_conversion(self): 239 source = ''' 240 struct X { 241 int n; 242 X(int n) : n(n) {} 243 }; 244 245 struct Arg { 246 Arg(int) {} 247 Arg() = default; 248 Arg(const Arg&) = delete; 249 Arg(Arg&&) = default; 250 Arg& operator=(const Arg&) = default; 251 Arg& operator=(Arg&&) = default; 252 }; 253 254 bool operator==(const Arg&, const Arg&); 255 256 namespace std { 257 template <> 258 struct hash<Arg> { 259 size_t operator()(const Arg&); 260 }; 261 } 262 263 fruit::Component<X> getParentComponent(int, std::string, Arg); 264 265 fruit::Component<X> getComponent() { 266 return fruit::createComponent() 267 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 268 } 269 ''' 270 expect_generic_compile_error( 271 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 272 r'|error: call to deleted constructor of .Arg.' 273 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function' 274 r'|.std::tuple<int,std::string,Arg>::tuple.: no overloaded function takes 3 arguments' 275 # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print 276 # a more useful error. 277 r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.', 278 COMMON_DEFINITIONS, 279 source) 280 281 def test_component_function_error_not_move_assignable(self): 282 source = ''' 283 struct X {}; 284 285 struct Arg { 286 Arg() = default; 287 Arg(const Arg&) = default; 288 Arg(Arg&&) = default; 289 Arg& operator=(const Arg&) = default; 290 Arg& operator=(Arg&&) = delete; 291 }; 292 293 bool operator==(const Arg&, const Arg&); 294 295 namespace std { 296 template <> 297 struct hash<Arg> { 298 size_t operator()(const Arg&); 299 }; 300 } 301 302 fruit::Component<X> getParentComponent(int, std::string, Arg); 303 304 fruit::Component<X> getComponent() { 305 return fruit::createComponent() 306 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 307 } 308 ''' 309 expect_generic_compile_error( 310 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 311 r'|error: overload resolution selected deleted operator .=.' 312 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 313 COMMON_DEFINITIONS, 314 source) 315 316 def test_component_function_error_not_move_assignable_with_conversion(self): 317 source = ''' 318 struct X {}; 319 320 struct Arg { 321 Arg(int) {} 322 Arg() = default; 323 Arg(const Arg&) = default; 324 Arg(Arg&&) = default; 325 Arg& operator=(const Arg&) = default; 326 Arg& operator=(Arg&&) = delete; 327 }; 328 329 bool operator==(const Arg&, const Arg&); 330 331 namespace std { 332 template <> 333 struct hash<Arg> { 334 size_t operator()(const Arg&); 335 }; 336 } 337 338 fruit::Component<X> getParentComponent(int, std::string, Arg); 339 340 fruit::Component<X> getComponent() { 341 return fruit::createComponent() 342 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 343 } 344 ''' 345 expect_generic_compile_error( 346 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 347 r'|error: overload resolution selected deleted operator .=.' 348 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 349 COMMON_DEFINITIONS, 350 source) 351 352 def test_component_function_error_not_copy_assignable(self): 353 source = ''' 354 struct X { 355 int n; 356 X(int n) : n(n) {} 357 }; 358 359 struct Arg { 360 Arg() = default; 361 Arg(const Arg&) = default; 362 Arg(Arg&&) = default; 363 Arg& operator=(const Arg&) = delete; 364 Arg& operator=(Arg&&) = default; 365 }; 366 367 bool operator==(const Arg&, const Arg&); 368 369 namespace std { 370 template <> 371 struct hash<Arg> { 372 size_t operator()(const Arg&); 373 }; 374 } 375 376 fruit::Component<X> getParentComponent(int, std::string, Arg); 377 378 fruit::Component<X> getComponent() { 379 return fruit::createComponent() 380 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 381 } 382 ''' 383 expect_generic_compile_error( 384 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 385 r'|error: overload resolution selected deleted operator .=.' 386 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 387 COMMON_DEFINITIONS, 388 source) 389 390 def test_component_function_error_not_copy_assignable_with_conversion(self): 391 source = ''' 392 struct X { 393 int n; 394 X(int n) : n(n) {} 395 }; 396 397 struct Arg { 398 Arg(int) {} 399 Arg() = default; 400 Arg(const Arg&) = default; 401 Arg(Arg&&) = default; 402 Arg& operator=(const Arg&) = delete; 403 Arg& operator=(Arg&&) = default; 404 }; 405 406 bool operator==(const Arg&, const Arg&); 407 408 namespace std { 409 template <> 410 struct hash<Arg> { 411 size_t operator()(const Arg&); 412 }; 413 } 414 415 fruit::Component<X> getParentComponent(int, std::string, Arg); 416 417 fruit::Component<X> getComponent() { 418 return fruit::createComponent() 419 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 420 } 421 ''' 422 expect_generic_compile_error( 423 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 424 r'|error: overload resolution selected deleted operator .=.' 425 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 426 COMMON_DEFINITIONS, 427 source) 428 429 def test_component_function_error_not_equality_comparable(self): 430 source = ''' 431 struct X { 432 int n; 433 X(int n) : n(n) {} 434 }; 435 436 struct Arg { 437 Arg() = default; 438 Arg(const Arg&) = default; 439 Arg(Arg&&) = default; 440 Arg& operator=(const Arg&) = default; 441 Arg& operator=(Arg&&) = default; 442 }; 443 444 namespace std { 445 template <> 446 struct hash<Arg> { 447 size_t operator()(const Arg&); 448 }; 449 } 450 451 fruit::Component<X> getParentComponent(int, std::string, Arg); 452 453 fruit::Component<X> getComponent() { 454 return fruit::createComponent() 455 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 456 } 457 ''' 458 expect_generic_compile_error( 459 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 460 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 461 r'|error C2676: binary .==.: .const Arg. does not define this operator', 462 COMMON_DEFINITIONS, 463 source) 464 465 def test_component_function_error_not_equality_comparable_with_conversion(self): 466 source = ''' 467 struct X { 468 int n; 469 X(int n) : n(n) {} 470 }; 471 472 struct Arg { 473 Arg(int) {} 474 Arg() = default; 475 Arg(const Arg&) = default; 476 Arg(Arg&&) = default; 477 Arg& operator=(const Arg&) = default; 478 Arg& operator=(Arg&&) = default; 479 }; 480 481 namespace std { 482 template <> 483 struct hash<Arg> { 484 size_t operator()(const Arg&); 485 }; 486 } 487 488 fruit::Component<X> getParentComponent(int, std::string, Arg); 489 490 fruit::Component<X> getComponent() { 491 return fruit::createComponent() 492 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 493 } 494 ''' 495 expect_generic_compile_error( 496 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 497 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 498 r'|error C2676: binary .==.: .const Arg. does not define this operator', 499 COMMON_DEFINITIONS, 500 source) 501 502 def test_component_function_error_not_hashable(self): 503 source = ''' 504 struct X {}; 505 506 struct Arg { 507 Arg() = default; 508 Arg(const Arg&) = default; 509 Arg(Arg&&) = default; 510 Arg& operator=(const Arg&) = default; 511 Arg& operator=(Arg&&) = default; 512 }; 513 514 bool operator==(const Arg&, const Arg&); 515 516 fruit::Component<X> getParentComponent(int, std::string, Arg); 517 518 fruit::Component<X> getComponent() { 519 return fruit::createComponent() 520 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 521 } 522 ''' 523 expect_generic_compile_error( 524 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 525 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 526 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 527 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 528 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 529 r'|error C2064: term does not evaluate to a function taking 1 arguments', 530 COMMON_DEFINITIONS, 531 source) 532 533 def test_component_function_error_not_hashable_with_conversion(self): 534 source = ''' 535 struct X {}; 536 537 struct Arg { 538 Arg(int) {} 539 Arg() = default; 540 Arg(const Arg&) = default; 541 Arg(Arg&&) = default; 542 Arg& operator=(const Arg&) = default; 543 Arg& operator=(Arg&&) = default; 544 }; 545 546 bool operator==(const Arg&, const Arg&); 547 548 fruit::Component<X> getParentComponent(int, std::string, Arg); 549 550 fruit::Component<X> getComponent() { 551 return fruit::createComponent() 552 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 553 } 554 ''' 555 expect_generic_compile_error( 556 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 557 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 558 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 559 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 560 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 561 r'|error C2064: term does not evaluate to a function taking 1 arguments', 562 COMMON_DEFINITIONS, 563 source) 564 565if __name__ == '__main__': 566 absltest.main() 567