aboutsummaryrefslogtreecommitdiff
path: root/tests/test_install.py
diff options
context:
space:
mode:
authorMarco Poletti <poletti.marco@gmail.com>2017-06-11 11:48:37 +0100
committerMarco Poletti <poletti.marco@gmail.com>2017-06-11 11:48:58 +0100
commit09843e08146cbcde5eae14bcae3a40c1e92d14cb (patch)
tree0693bef04f64e455415770ac690d1a448f4f9802 /tests/test_install.py
parentfef4823708f167a8267ff817fb54da441a57e0c1 (diff)
downloadgoogle-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-xtests/test_install.py328
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__)