Index: chrome/test/out_of_proc_test_runner.cc |
diff --git a/chrome/test/out_of_proc_test_runner.cc b/chrome/test/out_of_proc_test_runner.cc |
index aef88836d30a7297f56e466f4c1bdfa13a18aa5f..6a9291356e8f8c7ec6a93b61e980fe23bb4e88aa 100644 |
--- a/chrome/test/out_of_proc_test_runner.cc |
+++ b/chrome/test/out_of_proc_test_runner.cc |
@@ -2,6 +2,8 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "chrome/test/out_of_proc_test_runner.h" |
+ |
#include <string> |
#include <vector> |
@@ -538,6 +540,44 @@ void PrintUsage() { |
} // namespace |
+namespace test { |
+ |
+// Note that we cannot use the Singleton or LazyInstance here because the |
+// registration happens at linker-initialization, and we cannot rely on |
+// AtExitManager being available yet. The life cycle of |
+// |s_test_callback_registry| is from linker init through main (below) calling |
+// CallTestCallbacksAndClear. |
+typedef std::vector<RegisterTestCallback*> CallbackRegistry; |
+CallbackRegistry* s_callback_registry = NULL; |
+ |
+RegisterTestCallback::RegisterTestCallback() {} |
+ |
+RegisterTestCallback::~RegisterTestCallback() {} |
+ |
+void AddRegisterTestCallback(RegisterTestCallback* callback) { |
+ if (!s_callback_registry) |
+ s_callback_registry = new CallbackRegistry(); |
+ |
+ s_callback_registry->push_back(callback); |
+} |
+ |
+void CallRegisterTestCallbacksAndClear() { |
+ // |s_callback_registry| will only be non-NULL if tests are registered. |
+ if (!s_callback_registry) |
+ return; |
+ |
+ for (CallbackRegistry::const_iterator it = s_callback_registry->begin(); |
+ it != s_callback_registry->end(); ++it) { |
+ (*it)->RegisterTest(); |
+ delete *it; |
+ } |
+ s_callback_registry->clear(); |
+ delete s_callback_registry; |
+ s_callback_registry = NULL; |
+} |
+ |
+} // namespace test |
+ |
int main(int argc, char** argv) { |
#if defined(OS_MACOSX) |
chrome_browser_application_mac::RegisterBrowserCrApp(); |
@@ -551,6 +591,17 @@ int main(int argc, char** argv) { |
return 0; |
} |
+ // The exit manager is in charge of calling the dtors of singleton objects. |
+ // On Windows, the call to ChromeMain() below will construct one for the |
+ // chrome.dll module, but that global is not shared with this module, so if |
+ // chrome.dll calls back out to this module and the called code uses a |
+ // singleton, we'll need this. On other platforms, ChromeMain() isn't called |
+ // at all below, so we instantiate a TestSuite which contains an exit manager |
+ // for any code after this point. Any callbacks for test registry are called |
+ // afterwards in case they also need an exit manager. |
+ ChromeTestSuite test_suite(argc, argv); |
+ test::CallRegisterTestCallbacksAndClear(); |
+ |
// TODO(pkasting): This "single_process vs. single-process" design is terrible |
// UI. Instead, there should be some sort of signal flag on the command line, |
// with all subsequent arguments passed through to the underlying browser. |
@@ -576,21 +627,9 @@ int main(int argc, char** argv) { |
} |
} |
#endif |
- return ChromeTestSuite(argc, argv).Run(); |
+ return test_suite.Run(); |
} |
- // The exit manager is in charge of calling the dtors of singleton objects. |
- // On Windows, the call to ChromeMain() below will construct one for the |
- // chrome.dll module, but that global is not shared with this module, so if |
- // chrome.dll calls back out to this module and the called code uses a |
- // singleton, we'll need this. On other platforms, ChromeMain() isn't called |
- // at all below, so this is the lone exit manager for any code after this |
- // point. |
- // NOTE: We can't init this atop main() because ChromeTestSuite, as a subclass |
- // of TestSuite, creates one. So we wait until after the Run() call above to |
- // create the manager for the code path that _doesn't_ use ChromeTestSuite. |
- base::AtExitManager exit_manager; |
- |
#if defined(OS_WIN) |
if (command_line->HasSwitch(switches::kProcessType)) { |
// This is a child process, call ChromeMain. |