1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/tests/TestRefPtr.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,555 @@ 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 "nsAutoPtr.h" 1.13 +#include "nsISupports.h" 1.14 + 1.15 +#define NS_FOO_IID \ 1.16 +{ 0x6f7652e0, 0xee43, 0x11d1, \ 1.17 + { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } } 1.18 + 1.19 +class Foo : public nsISupports 1.20 + { 1.21 + public: 1.22 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_FOO_IID) 1.23 + 1.24 + public: 1.25 + Foo(); 1.26 + // virtual dtor because Bar uses our Release() 1.27 + virtual ~Foo(); 1.28 + 1.29 + NS_IMETHOD_(MozExternalRefCountType) AddRef(); 1.30 + NS_IMETHOD_(MozExternalRefCountType) Release(); 1.31 + NS_IMETHOD QueryInterface( const nsIID&, void** ); 1.32 + 1.33 + static void print_totals(); 1.34 + 1.35 + private: 1.36 + unsigned int refcount_; 1.37 + 1.38 + static unsigned int total_constructions_; 1.39 + static unsigned int total_destructions_; 1.40 + }; 1.41 + 1.42 +NS_DEFINE_STATIC_IID_ACCESSOR(Foo, NS_FOO_IID) 1.43 + 1.44 +class Bar; 1.45 + 1.46 + // some types I'll need 1.47 +typedef unsigned long NS_RESULT; 1.48 + 1.49 + // some functions I'll need (and define below) 1.50 + nsresult CreateFoo( void** ); 1.51 + nsresult CreateBar( void** result ); 1.52 + void AnFooPtrPtrContext( Foo** ); 1.53 + void AnISupportsPtrPtrContext( nsISupports** ); 1.54 + void AVoidPtrPtrContext( void** ); 1.55 + void set_a_Foo( nsRefPtr<Foo>* result ); 1.56 +nsRefPtr<Foo> return_a_Foo(); 1.57 + 1.58 + 1.59 + 1.60 + 1.61 +unsigned int Foo::total_constructions_; 1.62 +unsigned int Foo::total_destructions_; 1.63 + 1.64 +class test_message 1.65 + { 1.66 + public: 1.67 + test_message() 1.68 + { 1.69 + printf("BEGIN unit tests for |nsRefPtr|, compiled " __DATE__ "\n"); 1.70 + } 1.71 + 1.72 + ~test_message() 1.73 + { 1.74 + Foo::print_totals(); 1.75 + printf("END unit tests for |nsRefPtr|.\n"); 1.76 + } 1.77 + }; 1.78 + 1.79 +test_message gTestMessage; 1.80 + 1.81 + 1.82 + /* 1.83 + ... 1.84 + */ 1.85 + 1.86 +void 1.87 +Foo::print_totals() 1.88 + { 1.89 + printf("total constructions/destructions --> %d/%d\n", 1.90 + total_constructions_, total_destructions_); 1.91 + } 1.92 + 1.93 +Foo::Foo() 1.94 + : refcount_(0) 1.95 + { 1.96 + ++total_constructions_; 1.97 + printf(" new Foo@%p [#%d]\n", 1.98 + static_cast<void*>(this), total_constructions_); 1.99 + } 1.100 + 1.101 +Foo::~Foo() 1.102 + { 1.103 + ++total_destructions_; 1.104 + printf("Foo@%p::~Foo() [#%d]\n", 1.105 + static_cast<void*>(this), total_destructions_); 1.106 + } 1.107 + 1.108 +MozExternalRefCountType 1.109 +Foo::AddRef() 1.110 + { 1.111 + ++refcount_; 1.112 + printf("Foo@%p::AddRef(), refcount --> %d\n", 1.113 + static_cast<void*>(this), refcount_); 1.114 + return refcount_; 1.115 + } 1.116 + 1.117 +MozExternalRefCountType 1.118 +Foo::Release() 1.119 + { 1.120 + int newcount = --refcount_; 1.121 + if ( newcount == 0 ) 1.122 + printf(">>"); 1.123 + 1.124 + printf("Foo@%p::Release(), refcount --> %d\n", 1.125 + static_cast<void*>(this), refcount_); 1.126 + 1.127 + if ( newcount == 0 ) 1.128 + { 1.129 + printf(" delete Foo@%p\n", static_cast<void*>(this)); 1.130 + printf("<<Foo@%p::Release()\n", static_cast<void*>(this)); 1.131 + delete this; 1.132 + } 1.133 + 1.134 + return newcount; 1.135 + } 1.136 + 1.137 +nsresult 1.138 +Foo::QueryInterface( const nsIID& aIID, void** aResult ) 1.139 + { 1.140 + printf("Foo@%p::QueryInterface()\n", static_cast<void*>(this)); 1.141 + nsISupports* rawPtr = 0; 1.142 + nsresult status = NS_OK; 1.143 + 1.144 + if ( aIID.Equals(NS_GET_IID(Foo)) ) 1.145 + rawPtr = this; 1.146 + else 1.147 + { 1.148 + nsID iid_of_ISupports = NS_ISUPPORTS_IID; 1.149 + if ( aIID.Equals(iid_of_ISupports) ) 1.150 + rawPtr = static_cast<nsISupports*>(this); 1.151 + else 1.152 + status = NS_ERROR_NO_INTERFACE; 1.153 + } 1.154 + 1.155 + NS_IF_ADDREF(rawPtr); 1.156 + *aResult = rawPtr; 1.157 + 1.158 + return status; 1.159 + } 1.160 + 1.161 +nsresult 1.162 +CreateFoo( void** result ) 1.163 + // a typical factory function (that calls AddRef) 1.164 + { 1.165 + printf(">>CreateFoo() --> "); 1.166 + Foo* foop = new Foo; 1.167 + printf("Foo@%p\n", static_cast<void*>(foop)); 1.168 + 1.169 + foop->AddRef(); 1.170 + *result = foop; 1.171 + 1.172 + printf("<<CreateFoo()\n"); 1.173 + return NS_OK; 1.174 + } 1.175 + 1.176 +void 1.177 +set_a_Foo( nsRefPtr<Foo>* result ) 1.178 + { 1.179 + printf(">>set_a_Foo()\n"); 1.180 + assert(result); 1.181 + 1.182 + nsRefPtr<Foo> foop( do_QueryObject(new Foo) ); 1.183 + *result = foop; 1.184 + printf("<<set_a_Foo()\n"); 1.185 + } 1.186 + 1.187 +nsRefPtr<Foo> 1.188 +return_a_Foo() 1.189 + { 1.190 + printf(">>return_a_Foo()\n"); 1.191 + nsRefPtr<Foo> foop( do_QueryObject(new Foo) ); 1.192 + printf("<<return_a_Foo()\n"); 1.193 + return foop; 1.194 + } 1.195 + 1.196 + 1.197 + 1.198 + 1.199 +#define NS_BAR_IID \ 1.200 +{ 0x6f7652e1, 0xee43, 0x11d1, \ 1.201 + { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } } 1.202 + 1.203 +class Bar : public Foo 1.204 + { 1.205 + public: 1.206 + NS_DECLARE_STATIC_IID_ACCESSOR(NS_BAR_IID) 1.207 + 1.208 + public: 1.209 + Bar(); 1.210 + virtual ~Bar(); 1.211 + 1.212 + NS_IMETHOD QueryInterface( const nsIID&, void** ); 1.213 + }; 1.214 + 1.215 +NS_DEFINE_STATIC_IID_ACCESSOR(Bar, NS_BAR_IID) 1.216 + 1.217 +Bar::Bar() 1.218 + { 1.219 + printf(" new Bar@%p\n", static_cast<void*>(this)); 1.220 + } 1.221 + 1.222 +Bar::~Bar() 1.223 + { 1.224 + printf("Bar@%p::~Bar()\n", static_cast<void*>(this)); 1.225 + } 1.226 + 1.227 +nsresult 1.228 +Bar::QueryInterface( const nsID& aIID, void** aResult ) 1.229 + { 1.230 + printf("Bar@%p::QueryInterface()\n", static_cast<void*>(this)); 1.231 + nsISupports* rawPtr = 0; 1.232 + nsresult status = NS_OK; 1.233 + 1.234 + if ( aIID.Equals(NS_GET_IID(Bar)) ) 1.235 + rawPtr = this; 1.236 + else if ( aIID.Equals(NS_GET_IID(Foo)) ) 1.237 + rawPtr = static_cast<Foo*>(this); 1.238 + else 1.239 + { 1.240 + nsID iid_of_ISupports = NS_ISUPPORTS_IID; 1.241 + if ( aIID.Equals(iid_of_ISupports) ) 1.242 + rawPtr = static_cast<nsISupports*>(this); 1.243 + else 1.244 + status = NS_ERROR_NO_INTERFACE; 1.245 + } 1.246 + 1.247 + NS_IF_ADDREF(rawPtr); 1.248 + *aResult = rawPtr; 1.249 + 1.250 + return status; 1.251 + } 1.252 + 1.253 + 1.254 + 1.255 +nsresult 1.256 +CreateBar( void** result ) 1.257 + // a typical factory function (that calls AddRef) 1.258 + { 1.259 + printf(">>CreateBar() --> "); 1.260 + Bar* barp = new Bar; 1.261 + printf("Bar@%p\n", static_cast<void*>(barp)); 1.262 + 1.263 + barp->AddRef(); 1.264 + *result = barp; 1.265 + 1.266 + printf("<<CreateBar()\n"); 1.267 + return NS_OK; 1.268 + } 1.269 + 1.270 +void 1.271 +AnFooPtrPtrContext( Foo** ) 1.272 + { 1.273 + } 1.274 + 1.275 +void 1.276 +AVoidPtrPtrContext( void** ) 1.277 + { 1.278 + } 1.279 + 1.280 +void 1.281 +AnISupportsPtrPtrContext( nsISupports** ) 1.282 + { 1.283 + } 1.284 + 1.285 +nsresult 1.286 +TestBloat_Raw_Unsafe() 1.287 + { 1.288 + Bar* barP = 0; 1.289 + nsresult result = CreateBar(reinterpret_cast<void**>(&barP)); 1.290 + 1.291 + if ( barP ) 1.292 + { 1.293 + Foo* fooP = 0; 1.294 + if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(Foo), 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 + nsRefPtr<Bar> barP; 1.312 + nsresult result = CreateBar( getter_AddRefs(barP) ); 1.313 + 1.314 + nsRefPtr<Foo> fooP( do_QueryObject(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 +nsRefPtr<Foo> gFoop; 1.326 + 1.327 +int 1.328 +main() 1.329 + { 1.330 + printf(">>main()\n"); 1.331 + 1.332 + printf("sizeof(nsRefPtr<Foo>) --> %u\n", unsigned(sizeof(nsRefPtr<Foo>))); 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 + nsRefPtr<Foo> foop( do_QueryObject(new Foo) ); 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_QueryObject(new Foo); 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<Foo*>(foop)->AddRef(); 1.356 + 1.357 + printf("\n### Test 4: can you |Release| if you must?\n"); 1.358 + static_cast<Foo*>(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 + nsRefPtr<Foo> foop( do_QueryObject(new Bar) ); 1.366 + } 1.367 + 1.368 + { 1.369 + printf("\n### Test 7: can you compare one |nsCOMPtr| with another [!=]?\n"); 1.370 + 1.371 + nsRefPtr<Foo> foo1p( do_QueryObject(new Foo) ); 1.372 + 1.373 + // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|? 1.374 + //AnFooPtrPtrContext(&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 + nsRefPtr<Foo> foo2p( do_QueryObject(new Foo) ); 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 + Foo* 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 ( nsRefPtr<Foo>( 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 + Foo* raw_foo1p = new Foo; 1.452 + raw_foo1p->AddRef(); 1.453 + 1.454 + Foo* raw_foo2p = new Foo; 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 + nsRefPtr<Foo> foo1p( dont_AddRef(raw_foo1p) ); 1.459 + //nsRefPtr<Foo> 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 + nsRefPtr<Foo> 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 + nsRefPtr<Foo> foop; 1.475 + printf("### Test 17: basic parameter behavior?\n"); 1.476 + CreateFoo( nsRefPtrGetterAddRefs<Foo>(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 + nsRefPtr<Foo> foop; 1.484 + printf("### Test 18: basic parameter behavior, using the short form?\n"); 1.485 + CreateFoo( 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 + nsRefPtr<Foo> foop; 1.493 + printf("### Test 19: reference parameter behavior?\n"); 1.494 + set_a_Foo(address_of(foop)); 1.495 + 1.496 + printf("### Test 20: return value behavior?\n"); 1.497 + foop = return_a_Foo(); 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 + nsRefPtr<Foo> fooP; 1.504 + 1.505 + printf("### Test 21: is |QueryInterface| called on assigning in a raw pointer?\n"); 1.506 + fooP = do_QueryObject(new Foo); 1.507 + } 1.508 + printf("### End Test 21\n"); 1.509 + 1.510 + { 1.511 + printf("\n### setup for Test 22\n"); 1.512 + nsRefPtr<Foo> fooP; 1.513 + fooP = do_QueryObject(new Foo); 1.514 + 1.515 + nsRefPtr<Foo> 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 + nsRefPtr<Bar> barP( do_QueryObject(new Bar) ); 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 + nsRefPtr<Foo> fooP( do_QueryObject(barP) ); 1.529 + if ( fooP ) 1.530 + printf("an Bar* is an Foo*\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 + nsRefPtr<Foo> fooP( do_QueryObject(new Foo) ); 1.538 + 1.539 + printf("### Test 24: does |forget| avoid an AddRef/Release when assigning to another nsCOMPtr?\n"); 1.540 + nsRefPtr<Foo> fooP2( fooP.forget() ); 1.541 + } 1.542 + printf("### End Test 24\n"); 1.543 + 1.544 + { 1.545 + nsRefPtr<Foo> fooP; 1.546 + 1.547 + AnFooPtrPtrContext( getter_AddRefs(fooP) ); 1.548 + AVoidPtrPtrContext( getter_AddRefs(fooP) ); 1.549 + } 1.550 + 1.551 + 1.552 + printf("\n### Test 25: will a static |nsCOMPtr| |Release| before program termination?\n"); 1.553 + gFoop = do_QueryObject(new Foo); 1.554 + 1.555 + printf("<<main()\n"); 1.556 + return 0; 1.557 + } 1.558 +