Allow multiple AtExitManagers to be chained in a stack, this allows much easier testing for code that is expecting to be run via an AtExitManager.  This actually cleaned up a lot of the at exit code.

Clean up singleton_dll_unittest.  It is no longer windows specific DLL, and now is much simpler, and builds and runs cross platform.

BUG=1314043

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@646 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/singleton_unittest.cc b/base/singleton_unittest.cc
index 5d21593..167fa78c 100644
--- a/base/singleton_unittest.cc
+++ b/base/singleton_unittest.cc
@@ -27,54 +27,99 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "testing/gtest/include/gtest/gtest.h"
-#include "base/singleton_dll_unittest.h"
+#include "base/at_exit.h"
 #include "base/file_util.h"
 #include "base/path_service.h"
+#include "base/singleton.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class ShadowingAtExitManager : public base::AtExitManager {
+ public:
+  ShadowingAtExitManager() : AtExitManager(true) { }
+};
+
+COMPILE_ASSERT(DefaultSingletonTraits<int>::kRegisterAtExit == true, a);
+
+template<typename Type>
+struct LockTrait : public DefaultSingletonTraits<Type> {
+};
+
+struct Init5Trait : public DefaultSingletonTraits<int> {
+  static int* New() {
+    return new int(5);
+  }
+};
+
+typedef void (*CallbackFunc)();
+
+struct CallbackTrait : public DefaultSingletonTraits<CallbackFunc> {
+  static void Delete(CallbackFunc* p) {
+    if (*p)
+      (*p)();
+    DefaultSingletonTraits<CallbackFunc>::Delete(p);
+  }
+};
+
+struct NoLeakTrait : public CallbackTrait {
+};
+
+struct LeakTrait : public CallbackTrait {
+  static const bool kRegisterAtExit = false;
+};
+
+int* SingletonInt1() {
+  return Singleton<int>::get();
+}
+
+int* SingletonInt2() {
+  // Force to use a different singleton than SingletonInt1.
+  return Singleton<int, DefaultSingletonTraits<int> >::get();
+}
+
+class DummyDifferentiatingClass {
+};
+
+int* SingletonInt3() {
+  // Force to use a different singleton than SingletonInt1 and SingletonInt2.
+  // Note that any type can be used; int, float, std::wstring...
+  return Singleton<int, DefaultSingletonTraits<int>,
+                   DummyDifferentiatingClass>::get();
+}
+
+int* SingletonInt4() {
+  return Singleton<int, LockTrait<int> >::get();
+}
+
+int* SingletonInt5() {
+  return Singleton<int, Init5Trait>::get();
+}
+
+void SingletonNoLeak(CallbackFunc CallOnQuit) {
+  *Singleton<CallbackFunc, NoLeakTrait>::get() = CallOnQuit;
+}
+
+void SingletonLeak(CallbackFunc CallOnQuit) {
+  *Singleton<CallbackFunc, LeakTrait>::get() = CallOnQuit;
+}
+
+CallbackFunc* GetLeakySingleton() {
+  return Singleton<CallbackFunc, LeakTrait>::get();
+}
+
+}  // namespace
 
 class SingletonTest : public testing::Test {
  public:
-  SingletonTest() {
-  }
+  SingletonTest() { }
 
   virtual void SetUp() {
-    module_ = NULL;
     non_leak_called_ = false;
     leaky_called_ = false;
   }
 
-  virtual void TearDown() {
-    ASSERT_FALSE(module_);
-  }
-
-  static bool IsTestCaseDisabled() {
-    // Check if the dll exists beside the executable.
-    std::wstring path;
-    PathService::Get(base::DIR_EXE, &path);
-    file_util::AppendToPath(&path, kLibrary);
-    return !file_util::PathExists(path);
-  }
-
  protected:
-  void LoadLibrary() {
-    ASSERT_FALSE(module_);
-    module_ = ::LoadLibrary(kLibrary);
-    ASSERT_TRUE(module_ != NULL);
-  }
-
-  void FreeLibrary() {
-    ASSERT_TRUE(module_ != NULL);
-    ASSERT_TRUE(::FreeLibrary(module_));
-    module_ = NULL;
-  }
-
-  template<typename T>
-  void GetProc(const char* function_name, T* function) {
-    ASSERT_TRUE(module_ != NULL);
-    *function = reinterpret_cast<T>(GetProcAddress(module_, function_name));
-    ASSERT_TRUE(*function);
-  }
-
   void VerifiesCallbacks() {
     EXPECT_TRUE(non_leak_called_);
     EXPECT_FALSE(leaky_called_);
@@ -89,17 +134,15 @@
     leaky_called_ = false;
   }
 
-  static void WINAPI CallbackNoLeak() {
+  static void CallbackNoLeak() {
     non_leak_called_ = true;
   }
 
-  static void WINAPI CallbackLeak() {
+  static void CallbackLeak() {
     leaky_called_ = true;
   }
 
  private:
-  static const wchar_t* const kLibrary;
-  HMODULE module_;
   static bool non_leak_called_;
   static bool leaky_called_;
 };
@@ -107,48 +150,35 @@
 bool SingletonTest::non_leak_called_ = false;
 bool SingletonTest::leaky_called_ = false;
 
-const wchar_t* const SingletonTest::kLibrary = L"singleton_dll_unittest.dll";
-
 TEST_F(SingletonTest, Basic) {
-  if (IsTestCaseDisabled())
-    return;
-
   int* singleton_int_1;
   int* singleton_int_2;
   int* singleton_int_3;
   int* singleton_int_4;
   int* singleton_int_5;
-  CallBackFunc* leaky_singleton;
+  CallbackFunc* leaky_singleton;
 
-  LoadLibrary();
   {
-    SingletonIntFunc sut1;
-    SingletonIntFunc sut2;
-    SingletonIntFunc sut3;
-    SingletonIntFunc sut4;
-    SingletonIntFunc sut5;
+    ShadowingAtExitManager sem;
     {
-      GetProc("SingletonInt1", &sut1);
-      singleton_int_1 = sut1();
+      singleton_int_1 = SingletonInt1();
     }
     // Ensure POD type initialization.
     EXPECT_EQ(*singleton_int_1, 0);
     *singleton_int_1 = 1;
 
-    EXPECT_EQ(singleton_int_1, sut1());
+    EXPECT_EQ(singleton_int_1, SingletonInt1());
     EXPECT_EQ(*singleton_int_1, 1);
 
     {
-      GetProc("SingletonInt2", &sut2);
-      singleton_int_2 = sut2();
+      singleton_int_2 = SingletonInt2();
     }
     // Same instance that 1.
     EXPECT_EQ(*singleton_int_2, 1);
     EXPECT_EQ(singleton_int_1, singleton_int_2);
 
     {
-      GetProc("SingletonInt3", &sut3);
-      singleton_int_3 = sut3();
+      singleton_int_3 = SingletonInt3();
     }
     // Different instance than 1 and 2.
     EXPECT_EQ(*singleton_int_3, 0);
@@ -158,8 +188,7 @@
     EXPECT_EQ(*singleton_int_2, 1);
 
     {
-      GetProc("SingletonInt4", &sut4);
-      singleton_int_4 = sut4();
+      singleton_int_4 = SingletonInt4();
     }
     // Use a lock for creation. Not really tested at length.
     EXPECT_EQ(*singleton_int_4, 0);
@@ -168,60 +197,38 @@
     EXPECT_NE(singleton_int_3, singleton_int_4);
 
     {
-      GetProc("SingletonInt5", &sut5);
-      singleton_int_5 = sut5();
+      singleton_int_5 = SingletonInt5();
     }
     // Is default initialized to 5.
     EXPECT_EQ(*singleton_int_5, 5);
     EXPECT_NE(singleton_int_1, singleton_int_5);
     EXPECT_NE(singleton_int_3, singleton_int_5);
     EXPECT_NE(singleton_int_4, singleton_int_5);
-#ifdef _DEBUG
-    // In release, the optimizer may make both exports use exactly the same
-    // code.
-    EXPECT_NE(sut1, sut2);
-#endif
-    EXPECT_NE(sut2, sut3);
-    EXPECT_NE(sut3, sut4);
-    EXPECT_NE(sut4, sut5);
 
-    LeakySingletonFunc noleak;
-    GetProc("SingletonNoLeak", &noleak);
-    noleak(&CallbackNoLeak);
-    LeakySingletonFunc leak;
-    GetProc("SingletonLeak", &leak);
-    leak(&CallbackLeak);
-    GetLeakySingletonFunc get_leaky;
-    GetProc("GetLeakySingleton", &get_leaky);
-    leaky_singleton = get_leaky();
+    SingletonNoLeak(&CallbackNoLeak);
+    SingletonLeak(&CallbackLeak);
+    leaky_singleton = GetLeakySingleton();
     EXPECT_TRUE(leaky_singleton);
   }
-  FreeLibrary();
 
   // Verify that only the expected callback has been called.
   VerifiesCallbacks();
   // Delete the leaky singleton. It is interesting to note that Purify does
   // *not* detect the leak when this call is commented out. :(
-  EXPECT_TRUE(CustomAllocTrait<CallBackFunc>::Delete(leaky_singleton));
+  DefaultSingletonTraits<CallbackFunc>::Delete(leaky_singleton);
 
-  LoadLibrary();
   {
+    ShadowingAtExitManager sem;
     // Verifiy that the variables were reset.
     {
-      SingletonIntFunc sut1;
-      GetProc("SingletonInt1", &sut1);
-      singleton_int_1 = sut1();
+      singleton_int_1 = SingletonInt1();
       EXPECT_EQ(*singleton_int_1, 0);
     }
     {
-      SingletonIntFunc sut5;
-      GetProc("SingletonInt5", &sut5);
-      singleton_int_5 = sut5();
+      singleton_int_5 = SingletonInt5();
       EXPECT_EQ(*singleton_int_5, 5);
     }
   }
   // The leaky singleton shouldn't leak since SingletonLeak has not been called.
-  FreeLibrary();
-
   VerifiesCallbacksNotCalled();
 }