Bug 1313470 - Part 2: Convert TestCOMPtr to a gtest. r=froydnj
authorEric Rahm <erahm@mozilla.com>
Fri, 04 Nov 2016 16:22:14 -0700
changeset 321210 fa89c7fb96577c9eeb930279e30d9d6ab37baf7c
parent 321209 733ef60958c16161f51d2c345e6ac6c2fb8bedcb
child 321211 0ce11eb36fe5448240b1ed91eb969fc9e0960140
push id30920
push userphilringnalda@gmail.com
push dateSat, 05 Nov 2016 20:41:02 +0000
treeherdermozilla-central@c44c01dfd264 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1313470
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1313470 - Part 2: Convert TestCOMPtr to a gtest. r=froydnj MozReview-Commit-ID: HfcLTmvkRc8
testing/cppunittest.ini
xpcom/tests/TestCOMPtr.cpp
xpcom/tests/gtest/TestCOMPtr.cpp
xpcom/tests/gtest/moz.build
xpcom/tests/moz.build
--- a/testing/cppunittest.ini
+++ b/testing/cppunittest.ini
@@ -6,17 +6,16 @@
 [TestAudioBuffers]
 skip-if = os == 'b2g'  # Bug 1062937
 [TestAudioMixer]
 [TestBinarySearch]
 [TestBind]
 [TestBloomFilter]
 [TestCOM]
 skip-if = os != 'win'
-[TestCOMPtr]
 [TestCOMPtrEq]
 [TestCSPParser]
 skip-if = os == 'b2g' || (os == 'android' && debug) # Bug 1054246
 [TestCasting]
 [TestCeilingFloor]
 [TestCertDB]
 [TestCheckedInt]
 [TestCookie]
rename from xpcom/tests/TestCOMPtr.cpp
rename to xpcom/tests/gtest/TestCOMPtr.cpp
--- a/xpcom/tests/TestCOMPtr.cpp
+++ b/xpcom/tests/gtest/TestCOMPtr.cpp
@@ -1,140 +1,88 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include <assert.h>
-#include <stdio.h>
 #include "nsCOMPtr.h"
