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