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