File indexing completed on 2025-01-05 05:00:01

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
0003  SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 
0007 #include <testlib/qtest_zanshin.h>
0008 
0009 #include "utils/dependencymanager.h"
0010 
0011 using namespace Utils;
0012 
0013 class Interface0
0014 {
0015 public:
0016     typedef QSharedPointer<Interface0> Ptr;
0017 
0018     Interface0() {}
0019     virtual ~Interface0() {}
0020     virtual void doSomething() = 0;
0021 };
0022 
0023 class FirstImplementation0 : public Interface0
0024 {
0025 public:
0026     void doSomething() override { qDebug() << "FirstImplementation"; }
0027 };
0028 
0029 class SecondImplementation0 : public Interface0
0030 {
0031 public:
0032     void doSomething() override { qDebug() << "SecondImplementation"; }
0033 };
0034 
0035 #define DECLARE_IMPLEMENTED_INTERFACE(N) \
0036 class Interface##N \
0037 { \
0038 public: \
0039     typedef QSharedPointer<Interface##N> Ptr; \
0040  \
0041     Interface##N() {} \
0042     virtual ~Interface##N() {} \
0043     virtual void doSomething() = 0; \
0044 }; \
0045  \
0046 class Implementation##N : public Interface##N \
0047 { \
0048 public: \
0049     void doSomething() override { qDebug() << "Implementation##N"; } \
0050 };
0051 
0052 DECLARE_IMPLEMENTED_INTERFACE(1)
0053 DECLARE_IMPLEMENTED_INTERFACE(2)
0054 DECLARE_IMPLEMENTED_INTERFACE(3)
0055 DECLARE_IMPLEMENTED_INTERFACE(4)
0056 DECLARE_IMPLEMENTED_INTERFACE(5)
0057 DECLARE_IMPLEMENTED_INTERFACE(6)
0058 DECLARE_IMPLEMENTED_INTERFACE(7)
0059 DECLARE_IMPLEMENTED_INTERFACE(8)
0060 DECLARE_IMPLEMENTED_INTERFACE(9)
0061 DECLARE_IMPLEMENTED_INTERFACE(10)
0062 DECLARE_IMPLEMENTED_INTERFACE(11)
0063 DECLARE_IMPLEMENTED_INTERFACE(12)
0064 DECLARE_IMPLEMENTED_INTERFACE(13)
0065 DECLARE_IMPLEMENTED_INTERFACE(14)
0066 
0067 class AnotherInterface
0068 {
0069 public:
0070     AnotherInterface() {}
0071     virtual ~AnotherInterface() {}
0072     virtual void doSomethingDelegated() = 0;
0073 };
0074 
0075 class AnotherFirstImplementation : public AnotherInterface
0076 {
0077 public:
0078     explicit AnotherFirstImplementation(const Interface0::Ptr &iface)
0079         : m_iface(iface) {}
0080 
0081     void doSomethingDelegated() override { m_iface->doSomething(); }
0082 
0083     Interface0::Ptr iface() const { return m_iface; }
0084 
0085 private:
0086     Interface0::Ptr m_iface;
0087 };
0088 
0089 class AnotherSecondImplementation : public AnotherInterface
0090 {
0091 public:
0092     AnotherSecondImplementation(Interface0::Ptr iface0,
0093                                 Interface1::Ptr iface1,
0094                                 Interface2::Ptr iface2,
0095                                 Interface3::Ptr iface3,
0096                                 Interface4::Ptr iface4,
0097                                 Interface5::Ptr iface5,
0098                                 Interface6::Ptr iface6,
0099                                 Interface7::Ptr iface7,
0100                                 Interface8::Ptr iface8,
0101                                 Interface9::Ptr iface9,
0102                                 Interface10::Ptr iface10,
0103                                 Interface11::Ptr iface11,
0104                                 Interface12::Ptr iface12,
0105                                 Interface13::Ptr iface13,
0106                                 Interface14::Ptr iface14)
0107         : m_iface0(iface0),
0108           m_iface1(iface1),
0109           m_iface2(iface2),
0110           m_iface3(iface3),
0111           m_iface4(iface4),
0112           m_iface5(iface5),
0113           m_iface6(iface6),
0114           m_iface7(iface7),
0115           m_iface8(iface8),
0116           m_iface9(iface9),
0117           m_iface10(iface10),
0118           m_iface11(iface11),
0119           m_iface12(iface12),
0120           m_iface13(iface13),
0121           m_iface14(iface14)
0122     {
0123     }
0124 
0125     void doSomethingDelegated() override { m_iface1->doSomething(); }
0126 
0127     Interface0::Ptr iface0() const { return m_iface0; }
0128     Interface1::Ptr iface1() const { return m_iface1; }
0129     Interface2::Ptr iface2() const { return m_iface2; }
0130     Interface3::Ptr iface3() const { return m_iface3; }
0131     Interface4::Ptr iface4() const { return m_iface4; }
0132     Interface5::Ptr iface5() const { return m_iface5; }
0133     Interface6::Ptr iface6() const { return m_iface6; }
0134     Interface7::Ptr iface7() const { return m_iface7; }
0135     Interface8::Ptr iface8() const { return m_iface8; }
0136     Interface9::Ptr iface9() const { return m_iface9; }
0137     Interface10::Ptr iface10() const { return m_iface10; }
0138     Interface11::Ptr iface11() const { return m_iface11; }
0139     Interface12::Ptr iface12() const { return m_iface12; }
0140     Interface13::Ptr iface13() const { return m_iface13; }
0141     Interface14::Ptr iface14() const { return m_iface14; }
0142 
0143 private:
0144     Interface0::Ptr m_iface0;
0145     Interface1::Ptr m_iface1;
0146     Interface2::Ptr m_iface2;
0147     Interface3::Ptr m_iface3;
0148     Interface4::Ptr m_iface4;
0149     Interface5::Ptr m_iface5;
0150     Interface6::Ptr m_iface6;
0151     Interface7::Ptr m_iface7;
0152     Interface8::Ptr m_iface8;
0153     Interface9::Ptr m_iface9;
0154     Interface10::Ptr m_iface10;
0155     Interface11::Ptr m_iface11;
0156     Interface12::Ptr m_iface12;
0157     Interface13::Ptr m_iface13;
0158     Interface14::Ptr m_iface14;
0159 };
0160 
0161 class DependencyManagerTest : public QObject
0162 {
0163     Q_OBJECT
0164 private:
0165     static bool s_firstImplFactoryCalled;
0166     static DependencyManager *s_manager;
0167 
0168     static Interface0 *firstImplFactory(DependencyManager *manager)
0169     {
0170         s_firstImplFactoryCalled = true;
0171         s_manager = manager;
0172         return new FirstImplementation0;
0173     }
0174 
0175 private slots:
0176     void shouldMemorizeDependency()
0177     {
0178         DependencyManager deps;
0179         deps.add<Interface0, FirstImplementation0>();
0180         auto object1 = deps.create<Interface0>();
0181         QVERIFY(object1.dynamicCast<FirstImplementation0>());
0182         auto object2 = deps.create<Interface0>();
0183         QVERIFY(object2.dynamicCast<FirstImplementation0>());
0184         QVERIFY(object1 != object2);
0185     }
0186 
0187     void shouldAllowOurOwnFactory()
0188     {
0189         s_firstImplFactoryCalled = false;
0190         s_manager = nullptr;
0191         DependencyManager deps;
0192         deps.add<Interface0>(&DependencyManagerTest::firstImplFactory);
0193         auto object = deps.create<Interface0>();
0194         QVERIFY(object.dynamicCast<FirstImplementation0>());
0195         QVERIFY(s_firstImplFactoryCalled);
0196         QVERIFY(s_manager == &deps);
0197     }
0198 
0199     void shouldAllowUniqueInstances()
0200     {
0201         DependencyManager deps;
0202         deps.add<Interface0, FirstImplementation0, DependencyManager::UniqueInstance>();
0203         auto object1 = deps.create<Interface0>();
0204         QVERIFY(object1.dynamicCast<FirstImplementation0>());
0205         auto object2 = deps.create<Interface0>();
0206         QVERIFY(object2.dynamicCast<FirstImplementation0>());
0207         QVERIFY(object1 == object2);
0208     }
0209 
0210     void shouldAllowUniqueInstancesWithOurOwnFactory()
0211     {
0212         s_firstImplFactoryCalled = false;
0213         s_manager = nullptr;
0214         DependencyManager deps;
0215         deps.add<Interface0, DependencyManager::UniqueInstance>(&DependencyManagerTest::firstImplFactory);
0216         auto object1 = deps.create<Interface0>();
0217         QVERIFY(object1.dynamicCast<FirstImplementation0>());
0218         auto object2 = deps.create<Interface0>();
0219         QVERIFY(object2.dynamicCast<FirstImplementation0>());
0220         QVERIFY(s_firstImplFactoryCalled);
0221         QVERIFY(s_manager == &deps);
0222         QVERIFY(object1 == object2);
0223     }
0224 
0225     void shouldAllowOurOwnFactoryAsLambda()
0226     {
0227 #ifdef Q_COMPILER_LAMBDA
0228         bool ownFactoryCalled = false;
0229         DependencyManager *managerCalled = nullptr;
0230 
0231         DependencyManager deps;
0232         deps.add<Interface0>([&](DependencyManager *manager) -> Interface0* {
0233             ownFactoryCalled = true;
0234             managerCalled = manager;
0235             return new FirstImplementation0;
0236         });
0237         auto object = deps.create<Interface0>();
0238         QVERIFY(object.dynamicCast<FirstImplementation0>());
0239         QVERIFY(ownFactoryCalled);
0240         QVERIFY(managerCalled == &deps);
0241 #endif
0242     }
0243 
0244     void shouldMakeManagerSpecificDependencies()
0245     {
0246         DependencyManager deps1;
0247         deps1.add<Interface0, FirstImplementation0>();
0248         DependencyManager deps2;
0249         deps2.add<Interface0, SecondImplementation0>();
0250 
0251         auto object1 = deps1.create<Interface0>();
0252         auto object2 = deps2.create<Interface0>();
0253 
0254         QVERIFY(object1.dynamicCast<FirstImplementation0>());
0255         QVERIFY(object2.dynamicCast<SecondImplementation0>());
0256     }
0257 
0258     void shouldCleanupProviders()
0259     {
0260         QCOMPARE(Internal::Supplier<Interface0>::providersCount(), 0);
0261 
0262         {
0263             DependencyManager deps1;
0264             deps1.add<Interface0, FirstImplementation0>();
0265             QCOMPARE(Internal::Supplier<Interface0>::providersCount(), 1);
0266 
0267             {
0268                 DependencyManager deps2;
0269                 deps2.add<Interface0, SecondImplementation0>();
0270                 QCOMPARE(Internal::Supplier<Interface0>::providersCount(), 2);
0271             }
0272 
0273             QCOMPARE(Internal::Supplier<Interface0>::providersCount(), 1);
0274         }
0275 
0276         QCOMPARE(Internal::Supplier<Interface0>::providersCount(), 0);
0277     }
0278 
0279     void shouldInjectDependencyInConstructor()
0280     {
0281         DependencyManager deps;
0282         deps.add<Interface0, FirstImplementation0>();
0283         deps.add<AnotherInterface, AnotherFirstImplementation(Interface0*)>();
0284 
0285         auto object = deps.create<AnotherInterface>();
0286         auto impl = object.dynamicCast<AnotherFirstImplementation>();
0287         QVERIFY(impl != nullptr);
0288         QVERIFY(impl->iface().dynamicCast<FirstImplementation0>());
0289     }
0290 
0291     void shouldInjectDependenciesInConstructor()
0292     {
0293         DependencyManager deps;
0294         deps.add<Interface0, FirstImplementation0>();
0295         deps.add<Interface1, Implementation1>();
0296         deps.add<Interface2, Implementation2>();
0297         deps.add<Interface3, Implementation3>();
0298         deps.add<Interface4, Implementation4>();
0299         deps.add<Interface5, Implementation5>();
0300         deps.add<Interface6, Implementation6>();
0301         deps.add<Interface7, Implementation7>();
0302         deps.add<Interface8, Implementation8>();
0303         deps.add<Interface9, Implementation9>();
0304         deps.add<Interface10, Implementation10>();
0305         deps.add<Interface11, Implementation11>();
0306         deps.add<Interface12, Implementation12>();
0307         deps.add<Interface13, Implementation13>();
0308         deps.add<Interface14, Implementation14>();
0309         deps.add<AnotherInterface, AnotherSecondImplementation(Interface0*,
0310                                                                Interface1*,
0311                                                                Interface2*,
0312                                                                Interface3*,
0313                                                                Interface4*,
0314                                                                Interface5*,
0315                                                                Interface6*,
0316                                                                Interface7*,
0317                                                                Interface8*,
0318                                                                Interface9*,
0319                                                                Interface10*,
0320                                                                Interface11*,
0321                                                                Interface12*,
0322                                                                Interface13*,
0323                                                                Interface14*)>();
0324         auto object = deps.create<AnotherInterface>();
0325         auto impl = object.dynamicCast<AnotherSecondImplementation>();
0326         QVERIFY(impl != nullptr);
0327         QVERIFY(impl->iface0().dynamicCast<FirstImplementation0>());
0328         QVERIFY(impl->iface1().dynamicCast<Implementation1>());
0329         QVERIFY(impl->iface2().dynamicCast<Implementation2>());
0330         QVERIFY(impl->iface3().dynamicCast<Implementation3>());
0331         QVERIFY(impl->iface4().dynamicCast<Implementation4>());
0332         QVERIFY(impl->iface5().dynamicCast<Implementation5>());
0333         QVERIFY(impl->iface6().dynamicCast<Implementation6>());
0334         QVERIFY(impl->iface7().dynamicCast<Implementation7>());
0335         QVERIFY(impl->iface8().dynamicCast<Implementation8>());
0336         QVERIFY(impl->iface9().dynamicCast<Implementation9>());
0337         QVERIFY(impl->iface10().dynamicCast<Implementation10>());
0338         QVERIFY(impl->iface11().dynamicCast<Implementation11>());
0339         QVERIFY(impl->iface12().dynamicCast<Implementation12>());
0340         QVERIFY(impl->iface13().dynamicCast<Implementation13>());
0341         QVERIFY(impl->iface14().dynamicCast<Implementation14>());
0342     }
0343 };
0344 
0345 bool DependencyManagerTest::s_firstImplFactoryCalled = false;
0346 DependencyManager *DependencyManagerTest::s_manager = nullptr;
0347 
0348 ZANSHIN_TEST_MAIN(DependencyManagerTest)
0349 
0350 #include "dependencymanagertest.moc"