1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include "precompiled_cppuhelper.hxx"
23 
24 #include "com/sun/star/lang/XEventListener.hpp"
25 #include "cppuhelper/interfacecontainer.hxx"
26 #include "cppuhelper/queryinterface.hxx"
27 #include "cppuhelper/implbase1.hxx"
28 #include "cppuhelper/propshlp.hxx"
29 #include "gtest/gtest.h"
30 
31 using namespace com::sun::star;
32 using namespace com::sun::star::uno;
33 using namespace com::sun::star::lang;
34 
35 class ContainerListener;
36 
37 struct ContainerStats {
38     int m_nAlive;
39     int m_nDisposed;
ContainerStatsContainerStats40     ContainerStats() : m_nAlive(0), m_nDisposed(0) {}
41 };
42 
43 class ContainerListener : public ::cppu::WeakImplHelper1< XEventListener >
44 {
45     ContainerStats *m_pStats;
46 public:
ContainerListener(ContainerStats * pStats)47     ContainerListener(ContainerStats *pStats)
48         : m_pStats(pStats) { m_pStats->m_nAlive++; }
~ContainerListener()49     virtual ~ContainerListener() { m_pStats->m_nAlive--; }
disposing(const EventObject &)50     virtual void SAL_CALL disposing( const EventObject& )
51         throw (RuntimeException)
52     {
53         m_pStats->m_nDisposed++;
54     }
55 };
56 
57 namespace cppu_ifcontainer
58 {
59     class IfTest : public ::testing::Test
60     {
61     protected:
62         osl::Mutex m_aGuard;
63         static const int nTests = 10;
64     public:
65 
66         template < typename ContainerType, typename ContainedType >
doContainerTest(const ContainedType * pTypes)67         void doContainerTest(const ContainedType *pTypes)
68         {
69             ContainerStats aStats;
70             ContainerType *pContainer;
71             pContainer = new ContainerType(m_aGuard);
72 
73             int i;
74             Reference<XEventListener> xRefs[nTests * 2];
75 
76             // add these interfaces
77             for (i = 0; i < nTests * 2; i++)
78             {
79                 xRefs[i] = new ContainerListener(&aStats);
80                 pContainer->addInterface(pTypes[i / 2], xRefs[i]);
81             }
82 
83             // check it is all there
84             for (i = 0; i < nTests; i++)
85             {
86                 cppu::OInterfaceContainerHelper *pHelper;
87 
88                 pHelper = pContainer->getContainer(pTypes[i]);
89 
90                 ASSERT_TRUE(pHelper != NULL) << "no helper";
91                 Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
92                 ASSERT_TRUE(aSeq.getLength() == 2) << "wrong num elements";
93                 ASSERT_TRUE(aSeq[0] == xRefs[i*2]) << "match";
94                 ASSERT_TRUE(aSeq[1] == xRefs[i*2+1]) << "match";
95             }
96 
97             // remove every other interface
98             for (i = 0; i < nTests; i++)
99                 pContainer->removeInterface(pTypes[i], xRefs[i*2+1]);
100 
101             // check it is half there
102             for (i = 0; i < nTests; i++)
103             {
104                 cppu::OInterfaceContainerHelper *pHelper;
105 
106                 pHelper = pContainer->getContainer(pTypes[i]);
107 
108                 ASSERT_TRUE(pHelper != NULL) << "no helper";
109                 Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
110                 ASSERT_TRUE(aSeq.getLength() == 1) << "wrong num elements";
111                 ASSERT_TRUE(aSeq[0] == xRefs[i*2]) << "match";
112             }
113 
114             // remove the 1st half of the rest
115             for (i = 0; i < nTests / 2; i++)
116                 pContainer->removeInterface(pTypes[i], xRefs[i*2]);
117 
118             // check it is half there
119             for (i = 0; i < nTests / 2; i++)
120             {
121                 cppu::OInterfaceContainerHelper *pHelper;
122 
123                 pHelper = pContainer->getContainer(pTypes[i]);
124                 ASSERT_TRUE(pHelper != NULL) << "no helper";
125                 Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
126                 ASSERT_TRUE(aSeq.getLength() == 0) << "wrong num elements";
127             }
128 
129             delete pContainer;
130         }
131     };
132 
TEST_F(IfTest,testCreateDispose)133     TEST_F(IfTest, testCreateDispose)
134     {
135         ContainerStats aStats;
136         cppu::OInterfaceContainerHelper *pContainer;
137 
138         pContainer = new cppu::OInterfaceContainerHelper(m_aGuard);
139 
140         ASSERT_TRUE(pContainer->getLength() == 0) << "Empty container not empty";
141 
142         int i;
143         for (i = 0; i < nTests; i++)
144         {
145             Reference<XEventListener> xRef = new ContainerListener(&aStats);
146             int nNewLen = pContainer->addInterface(xRef);
147 
148             ASSERT_TRUE(nNewLen == i + 1) << "addition length mismatch";
149             ASSERT_TRUE(pContainer->getLength() == i + 1) << "addition length mismatch";
150         }
151         ASSERT_TRUE(aStats.m_nAlive == nTests) << "alive count mismatch";
152 
153         EventObject aObj;
154         pContainer->disposeAndClear(aObj);
155 
156         ASSERT_TRUE(aStats.m_nDisposed == nTests) << "dispose count mismatch";
157         ASSERT_TRUE(aStats.m_nAlive == 0) << "leaked container left alive";
158 
159         delete pContainer;
160     }
161 
TEST_F(IfTest,testEnumerate)162     TEST_F(IfTest, testEnumerate)
163     {
164         int i;
165         ContainerStats aStats;
166         cppu::OInterfaceContainerHelper *pContainer;
167         pContainer = new cppu::OInterfaceContainerHelper(m_aGuard);
168 
169         std::vector< Reference< XEventListener > > aListeners;
170         for (i = 0; i < nTests; i++)
171         {
172             Reference<XEventListener> xRef = new ContainerListener(&aStats);
173             pContainer->addInterface(xRef);
174             aListeners.push_back(xRef);
175         }
176         Sequence< Reference< XInterface > > aElements;
177         aElements = pContainer->getElements();
178 
179         ASSERT_TRUE((int)aElements.getLength() == nTests) << "query contents";
180         if ((int)aElements.getLength() == nTests)
181         {
182             for (i = 0; i < nTests; i++)
183             {
184                 ASSERT_TRUE(aElements[i] == aListeners[i]) << "mismatching elements";
185             }
186         }
187         pContainer->clear();
188 
189         ASSERT_TRUE(pContainer->getLength() == 0) << "non-empty container post clear";
190         delete pContainer;
191     }
192 
TEST_F(IfTest,testOMultiTypeInterfaceContainerHelper)193     TEST_F(IfTest, testOMultiTypeInterfaceContainerHelper)
194     {
195         uno::Type pTypes[nTests] =
196         {
197             ::cppu::UnoType< bool >::get(),
198             ::cppu::UnoType< float >::get(),
199             ::cppu::UnoType< double >::get(),
200             ::cppu::UnoType< ::sal_uInt64 >::get(),
201             ::cppu::UnoType< ::sal_Int64 >::get(),
202             ::cppu::UnoType< ::sal_uInt32 >::get(),
203             ::cppu::UnoType< ::sal_Int32 >::get(),
204             ::cppu::UnoType< ::sal_Int16 >::get(),
205             ::cppu::UnoType< ::rtl::OUString >::get(),
206             ::cppu::UnoType< ::sal_Int8 >::get()
207         };
208         doContainerTest< cppu::OMultiTypeInterfaceContainerHelper,
209             uno::Type> (pTypes);
210     }
211 
TEST_F(IfTest,testOMultiTypeInterfaceContainerHelperInt32)212     TEST_F(IfTest, testOMultiTypeInterfaceContainerHelperInt32)
213     {
214         sal_Int32 pTypes[nTests] =
215         {
216             0,
217             -1,
218             1,
219             256,
220             1024,
221             3,
222             7,
223             8,
224             9,
225             10
226         };
227         doContainerTest< cppu::OMultiTypeInterfaceContainerHelperInt32, sal_Int32> (pTypes);
228     }
229 
TEST_F(IfTest,testOMultiTypeInterfaceContainerHelperVar)230     TEST_F(IfTest, testOMultiTypeInterfaceContainerHelperVar)
231     {
232         typedef ::cppu::OMultiTypeInterfaceContainerHelperVar<
233             const char*, rtl::CStringHash, rtl::CStringEqual> StrContainer;
234 
235         const char *pTypes[nTests] =
236         {
237             "this_is", "such", "fun", "writing", "unit", "tests", "when", "it", "works", "anyway"
238         };
239         doContainerTest< StrContainer, const char *> (pTypes);
240     }
241 
242 
243 } // namespace cppu_ifcontainer
244 
245