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 
23 
24 #include <testshl/simpleheader.hxx>
25 
26 #include "com/sun/star/lang/XEventListener.hpp"
27 #include "cppuhelper/interfacecontainer.hxx"
28 #include "cppuhelper/queryinterface.hxx"
29 #include "cppuhelper/implbase1.hxx"
30 #include "cppuhelper/propshlp.hxx"
31 
32 using namespace com::sun::star;
33 using namespace com::sun::star::uno;
34 using namespace com::sun::star::lang;
35 
36 class ContainerListener;
37 
38 struct ContainerStats {
39     int m_nAlive;
40     int m_nDisposed;
ContainerStatsContainerStats41     ContainerStats() : m_nAlive(0), m_nDisposed(0) {}
42 };
43 
44 class ContainerListener : public ::cppu::WeakImplHelper1< XEventListener >
45 {
46     ContainerStats *m_pStats;
47 public:
ContainerListener(ContainerStats * pStats)48     ContainerListener(ContainerStats *pStats)
49         : m_pStats(pStats) { m_pStats->m_nAlive++; }
~ContainerListener()50     virtual ~ContainerListener() { m_pStats->m_nAlive--; }
disposing(const EventObject &)51     virtual void SAL_CALL disposing( const EventObject& )
52         throw (RuntimeException)
53     {
54         m_pStats->m_nDisposed++;
55     }
56 };
57 
58 namespace cppu_ifcontainer
59 {
60     class IfTest : public CppUnit::TestFixture
61     {
62         osl::Mutex m_aGuard;
63         static const int nTests = 10;
64     public:
testCreateDispose()65         void testCreateDispose()
66         {
67             ContainerStats aStats;
68             cppu::OInterfaceContainerHelper *pContainer;
69 
70             pContainer = new cppu::OInterfaceContainerHelper(m_aGuard);
71 
72             CPPUNIT_ASSERT_MESSAGE("Empty container not empty",
73                                    pContainer->getLength() == 0);
74 
75             int i;
76             for (i = 0; i < nTests; i++)
77             {
78                 Reference<XEventListener> xRef = new ContainerListener(&aStats);
79                 int nNewLen = pContainer->addInterface(xRef);
80 
81                 CPPUNIT_ASSERT_MESSAGE("addition length mismatch",
82                                        nNewLen == i + 1);
83                 CPPUNIT_ASSERT_MESSAGE("addition length mismatch",
84                                        pContainer->getLength() == i + 1);
85             }
86             CPPUNIT_ASSERT_MESSAGE("alive count mismatch",
87                                    aStats.m_nAlive == nTests);
88 
89             EventObject aObj;
90             pContainer->disposeAndClear(aObj);
91 
92             CPPUNIT_ASSERT_MESSAGE("dispose count mismatch",
93                                    aStats.m_nDisposed == nTests);
94             CPPUNIT_ASSERT_MESSAGE("leaked container left alive",
95                                    aStats.m_nAlive == 0);
96 
97             delete pContainer;
98         }
99 
testEnumerate()100         void testEnumerate()
101         {
102             int i;
103             ContainerStats aStats;
104             cppu::OInterfaceContainerHelper *pContainer;
105             pContainer = new cppu::OInterfaceContainerHelper(m_aGuard);
106 
107             std::vector< Reference< XEventListener > > aListeners;
108             for (i = 0; i < nTests; i++)
109             {
110                 Reference<XEventListener> xRef = new ContainerListener(&aStats);
111                 int nNewLen = pContainer->addInterface(xRef);
112                 aListeners.push_back(xRef);
113             }
114             Sequence< Reference< XInterface > > aElements;
115             aElements = pContainer->getElements();
116 
117             CPPUNIT_ASSERT_MESSAGE("query contents",
118                                    (int)aElements.getLength() == nTests);
119             if ((int)aElements.getLength() == nTests)
120             {
121                 for (i = 0; i < nTests; i++)
122                 {
123                     CPPUNIT_ASSERT_MESSAGE("mismatching elements",
124                                            aElements[i] == aListeners[i]);
125                 }
126             }
127             pContainer->clear();
128 
129             CPPUNIT_ASSERT_MESSAGE("non-empty container post clear",
130                                    pContainer->getLength() == 0);
131             delete pContainer;
132         }
133 
134         template < typename ContainerType, typename ContainedType >
doContainerTest(const ContainedType * pTypes)135         void doContainerTest(const ContainedType *pTypes)
136         {
137             ContainerStats aStats;
138             ContainerType *pContainer;
139             pContainer = new ContainerType(m_aGuard);
140 
141             int i;
142             Reference<XEventListener> xRefs[nTests * 2];
143 
144             // add these interfaces
145             for (i = 0; i < nTests * 2; i++)
146             {
147                 xRefs[i] = new ContainerListener(&aStats);
148                 pContainer->addInterface(pTypes[i / 2], xRefs[i]);
149             }
150 
151             // check it is all there
152             for (i = 0; i < nTests; i++)
153             {
154                 cppu::OInterfaceContainerHelper *pHelper;
155 
156                 pHelper = pContainer->getContainer(pTypes[i]);
157 
158                 CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != NULL);
159                 Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
160                 CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 2);
161                 CPPUNIT_ASSERT_MESSAGE("match", aSeq[0] == xRefs[i*2]);
162                 CPPUNIT_ASSERT_MESSAGE("match", aSeq[1] == xRefs[i*2+1]);
163             }
164 
165             // remove every other interface
166             for (i = 0; i < nTests; i++)
167                 pContainer->removeInterface(pTypes[i], xRefs[i*2+1]);
168 
169             // check it is half there
170             for (i = 0; i < nTests; i++)
171             {
172                 cppu::OInterfaceContainerHelper *pHelper;
173 
174                 pHelper = pContainer->getContainer(pTypes[i]);
175 
176                 CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != NULL);
177                 Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
178                 CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 1);
179                 CPPUNIT_ASSERT_MESSAGE("match", aSeq[0] == xRefs[i*2]);
180             }
181 
182             // remove the 1st half of the rest
183             for (i = 0; i < nTests / 2; i++)
184                 pContainer->removeInterface(pTypes[i], xRefs[i*2]);
185 
186             // check it is half there
187             for (i = 0; i < nTests / 2; i++)
188             {
189                 cppu::OInterfaceContainerHelper *pHelper;
190 
191                 pHelper = pContainer->getContainer(pTypes[i]);
192                 CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != NULL);
193                 Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
194                 CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 0);
195             }
196 
197             delete pContainer;
198         }
199 
testOMultiTypeInterfaceContainerHelper()200         void testOMultiTypeInterfaceContainerHelper()
201         {
202             uno::Type pTypes[nTests] =
203             {
204                 ::cppu::UnoType< bool >::get(),
205                 ::cppu::UnoType< float >::get(),
206                 ::cppu::UnoType< double >::get(),
207                 ::cppu::UnoType< ::sal_uInt64 >::get(),
208                 ::cppu::UnoType< ::sal_Int64 >::get(),
209                 ::cppu::UnoType< ::sal_uInt32 >::get(),
210                 ::cppu::UnoType< ::sal_Int32 >::get(),
211                 ::cppu::UnoType< ::sal_Int16 >::get(),
212                 ::cppu::UnoType< ::rtl::OUString >::get(),
213                 ::cppu::UnoType< ::sal_Int8 >::get()
214             };
215             doContainerTest< cppu::OMultiTypeInterfaceContainerHelper,
216                 uno::Type> (pTypes);
217         }
218 
testOMultiTypeInterfaceContainerHelperInt32()219         void testOMultiTypeInterfaceContainerHelperInt32()
220         {
221             sal_Int32 pTypes[nTests] =
222             {
223                 0,
224                 -1,
225                 1,
226                 256,
227                 1024,
228                 3,
229                 7,
230                 8,
231                 9,
232                 10
233             };
234             doContainerTest< cppu::OMultiTypeInterfaceContainerHelperInt32, sal_Int32> (pTypes);
235         }
236 
testOMultiTypeInterfaceContainerHelperVar()237         void testOMultiTypeInterfaceContainerHelperVar()
238         {
239             typedef ::cppu::OMultiTypeInterfaceContainerHelperVar<
240                 const char*, rtl::CStringHash, rtl::CStringEqual> StrContainer;
241 
242             const char *pTypes[nTests] =
243             {
244                 "this_is", "such", "fun", "writing", "unit", "tests", "when", "it", "works", "anyway"
245             };
246             doContainerTest< StrContainer, const char *> (pTypes);
247         }
248 
249         // Automatic registration code
250         CPPUNIT_TEST_SUITE(IfTest);
251         CPPUNIT_TEST(testCreateDispose);
252         CPPUNIT_TEST(testEnumerate);
253         CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelper);
254         CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelperVar);
255         CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelperInt32);
256         CPPUNIT_TEST_SUITE_END();
257     };
258 } // namespace cppu_ifcontainer
259 
260 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(cppu_ifcontainer::IfTest,
261                                       "cppu_ifcontainer");
262 
263 NOADDITIONAL;
264