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\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .const Arg &.' 153 r'|.Arg::Arg\(Arg &&\).: attempting to reference a deleted function', 154 COMMON_DEFINITIONS, 155 source) 156 157 def test_component_function_error_not_move_constructible_with_conversion(self): 158 source = ''' 159 struct X {}; 160 161 struct Arg { 162 Arg(int) {} 163 Arg() = default; 164 Arg(const Arg&) = default; 165 Arg(Arg&&) = delete; 166 Arg& operator=(const Arg&) = default; 167 Arg& operator=(Arg&&) = default; 168 }; 169 170 bool operator==(const Arg&, const Arg&); 171 172 namespace std { 173 template <> 174 struct hash<Arg> { 175 size_t operator()(const Arg&); 176 }; 177 } 178 179 fruit::Component<X> getParentComponent(int, std::string, Arg); 180 181 fruit::Component<X> getComponent() { 182 return fruit::createComponent() 183 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 184 } 185 ''' 186 expect_generic_compile_error( 187 r'error: use of deleted function .Arg::Arg\(Arg&&\).' 188 r'|error: call to deleted constructor of .Arg.' 189 r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.' 190 r'|error: copying parameter of type .Arg. invokes deleted constructor' 191 r'|error C2280: .Arg::Arg\(Arg &&\).: attempting to reference a deleted function', 192 COMMON_DEFINITIONS, 193 source) 194 195 def test_component_function_error_not_copy_constructible(self): 196 source = ''' 197 struct X { 198 int n; 199 X(int n) : n(n) {} 200 }; 201 202 struct Arg { 203 Arg() = default; 204 Arg(const Arg&) = delete; 205 Arg(Arg&&) = default; 206 Arg& operator=(const Arg&) = default; 207 Arg& operator=(Arg&&) = default; 208 }; 209 210 bool operator==(const Arg&, const Arg&); 211 212 namespace std { 213 template <> 214 struct hash<Arg> { 215 size_t operator()(const Arg&); 216 }; 217 } 218 219 fruit::Component<X> getParentComponent(int, std::string, Arg); 220 221 fruit::Component<X> getComponent() { 222 return fruit::createComponent() 223 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 224 } 225 ''' 226 expect_generic_compile_error( 227 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 228 r'|error: call to deleted constructor of .Arg.' 229 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function' 230 # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print 231 # a more useful error. 232 r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.', 233 COMMON_DEFINITIONS, 234 source) 235 236 def test_component_function_error_not_copy_constructible_with_conversion(self): 237 source = ''' 238 struct X { 239 int n; 240 X(int n) : n(n) {} 241 }; 242 243 struct Arg { 244 Arg(int) {} 245 Arg() = default; 246 Arg(const Arg&) = delete; 247 Arg(Arg&&) = default; 248 Arg& operator=(const Arg&) = default; 249 Arg& operator=(Arg&&) = default; 250 }; 251 252 bool operator==(const Arg&, const Arg&); 253 254 namespace std { 255 template <> 256 struct hash<Arg> { 257 size_t operator()(const Arg&); 258 }; 259 } 260 261 fruit::Component<X> getParentComponent(int, std::string, Arg); 262 263 fruit::Component<X> getComponent() { 264 return fruit::createComponent() 265 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 266 } 267 ''' 268 expect_generic_compile_error( 269 r'error: use of deleted function .Arg::Arg\(const Arg&\).' 270 r'|error: call to deleted constructor of .Arg.' 271 r'|error C2280: .Arg::Arg\(const Arg &\).: attempting to reference a deleted function' 272 # This is the error printed by MSVC. It's not great but I couldn't find a way to have it print 273 # a more useful error. 274 r'|cannot convert argument 1 from .int. to .std::allocator_arg_t.', 275 COMMON_DEFINITIONS, 276 source) 277 278 def test_component_function_error_not_move_assignable(self): 279 source = ''' 280 struct X {}; 281 282 struct Arg { 283 Arg() = default; 284 Arg(const Arg&) = default; 285 Arg(Arg&&) = default; 286 Arg& operator=(const Arg&) = default; 287 Arg& operator=(Arg&&) = delete; 288 }; 289 290 bool operator==(const Arg&, const Arg&); 291 292 namespace std { 293 template <> 294 struct hash<Arg> { 295 size_t operator()(const Arg&); 296 }; 297 } 298 299 fruit::Component<X> getParentComponent(int, std::string, Arg); 300 301 fruit::Component<X> getComponent() { 302 return fruit::createComponent() 303 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 304 } 305 ''' 306 expect_generic_compile_error( 307 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 308 r'|error: overload resolution selected deleted operator .=.' 309 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 310 COMMON_DEFINITIONS, 311 source) 312 313 def test_component_function_error_not_move_assignable_with_conversion(self): 314 source = ''' 315 struct X {}; 316 317 struct Arg { 318 Arg(int) {} 319 Arg() = default; 320 Arg(const Arg&) = default; 321 Arg(Arg&&) = default; 322 Arg& operator=(const Arg&) = default; 323 Arg& operator=(Arg&&) = delete; 324 }; 325 326 bool operator==(const Arg&, const Arg&); 327 328 namespace std { 329 template <> 330 struct hash<Arg> { 331 size_t operator()(const Arg&); 332 }; 333 } 334 335 fruit::Component<X> getParentComponent(int, std::string, Arg); 336 337 fruit::Component<X> getComponent() { 338 return fruit::createComponent() 339 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 340 } 341 ''' 342 expect_generic_compile_error( 343 r'error: use of deleted function .Arg& Arg::operator=\(Arg&&\).' 344 r'|error: overload resolution selected deleted operator .=.' 345 r'|error C2280: .Arg &Arg::operator =\(Arg &&\).: attempting to reference a deleted function', 346 COMMON_DEFINITIONS, 347 source) 348 349 def test_component_function_error_not_copy_assignable(self): 350 source = ''' 351 struct X { 352 int n; 353 X(int n) : n(n) {} 354 }; 355 356 struct Arg { 357 Arg() = default; 358 Arg(const Arg&) = default; 359 Arg(Arg&&) = default; 360 Arg& operator=(const Arg&) = delete; 361 Arg& operator=(Arg&&) = default; 362 }; 363 364 bool operator==(const Arg&, const Arg&); 365 366 namespace std { 367 template <> 368 struct hash<Arg> { 369 size_t operator()(const Arg&); 370 }; 371 } 372 373 fruit::Component<X> getParentComponent(int, std::string, Arg); 374 375 fruit::Component<X> getComponent() { 376 return fruit::createComponent() 377 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 378 } 379 ''' 380 expect_generic_compile_error( 381 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 382 r'|error: overload resolution selected deleted operator .=.' 383 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 384 COMMON_DEFINITIONS, 385 source) 386 387 def test_component_function_error_not_copy_assignable_with_conversion(self): 388 source = ''' 389 struct X { 390 int n; 391 X(int n) : n(n) {} 392 }; 393 394 struct Arg { 395 Arg(int) {} 396 Arg() = default; 397 Arg(const Arg&) = default; 398 Arg(Arg&&) = default; 399 Arg& operator=(const Arg&) = delete; 400 Arg& operator=(Arg&&) = default; 401 }; 402 403 bool operator==(const Arg&, const Arg&); 404 405 namespace std { 406 template <> 407 struct hash<Arg> { 408 size_t operator()(const Arg&); 409 }; 410 } 411 412 fruit::Component<X> getParentComponent(int, std::string, Arg); 413 414 fruit::Component<X> getComponent() { 415 return fruit::createComponent() 416 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 417 } 418 ''' 419 expect_generic_compile_error( 420 r'error: use of deleted function .Arg& Arg::operator=\(const Arg&\).' 421 r'|error: overload resolution selected deleted operator .=.' 422 r'|error C2280: .Arg &Arg::operator =\(const Arg &\).: attempting to reference a deleted function', 423 COMMON_DEFINITIONS, 424 source) 425 426 def test_component_function_error_not_equality_comparable(self): 427 source = ''' 428 struct X { 429 int n; 430 X(int n) : n(n) {} 431 }; 432 433 struct Arg { 434 Arg() = default; 435 Arg(const Arg&) = default; 436 Arg(Arg&&) = default; 437 Arg& operator=(const Arg&) = default; 438 Arg& operator=(Arg&&) = default; 439 }; 440 441 namespace std { 442 template <> 443 struct hash<Arg> { 444 size_t operator()(const Arg&); 445 }; 446 } 447 448 fruit::Component<X> getParentComponent(int, std::string, Arg); 449 450 fruit::Component<X> getComponent() { 451 return fruit::createComponent() 452 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 453 } 454 ''' 455 expect_generic_compile_error( 456 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 457 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 458 r'|error C2676: binary .==.: .const Arg. does not define this operator', 459 COMMON_DEFINITIONS, 460 source) 461 462 def test_component_function_error_not_equality_comparable_with_conversion(self): 463 source = ''' 464 struct X { 465 int n; 466 X(int n) : n(n) {} 467 }; 468 469 struct Arg { 470 Arg(int) {} 471 Arg() = default; 472 Arg(const Arg&) = default; 473 Arg(Arg&&) = default; 474 Arg& operator=(const Arg&) = default; 475 Arg& operator=(Arg&&) = default; 476 }; 477 478 namespace std { 479 template <> 480 struct hash<Arg> { 481 size_t operator()(const Arg&); 482 }; 483 } 484 485 fruit::Component<X> getParentComponent(int, std::string, Arg); 486 487 fruit::Component<X> getComponent() { 488 return fruit::createComponent() 489 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 490 } 491 ''' 492 expect_generic_compile_error( 493 r'error: no match for .operator==. \(operand types are .const Arg. and .const Arg.\)' 494 r'|error: invalid operands to binary expression \(.const Arg. and .const Arg.\)' 495 r'|error C2676: binary .==.: .const Arg. does not define this operator', 496 COMMON_DEFINITIONS, 497 source) 498 499 def test_component_function_error_not_hashable(self): 500 source = ''' 501 struct X {}; 502 503 struct Arg { 504 Arg() = default; 505 Arg(const Arg&) = default; 506 Arg(Arg&&) = default; 507 Arg& operator=(const Arg&) = default; 508 Arg& operator=(Arg&&) = default; 509 }; 510 511 bool operator==(const Arg&, const Arg&); 512 513 fruit::Component<X> getParentComponent(int, std::string, Arg); 514 515 fruit::Component<X> getComponent() { 516 return fruit::createComponent() 517 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), Arg{})); 518 } 519 ''' 520 expect_generic_compile_error( 521 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 522 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 523 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 524 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 525 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 526 r'|error C2064: term does not evaluate to a function taking 1 arguments', 527 COMMON_DEFINITIONS, 528 source) 529 530 def test_component_function_error_not_hashable_with_conversion(self): 531 source = ''' 532 struct X {}; 533 534 struct Arg { 535 Arg(int) {} 536 Arg() = default; 537 Arg(const Arg&) = default; 538 Arg(Arg&&) = default; 539 Arg& operator=(const Arg&) = default; 540 Arg& operator=(Arg&&) = default; 541 }; 542 543 bool operator==(const Arg&, const Arg&); 544 545 fruit::Component<X> getParentComponent(int, std::string, Arg); 546 547 fruit::Component<X> getComponent() { 548 return fruit::createComponent() 549 .installComponentFunctions(fruit::componentFunction(getParentComponent, 5, std::string("Hello"), 15)); 550 } 551 ''' 552 expect_generic_compile_error( 553 r'error: use of deleted function .std::hash<Arg>::hash\(\).' 554 r'|error: call to implicitly-deleted default constructor of .std::hash<Arg>.' 555 r'|error: invalid use of incomplete type .struct std::hash<Arg>.' 556 r'|error: implicit instantiation of undefined template .std::(__1::)?hash<Arg>.' 557 r'|error C2338: The C\+\+ Standard doesn.t provide a hash for this type.' 558 r'|error C2064: term does not evaluate to a function taking 1 arguments', 559 COMMON_DEFINITIONS, 560 source) 561 562if __name__ == '__main__': 563 absltest.main() 564