1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <testshl/simpleheader.hxx> 29 30 #include "com/sun/star/lang/XEventListener.hpp" 31 #include "cppuhelper/interfacecontainer.hxx" 32 #include "cppuhelper/queryinterface.hxx" 33 #include "cppuhelper/implbase1.hxx" 34 #include "cppuhelper/propshlp.hxx" 35 36 using namespace com::sun::star; 37 using namespace com::sun::star::uno; 38 using namespace com::sun::star::lang; 39 40 41 struct equalStr 42 { 43 bool operator()( 44 const char * const &rA, 45 const char * const &rB) const 46 { return !strcmp(rA, rB); } 47 }; 48 struct hashStr 49 { 50 size_t operator()( const char * &rName ) const 51 { 52 return rtl::OString(rName).hashCode(); 53 } 54 }; 55 56 class ContainerListener; 57 58 struct ContainerStats { 59 int m_nAlive; 60 int m_nDisposed; 61 ContainerStats() : m_nAlive(0), m_nDisposed(0) {} 62 }; 63 64 class ContainerListener : public ::cppu::WeakImplHelper1< XEventListener > 65 { 66 ContainerStats *m_pStats; 67 public: 68 ContainerListener(ContainerStats *pStats) 69 : m_pStats(pStats) { m_pStats->m_nAlive++; } 70 virtual ~ContainerListener() { m_pStats->m_nAlive--; } 71 virtual void SAL_CALL disposing( const EventObject& ) 72 throw (RuntimeException) 73 { 74 m_pStats->m_nDisposed++; 75 } 76 }; 77 78 namespace cppu_ifcontainer 79 { 80 class IfTest : public CppUnit::TestFixture 81 { 82 osl::Mutex m_aGuard; 83 static const int nTests = 10; 84 public: 85 void testCreateDispose() 86 { 87 ContainerStats aStats; 88 cppu::OInterfaceContainerHelper *pContainer; 89 90 pContainer = new cppu::OInterfaceContainerHelper(m_aGuard); 91 92 CPPUNIT_ASSERT_MESSAGE("Empty container not empty", 93 pContainer->getLength() == 0); 94 95 int i; 96 for (i = 0; i < nTests; i++) 97 { 98 Reference<XEventListener> xRef = new ContainerListener(&aStats); 99 int nNewLen = pContainer->addInterface(xRef); 100 101 CPPUNIT_ASSERT_MESSAGE("addition length mismatch", 102 nNewLen == i + 1); 103 CPPUNIT_ASSERT_MESSAGE("addition length mismatch", 104 pContainer->getLength() == i + 1); 105 } 106 CPPUNIT_ASSERT_MESSAGE("alive count mismatch", 107 aStats.m_nAlive == nTests); 108 109 EventObject aObj; 110 pContainer->disposeAndClear(aObj); 111 112 CPPUNIT_ASSERT_MESSAGE("dispose count mismatch", 113 aStats.m_nDisposed == nTests); 114 CPPUNIT_ASSERT_MESSAGE("leaked container left alive", 115 aStats.m_nAlive == 0); 116 117 delete pContainer; 118 } 119 120 void testEnumerate() 121 { 122 int i; 123 ContainerStats aStats; 124 cppu::OInterfaceContainerHelper *pContainer; 125 pContainer = new cppu::OInterfaceContainerHelper(m_aGuard); 126 127 std::vector< Reference< XEventListener > > aListeners; 128 for (i = 0; i < nTests; i++) 129 { 130 Reference<XEventListener> xRef = new ContainerListener(&aStats); 131 int nNewLen = pContainer->addInterface(xRef); 132 aListeners.push_back(xRef); 133 } 134 Sequence< Reference< XInterface > > aElements; 135 aElements = pContainer->getElements(); 136 137 CPPUNIT_ASSERT_MESSAGE("query contents", 138 (int)aElements.getLength() == nTests); 139 if ((int)aElements.getLength() == nTests) 140 { 141 for (i = 0; i < nTests; i++) 142 { 143 CPPUNIT_ASSERT_MESSAGE("mismatching elements", 144 aElements[i] == aListeners[i]); 145 } 146 } 147 pContainer->clear(); 148 149 CPPUNIT_ASSERT_MESSAGE("non-empty container post clear", 150 pContainer->getLength() == 0); 151 delete pContainer; 152 } 153 154 template < typename ContainerType, typename ContainedType > 155 void doContainerTest(const ContainedType *pTypes) 156 { 157 ContainerStats aStats; 158 ContainerType *pContainer; 159 pContainer = new ContainerType(m_aGuard); 160 161 int i; 162 Reference<XEventListener> xRefs[nTests * 2]; 163 164 // add these interfaces 165 for (i = 0; i < nTests * 2; i++) 166 { 167 xRefs[i] = new ContainerListener(&aStats); 168 pContainer->addInterface(pTypes[i / 2], xRefs[i]); 169 } 170 171 // check it is all there 172 for (i = 0; i < nTests; i++) 173 { 174 cppu::OInterfaceContainerHelper *pHelper; 175 176 pHelper = pContainer->getContainer(pTypes[i]); 177 178 CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != NULL); 179 Sequence<Reference< XInterface > > aSeq = pHelper->getElements(); 180 CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 2); 181 CPPUNIT_ASSERT_MESSAGE("match", aSeq[0] == xRefs[i*2]); 182 CPPUNIT_ASSERT_MESSAGE("match", aSeq[1] == xRefs[i*2+1]); 183 } 184 185 // remove every other interface 186 for (i = 0; i < nTests; i++) 187 pContainer->removeInterface(pTypes[i], xRefs[i*2+1]); 188 189 // check it is half there 190 for (i = 0; i < nTests; i++) 191 { 192 cppu::OInterfaceContainerHelper *pHelper; 193 194 pHelper = pContainer->getContainer(pTypes[i]); 195 196 CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != NULL); 197 Sequence<Reference< XInterface > > aSeq = pHelper->getElements(); 198 CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 1); 199 CPPUNIT_ASSERT_MESSAGE("match", aSeq[0] == xRefs[i*2]); 200 } 201 202 // remove the 1st half of the rest 203 for (i = 0; i < nTests / 2; i++) 204 pContainer->removeInterface(pTypes[i], xRefs[i*2]); 205 206 // check it is half there 207 for (i = 0; i < nTests / 2; i++) 208 { 209 cppu::OInterfaceContainerHelper *pHelper; 210 211 pHelper = pContainer->getContainer(pTypes[i]); 212 CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != NULL); 213 Sequence<Reference< XInterface > > aSeq = pHelper->getElements(); 214 CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 0); 215 } 216 217 delete pContainer; 218 } 219 220 void testOMultiTypeInterfaceContainerHelper() 221 { 222 uno::Type pTypes[nTests] = 223 { 224 ::cppu::UnoType< bool >::get(), 225 ::cppu::UnoType< float >::get(), 226 ::cppu::UnoType< double >::get(), 227 ::cppu::UnoType< ::sal_uInt64 >::get(), 228 ::cppu::UnoType< ::sal_Int64 >::get(), 229 ::cppu::UnoType< ::sal_uInt32 >::get(), 230 ::cppu::UnoType< ::sal_Int32 >::get(), 231 ::cppu::UnoType< ::sal_Int16 >::get(), 232 ::cppu::UnoType< ::rtl::OUString >::get(), 233 ::cppu::UnoType< ::sal_Int8 >::get() 234 }; 235 doContainerTest< cppu::OMultiTypeInterfaceContainerHelper, 236 uno::Type> (pTypes); 237 } 238 239 void testOMultiTypeInterfaceContainerHelperInt32() 240 { 241 sal_Int32 pTypes[nTests] = 242 { 243 0, 244 -1, 245 1, 246 256, 247 1024, 248 3, 249 7, 250 8, 251 9, 252 10 253 }; 254 doContainerTest< cppu::OMultiTypeInterfaceContainerHelperInt32, sal_Int32> (pTypes); 255 } 256 257 void testOMultiTypeInterfaceContainerHelperVar() 258 { 259 typedef ::cppu::OMultiTypeInterfaceContainerHelperVar< 260 const char *,hashStr,equalStr> StrContainer; 261 262 const char *pTypes[nTests] = 263 { 264 "this_is", "such", "fun", "writing", "unit", "tests", "when", "it", "works", "anyway" 265 }; 266 doContainerTest< StrContainer, const char *> (pTypes); 267 } 268 269 // Automatic registration code 270 CPPUNIT_TEST_SUITE(IfTest); 271 CPPUNIT_TEST(testCreateDispose); 272 CPPUNIT_TEST(testEnumerate); 273 CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelper); 274 CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelperVar); 275 CPPUNIT_TEST(testOMultiTypeInterfaceContainerHelperInt32); 276 CPPUNIT_TEST_SUITE_END(); 277 }; 278 } // namespace cppu_ifcontainer 279 280 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(cppu_ifcontainer::IfTest, 281 "cppu_ifcontainer"); 282 283 NOADDITIONAL; 284