source: trunk/third/firefox/xpcom/tests/TestCOMPtr.cpp @ 21695

Revision 21695, 15.2 KB checked in by rbasch, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21694, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *   Pierre Phaneuf <pp@ludusdesign.com>
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the NPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the NPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39#include <assert.h>
40#include <stdio.h>
41#include "nsCOMPtr.h"
42#include "nsISupports.h"
43
44#ifdef HAVE_CPP_NEW_CASTS
45  #define STATIC_CAST(T,x)  static_cast<T>(x)
46  #define REINTERPRET_CAST(T,x) reinterpret_cast<T>(x)
47#else
48  #define STATIC_CAST(T,x)  ((T)(x))
49  #define REINTERPRET_CAST(T,x) ((T)(x))
50#endif
51
52
53#define NS_IFOO_IID \
54{ 0x6f7652e0,  0xee43, 0x11d1, \
55 { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
56
57class IFoo : public nsISupports
58  {
59                public:
60                        NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
61
62                public:
63      IFoo();
64      // virtual dtor because IBar uses our Release()
65      virtual ~IFoo();
66
67      NS_IMETHOD_(nsrefcnt) AddRef();
68      NS_IMETHOD_(nsrefcnt) Release();
69      NS_IMETHOD QueryInterface( const nsIID&, void** );
70
71      static void print_totals();
72
73    private:
74      unsigned int refcount_;
75
76      static unsigned int total_constructions_;
77      static unsigned int total_destructions_;
78  };
79
80class IBar;
81
82  // some types I'll need
83typedef unsigned long NS_RESULT;
84
85  // some functions I'll need (and define below)
86          nsresult  CreateIFoo( void** );
87          nsresult  CreateIBar( void** result );
88              void  AnIFooPtrPtrContext( IFoo** );
89              void      AnISupportsPtrPtrContext( nsISupports** );
90              void  AVoidPtrPtrContext( void** );
91              void  set_a_IFoo( nsCOMPtr<IFoo>* result );
92nsCOMPtr<IFoo>  return_a_IFoo();
93
94
95
96
97unsigned int IFoo::total_constructions_;
98unsigned int IFoo::total_destructions_;
99
100class test_message
101  {
102    public:
103      test_message()
104        {
105          printf("BEGIN unit tests for |nsCOMPtr|, compiled " __DATE__ "\n");
106        }
107
108     ~test_message()
109        {
110          IFoo::print_totals();
111          printf("END unit tests for |nsCOMPtr|.\n");
112        }
113  };
114
115test_message gTestMessage;
116
117
118  /*
119    ...
120  */
121
122void
123IFoo::print_totals()
124  {
125    printf("total constructions/destructions --> %d/%d\n",
126           total_constructions_, total_destructions_);
127  }
128
129IFoo::IFoo()
130    : refcount_(0)
131  {
132    ++total_constructions_;
133    printf("  new IFoo@%p [#%d]\n",
134           STATIC_CAST(void*, this), total_constructions_);
135  }
136
137IFoo::~IFoo()
138  {
139    ++total_destructions_;
140    printf("IFoo@%p::~IFoo() [#%d]\n",
141           STATIC_CAST(void*, this), total_destructions_);
142  }
143
144nsrefcnt
145IFoo::AddRef()
146  {
147    ++refcount_;
148    printf("IFoo@%p::AddRef(), refcount --> %d\n",
149           STATIC_CAST(void*, this), refcount_);
150    return refcount_;
151  }
152
153nsrefcnt
154IFoo::Release()
155  {
156    int wrap_message = (refcount_ == 1);
157    if ( wrap_message )
158      printf(">>");
159     
160    --refcount_;
161    printf("IFoo@%p::Release(), refcount --> %d\n",
162           STATIC_CAST(void*, this), refcount_);
163
164    if ( !refcount_ )
165      {
166        printf("  delete IFoo@%p\n", STATIC_CAST(void*, this));
167        delete this;
168      }
169
170    if ( wrap_message )
171      printf("<<IFoo@%p::Release()\n", STATIC_CAST(void*, this));
172
173    return refcount_;
174  }
175
176nsresult
177IFoo::QueryInterface( const nsIID& aIID, void** aResult )
178        {
179    printf("IFoo@%p::QueryInterface()\n", STATIC_CAST(void*, this));
180                nsISupports* rawPtr = 0;
181                nsresult status = NS_OK;
182
183                if ( aIID.Equals(GetIID()) )
184                        rawPtr = this;
185                else
186                        {
187                                nsID iid_of_ISupports = NS_ISUPPORTS_IID;
188                                if ( aIID.Equals(iid_of_ISupports) )
189                                        rawPtr = STATIC_CAST(nsISupports*, this);
190                                else
191                                        status = NS_ERROR_NO_INTERFACE;
192                        }
193
194                NS_IF_ADDREF(rawPtr);
195                *aResult = rawPtr;
196
197                return status;
198        }
199
200nsresult
201CreateIFoo( void** result )
202    // a typical factory function (that calls AddRef)
203  {
204    printf(">>CreateIFoo() --> ");
205    IFoo* foop = new IFoo;
206    printf("IFoo@%p\n", STATIC_CAST(void*, foop));
207
208    foop->AddRef();
209    *result = foop;
210
211    printf("<<CreateIFoo()\n");
212    return 0;
213  }
214
215void
216set_a_IFoo( nsCOMPtr<IFoo>* result )
217  {
218    printf(">>set_a_IFoo()\n");
219    assert(result);
220
221    nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
222    *result = foop;
223    printf("<<set_a_IFoo()\n");
224  }
225
226nsCOMPtr<IFoo>
227return_a_IFoo()
228  {
229    printf(">>return_a_IFoo()\n");
230    nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
231    printf("<<return_a_IFoo()\n");
232    return foop;
233  }
234
235
236
237
238#define NS_IBAR_IID \
239{ 0x6f7652e1,  0xee43, 0x11d1, \
240 { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
241
242class IBar : public IFoo
243  {
244        public:
245                NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBAR_IID)
246
247    public:
248      IBar();
249      virtual ~IBar();
250
251      NS_IMETHOD QueryInterface( const nsIID&, void** );
252  };
253
254IBar::IBar()
255  {
256    printf("  new IBar@%p\n", STATIC_CAST(void*, this));
257  }
258
259IBar::~IBar()
260  {
261    printf("IBar@%p::~IBar()\n", STATIC_CAST(void*, this));
262  }
263
264nsresult
265IBar::QueryInterface( const nsID& aIID, void** aResult )
266        {
267    printf("IBar@%p::QueryInterface()\n", STATIC_CAST(void*, this));
268                nsISupports* rawPtr = 0;
269                nsresult status = NS_OK;
270
271                if ( aIID.Equals(GetIID()) )
272                        rawPtr = this;
273                else if ( aIID.Equals(NS_GET_IID(IFoo)) )
274                        rawPtr = STATIC_CAST(IFoo*, this);
275                else
276                        {
277                                nsID iid_of_ISupports = NS_ISUPPORTS_IID;
278                                if ( aIID.Equals(iid_of_ISupports) )
279                                        rawPtr = STATIC_CAST(nsISupports*, this);
280                                else
281                                        status = NS_ERROR_NO_INTERFACE;
282                        }
283
284                NS_IF_ADDREF(rawPtr);
285                *aResult = rawPtr;
286
287                return status;
288        }
289
290
291
292nsresult
293CreateIBar( void** result )
294    // a typical factory function (that calls AddRef)
295  {
296    printf(">>CreateIBar() --> ");
297    IBar* barp = new IBar;
298    printf("IBar@%p\n", STATIC_CAST(void*, barp));
299
300    barp->AddRef();
301    *result = barp;
302
303    printf("<<CreateIBar()\n");
304    return 0;
305  }
306
307void
308AnIFooPtrPtrContext( IFoo** )
309  {
310  }
311
312void
313AVoidPtrPtrContext( void** )
314  {
315  }
316
317void
318AnISupportsPtrPtrContext( nsISupports** )
319        {
320        }
321
322
323// Optimism
324#define TEST_EXCEPTIONS 1
325
326// HAVE_CPP_EXCEPTIONS is defined automagically on unix
327#if defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2)
328#if !defined(HAVE_CPP_EXCEPTIONS)
329#undef TEST_EXCEPTIONS
330#endif
331#endif
332
333#ifdef TEST_EXCEPTIONS
334static
335nsresult
336TestBloat_Raw()
337        {
338                IBar* barP = 0;
339                nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
340
341                if ( barP )
342                        {
343                                try
344                                        {
345                                                IFoo* fooP = 0;
346                                                if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), REINTERPRET_CAST(void**, &fooP)) ) )
347                                                        {
348                                                                try
349                                                                        {
350                                                                                fooP->print_totals();
351                                                                        }
352                                                                catch( ... )
353                                                                        {
354                                                                                NS_RELEASE(fooP);
355                                                                                throw;
356                                                                        }
357
358                                                                NS_RELEASE(fooP);
359                                                        }
360                                        }
361                                catch( ... )
362                                        {
363                                                NS_RELEASE(barP);
364                                                throw;
365                                        }
366
367                                NS_RELEASE(barP);
368                        }
369
370                return result;
371        }
372#endif // TEST_EXCEPTIONS
373
374static
375nsresult
376TestBloat_Raw_Unsafe()
377        {
378                IBar* barP = 0;
379                nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
380
381                if ( barP )
382                        {
383                                IFoo* fooP = 0;
384                                if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), REINTERPRET_CAST(void**, &fooP)) ) )
385                                        {
386                                                fooP->print_totals();
387                                                NS_RELEASE(fooP);
388                                        }
389
390                                NS_RELEASE(barP);
391                        }
392
393                return result;
394        }
395
396
397static
398nsresult
399TestBloat_Smart()
400        {
401                nsCOMPtr<IBar> barP;
402                nsresult result = CreateIBar( getter_AddRefs(barP) );
403
404                nsCOMPtr<IFoo> fooP( do_QueryInterface(barP, &result) );
405
406                if ( fooP )
407                        fooP->print_totals();
408
409                return result;
410        }
411
412
413
414
415nsCOMPtr<IFoo> gFoop;
416
417int
418main()
419  {
420    printf(">>main()\n");
421
422                printf("sizeof(nsCOMPtr<IFoo>) --> %d\n", sizeof(nsCOMPtr<IFoo>));
423
424#ifdef TEST_EXCEPTIONS
425                TestBloat_Raw();
426#endif // TEST_EXCEPTIONS
427                TestBloat_Raw_Unsafe();
428                TestBloat_Smart();
429
430
431    {
432      printf("\n### Test  1: will a |nsCOMPtr| call |AddRef| on a pointer assigned into it?\n");
433      nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
434
435      printf("\n### Test  2: will a |nsCOMPtr| |Release| its old pointer when a new one is assigned in?\n");
436      foop = do_QueryInterface(new IFoo);
437
438        // [Shouldn't compile] Is it a compile time error to try to |AddRef| by hand?
439      //foop->AddRef();
440
441        // [Shouldn't compile] Is it a compile time error to try to |Release| be hand?
442      //foop->Release();
443
444                                // [Shouldn't compile] Is it a compile time error to try to |delete| an |nsCOMPtr|?
445                        //delete foop;
446
447      printf("\n### Test  3: can you |AddRef| if you must?\n");
448      STATIC_CAST(IFoo*, foop)->AddRef();
449
450      printf("\n### Test  4: can you |Release| if you must?\n");
451      STATIC_CAST(IFoo*, foop)->Release();
452
453      printf("\n### Test  5: will a |nsCOMPtr| |Release| when it goes out of scope?\n");
454    }
455
456    {
457      printf("\n### Test  6: will a |nsCOMPtr| call the correct destructor?\n");
458      nsCOMPtr<IFoo> foop( do_QueryInterface(new IBar) );
459    }
460
461    {
462      printf("\n### Test  7: can you compare one |nsCOMPtr| with another [!=]?\n");
463
464      nsCOMPtr<IFoo> foo1p( do_QueryInterface(new IFoo) );
465
466        // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
467      //AnIFooPtrPtrContext(&foo1p);
468
469        // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
470      //AVoidPtrPtrContext(&foo1p);
471
472      nsCOMPtr<IFoo> foo2p( do_QueryInterface(new IFoo) );
473
474      if ( foo1p != foo2p )
475        printf("foo1p != foo2p\n");
476      else
477        printf("foo1p == foo2p\n");
478
479      printf("\n### Test  7.5: can you compare a |nsCOMPtr| with NULL, 0, nsnull [!=]?\n");
480      if ( foo1p != 0 )
481        printf("foo1p != 0\n");
482      if ( 0 != foo1p )
483        printf("0 != foo1p\n");
484      if ( foo1p == 0 )
485        printf("foo1p == 0\n");
486      if ( 0 == foo1p )
487        printf("0 == foo1p\n");
488                       
489
490      IFoo* raw_foo2p = foo2p.get();
491
492      printf("\n### Test  8: can you compare a |nsCOMPtr| with a raw interface pointer [!=]?\n");
493      if ( foo1p.get() != raw_foo2p )
494        printf("foo1p != raw_foo2p\n");
495      else
496        printf("foo1p == raw_foo2p\n");
497
498
499      printf("\n### Test  9: can you assign one |nsCOMPtr| into another?\n");
500      foo1p = foo2p;
501
502      printf("\n### Test 10: can you compare one |nsCOMPtr| with another [==]?\n");
503      if ( foo1p == foo2p )
504        printf("foo1p == foo2p\n");
505      else
506        printf("foo1p != foo2p\n");
507
508      printf("\n### Test 11: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
509      if ( raw_foo2p == foo2p.get() )
510        printf("raw_foo2p == foo2p\n");
511      else
512        printf("raw_foo2p != foo2p\n");
513
514#if 1
515      printf("\n### Test 11.5: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
516      if ( nsCOMPtr<IFoo>( raw_foo2p ) == foo2p )
517        printf("raw_foo2p == foo2p\n");
518      else
519        printf("raw_foo2p != foo2p\n");
520#endif
521
522      printf("\n### Test 12: bare pointer test?\n");
523      if ( foo1p )
524        printf("foo1p is not NULL\n");
525      else
526        printf("foo1p is NULL\n");
527
528      printf("\n### Test 13: numeric pointer test?\n");
529      if ( foo1p == 0 )
530        printf("foo1p is NULL\n");
531      else
532        printf("foo1p is not NULL\n");
533
534#if 0
535                        if ( foo1p == 1 )
536                                printf("foo1p allowed compare with in\n");
537#endif
538
539      printf("\n### Test 14: how about when two |nsCOMPtr|s referring to the same object go out of scope?\n");
540    }
541
542    {
543      printf("\n### Test 15,16 ...setup...\n");
544      IFoo* raw_foo1p = new IFoo;
545      raw_foo1p->AddRef();
546
547      IFoo* raw_foo2p = new IFoo;
548      raw_foo2p->AddRef();
549
550      printf("\n### Test 15: what if I don't want to |AddRef| when I construct?\n");
551      nsCOMPtr<IFoo> foo1p( dont_AddRef(raw_foo1p) );
552      //nsCOMPtr<IFoo> foo1p = dont_AddRef(raw_foo1p);
553
554      printf("\n### Test 16: what if I don't want to |AddRef| when I assign in?\n");
555      nsCOMPtr<IFoo> foo2p;
556      foo2p = dont_AddRef(raw_foo2p);
557    }
558
559
560
561
562
563
564
565    {
566        printf("\n### setup for Test 17\n");
567      nsCOMPtr<IFoo> foop;
568      printf("### Test 17: basic parameter behavior?\n");
569      CreateIFoo( nsGetterAddRefs<IFoo>(foop) );
570    }
571    printf("### End Test 17\n");
572
573
574    {
575        printf("\n### setup for Test 18\n");
576      nsCOMPtr<IFoo> foop;
577      printf("### Test 18: basic parameter behavior, using the short form?\n");
578      CreateIFoo( getter_AddRefs(foop) );
579    }
580    printf("### End Test 18\n");
581
582
583    {
584        printf("\n### setup for Test 19, 20\n");
585      nsCOMPtr<IFoo> foop;
586      printf("### Test 19: reference parameter behavior?\n");
587      set_a_IFoo(address_of(foop));
588
589      printf("### Test 20: return value behavior?\n");
590      foop = return_a_IFoo();
591    }
592    printf("### End Test 19, 20\n");
593
594                {
595        printf("\n### setup for Test 21\n");
596                        nsCOMPtr<IFoo> fooP;
597
598                        printf("### Test 21: is |QueryInterface| called on assigning in a raw pointer?\n");
599                        fooP = do_QueryInterface(new IFoo);
600                }
601    printf("### End Test 21\n");
602
603                {
604        printf("\n### setup for Test 22\n");
605                        nsCOMPtr<IFoo> fooP;
606                        fooP = do_QueryInterface(new IFoo);
607
608                        nsCOMPtr<IFoo> foo2P;
609
610                        printf("### Test 22: is |QueryInterface| _not_ called when assigning in a smart-pointer of the same type?\n");
611                        foo2P = fooP;
612                }
613    printf("### End Test 22\n");
614
615                {
616        printf("\n### setup for Test 23\n");
617                        nsCOMPtr<IBar> barP( do_QueryInterface(new IBar) );
618
619                        printf("### Test 23: is |QueryInterface| called when assigning in a smart-pointer of a different type?\n");
620
621                        nsCOMPtr<IFoo> fooP( do_QueryInterface(barP) );
622                        if ( fooP )
623                                printf("an IBar* is an IFoo*\n");
624                }
625    printf("### End Test 23\n");
626
627
628                {
629                        nsCOMPtr<IFoo> fooP;
630
631                        AnIFooPtrPtrContext( getter_AddRefs(fooP) );
632                        AVoidPtrPtrContext( getter_AddRefs(fooP) );
633                        AnISupportsPtrPtrContext( getter_AddRefs(fooP) );
634                }
635
636
637                {
638                        nsCOMPtr<nsISupports> supportsP;
639
640                        AVoidPtrPtrContext( getter_AddRefs(supportsP) );
641                        AnISupportsPtrPtrContext( getter_AddRefs(supportsP) );
642                }
643
644
645    printf("\n### Test 24: will a static |nsCOMPtr| |Release| before program termination?\n");
646    gFoop = do_QueryInterface(new IFoo);
647   
648    printf("<<main()\n");
649    return 0;
650  }
651
Note: See TracBrowser for help on using the repository browser.