1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/tests/TestCOMPtr.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,563 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <assert.h> 1.10 +#include <stdio.h> 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsISupports.h" 1.13 + 1.14 +#define NS_IFOO_IID \ 1.15 +{ 0x6f7652e0, 0xee43, 0x11d1, \ 1.16 + { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } } 1.17 + 1.18 +class IFoo : public nsISupports 1.19 + { 1.20 + public: 1.21 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOO_IID) 1.22 + 1.23 + public: 1.24 + IFoo(); 1.25 + // virtual dtor because IBar uses our Release() 1.26 + virtual ~IFoo(); 1.27 + 1.28 + NS_IMETHOD_(MozExternalRefCountType) AddRef(); 1.29 + NS_IMETHOD_(MozExternalRefCountType) Release(); 1.30 + NS_IMETHOD QueryInterface( const nsIID&, void** ); 1.31 + 1.32 + static void print_totals(); 1.33 + 1.34 + private: 1.35 + unsigned int refcount_; 1.36 + 1.37 + static unsigned int total_constructions_; 1.38 + static unsigned int total_destructions_; 1.39 + }; 1.40 + 1.41 +NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID) 1.42 + 1.43 +class IBar; 1.44 + 1.45 + // some types I'll need 1.46 +typedef unsigned long NS_RESULT; 1.47 + 1.48 + // some functions I'll need (and define below) 1.49 + nsresult CreateIFoo( void** ); 1.50 + nsresult CreateIBar( void** result ); 1.51 + void AnIFooPtrPtrContext( IFoo** ); 1.52 + void AnISupportsPtrPtrContext( nsISupports** ); 1.53 + void AVoidPtrPtrContext( void** ); 1.54 + void set_a_IFoo( nsCOMPtr<IFoo>* result ); 1.55 +nsCOMPtr<IFoo> return_a_IFoo(); 1.56 + 1.57 + 1.58 + 1.59 + 1.60 +unsigned int IFoo::total_constructions_; 1.61 +unsigned int IFoo::total_destructions_; 1.62 + 1.63 +class test_message 1.64 + { 1.65 + public: 1.66 + test_message() 1.67 + { 1.68 + printf("BEGIN unit tests for |nsCOMPtr|, compiled " __DATE__ "\n"); 1.69 + } 1.70 + 1.71 + ~test_message() 1.72 + { 1.73 + IFoo::print_totals(); 1.74 + printf("END unit tests for |nsCOMPtr|.\n"); 1.75 + } 1.76 + }; 1.77 + 1.78 +test_message gTestMessage; 1.79 + 1.80 + 1.81 + /* 1.82 + ... 1.83 + */ 1.84 + 1.85 +void 1.86 +IFoo::print_totals() 1.87 + { 1.88 + printf("total constructions/destructions --> %d/%d\n", 1.89 + total_constructions_, total_destructions_); 1.90 + } 1.91 + 1.92 +IFoo::IFoo() 1.93 + : refcount_(0) 1.94 + { 1.95 + ++total_constructions_; 1.96 + printf(" new IFoo@%p [#%d]\n", 1.97 + static_cast<void*>(this), total_constructions_); 1.98 + } 1.99 + 1.100 +IFoo::~IFoo() 1.101 + { 1.102 + ++total_destructions_; 1.103 + printf("IFoo@%p::~IFoo() [#%d]\n", 1.104 + static_cast<void*>(this), total_destructions_); 1.105 + } 1.106 + 1.107 +MozExternalRefCountType 1.108 +IFoo::AddRef() 1.109 + { 1.110 + ++refcount_; 1.111 + printf("IFoo@%p::AddRef(), refcount --> %d\n", 1.112 + static_cast<void*>(this), refcount_); 1.113 + return refcount_; 1.114 + } 1.115 + 1.116 +MozExternalRefCountType 1.117 +IFoo::Release() 1.118 + { 1.119 + int newcount = --refcount_; 1.120 + if ( newcount == 0 ) 1.121 + printf(">>"); 1.122 + 1.123 + printf("IFoo@%p::Release(), refcount --> %d\n", 1.124 + static_cast<void*>(this), refcount_); 1.125 + 1.126 + if ( newcount == 0 ) 1.127 + { 1.128 + printf(" delete IFoo@%p\n", static_cast<void*>(this)); 1.129 + printf("<<IFoo@%p::Release()\n", static_cast<void*>(this)); 1.130 + delete this; 1.131 + } 1.132 + 1.133 + return newcount; 1.134 + } 1.135 + 1.136 +nsresult 1.137 +IFoo::QueryInterface( const nsIID& aIID, void** aResult ) 1.138 + { 1.139 + printf("IFoo@%p::QueryInterface()\n", static_cast<void*>(this)); 1.140 + nsISupports* rawPtr = 0; 1.141 + nsresult status = NS_OK; 1.142 + 1.143 + if ( aIID.Equals(NS_GET_IID(IFoo)) ) 1.144 + rawPtr = this; 1.145 + else 1.146 + { 1.147 + nsID iid_of_ISupports = NS_ISUPPORTS_IID; 1.148 + if ( aIID.Equals(iid_of_ISupports) ) 1.149 + rawPtr = static_cast<nsISupports*>(this); 1.150 + else 1.151 + status = NS_ERROR_NO_INTERFACE; 1.152 + } 1.153 + 1.154 + NS_IF_ADDREF(rawPtr); 1.155 + *aResult = rawPtr; 1.156 + 1.157 + return status; 1.158 + } 1.159 + 1.160 +nsresult 1.161 +CreateIFoo( void** result ) 1.162 + // a typical factory function (that calls AddRef) 1.163 + { 1.164 + printf(">>CreateIFoo() --> "); 1.165 + IFoo* foop = new IFoo; 1.166 + printf("IFoo@%p\n", static_cast<void*>(foop)); 1.167 + 1.168 + foop->AddRef(); 1.169 + *result = foop; 1.170 + 1.171 + printf("<<CreateIFoo()\n"); 1.172 + return NS_OK; 1.173 + } 1.174 + 1.175 +void 1.176 +set_a_IFoo( nsCOMPtr<IFoo>* result ) 1.177 + { 1.178 + printf(">>set_a_IFoo()\n"); 1.179 + assert(result); 1.180 + 1.181 + nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) ); 1.182 + *result = foop; 1.183 + printf("<<set_a_IFoo()\n"); 1.184 + } 1.185 + 1.186 +nsCOMPtr<IFoo> 1.187 +return_a_IFoo() 1.188 + { 1.189 + printf(">>return_a_IFoo()\n"); 1.190 + nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) ); 1.191 + printf("<<return_a_IFoo()\n"); 1.192 + return foop; 1.193 + } 1.194 + 1.195 + 1.196 + 1.197 + 1.198 +#define NS_IBAR_IID \ 1.199 +{ 0x6f7652e1, 0xee43, 0x11d1, \ 1.200 + { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } } 1.201 + 1.202 +class IBar : public IFoo 1.203 + { 1.204 + public: 1.205 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IBAR_IID) 1.206 + 1.207 + public: 1.208 + IBar(); 1.209 + virtual ~IBar(); 1.210 + 1.211 + NS_IMETHOD QueryInterface( const nsIID&, void** ); 1.212 + }; 1.213 + 1.214 +NS_DEFINE_STATIC_IID_ACCESSOR(IBar, NS_IBAR_IID) 1.215 + 1.216 +IBar::IBar() 1.217 + { 1.218 + printf(" new IBar@%p\n", static_cast<void*>(this)); 1.219 + } 1.220 + 1.221 +IBar::~IBar() 1.222 + { 1.223 + printf("IBar@%p::~IBar()\n", static_cast<void*>(this)); 1.224 + } 1.225 + 1.226 +nsresult 1.227 +IBar::QueryInterface( const nsID& aIID, void** aResult ) 1.228 + { 1.229 + printf("IBar@%p::QueryInterface()\n", static_cast<void*>(this)); 1.230 + nsISupports* rawPtr = 0; 1.231 + nsresult status = NS_OK; 1.232 + 1.233 + if ( aIID.Equals(NS_GET_IID(IBar)) ) 1.234 + rawPtr = this; 1.235 + else if ( aIID.Equals(NS_GET_IID(IFoo)) ) 1.236 + rawPtr = static_cast<IFoo*>(this); 1.237 + else 1.238 + { 1.239 + nsID iid_of_ISupports = NS_ISUPPORTS_IID; 1.240 + if ( aIID.Equals(iid_of_ISupports) ) 1.241 + rawPtr = static_cast<nsISupports*>(this); 1.242 + else 1.243 + status = NS_ERROR_NO_INTERFACE; 1.244 + } 1.245 + 1.246 + NS_IF_ADDREF(rawPtr); 1.247 + *aResult = rawPtr; 1.248 + 1.249 + return status; 1.250 + } 1.251 + 1.252 + 1.253 + 1.254 +nsresult 1.255 +CreateIBar( void** result ) 1.256 + // a typical factory function (that calls AddRef) 1.257 + { 1.258 + printf(">>CreateIBar() --> "); 1.259 + IBar* barp = new IBar; 1.260 + printf("IBar@%p\n", static_cast<void*>(barp)); 1.261 + 1.262 + barp->AddRef(); 1.263 + *result = barp; 1.264 + 1.265 + printf("<<CreateIBar()\n"); 1.266 + return NS_OK; 1.267 + } 1.268 + 1.269 +void 1.270 +AnIFooPtrPtrContext( IFoo** ) 1.271 + { 1.272 + } 1.273 + 1.274 +void 1.275 +AVoidPtrPtrContext( void** ) 1.276 + { 1.277 + } 1.278 + 1.279 +void 1.280 +AnISupportsPtrPtrContext( nsISupports** ) 1.281 + { 1.282 + } 1.283 + 1.284 +static 1.285 +nsresult 1.286 +TestBloat_Raw_Unsafe() 1.287 + { 1.288 + IBar* barP = 0; 1.289 + nsresult result = CreateIBar(reinterpret_cast<void**>(&barP)); 1.290 + 1.291 + if ( barP ) 1.292 + { 1.293 + IFoo* fooP = 0; 1.294 + if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), reinterpret_cast<void**>(&fooP)) ) ) 1.295 + { 1.296 + fooP->print_totals(); 1.297 + NS_RELEASE(fooP); 1.298 + } 1.299 + 1.300 + NS_RELEASE(barP); 1.301 + } 1.302 + 1.303 + return result; 1.304 + } 1.305 + 1.306 + 1.307 +static 1.308 +nsresult 1.309 +TestBloat_Smart() 1.310 + { 1.311 + nsCOMPtr<IBar> barP; 1.312 + nsresult result = CreateIBar( getter_AddRefs(barP) ); 1.313 + 1.314 + nsCOMPtr<IFoo> fooP( do_QueryInterface(barP, &result) ); 1.315 + 1.316 + if ( fooP ) 1.317 + fooP->print_totals(); 1.318 + 1.319 + return result; 1.320 + } 1.321 + 1.322 + 1.323 + 1.324 + 1.325 +nsCOMPtr<IFoo> gFoop; 1.326 + 1.327 +int 1.328 +main() 1.329 + { 1.330 + printf(">>main()\n"); 1.331 + 1.332 + printf("sizeof(nsCOMPtr<IFoo>) --> %u\n", unsigned(sizeof(nsCOMPtr<IFoo>))); 1.333 + 1.334 + TestBloat_Raw_Unsafe(); 1.335 + TestBloat_Smart(); 1.336 + 1.337 + 1.338 + { 1.339 + printf("\n### Test 1: will a |nsCOMPtr| call |AddRef| on a pointer assigned into it?\n"); 1.340 + nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) ); 1.341 + 1.342 + printf("\n### Test 2: will a |nsCOMPtr| |Release| its old pointer when a new one is assigned in?\n"); 1.343 + foop = do_QueryInterface(new IFoo); 1.344 + 1.345 + // [Shouldn't compile] Is it a compile time error to try to |AddRef| by hand? 1.346 + //foop->AddRef(); 1.347 + 1.348 + // [Shouldn't compile] Is it a compile time error to try to |Release| be hand? 1.349 + //foop->Release(); 1.350 + 1.351 + // [Shouldn't compile] Is it a compile time error to try to |delete| an |nsCOMPtr|? 1.352 + //delete foop; 1.353 + 1.354 + printf("\n### Test 3: can you |AddRef| if you must?\n"); 1.355 + static_cast<IFoo*>(foop)->AddRef(); 1.356 + 1.357 + printf("\n### Test 4: can you |Release| if you must?\n"); 1.358 + static_cast<IFoo*>(foop)->Release(); 1.359 + 1.360 + printf("\n### Test 5: will a |nsCOMPtr| |Release| when it goes out of scope?\n"); 1.361 + } 1.362 + 1.363 + { 1.364 + printf("\n### Test 6: will a |nsCOMPtr| call the correct destructor?\n"); 1.365 + nsCOMPtr<IFoo> foop( do_QueryInterface(new IBar) ); 1.366 + } 1.367 + 1.368 + { 1.369 + printf("\n### Test 7: can you compare one |nsCOMPtr| with another [!=]?\n"); 1.370 + 1.371 + nsCOMPtr<IFoo> foo1p( do_QueryInterface(new IFoo) ); 1.372 + 1.373 + // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|? 1.374 + //AnIFooPtrPtrContext(&foo1p); 1.375 + 1.376 + // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|? 1.377 + //AVoidPtrPtrContext(&foo1p); 1.378 + 1.379 + nsCOMPtr<IFoo> foo2p( do_QueryInterface(new IFoo) ); 1.380 + 1.381 + if ( foo1p != foo2p ) 1.382 + printf("foo1p != foo2p\n"); 1.383 + else 1.384 + printf("foo1p == foo2p\n"); 1.385 + 1.386 + printf("\n### Test 7.5: can you compare a |nsCOMPtr| with NULL, 0, nullptr [!=]?\n"); 1.387 + if ( foo1p != 0 ) 1.388 + printf("foo1p != 0\n"); 1.389 + if ( 0 != foo1p ) 1.390 + printf("0 != foo1p\n"); 1.391 + if ( foo1p == 0 ) 1.392 + printf("foo1p == 0\n"); 1.393 + if ( 0 == foo1p ) 1.394 + printf("0 == foo1p\n"); 1.395 + 1.396 + 1.397 + IFoo* raw_foo2p = foo2p.get(); 1.398 + 1.399 + printf("\n### Test 8: can you compare a |nsCOMPtr| with a raw interface pointer [!=]?\n"); 1.400 + if ( foo1p.get() != raw_foo2p ) 1.401 + printf("foo1p != raw_foo2p\n"); 1.402 + else 1.403 + printf("foo1p == raw_foo2p\n"); 1.404 + 1.405 + 1.406 + printf("\n### Test 9: can you assign one |nsCOMPtr| into another?\n"); 1.407 + foo1p = foo2p; 1.408 + 1.409 + printf("\n### Test 10: can you compare one |nsCOMPtr| with another [==]?\n"); 1.410 + if ( foo1p == foo2p ) 1.411 + printf("foo1p == foo2p\n"); 1.412 + else 1.413 + printf("foo1p != foo2p\n"); 1.414 + 1.415 + printf("\n### Test 11: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n"); 1.416 + if ( raw_foo2p == foo2p.get() ) 1.417 + printf("raw_foo2p == foo2p\n"); 1.418 + else 1.419 + printf("raw_foo2p != foo2p\n"); 1.420 + 1.421 +#if 1 1.422 + printf("\n### Test 11.5: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n"); 1.423 + if ( nsCOMPtr<IFoo>( raw_foo2p ) == foo2p ) 1.424 + printf("raw_foo2p == foo2p\n"); 1.425 + else 1.426 + printf("raw_foo2p != foo2p\n"); 1.427 +#endif 1.428 + 1.429 + printf("\n### Test 12: bare pointer test?\n"); 1.430 + if ( foo1p ) 1.431 + printf("foo1p is not NULL\n"); 1.432 + else 1.433 + printf("foo1p is NULL\n"); 1.434 + 1.435 + printf("\n### Test 13: numeric pointer test?\n"); 1.436 + if ( foo1p == 0 ) 1.437 + printf("foo1p is NULL\n"); 1.438 + else 1.439 + printf("foo1p is not NULL\n"); 1.440 + 1.441 +#if 0 1.442 + if ( foo1p == 1 ) 1.443 + printf("foo1p allowed compare with in\n"); 1.444 +#endif 1.445 + 1.446 + printf("\n### Test 14: how about when two |nsCOMPtr|s referring to the same object go out of scope?\n"); 1.447 + } 1.448 + 1.449 + { 1.450 + printf("\n### Test 15,16 ...setup...\n"); 1.451 + IFoo* raw_foo1p = new IFoo; 1.452 + raw_foo1p->AddRef(); 1.453 + 1.454 + IFoo* raw_foo2p = new IFoo; 1.455 + raw_foo2p->AddRef(); 1.456 + 1.457 + printf("\n### Test 15: what if I don't want to |AddRef| when I construct?\n"); 1.458 + nsCOMPtr<IFoo> foo1p( dont_AddRef(raw_foo1p) ); 1.459 + //nsCOMPtr<IFoo> foo1p = dont_AddRef(raw_foo1p); 1.460 + 1.461 + printf("\n### Test 16: what if I don't want to |AddRef| when I assign in?\n"); 1.462 + nsCOMPtr<IFoo> foo2p; 1.463 + foo2p = dont_AddRef(raw_foo2p); 1.464 + } 1.465 + 1.466 + 1.467 + 1.468 + 1.469 + 1.470 + 1.471 + 1.472 + { 1.473 + printf("\n### setup for Test 17\n"); 1.474 + nsCOMPtr<IFoo> foop; 1.475 + printf("### Test 17: basic parameter behavior?\n"); 1.476 + CreateIFoo( nsGetterAddRefs<IFoo>(foop) ); 1.477 + } 1.478 + printf("### End Test 17\n"); 1.479 + 1.480 + 1.481 + { 1.482 + printf("\n### setup for Test 18\n"); 1.483 + nsCOMPtr<IFoo> foop; 1.484 + printf("### Test 18: basic parameter behavior, using the short form?\n"); 1.485 + CreateIFoo( getter_AddRefs(foop) ); 1.486 + } 1.487 + printf("### End Test 18\n"); 1.488 + 1.489 + 1.490 + { 1.491 + printf("\n### setup for Test 19, 20\n"); 1.492 + nsCOMPtr<IFoo> foop; 1.493 + printf("### Test 19: reference parameter behavior?\n"); 1.494 + set_a_IFoo(address_of(foop)); 1.495 + 1.496 + printf("### Test 20: return value behavior?\n"); 1.497 + foop = return_a_IFoo(); 1.498 + } 1.499 + printf("### End Test 19, 20\n"); 1.500 + 1.501 + { 1.502 + printf("\n### setup for Test 21\n"); 1.503 + nsCOMPtr<IFoo> fooP; 1.504 + 1.505 + printf("### Test 21: is |QueryInterface| called on assigning in a raw pointer?\n"); 1.506 + fooP = do_QueryInterface(new IFoo); 1.507 + } 1.508 + printf("### End Test 21\n"); 1.509 + 1.510 + { 1.511 + printf("\n### setup for Test 22\n"); 1.512 + nsCOMPtr<IFoo> fooP; 1.513 + fooP = do_QueryInterface(new IFoo); 1.514 + 1.515 + nsCOMPtr<IFoo> foo2P; 1.516 + 1.517 + printf("### Test 22: is |QueryInterface| _not_ called when assigning in a smart-pointer of the same type?\n"); 1.518 + foo2P = fooP; 1.519 + } 1.520 + printf("### End Test 22\n"); 1.521 + 1.522 + { 1.523 + printf("\n### setup for Test 23\n"); 1.524 + nsCOMPtr<IBar> barP( do_QueryInterface(new IBar) ); 1.525 + 1.526 + printf("### Test 23: is |QueryInterface| called when assigning in a smart-pointer of a different type?\n"); 1.527 + 1.528 + nsCOMPtr<IFoo> fooP( do_QueryInterface(barP) ); 1.529 + if ( fooP ) 1.530 + printf("an IBar* is an IFoo*\n"); 1.531 + } 1.532 + printf("### End Test 23\n"); 1.533 + 1.534 + 1.535 + { 1.536 + printf("\n### setup for Test 24\n"); 1.537 + nsCOMPtr<IFoo> fooP( do_QueryInterface(new IFoo) ); 1.538 + 1.539 + printf("### Test 24: does |forget| avoid an AddRef/Release when assigning to another nsCOMPtr?\n"); 1.540 + nsCOMPtr<IFoo> fooP2( fooP.forget() ); 1.541 + } 1.542 + printf("### End Test 24\n"); 1.543 + 1.544 + { 1.545 + nsCOMPtr<IFoo> fooP; 1.546 + 1.547 + AnIFooPtrPtrContext( getter_AddRefs(fooP) ); 1.548 + AVoidPtrPtrContext( getter_AddRefs(fooP) ); 1.549 + } 1.550 + 1.551 + 1.552 + { 1.553 + nsCOMPtr<nsISupports> supportsP; 1.554 + 1.555 + AVoidPtrPtrContext( getter_AddRefs(supportsP) ); 1.556 + AnISupportsPtrPtrContext( getter_AddRefs(supportsP) ); 1.557 + } 1.558 + 1.559 + 1.560 + printf("\n### Test 25: will a static |nsCOMPtr| |Release| before program termination?\n"); 1.561 + gFoop = do_QueryInterface(new IFoo); 1.562 + 1.563 + printf("<<main()\n"); 1.564 + return 0; 1.565 + } 1.566 +