1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/tests/TestCOMArray.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,361 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// vim:cindent:ts=4:et:sw=4: 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "TestHarness.h" 1.11 +#include "nsCOMArray.h" 1.12 +#include "mozilla/Attributes.h" 1.13 + 1.14 +// {9e70a320-be02-11d1-8031-006008159b5a} 1.15 +#define NS_IFOO_IID \ 1.16 + {0x9e70a320, 0xbe02, 0x11d1, \ 1.17 + {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}} 1.18 + 1.19 +class IFoo : public nsISupports { 1.20 +public: 1.21 + 1.22 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOO_IID) 1.23 + 1.24 + NS_IMETHOD_(MozExternalRefCountType) RefCnt() = 0; 1.25 + NS_IMETHOD_(int32_t) ID() = 0; 1.26 +}; 1.27 + 1.28 +NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID) 1.29 + 1.30 +class Foo MOZ_FINAL : public IFoo { 1.31 +public: 1.32 + 1.33 + Foo(int32_t aID); 1.34 + ~Foo(); 1.35 + 1.36 + // nsISupports implementation 1.37 + NS_DECL_ISUPPORTS 1.38 + 1.39 + // IFoo implementation 1.40 + NS_IMETHOD_(MozExternalRefCountType) RefCnt() { return mRefCnt; } 1.41 + NS_IMETHOD_(int32_t) ID() { return mID; } 1.42 + 1.43 + static int32_t gCount; 1.44 + 1.45 + int32_t mID; 1.46 +}; 1.47 + 1.48 +int32_t Foo::gCount = 0; 1.49 + 1.50 +Foo::Foo(int32_t aID) 1.51 +{ 1.52 + mID = aID; 1.53 + ++gCount; 1.54 +} 1.55 + 1.56 +Foo::~Foo() 1.57 +{ 1.58 + --gCount; 1.59 +} 1.60 + 1.61 +NS_IMPL_ISUPPORTS(Foo, IFoo) 1.62 + 1.63 + 1.64 +typedef nsCOMArray<IFoo> Array; 1.65 + 1.66 + 1.67 +// {0e70a320-be02-11d1-8031-006008159b5a} 1.68 +#define NS_IBAR_IID \ 1.69 + {0x0e70a320, 0xbe02, 0x11d1, \ 1.70 + {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}} 1.71 + 1.72 +class IBar : public nsISupports { 1.73 +public: 1.74 + 1.75 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IBAR_IID) 1.76 +}; 1.77 + 1.78 +NS_DEFINE_STATIC_IID_ACCESSOR(IBar, NS_IBAR_IID) 1.79 + 1.80 +class Bar MOZ_FINAL : public IBar { 1.81 +public: 1.82 + 1.83 + explicit Bar(nsCOMArray<IBar>& aArray); 1.84 + ~Bar(); 1.85 + 1.86 + // nsISupports implementation 1.87 + NS_DECL_ISUPPORTS 1.88 + 1.89 + static int32_t sReleaseCalled; 1.90 + 1.91 +private: 1.92 + nsCOMArray<IBar>& mArray; 1.93 +}; 1.94 + 1.95 +int32_t Bar::sReleaseCalled = 0; 1.96 + 1.97 +typedef nsCOMArray<IBar> Array2; 1.98 + 1.99 +Bar::Bar(Array2& aArray) 1.100 + : mArray(aArray) 1.101 +{ 1.102 +} 1.103 + 1.104 +Bar::~Bar() 1.105 +{ 1.106 + if (mArray.RemoveObject(this)) { 1.107 + fail("We should never manage to remove the object here"); 1.108 + } 1.109 +} 1.110 + 1.111 +NS_IMPL_ADDREF(Bar) 1.112 +NS_IMPL_QUERY_INTERFACE(Bar, IBar) 1.113 + 1.114 +NS_IMETHODIMP_(MozExternalRefCountType) 1.115 +Bar::Release(void) 1.116 +{ 1.117 + ++Bar::sReleaseCalled; 1.118 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); 1.119 + NS_ASSERT_OWNINGTHREAD(_class); 1.120 + --mRefCnt; 1.121 + NS_LOG_RELEASE(this, mRefCnt, "Bar"); 1.122 + if (mRefCnt == 0) { 1.123 + mRefCnt = 1; /* stabilize */ 1.124 + delete this; 1.125 + return 0; 1.126 + } 1.127 + return mRefCnt; 1.128 +} 1.129 + 1.130 + 1.131 +int main(int argc, char **argv) 1.132 +{ 1.133 + ScopedXPCOM xpcom("nsCOMArrayTests"); 1.134 + if (xpcom.failed()) { 1.135 + return 1; 1.136 + } 1.137 + 1.138 + int rv = 0; 1.139 + 1.140 + Array arr; 1.141 + 1.142 + for (int32_t i = 0; i < 20; ++i) { 1.143 + nsCOMPtr<IFoo> foo = new Foo(i); 1.144 + arr.AppendObject(foo); 1.145 + } 1.146 + 1.147 + if (arr.Count() != 20 || Foo::gCount != 20) { 1.148 + fail("nsCOMArray::AppendObject failed"); 1.149 + rv = 1; 1.150 + } 1.151 + 1.152 + arr.TruncateLength(10); 1.153 + 1.154 + if (arr.Count() != 10 || Foo::gCount != 10) { 1.155 + fail("nsCOMArray::TruncateLength shortening of array failed"); 1.156 + rv = 1; 1.157 + } 1.158 + 1.159 + arr.SetCount(30); 1.160 + 1.161 + if (arr.Count() != 30 || Foo::gCount != 10) { 1.162 + fail("nsCOMArray::SetCount lengthening of array failed"); 1.163 + rv = 1; 1.164 + } 1.165 + 1.166 + for (int32_t i = 0; i < 10; ++i) { 1.167 + if (arr[i] == nullptr) { 1.168 + fail("nsCOMArray elements should be non-null"); 1.169 + rv = 1; 1.170 + break; 1.171 + } 1.172 + } 1.173 + 1.174 + for (int32_t i = 10; i < 30; ++i) { 1.175 + if (arr[i] != nullptr) { 1.176 + fail("nsCOMArray elements should be null"); 1.177 + rv = 1; 1.178 + break; 1.179 + } 1.180 + } 1.181 + 1.182 + int32_t base; 1.183 + { 1.184 + Array2 arr2; 1.185 + 1.186 + IBar *thirdObject = nullptr, 1.187 + *fourthObject = nullptr, 1.188 + *fifthObject = nullptr, 1.189 + *ninthObject = nullptr; 1.190 + for (int32_t i = 0; i < 20; ++i) { 1.191 + nsCOMPtr<IBar> bar = new Bar(arr2); 1.192 + switch (i) { 1.193 + case 2: 1.194 + thirdObject = bar; break; 1.195 + case 3: 1.196 + fourthObject = bar; break; 1.197 + case 4: 1.198 + fifthObject = bar; break; 1.199 + case 8: 1.200 + ninthObject = bar; break; 1.201 + } 1.202 + arr2.AppendObject(bar); 1.203 + } 1.204 + 1.205 + base = Bar::sReleaseCalled; 1.206 + 1.207 + arr2.SetCount(10); 1.208 + if (Bar::sReleaseCalled != base + 10) { 1.209 + fail("Release called multiple times for SetCount"); 1.210 + } 1.211 + if (arr2.Count() != 10) { 1.212 + fail("SetCount(10) should remove exactly ten objects"); 1.213 + } 1.214 + 1.215 + arr2.RemoveObjectAt(9); 1.216 + if (Bar::sReleaseCalled != base + 11) { 1.217 + fail("Release called multiple times for RemoveObjectAt"); 1.218 + } 1.219 + if (arr2.Count() != 9) { 1.220 + fail("RemoveObjectAt should remove exactly one object"); 1.221 + } 1.222 + 1.223 + arr2.RemoveObject(ninthObject); 1.224 + if (Bar::sReleaseCalled != base + 12) { 1.225 + fail("Release called multiple times for RemoveObject"); 1.226 + } 1.227 + if (arr2.Count() != 8) { 1.228 + fail("RemoveObject should remove exactly one object"); 1.229 + } 1.230 + 1.231 + arr2.RemoveObjectsAt(2, 3); 1.232 + if (Bar::sReleaseCalled != base + 15) { 1.233 + fail("Release called more or less than three times for RemoveObjectsAt"); 1.234 + } 1.235 + if (arr2.Count() != 5) { 1.236 + fail("RemoveObjectsAt should remove exactly three objects"); 1.237 + } 1.238 + for (int32_t j = 0; j < arr2.Count(); ++j) { 1.239 + if (arr2.ObjectAt(j) == thirdObject) { 1.240 + fail("RemoveObjectsAt should have removed thirdObject"); 1.241 + } 1.242 + if (arr2.ObjectAt(j) == fourthObject) { 1.243 + fail("RemoveObjectsAt should have removed fourthObject"); 1.244 + } 1.245 + if (arr2.ObjectAt(j) == fifthObject) { 1.246 + fail("RemoveObjectsAt should have removed fifthObject"); 1.247 + } 1.248 + } 1.249 + 1.250 + arr2.RemoveObjectsAt(4, 1); 1.251 + if (Bar::sReleaseCalled != base + 16) { 1.252 + fail("Release called more or less than one time for RemoveObjectsAt"); 1.253 + } 1.254 + if (arr2.Count() != 4) { 1.255 + fail("RemoveObjectsAt should work for removing the last element"); 1.256 + } 1.257 + 1.258 + arr2.Clear(); 1.259 + if (Bar::sReleaseCalled != base + 20) { 1.260 + fail("Release called multiple times for Clear"); 1.261 + } 1.262 + } 1.263 + 1.264 + { 1.265 + Array2 arr2; 1.266 + 1.267 + IBar *thirdElement = nullptr, 1.268 + *fourthElement = nullptr, 1.269 + *fifthElement = nullptr, 1.270 + *ninthElement = nullptr; 1.271 + for (int32_t i = 0; i < 20; ++i) { 1.272 + nsCOMPtr<IBar> bar = new Bar(arr2); 1.273 + switch (i) { 1.274 + case 2: 1.275 + thirdElement = bar; break; 1.276 + case 3: 1.277 + fourthElement = bar; break; 1.278 + case 4: 1.279 + fifthElement = bar; break; 1.280 + case 8: 1.281 + ninthElement = bar; break; 1.282 + } 1.283 + arr2.AppendElement(bar); 1.284 + } 1.285 + 1.286 + base = Bar::sReleaseCalled; 1.287 + 1.288 + arr2.TruncateLength(10); 1.289 + if (Bar::sReleaseCalled != base + 10) { 1.290 + fail("Release called multiple times for TruncateLength"); 1.291 + } 1.292 + if (arr2.Length() != 10) { 1.293 + fail("TruncateLength(10) should remove exactly ten objects"); 1.294 + } 1.295 + 1.296 + arr2.RemoveElementAt(9); 1.297 + if (Bar::sReleaseCalled != base + 11) { 1.298 + fail("Release called multiple times for RemoveElementAt"); 1.299 + } 1.300 + if (arr2.Length() != 9) { 1.301 + fail("RemoveElementAt should remove exactly one object"); 1.302 + } 1.303 + 1.304 + arr2.RemoveElement(ninthElement); 1.305 + if (Bar::sReleaseCalled != base + 12) { 1.306 + fail("Release called multiple times for RemoveElement"); 1.307 + } 1.308 + if (arr2.Length() != 8) { 1.309 + fail("RemoveElement should remove exactly one object"); 1.310 + } 1.311 + 1.312 + arr2.RemoveElementsAt(2, 3); 1.313 + if (Bar::sReleaseCalled != base + 15) { 1.314 + fail("Release called more or less than three times for RemoveElementsAt"); 1.315 + } 1.316 + if (arr2.Length() != 5) { 1.317 + fail("RemoveElementsAt should remove exactly three objects"); 1.318 + } 1.319 + for (uint32_t j = 0; j < arr2.Length(); ++j) { 1.320 + if (arr2.ElementAt(j) == thirdElement) { 1.321 + fail("RemoveElementsAt should have removed thirdElement"); 1.322 + } 1.323 + if (arr2.ElementAt(j) == fourthElement) { 1.324 + fail("RemoveElementsAt should have removed fourthElement"); 1.325 + } 1.326 + if (arr2.ElementAt(j) == fifthElement) { 1.327 + fail("RemoveElementsAt should have removed fifthElement"); 1.328 + } 1.329 + } 1.330 + 1.331 + arr2.RemoveElementsAt(4, 1); 1.332 + if (Bar::sReleaseCalled != base + 16) { 1.333 + fail("Release called more or less than one time for RemoveElementsAt"); 1.334 + } 1.335 + if (arr2.Length() != 4) { 1.336 + fail("RemoveElementsAt should work for removing the last element"); 1.337 + } 1.338 + 1.339 + arr2.Clear(); 1.340 + if (Bar::sReleaseCalled != base + 20) { 1.341 + fail("Release called multiple times for Clear"); 1.342 + } 1.343 + } 1.344 + 1.345 + Bar::sReleaseCalled = 0; 1.346 + 1.347 + { 1.348 + Array2 arr2; 1.349 + 1.350 + for (int32_t i = 0; i < 20; ++i) { 1.351 + nsCOMPtr<IBar> bar = new Bar(arr2); 1.352 + arr2.AppendObject(bar); 1.353 + } 1.354 + 1.355 + base = Bar::sReleaseCalled; 1.356 + 1.357 + // Let arr2 be destroyed 1.358 + } 1.359 + if (Bar::sReleaseCalled != base + 20) { 1.360 + fail("Release called multiple times for nsCOMArray::~nsCOMArray"); 1.361 + } 1.362 + 1.363 + return rv; 1.364 +}