1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "webkit/support/webkit_support.h" 6 7 #include "base/command_line.h" 8 #include "base/debug/debugger.h" 9 #include "base/debug/stack_trace.h" 10 #include "base/logging.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/path_service.h" 13 #include "base/process/memory.h" 14 #include "base/run_loop.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "third_party/WebKit/public/web/WebCache.h" 17 #include "third_party/WebKit/public/web/WebKit.h" 18 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" 19 #include "url/url_util.h" 20 #include "webkit/child/webkitplatformsupport_impl.h" 21 #include "webkit/common/user_agent/user_agent.h" 22 #include "webkit/common/user_agent/user_agent_util.h" 23 #include "webkit/glue/webkit_glue.h" 24 #include "webkit/support/platform_support.h" 25 #include "webkit/support/test_webkit_platform_support.h" 26 27 #if defined(OS_ANDROID) 28 #include "base/test/test_support_android.h" 29 #endif 30 31 namespace { 32 33 // All fatal log messages (e.g. DCHECK failures) imply unit test failures 34 void UnitTestAssertHandler(const std::string& str) { 35 FAIL() << str; 36 } 37 38 void InitLogging() { 39 #if defined(OS_WIN) 40 if (!::IsDebuggerPresent()) { 41 UINT new_flags = SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX 42 | SEM_NOGPFAULTERRORBOX; 43 44 // Preserve existing error mode, as discussed at 45 // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx 46 UINT existing_flags = SetErrorMode(new_flags); 47 SetErrorMode(existing_flags | new_flags); 48 49 // Don't pop up dialog on assertion failure, log to stdout instead. 50 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); 51 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); 52 } 53 #endif 54 55 #if defined(OS_ANDROID) 56 // On Android we expect the log to appear in logcat. 57 base::InitAndroidTestLogging(); 58 #else 59 base::FilePath log_filename; 60 PathService::Get(base::DIR_EXE, &log_filename); 61 log_filename = log_filename.AppendASCII("DumpRenderTree.log"); 62 logging::LoggingSettings settings; 63 // Only log to a file. This prevents debugging output from disrupting 64 // whether or not we pass. 65 settings.logging_dest = logging::LOG_TO_FILE; 66 settings.log_file = log_filename.value().c_str(); 67 settings.delete_old = logging::DELETE_OLD_LOG_FILE; 68 logging::InitLogging(settings); 69 70 // We want process and thread IDs because we may have multiple processes. 71 const bool kProcessId = true; 72 const bool kThreadId = true; 73 const bool kTimestamp = true; 74 const bool kTickcount = true; 75 logging::SetLogItems(kProcessId, kThreadId, !kTimestamp, kTickcount); 76 #endif // else defined(OS_ANDROID) 77 } 78 79 class TestEnvironment { 80 public: 81 #if defined(OS_ANDROID) 82 // Android UI message loop goes through Java, so don't use it in tests. 83 typedef base::MessageLoop MessageLoopType; 84 #else 85 typedef base::MessageLoopForUI MessageLoopType; 86 #endif 87 88 TestEnvironment() { 89 logging::SetLogAssertHandler(UnitTestAssertHandler); 90 main_message_loop_.reset(new MessageLoopType); 91 92 // TestWebKitPlatformSupport must be instantiated after MessageLoopType. 93 webkit_platform_support_.reset(new TestWebKitPlatformSupport); 94 } 95 96 TestWebKitPlatformSupport* webkit_platform_support() const { 97 return webkit_platform_support_.get(); 98 } 99 100 private: 101 scoped_ptr<MessageLoopType> main_message_loop_; 102 scoped_ptr<TestWebKitPlatformSupport> webkit_platform_support_; 103 }; 104 105 TestEnvironment* test_environment; 106 107 } // namespace 108 109 namespace webkit_support { 110 111 void SetUpTestEnvironmentForUnitTests() { 112 base::debug::EnableInProcessStackDumping(); 113 base::EnableTerminationOnHeapCorruption(); 114 115 // Initialize the singleton CommandLine with fixed values. Some code refer to 116 // CommandLine::ForCurrentProcess(). We don't use the actual command-line 117 // arguments of DRT to avoid unexpected behavior change. 118 // 119 // webkit/glue/plugin/plugin_list_posix.cc checks --debug-plugin-loading. 120 // webkit/glue/plugin/plugin_list_win.cc checks --old-wmp. 121 // If DRT needs these flags, specify them in the following kFixedArguments. 122 const char* kFixedArguments[] = {"DumpRenderTree"}; 123 CommandLine::Init(arraysize(kFixedArguments), kFixedArguments); 124 125 WebKit::WebRuntimeFeatures::enableStableFeatures(true); 126 WebKit::WebRuntimeFeatures::enableExperimentalFeatures(true); 127 WebKit::WebRuntimeFeatures::enableTestOnlyFeatures(true); 128 129 // Explicitly initialize the GURL library before spawning any threads. 130 // Otherwise crash may happend when different threads try to create a GURL 131 // at same time. 132 url_util::Initialize(); 133 webkit_support::BeforeInitialize(); 134 test_environment = new TestEnvironment; 135 webkit_support::AfterInitialize(); 136 webkit_glue::SetUserAgent(webkit_glue::BuildUserAgentFromProduct( 137 "DumpRenderTree/0.0.0.0"), false); 138 } 139 140 void TearDownTestEnvironment() { 141 // Flush any remaining messages before we kill ourselves. 142 // http://code.google.com/p/chromium/issues/detail?id=9500 143 base::RunLoop().RunUntilIdle(); 144 145 BeforeShutdown(); 146 if (RunningOnValgrind()) 147 WebKit::WebCache::clear(); 148 WebKit::shutdown(); 149 delete test_environment; 150 test_environment = NULL; 151 AfterShutdown(); 152 logging::CloseLogFile(); 153 } 154 155 } // namespace webkit_support 156