diff options
author | Marco Poletti <poletti.marco@gmail.com> | 2017-06-11 11:48:37 +0100 |
---|---|---|
committer | Marco Poletti <poletti.marco@gmail.com> | 2017-06-11 11:48:58 +0100 |
commit | 09843e08146cbcde5eae14bcae3a40c1e92d14cb (patch) | |
tree | 0693bef04f64e455415770ac690d1a448f4f9802 /tests/test_install.py | |
parent | fef4823708f167a8267ff817fb54da441a57e0c1 (diff) | |
download | google-fruit-09843e08146cbcde5eae14bcae3a40c1e92d14cb.tar.gz |
Add a new PartialComponent#install() method that takes a function + args. This has the potential of being much more efficient than the one that takes a Component; however for now it's just implemented as a wrapper around the old install() method.
Diffstat (limited to 'tests/test_install.py')
-rwxr-xr-x | tests/test_install.py | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/tests/test_install.py b/tests/test_install.py index bfb377f..075cba2 100755 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -38,6 +38,31 @@ def test_success(): fruit::Component<X> getComponent() { return fruit::createComponent() + .install(getParentComponent); + } + + int main() { + fruit::Injector<X> injector(getComponent()); + X x = injector.get<X>(); + Assert(x.n == 5); + } + ''' + expect_success(COMMON_DEFINITIONS, source) + +def test_success_old_style(): + source = ''' + struct X { + int n; + X(int n) : n(n) {} + }; + + fruit::Component<X> getParentComponent() { + return fruit::createComponent() + .registerProvider([]() { return X(5); }); + } + + fruit::Component<X> getComponent() { + return fruit::createComponent() .install(getParentComponent()); } @@ -68,6 +93,42 @@ def test_with_requirements_success(): fruit::Component<fruit::Required<X>, Y> getYComponent() { return fruit::createComponent() + .install(getParentYComponent); + } + + fruit::Component<Y> getComponent() { + return fruit::createComponent() + .registerProvider([]() { return X(5); }) + .install(getYComponent); + } + + int main() { + fruit::Injector<Y> injector(getComponent()); + Y y = injector.get<Y>(); + Assert(y.x.n == 5); + } + ''' + expect_success(COMMON_DEFINITIONS, source) + +def test_with_requirements_success_old_style(): + source = ''' + struct X { + int n; + X(int n) : n(n) {} + }; + + struct Y { + X x; + Y(X x): x(x) {} + }; + + fruit::Component<fruit::Required<X>, Y> getParentYComponent() { + return fruit::createComponent() + .registerProvider([](X x) { return Y(x); }); + } + + fruit::Component<fruit::Required<X>, Y> getYComponent() { + return fruit::createComponent() .install(getParentYComponent()); } @@ -105,6 +166,35 @@ def test_with_requirements_not_specified_in_child_component_error(): // We intentionally don't have fruit::Required<X> here, we want to test that this results in an error. fruit::Component<Y> getYComponent() { return fruit::createComponent() + .install(getParentYComponent); + } + ''' + expect_compile_error( + 'NoBindingFoundError<X>', + 'No explicit binding nor C::Inject definition was found for T', + COMMON_DEFINITIONS, + source) + +def test_with_requirements_not_specified_in_child_component_error_old_style(): + source = ''' + struct X { + int n; + X(int n) : n(n) {} + }; + + struct Y { + X x; + Y(X x): x(x) {} + }; + + fruit::Component<fruit::Required<X>, Y> getParentYComponent() { + return fruit::createComponent() + .registerProvider([](X x) { return Y(x); }); + } + + // We intentionally don't have fruit::Required<X> here, we want to test that this results in an error. + fruit::Component<Y> getYComponent() { + return fruit::createComponent() .install(getParentYComponent()); } ''' @@ -114,5 +204,243 @@ def test_with_requirements_not_specified_in_child_component_error(): COMMON_DEFINITIONS, source) +def test_install_with_args_success(): + source = ''' + struct X { + int n; + X(int n) : n(n) {} + }; + + struct Arg { + Arg(const Arg&) = default; + Arg(Arg&&) = default; + Arg& operator=(const Arg&) = default; + Arg& operator=(Arg&&) = default; + }; + + bool operator==(const Arg&, const Arg&) { + return true; + } + + namespace std { + template <> + struct hash<Arg> { + size_t operator()(const Arg&) { + return 0; + } + }; + } + + fruit::Component<X> getParentComponent(int, std::string, Arg) { + return fruit::createComponent() + .registerProvider([]() { return X(5); }); + } + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .install(getParentComponent, 5, std::string("Hello"), Arg{}); + } + + int main() { + fruit::Injector<X> injector(getComponent()); + X x = injector.get<X>(); + Assert(x.n == 5); + } + ''' + expect_success(COMMON_DEFINITIONS, source) + +def test_install_with_args_error_not_move_constructible(): + source = ''' + struct Arg { + Arg(const Arg&) = default; + Arg(Arg&&) = delete; + Arg& operator=(const Arg&) = default; + Arg& operator=(Arg&&) = default; + }; + + bool operator==(const Arg&, const Arg&); + + namespace std { + template <> + struct hash<Arg> { + size_t operator()(const Arg&); + }; + } + + fruit::Component<X> getParentComponent(int, std::string, Arg); + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .install(getParentComponent, 5, std::string("Hello"), Arg{}); + } + ''' + expect_generic_compile_error( + 'error: use of deleted function \'Arg::Arg\(Arg&&\)\'' + + '|error: call to deleted constructor of \'.*\' \(aka \'Arg\'\)', + COMMON_DEFINITIONS, + source) + +def test_install_with_args_error_not_copy_constructible(): + source = ''' + struct X { + int n; + X(int n) : n(n) {} + }; + + struct Arg { + Arg(const Arg&) = delete; + Arg(Arg&&) = default; + Arg& operator=(const Arg&) = default; + Arg& operator=(Arg&&) = default; + }; + + bool operator==(const Arg&, const Arg&); + + namespace std { + template <> + struct hash<Arg> { + size_t operator()(const Arg&); + }; + } + + fruit::Component<X> getParentComponent(int, std::string, Arg); + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .install(getParentComponent, 5, std::string("Hello"), Arg{}); + } + ''' + expect_generic_compile_error( + 'error: use of deleted function \'Arg::Arg\(const Arg&\)\'' + + '|error: call to deleted constructor of \'Arg\'', + COMMON_DEFINITIONS, + source) + +def test_install_with_args_error_not_move_assignable(): + source = ''' + struct Arg { + Arg(const Arg&) = default; + Arg(Arg&&) = default; + Arg& operator=(const Arg&) = default; + Arg& operator=(Arg&&) = delete; + }; + + bool operator==(const Arg&, const Arg&); + + namespace std { + template <> + struct hash<Arg> { + size_t operator()(const Arg&); + }; + } + + fruit::Component<X> getParentComponent(int, std::string, Arg); + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .install(getParentComponent, 5, std::string("Hello"), Arg{}); + } + ''' + expect_generic_compile_error( + 'error: use of deleted function \'Arg& Arg::operator=\(Arg&&\)\'' + + '|error: overload resolution selected deleted operator \'=\'', + COMMON_DEFINITIONS, + source) + +def test_install_with_args_error_not_copy_assignable(): + source = ''' + struct X { + int n; + X(int n) : n(n) {} + }; + + struct Arg { + Arg(const Arg&) = default; + Arg(Arg&&) = default; + Arg& operator=(const Arg&) = delete; + Arg& operator=(Arg&&) = default; + }; + + bool operator==(const Arg&, const Arg&); + + namespace std { + template <> + struct hash<Arg> { + size_t operator()(const Arg&); + }; + } + + fruit::Component<X> getParentComponent(int, std::string, Arg); + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .install(getParentComponent, 5, std::string("Hello"), Arg{}); + } + ''' + expect_generic_compile_error( + 'error: use of deleted function \'Arg& Arg::operator=\(const Arg&\)\'' + + '|error: overload resolution selected deleted operator \'=\'', + COMMON_DEFINITIONS, + source) + +def test_install_with_args_error_not_equality_comparable(): + source = ''' + struct X { + int n; + X(int n) : n(n) {} + }; + + struct Arg { + Arg(const Arg&) = default; + Arg(Arg&&) = default; + Arg& operator=(const Arg&) = default; + Arg& operator=(Arg&&) = default; + }; + + namespace std { + template <> + struct hash<Arg> { + size_t operator()(const Arg&); + }; + } + + fruit::Component<X> getParentComponent(int, std::string, Arg); + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .install(getParentComponent, 5, std::string("Hello"), Arg{}); + } + ''' + expect_generic_compile_error( + 'error: no match for \'operator==\' \(operand types are \'const Arg\' and \'const Arg\'\)' + + '|error: invalid operands to binary expression \(\'const Arg\' and \'const Arg\'\)', + COMMON_DEFINITIONS, + source) + +def test_install_with_args_error_not_hashable(): + source = ''' + struct Arg { + Arg(const Arg&) = default; + Arg(Arg&&) = default; + Arg& operator=(const Arg&) = default; + Arg& operator=(Arg&&) = default; + }; + + bool operator==(const Arg&, const Arg&); + + fruit::Component<X> getParentComponent(int, std::string, Arg); + + fruit::Component<X> getComponent() { + return fruit::createComponent() + .install(getParentComponent, 5, std::string("Hello"), Arg{}); + } + ''' + expect_generic_compile_error( + 'error: use of deleted function \'std::hash<Arg>::hash\(\)\'' + + '|error: call to implicitly-deleted default constructor of \'std::hash<Arg>\'', + COMMON_DEFINITIONS, + source) + + if __name__== '__main__': main(__file__) |