#!/usr/bin/env python3 # Copyright 2016 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS-IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from fruit_test_common import * COMMON_DEFINITIONS = ''' #include "test_common.h" template <typename T> class V {}; template <typename T> class X { private: X() {} public: INJECT(X(ASSISTED(int))) { } }; using XFactory = std::function<X<V<float>>(int)>; ''' def test_misc(): source = ''' fruit::Component<X<V<float>>> getXProvider2() { return fruit::createComponent() .registerProvider([](){return X<V<float>>(1);}); } struct AssistedMultiparamExample { INJECT(AssistedMultiparamExample(ASSISTED(std::map<int, float>))) {} }; struct Implementation1 { bool constructed = true; Implementation1(V<int>&&, XFactory) { std::cout << "Called Implementation1() for object " << this << std::endl; } Implementation1() = delete; Implementation1(const Implementation1&) = delete; Implementation1& operator=(const Implementation1&) = delete; Implementation1& operator=(Implementation1&&) = delete; Implementation1(Implementation1&&) { std::cout << "Moving an Implementation1 into object" << this << std::endl; } ~Implementation1() { std::cout << "Called ~Implementation1() for object " << this << std::endl; constructed = 0; } int x; }; struct Interface2 { virtual void f() = 0; }; struct Implementation2 : public Interface2 { INJECT(Implementation2(std::function<Implementation1(int)>)) { std::cout << "Called Implementation2()" << std::endl; } virtual ~Implementation2() {} virtual void f() {}; }; fruit::Component<Interface2, XFactory, std::function<Implementation1(int)>> getParentComponent() { return fruit::createComponent() .registerFactory<Implementation1(fruit::Assisted<int>, XFactory)>( [](int, XFactory xFactory) { return Implementation1(V<int>(), xFactory); }) .bind<Interface2, Implementation2>(); } //************************************* struct Interface3 { virtual void f() = 0; }; struct Implementation3 : public Interface3 { INJECT(Implementation3(Implementation2*, fruit::Provider<Implementation2> provider)) { (void) provider.get(); std::cout << "Called Implementation2()" << std::endl; } virtual ~Implementation3() {} virtual void f() {}; }; fruit::Component<Interface3, std::function<Implementation1(int)>> getMyComponent() { return fruit::createComponent() // Must fail at runtime. // .install(getXProvider2) .bind<Interface3, Implementation3>() .install(getParentComponent); } fruit::Component<std::function<AssistedMultiparamExample(std::map<int, float>)>> getAssistedMultiparamExampleComponent() { return fruit::createComponent(); } int main() { fruit::Injector< Interface3, // XFactory, std::function<Implementation1(int)> > oldInjector(getMyComponent); // The move is completely unnecessary, it's just to check that it works. fruit::Injector< Interface3, // XFactory, std::function<Implementation1(int)> > injector(std::move(oldInjector)); std::cout << "Constructing an Interface3" << std::endl; Interface3* interface3(injector); std::cout << std::endl; (void) interface3; std::cout << "Constructing another Interface3" << std::endl; Interface3* interface3_obj2 = injector.get<Interface3*>(); std::cout << std::endl; (void) interface3_obj2; std::function<Implementation1(int)> implementation1Factory(injector); { std::cout << "Constructing another Implementation1" << std::endl; Implementation1 implementation1 = implementation1Factory(12); (void) implementation1; } std::cout << "Destroying injector" << std::endl; fruit::Injector<std::function<AssistedMultiparamExample(std::map<int, float>)>> assistedMultiparamExampleInjector( getAssistedMultiparamExampleComponent); return 0; } ''' expect_success( COMMON_DEFINITIONS, source, locals()) if __name__== '__main__': main(__file__)