// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/test/base/chrome_test_suite.h" #if defined(OS_CHROMEOS) #include <stdio.h> #include <unistd.h> #endif #include "base/command_line.h" #include "base/memory/ref_counted.h" #include "base/metrics/stats_table.h" #include "base/path_service.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/chrome_extensions_client.h" #include "chrome/common/url_constants.h" #include "chrome/utility/chrome_content_utility_client.h" #include "content/public/test/test_launcher.h" #include "extensions/common/extension_paths.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_handle.h" #if defined(OS_ANDROID) #include "base/android/jni_android.h" #include "chrome/browser/android/chrome_jni_registrar.h" #include "net/android/net_jni_registrar.h" #include "ui/base/android/ui_base_jni_registrar.h" #include "ui/gfx/android/gfx_jni_registrar.h" #include "ui/gl/android/gl_jni_registrar.h" #endif #if defined(OS_CHROMEOS) #include "base/process/process_metrics.h" #include "chromeos/chromeos_paths.h" #endif #if defined(OS_MACOSX) #include "base/mac/bundle_locations.h" #include "base/mac/scoped_nsautorelease_pool.h" #if !defined(OS_IOS) #include "base/mac/mac_util.h" #include "chrome/browser/chrome_browser_application_mac.h" #endif // !defined(OS_IOS) #endif #if defined(OS_POSIX) #include "base/memory/shared_memory.h" #endif namespace { void RemoveSharedMemoryFile(const std::string& filename) { // Stats uses SharedMemory under the hood. On posix, this results in a file // on disk. #if defined(OS_POSIX) base::SharedMemory memory; memory.Delete(filename); #endif } bool IsCrosPythonProcess() { #if defined(OS_CHROMEOS) char buf[80]; int num_read = readlink(base::kProcSelfExe, buf, sizeof(buf) - 1); if (num_read == -1) return false; buf[num_read] = 0; const char kPythonPrefix[] = "/python"; return !strncmp(strrchr(buf, '/'), kPythonPrefix, sizeof(kPythonPrefix) - 1); #else return false; #endif // defined(OS_CHROMEOS) } // Initializes services needed by both unit tests and browser tests. // See also ChromeUnitTestSuite for additional services created for unit tests. class ChromeTestSuiteInitializer : public testing::EmptyTestEventListener { public: ChromeTestSuiteInitializer() { } virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE { content_client_.reset(new ChromeContentClient); content::SetContentClient(content_client_.get()); // TODO(ios): Bring this back once ChromeContentBrowserClient is building. #if !defined(OS_IOS) browser_content_client_.reset(new chrome::ChromeContentBrowserClient()); content::SetBrowserClientForTesting(browser_content_client_.get()); utility_content_client_.reset(new chrome::ChromeContentUtilityClient()); content::SetUtilityClientForTesting(utility_content_client_.get()); #endif } virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE { // TODO(ios): Bring this back once ChromeContentBrowserClient is building. #if !defined(OS_IOS) browser_content_client_.reset(); utility_content_client_.reset(); #endif content_client_.reset(); content::SetContentClient(NULL); } private: // Client implementations for the content module. scoped_ptr<ChromeContentClient> content_client_; // TODO(ios): Bring this back once ChromeContentBrowserClient is building. #if !defined(OS_IOS) scoped_ptr<chrome::ChromeContentBrowserClient> browser_content_client_; scoped_ptr<chrome::ChromeContentUtilityClient> utility_content_client_; #endif DISALLOW_COPY_AND_ASSIGN(ChromeTestSuiteInitializer); }; } // namespace ChromeTestSuite::ChromeTestSuite(int argc, char** argv) : content::ContentTestSuiteBase(argc, argv) { } ChromeTestSuite::~ChromeTestSuite() { } void ChromeTestSuite::Initialize() { #if defined(OS_MACOSX) base::mac::ScopedNSAutoreleasePool autorelease_pool; #if !defined(OS_IOS) chrome_browser_application_mac::RegisterBrowserCrApp(); #endif // !defined(OS_IOS) #endif #if defined(OS_ANDROID) // Register JNI bindings for android. gfx::android::RegisterJni(base::android::AttachCurrentThread()); net::android::RegisterJni(base::android::AttachCurrentThread()); ui::android::RegisterJni(base::android::AttachCurrentThread()); ui::gl::android::RegisterJni(base::android::AttachCurrentThread()); chrome::android::RegisterJni(base::android::AttachCurrentThread()); #endif chrome::RegisterPathProvider(); #if defined(OS_CHROMEOS) chromeos::RegisterPathProvider(); #endif if (!browser_dir_.empty()) { PathService::Override(base::DIR_EXE, browser_dir_); PathService::Override(base::DIR_MODULE, browser_dir_); } #if !defined(OS_IOS) extensions::RegisterPathProvider(); extensions::ExtensionsClient::Set( extensions::ChromeExtensionsClient::GetInstance()); // Only want to do this for unit tests. if (!content::GetCurrentTestLauncherDelegate()) { // For browser tests, this won't create the right object since // TestChromeWebUIControllerFactory is used. That's created and // registered in ChromeBrowserMainParts as in normal startup. content::WebUIControllerFactory::RegisterFactory( ChromeWebUIControllerFactory::GetInstance()); } #endif // Disable external libraries load if we are under python process in // ChromeOS. That means we are autotest and, if ASAN is used, // external libraries load crashes. content::ContentTestSuiteBase::set_external_libraries_enabled( !IsCrosPythonProcess()); // Initialize after overriding paths as some content paths depend on correct // values for DIR_EXE and DIR_MODULE. content::ContentTestSuiteBase::Initialize(); #if defined(OS_MACOSX) && !defined(OS_IOS) // Look in the framework bundle for resources. base::FilePath path; PathService::Get(base::DIR_EXE, &path); path = path.Append(chrome::kFrameworkName); base::mac::SetOverrideFrameworkBundlePath(path); #endif // Force unittests to run using en-US so if we test against string // output, it'll pass regardless of the system language. ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL); base::FilePath resources_pack_path; #if defined(OS_MACOSX) && !defined(OS_IOS) PathService::Get(base::DIR_MODULE, &resources_pack_path); resources_pack_path = resources_pack_path.Append(FILE_PATH_LITERAL("resources.pak")); #else PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); #endif ResourceBundle::GetSharedInstance().AddDataPackFromPath( resources_pack_path, ui::SCALE_FACTOR_NONE); stats_filename_ = base::StringPrintf("unit_tests-%d", base::GetCurrentProcId()); RemoveSharedMemoryFile(stats_filename_); stats_table_.reset(new base::StatsTable(stats_filename_, 20, 200)); base::StatsTable::set_current(stats_table_.get()); testing::TestEventListeners& listeners = testing::UnitTest::GetInstance()->listeners(); listeners.Append(new ChromeTestSuiteInitializer); } content::ContentClient* ChromeTestSuite::CreateClientForInitialization() { return new ChromeContentClient(); } void ChromeTestSuite::Shutdown() { ResourceBundle::CleanupSharedInstance(); #if defined(OS_MACOSX) && !defined(OS_IOS) base::mac::SetOverrideFrameworkBundle(NULL); #endif base::StatsTable::set_current(NULL); stats_table_.reset(); RemoveSharedMemoryFile(stats_filename_); base::TestSuite::Shutdown(); }