-#include "nsISupports.h"
+#include "gtest/gtest.h"
+
 #include "mozilla/Unused.h"
 
 #define NS_IFOO_IID \
 { 0x6f7652e0,  0xee43, 0x11d1, \
   { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
 
+namespace TestCOMPtr
+{
+
 class IFoo : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
 
 public:
   IFoo();
   // virtual dtor because IBar uses our Release()
   virtual ~IFoo();
 
   NS_IMETHOD_(MozExternalRefCountType) AddRef();
   NS_IMETHOD_(MozExternalRefCountType) Release();
   NS_IMETHOD QueryInterface( const nsIID&, void** );
 
-  static void print_totals();
-
-private:
   unsigned int refcount_;
 
-  static unsigned int total_constructions_;
-  static unsigned int total_destructions_;
+  static int total_constructions_;
+  static int total_destructions_;
+  static int total_queries_;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID)
 
-class IBar;
-
-// some types I'll need
-typedef unsigned long NS_RESULT;
-
-// some functions I'll need (and define below)
-nsresult  CreateIFoo( void** );
-nsresult  CreateIBar( void** result );
-void  AnIFooPtrPtrContext( IFoo** );
-void	AnISupportsPtrPtrContext( nsISupports** );
-void  AVoidPtrPtrContext( void** );
-void  set_a_IFoo( nsCOMPtr<IFoo>* result );
-nsCOMPtr<IFoo>  return_a_IFoo();
-
-
-
-
-unsigned int IFoo::total_constructions_;
-unsigned int IFoo::total_destructions_;
-
-class test_message
-{
-  public:
-    test_message()
-    {
-      printf("BEGIN unit tests for |nsCOMPtr|, compiled " __DATE__ "\n");
-    }
-
-    ~test_message()
-    {
-      IFoo::print_totals();
-      printf("END unit tests for |nsCOMPtr|.\n");
-    }
-};
-
-test_message gTestMessage;
-
-void
-IFoo::print_totals()
-{
-  printf("total constructions/destructions --> %d/%d\n", 
-      total_constructions_, total_destructions_);
-}
+int IFoo::total_constructions_;
+int IFoo::total_destructions_;
+int IFoo::total_queries_;
 
 IFoo::IFoo()
   : refcount_(0)
 {
   ++total_constructions_;
-  printf("  new IFoo@%p [#%d]\n",
-      static_cast<void*>(this), total_constructions_);
 }
 
 IFoo::~IFoo()
 {
   ++total_destructions_;
-  printf("IFoo@%p::~IFoo() [#%d]\n",
-      static_cast<void*>(this), total_destructions_);
 }
 
 MozExternalRefCountType
 IFoo::AddRef()
 {
   ++refcount_;
-  printf("IFoo@%p::AddRef(), refcount --> %d\n", 
-      static_cast<void*>(this), refcount_);
   return refcount_;
 }
 
 MozExternalRefCountType
 IFoo::Release()
 {
   int newcount = --refcount_;
-  if ( newcount == 0 )
-    printf(">>");
-
-  printf("IFoo@%p::Release(), refcount --> %d\n",
-      static_cast<void*>(this), refcount_);
 
   if ( newcount == 0 )
   {
-    printf("  delete IFoo@%p\n", static_cast<void*>(this));
-    printf("<<IFoo@%p::Release()\n", static_cast<void*>(this));
     delete this;
   }
 
   return newcount;
 }
 
 nsresult
 IFoo::QueryInterface( const nsIID& aIID, void** aResult )
 {
-  printf("IFoo@%p::QueryInterface()\n", static_cast<void*>(this));
+  total_queries_++;
+
   nsISupports* rawPtr = 0;
   nsresult status = NS_OK;
 
   if ( aIID.Equals(NS_GET_IID(IFoo)) )
     rawPtr = this;
   else
   {
     nsID iid_of_ISupports = NS_ISUPPORTS_IID;
@@ -149,82 +97,76 @@ IFoo::QueryInterface( const nsIID& aIID,
 
   return status;
 }
 
 nsresult
 CreateIFoo( void** result )
 // a typical factory function (that calls AddRef)
 {
-  printf(">>CreateIFoo() --> ");
   IFoo* foop = new IFoo;
-  printf("IFoo@%p\n", static_cast<void*>(foop));
 
   foop->AddRef();
   *result = foop;
 
-  printf("<<CreateIFoo()\n");
   return NS_OK;
 }
 
 void
 set_a_IFoo( nsCOMPtr<IFoo>* result )
 {
-  printf(">>set_a_IFoo()\n");
-  assert(result);
-
   nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
   *result = foop;
-  printf("<<set_a_IFoo()\n");
 }
 
 nsCOMPtr<IFoo>
 return_a_IFoo()
 {
-  printf(">>return_a_IFoo()\n");
   nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
-  printf("<<return_a_IFoo()\n");
   return foop;
 }
 
-
-
-
 #define NS_IBAR_IID \
 { 0x6f7652e1,  0xee43, 0x11d1, \
   { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
 
 class IBar : public IFoo
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IBAR_IID)
 
 public:
   IBar();
   virtual ~IBar();
 
   NS_IMETHOD QueryInterface( const nsIID&, void** );
+
+  static int total_destructions_;
+  static int total_queries_;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(IBar, NS_IBAR_IID)
 
+int IBar::total_destructions_;
+int IBar::total_queries_;
+
 IBar::IBar()
 {
-  printf("  new IBar@%p\n", static_cast<void*>(this));
 }
 
 IBar::~IBar()
 {
-  printf("IBar@%p::~IBar()\n", static_cast<void*>(this));
+  total_destructions_++;
 }
 
 nsresult
 IBar::QueryInterface( const nsID& aIID, void** aResult )
 {
-  printf("IBar@%p::QueryInterface()\n", static_cast<void*>(this));
+  total_queries_++;
+
   nsISupports* rawPtr = 0;
   nsresult status = NS_OK;
 
   if ( aIID.Equals(NS_GET_IID(IBar)) )
     rawPtr = this;
   else if ( aIID.Equals(NS_GET_IID(IFoo)) )
     rawPtr = static_cast<IFoo*>(this);
   else
@@ -243,24 +185,21 @@ IBar::QueryInterface( const nsID& aIID, 
 }
 
 
 
 nsresult
 CreateIBar( void** result )
   // a typical factory function (that calls AddRef)
 {
-  printf(">>CreateIBar() --> ");
   IBar* barp = new IBar;
-  printf("IBar@%p\n", static_cast<void*>(barp));
 
   barp->AddRef();
   *result = barp;
 
-  printf("<<CreateIBar()\n");
   return NS_OK;
 }
 
 void
 AnIFooPtrPtrContext( IFoo** )
 {
 }
 
@@ -269,288 +208,259 @@ AVoidPtrPtrContext( void** )
 {
 }
 
 void
 AnISupportsPtrPtrContext( nsISupports** )
 {
 }
 
-static
-nsresult
-TestBloat_Raw_Unsafe()
-{
-  IBar* barP = 0;
-  nsresult result = CreateIBar(reinterpret_cast<void**>(&barP));
+} // namespace TestCOMPtr
+
+using namespace TestCOMPtr;
 
-  if ( barP )
-  {
-    IFoo* fooP = 0;
-    if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), reinterpret_cast<void**>(&fooP)) ) )
-    {
-      fooP->print_totals();
-      NS_RELEASE(fooP);
-    }
+TEST(COMPtr, Bloat_Raw_Unsafe)
+{
+  // ER: I'm not sure what this is testing...
+  IBar* barP = 0;
+  nsresult rv = CreateIBar(reinterpret_cast<void**>(&barP));
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+  ASSERT_TRUE(barP);
 
-    NS_RELEASE(barP);
-  }
+  IFoo* fooP = 0;
+  rv = barP->QueryInterface(NS_GET_IID(IFoo), reinterpret_cast<void**>(&fooP));
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+  ASSERT_TRUE(fooP);
 
-  return result;
+  NS_RELEASE(fooP);
+  NS_RELEASE(barP);
 }
 
-
-static
-nsresult
-TestBloat_Smart()
+TEST(COMPtr, Bloat_Smart)
 {
+  // ER: I'm not sure what this is testing...
   nsCOMPtr<IBar> barP;
-  nsresult result = CreateIBar( getter_AddRefs(barP) );
-
-  nsCOMPtr<IFoo> fooP( do_QueryInterface(barP, &result) );
+  nsresult rv = CreateIBar( getter_AddRefs(barP) );
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+  ASSERT_TRUE(barP);
 
-  if ( fooP )
-    fooP->print_totals();
-
-  return result;
+  nsCOMPtr<IFoo> fooP( do_QueryInterface(barP, &rv) );
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+  ASSERT_TRUE(fooP);
 }
 
-void AddRefAndRelease()
+TEST(COMPtr, AddRefAndRelease)
 {
+  IFoo::total_constructions_ = 0;
+  IFoo::total_destructions_ = 0;
+  IBar::total_destructions_ = 0;
+
   {
-    printf("\n### Test  1: will a |nsCOMPtr| call |AddRef| on a pointer assigned into it?\n");
     nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
+    ASSERT_EQ(foop->refcount_, (unsigned int)1);
+    ASSERT_EQ(IFoo::total_constructions_, 1);
+    ASSERT_EQ(IFoo::total_destructions_, 0);
 
-    printf("\n### Test  2: will a |nsCOMPtr| |Release| its old pointer when a new one is assigned in?\n");
     foop = do_QueryInterface(new IFoo);
+    ASSERT_EQ(foop->refcount_, (unsigned int)1);
+    ASSERT_EQ(IFoo::total_constructions_, 2);
+    ASSERT_EQ(IFoo::total_destructions_, 1);
 
     // [Shouldn't compile] Is it a compile time error to try to |AddRef| by hand?
     //foop->AddRef();
 
     // [Shouldn't compile] Is it a compile time error to try to |Release| be hand?
     //foop->Release();
 
     // [Shouldn't compile] Is it a compile time error to try to |delete| an |nsCOMPtr|?
     //delete foop;
 
-    printf("\n### Test  3: can you |AddRef| if you must?\n");
     static_cast<IFoo*>(foop)->AddRef();
+    ASSERT_EQ(foop->refcount_, (unsigned int)2);
+    ASSERT_EQ(IFoo::total_constructions_, 2);
+    ASSERT_EQ(IFoo::total_destructions_, 1);
 
-    printf("\n### Test  4: can you |Release| if you must?\n");
     static_cast<IFoo*>(foop)->Release();
-
-    printf("\n### Test  5: will a |nsCOMPtr| |Release| when it goes out of scope?\n");
+    ASSERT_EQ(foop->refcount_, (unsigned int)1);
+    ASSERT_EQ(IFoo::total_constructions_, 2);
+    ASSERT_EQ(IFoo::total_destructions_, 1);
   }
 
+  ASSERT_EQ(IFoo::total_constructions_, 2);
+  ASSERT_EQ(IFoo::total_destructions_, 2);
+
   {
-    printf("\n### Test  6: will a |nsCOMPtr| call the correct destructor?\n");
     nsCOMPtr<IFoo> foop( do_QueryInterface(new IBar) );
     mozilla::Unused << foop;
   }
+
+  ASSERT_EQ(IBar::total_destructions_, 1);
 }
 
 void Comparison()
 {
-  {
-    printf("\n### Test  7: can you compare one |nsCOMPtr| with another [!=]?\n");
-
-    nsCOMPtr<IFoo> foo1p( do_QueryInterface(new IFoo) );
+  IFoo::total_constructions_ = 0;
+  IFoo::total_destructions_ = 0;
 
-    // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
-    //AnIFooPtrPtrContext(&foo1p);
-
-    // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
-    //AVoidPtrPtrContext(&foo1p);
-
+  {
+    nsCOMPtr<IFoo> foo1p( do_QueryInterface(new IFoo) );
     nsCOMPtr<IFoo> foo2p( do_QueryInterface(new IFoo) );
 
-    if ( foo1p != foo2p )
-      printf("foo1p != foo2p\n");
-    else
-      printf("foo1p == foo2p\n");
-
-
-    IFoo* raw_foo2p = foo2p.get();
+    ASSERT_EQ(IFoo::total_constructions_, 2);
 
-    printf("\n### Test  8: can you compare a |nsCOMPtr| with a raw interface pointer [!=]?\n");
-    if ( foo1p.get() != raw_foo2p )
-      printf("foo1p != raw_foo2p\n");
-    else
-      printf("foo1p == raw_foo2p\n");
+    // Test != operator
+    ASSERT_NE(foo1p, foo2p);
+    ASSERT_NE(foo1p, foo2p.get());
 
-
-    printf("\n### Test  9: can you assign one |nsCOMPtr| into another?\n");
+    // Test == operator
     foo1p = foo2p;
 
-    printf("\n### Test 10: can you compare one |nsCOMPtr| with another [==]?\n");
-    if ( foo1p == foo2p )
-      printf("foo1p == foo2p\n");
-    else
-      printf("foo1p != foo2p\n");
+    ASSERT_EQ(IFoo::total_destructions_, 1);
 
-    printf("\n### Test 11: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
-    if ( raw_foo2p == foo2p.get() )
-      printf("raw_foo2p == foo2p\n");
-    else
-      printf("raw_foo2p != foo2p\n");
+    ASSERT_EQ(foo1p, foo2p);
+    ASSERT_EQ(foo2p, foo2p.get());
+    ASSERT_EQ(foo2p.get(), foo2p);
 
-#if 1
-    printf("\n### Test 11.5: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
-    if ( nsCOMPtr<IFoo>( raw_foo2p ) == foo2p )
-      printf("raw_foo2p == foo2p\n");
-    else
-      printf("raw_foo2p != foo2p\n");
-#endif
+    // Test () operator
+    ASSERT_TRUE(foo1p);
 
-    printf("\n### Test 12: bare pointer test?\n");
-    if ( foo1p )
-      printf("foo1p is not NULL\n");
-    else
-      printf("foo1p is NULL\n");
+    ASSERT_EQ(foo1p->refcount_, (unsigned int)2);
+    ASSERT_EQ(foo2p->refcount_, (unsigned int)2);
+  }
 
-#if 0
-    if ( foo1p == 1 )
-      printf("foo1p allowed compare with in\n");
-#endif
-
-    printf("\n### Test 13: how about when two |nsCOMPtr|s referring to the same object go out of scope?\n");
-  }
+  ASSERT_EQ(IFoo::total_destructions_, 2);
 }
 
 void DontAddRef()
 {
   {
-    printf("\n### Test 14,15 ...setup...\n");
     IFoo* raw_foo1p = new IFoo;
     raw_foo1p->AddRef();
 
     IFoo* raw_foo2p = new IFoo;
     raw_foo2p->AddRef();
 
-    printf("\n### Test 14: what if I don't want to |AddRef| when I construct?\n");
     nsCOMPtr<IFoo> foo1p( dont_AddRef(raw_foo1p) );
-    //nsCOMPtr<IFoo> foo1p = dont_AddRef(raw_foo1p);
+    ASSERT_EQ(raw_foo1p, foo1p);
+    ASSERT_EQ(foo1p->refcount_, (unsigned int)1);
 
-    printf("\n### Test 15: what if I don't want to |AddRef| when I assign in?\n");
     nsCOMPtr<IFoo> foo2p;
     foo2p = dont_AddRef(raw_foo2p);
+    ASSERT_EQ(raw_foo2p, foo2p);
+    ASSERT_EQ(foo2p->refcount_, (unsigned int)1);
   }
 }
 
-void AssignmentHelpers()
+TEST(COMPtr, AssignmentHelpers)
 {
-  {
-    printf("\n### setup for Test 16\n");
-    nsCOMPtr<IFoo> foop;
-    printf("### Test 16: basic parameter behavior?\n");
-    CreateIFoo( nsGetterAddRefs<IFoo>(foop) );
-  }
-  printf("### End Test 16\n");
-
+  IFoo::total_constructions_ = 0;
+  IFoo::total_destructions_ = 0;
 
   {
-    printf("\n### setup for Test 17\n");
     nsCOMPtr<IFoo> foop;
-    printf("### Test 17: basic parameter behavior, using the short form?\n");
+    ASSERT_FALSE(foop);
+    CreateIFoo( nsGetterAddRefs<IFoo>(foop) );
+    ASSERT_TRUE(foop);
+  }
+
+  ASSERT_EQ(IFoo::total_constructions_, 1);
+  ASSERT_EQ(IFoo::total_destructions_, 1);
+
+  {
+    nsCOMPtr<IFoo> foop;
+    ASSERT_FALSE(foop);
     CreateIFoo( getter_AddRefs(foop) );
+    ASSERT_TRUE(foop);
   }
-  printf("### End Test 17\n");
 
+  ASSERT_EQ(IFoo::total_constructions_, 2);
+  ASSERT_EQ(IFoo::total_destructions_, 2);
 
   {
-    printf("\n### setup for Test 18, 19\n");
     nsCOMPtr<IFoo> foop;
-    printf("### Test 18: reference parameter behavior?\n");
+    ASSERT_FALSE(foop);
     set_a_IFoo(address_of(foop));
+    ASSERT_TRUE(foop);
+
+    ASSERT_EQ(IFoo::total_constructions_, 3);
+    ASSERT_EQ(IFoo::total_destructions_, 2);
 
-    printf("### Test 19: return value behavior?\n");
     foop = return_a_IFoo();
+    ASSERT_TRUE(foop);
+
+    ASSERT_EQ(IFoo::total_constructions_, 4);
+    ASSERT_EQ(IFoo::total_destructions_, 3);
   }
-  printf("### End Test 18, 19\n");
+
+  ASSERT_EQ(IFoo::total_constructions_, 4);
+  ASSERT_EQ(IFoo::total_destructions_, 4);
 
   {
-    printf("\n### setup for Test 23\n");
     nsCOMPtr<IFoo> fooP( do_QueryInterface(new IFoo) );
+    ASSERT_TRUE(fooP);
+
+    ASSERT_EQ(IFoo::total_constructions_, 5);
+    ASSERT_EQ(IFoo::total_destructions_, 4);
 
-    printf("### Test 23: does |forget| avoid an AddRef/Release when assigning to another nsCOMPtr?\n");
     nsCOMPtr<IFoo> fooP2( fooP.forget() );
+    ASSERT_TRUE(fooP2);
+
+    ASSERT_EQ(IFoo::total_constructions_, 5);
+    ASSERT_EQ(IFoo::total_destructions_, 4);
   }
-  printf("### End Test 23\n");
+
+  ASSERT_EQ(IFoo::total_constructions_, 5);
+  ASSERT_EQ(IFoo::total_destructions_, 5);
 }
 
-void QueryInterface()
+TEST(COMPtr, QueryInterface)
 {
-  {
-    printf("\n### setup for Test 20\n");
-    nsCOMPtr<IFoo> fooP;
-
-    printf("### Test 20: is |QueryInterface| called on assigning in a raw pointer?\n");
-    fooP = do_QueryInterface(new IFoo);
-  }
-  printf("### End Test 20\n");
+  IFoo::total_queries_ = 0;
+  IBar::total_queries_ = 0;
 
   {
-    printf("\n### setup for Test 21\n");
     nsCOMPtr<IFoo> fooP;
+    ASSERT_FALSE(fooP);
     fooP = do_QueryInterface(new IFoo);
+    ASSERT_TRUE(fooP);
+    ASSERT_EQ(IFoo::total_queries_, 1);
 
     nsCOMPtr<IFoo> foo2P;
 
-    printf("### Test 21: is |QueryInterface| _not_ called when assigning in a smart-pointer of the same type?\n");
+    // Test that |QueryInterface| _not_ called when assigning a smart-pointer
+    // of the same type.);
     foo2P = fooP;
+    ASSERT_EQ(IFoo::total_queries_, 1);
   }
-  printf("### End Test 21\n");
 
   {
-    printf("\n### setup for Test 22\n");
     nsCOMPtr<IBar> barP( do_QueryInterface(new IBar) );
-
-    printf("### Test 22: is |QueryInterface| called when assigning in a smart-pointer of a different type?\n");
+    ASSERT_EQ(IBar::total_queries_, 1);
 
+    // Test that |QueryInterface| is called when assigning a smart-pointer of
+    // a different type.
     nsCOMPtr<IFoo> fooP( do_QueryInterface(barP) );
-    if ( fooP )
-      printf("an IBar* is an IFoo*\n");
+    ASSERT_EQ(IBar::total_queries_, 2);
+    ASSERT_EQ(IFoo::total_queries_, 1);
+    ASSERT_TRUE(fooP);
   }
-  printf("### End Test 22\n");
 }
 
-void GetterConversions()
+TEST(COMPtr, GetterConversions)
 {
+  // This is just a compilation test. We add a few asserts to keep gtest happy.
   {
     nsCOMPtr<IFoo> fooP;
+    ASSERT_FALSE(fooP);
 
     AnIFooPtrPtrContext( getter_AddRefs(fooP) );
     AVoidPtrPtrContext( getter_AddRefs(fooP) );
   }
 
 
   {
     nsCOMPtr<nsISupports> supportsP;
+    ASSERT_FALSE(supportsP);
 
     AVoidPtrPtrContext( getter_AddRefs(supportsP) );
     AnISupportsPtrPtrContext( getter_AddRefs(supportsP) );
   }
 }
-
-nsCOMPtr<IFoo> gFoop;
-
-int
-main()
-{
-  printf(">>main()\n");
-
-  printf("sizeof(nsCOMPtr<IFoo>) --> %u\n", unsigned(sizeof(nsCOMPtr<IFoo>)));
-
-  TestBloat_Raw_Unsafe();
-  TestBloat_Smart();
-
-  AddRefAndRelease();
-  Comparison();
-  DontAddRef();
-  AssignmentHelpers();
-  QueryInterface();
-  GetterConversions();
-
-  printf("\n### Test 24: will a static |nsCOMPtr| |Release| before program termination?\n");
-  gFoop = do_QueryInterface(new IFoo);
-
-  printf("<<main()\n");
-  return 0;
-}
--- a/xpcom/tests/gtest/moz.build
+++ b/xpcom/tests/gtest/moz.build
@@ -34,15 +34,16 @@ UNIFIED_SOURCES += [
     'TestUTF.cpp',
     'TestXPIDLString.cpp',
 ]
 
 # Compile TestAllocReplacement separately so Windows headers don't pollute
 # the global namespace for other files.
 SOURCES += [
     'TestAllocReplacement.cpp',
+    'TestCOMPtr.cpp', # Redefines IFoo and IBar
 ]
 
 LOCAL_INCLUDES += [
     '../../base',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
--- a/xpcom/tests/moz.build
+++ b/xpcom/tests/moz.build
@@ -41,17 +41,16 @@ if CONFIG['OS_TARGET'] == 'WINNT':
 if CONFIG['WRAP_STL_INCLUDES'] and not CONFIG['CLANG_CL']:
     GeckoSimplePrograms([
         'TestSTLWrappers',
     ])
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 
 GeckoCppUnitTests([
-    'TestCOMPtr',
     'TestCOMPtrEq',
     'TestFile',
     'TestHashtables',
     'TestID',
     'TestNsRefPtr',
     'TestObserverArray',
     'TestObserverService',
     'TestStringAPI',