| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Creates an instance of the test_shell. | 5 // Creates an instance of the test_shell. |
| 6 | 6 |
| 7 #include <stdlib.h> // required by _set_abort_behavior | 7 #include <stdlib.h> // required by _set_abort_behavior |
| 8 | 8 |
| 9 #include <windows.h> | 9 #include <windows.h> |
| 10 #include <commctrl.h> | 10 #include <commctrl.h> |
| 11 | 11 |
| 12 #include "base/at_exit.h" | 12 #include "base/at_exit.h" |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/event_recorder.h" | 15 #include "base/event_recorder.h" |
| 16 #include "base/file_util.h" | 16 #include "base/file_util.h" |
| 17 #include "base/gfx/native_theme.h" | 17 #include "base/gfx/native_theme.h" |
| 18 #include "base/icu_util.h" | 18 #include "base/icu_util.h" |
| 19 #include "base/memory_debug.h" | 19 #include "base/memory_debug.h" |
| 20 #include "base/message_loop.h" | 20 #include "base/message_loop.h" |
| 21 #include "base/path_service.h" | 21 #include "base/path_service.h" |
| 22 #include "base/process_util.h" |
| 22 #include "base/resource_util.h" | 23 #include "base/resource_util.h" |
| 23 #include "base/stack_container.h" | 24 #include "base/stack_container.h" |
| 24 #include "base/stats_table.h" | 25 #include "base/stats_table.h" |
| 25 #include "base/string_util.h" | 26 #include "base/string_util.h" |
| 26 #include "base/trace_event.h" | 27 #include "base/trace_event.h" |
| 27 #include "breakpad/src/client/windows/handler/exception_handler.h" | 28 #include "breakpad/src/client/windows/handler/exception_handler.h" |
| 28 #include "net/base/cookie_monster.h" | 29 #include "net/base/cookie_monster.h" |
| 29 #include "net/base/net_module.h" | 30 #include "net/base/net_module.h" |
| 30 #include "net/http/http_cache.h" | 31 #include "net/http/http_cache.h" |
| 31 #include "net/http/http_network_layer.h" | 32 #include "net/http/http_network_layer.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 newPath->append(L".dmp"); | 105 newPath->append(L".dmp"); |
| 105 | 106 |
| 106 // May use the heap, but oh well. If this fails, we'll just have the | 107 // May use the heap, but oh well. If this fails, we'll just have the |
| 107 // original dump file lying around. | 108 // original dump file lying around. |
| 108 _wrename(origPath->c_str(), newPath->c_str()); | 109 _wrename(origPath->c_str(), newPath->c_str()); |
| 109 | 110 |
| 110 return false; | 111 return false; |
| 111 } | 112 } |
| 112 } // namespace | 113 } // namespace |
| 113 | 114 |
| 114 int main(int argc, char* argv[]) | 115 int main(int argc, char* argv[]) { |
| 115 { | 116 process_util::EnableTerminationOnHeapCorruption(); |
| 116 #ifdef _CRTDBG_MAP_ALLOC | 117 #ifdef _CRTDBG_MAP_ALLOC |
| 117 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); | 118 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); |
| 118 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); | 119 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); |
| 119 #endif | 120 #endif |
| 120 // Some tests may use base::Singleton<>, thus we need to instanciate | 121 // Some tests may use base::Singleton<>, thus we need to instanciate |
| 121 // the AtExitManager or else we will leak objects. | 122 // the AtExitManager or else we will leak objects. |
| 122 base::AtExitManager at_exit_manager; | 123 base::AtExitManager at_exit_manager; |
| 123 | 124 |
| 124 CommandLine parsed_command_line; | 125 CommandLine parsed_command_line; |
| 125 if (parsed_command_line.HasSwitch(test_shell::kStartupDialog)) | 126 if (parsed_command_line.HasSwitch(test_shell::kStartupDialog)) |
| 126 MessageBox(NULL, L"attach to me?", L"test_shell", MB_OK); | 127 MessageBox(NULL, L"attach to me?", L"test_shell", MB_OK); |
| 127 //webkit_glue::SetLayoutTestMode(true); | 128 //webkit_glue::SetLayoutTestMode(true); |
| 128 | 129 |
| 129 // Allocate a message loop for this thread. Although it is not used | 130 // Allocate a message loop for this thread. Although it is not used |
| 130 // directly, its constructor sets up some necessary state. | 131 // directly, its constructor sets up some necessary state. |
| 131 MessageLoopForUI main_message_loop; | 132 MessageLoopForUI main_message_loop; |
| 132 | 133 |
| 133 bool suppress_error_dialogs = | 134 bool suppress_error_dialogs = |
| 134 (GetEnvironmentVariable(L"CHROME_HEADLESS", NULL, 0) || | 135 (GetEnvironmentVariable(L"CHROME_HEADLESS", NULL, 0) || |
| 135 parsed_command_line.HasSwitch(test_shell::kNoErrorDialogs) || | 136 parsed_command_line.HasSwitch(test_shell::kNoErrorDialogs) || |
| 136 parsed_command_line.HasSwitch(test_shell::kLayoutTests)); | 137 parsed_command_line.HasSwitch(test_shell::kLayoutTests)); |
| 137 TestShell::InitLogging(suppress_error_dialogs); | 138 TestShell::InitLogging(suppress_error_dialogs); |
| 138 | 139 |
| 139 // Suppress abort message in v8 library in debugging mode. | 140 // Suppress abort message in v8 library in debugging mode. |
| 140 // V8 calls abort() when it hits assertion errors. | 141 // V8 calls abort() when it hits assertion errors. |
| 141 if (suppress_error_dialogs) { | 142 if (suppress_error_dialogs) { |
| 142 _set_abort_behavior(0, _WRITE_ABORT_MSG); | 143 _set_abort_behavior(0, _WRITE_ABORT_MSG); |
| 143 } | 144 } |
| 144 | 145 |
| 145 if (parsed_command_line.HasSwitch(test_shell::kEnableTracing)) | 146 if (parsed_command_line.HasSwitch(test_shell::kEnableTracing)) |
| 146 base::TraceLog::StartTracing(); | 147 base::TraceLog::StartTracing(); |
| 147 | 148 |
| 148 // Make the selection of network stacks early on before any consumers try to | 149 // Make the selection of network stacks early on before any consumers try to |
| 149 // issue HTTP requests. | 150 // issue HTTP requests. |
| 150 if (parsed_command_line.HasSwitch(test_shell::kUseNewHttp)) | 151 if (parsed_command_line.HasSwitch(test_shell::kUseNewHttp)) |
| 151 net::HttpNetworkLayer::UseWinHttp(false); | 152 net::HttpNetworkLayer::UseWinHttp(false); |
| 152 | 153 |
| 153 bool layout_test_mode = | 154 bool layout_test_mode = |
| 154 parsed_command_line.HasSwitch(test_shell::kLayoutTests); | 155 parsed_command_line.HasSwitch(test_shell::kLayoutTests); |
| 155 | 156 |
| 156 net::HttpCache::Mode cache_mode = net::HttpCache::NORMAL; | 157 net::HttpCache::Mode cache_mode = net::HttpCache::NORMAL; |
| 157 bool playback_mode = | 158 bool playback_mode = |
| 158 parsed_command_line.HasSwitch(test_shell::kPlaybackMode); | 159 parsed_command_line.HasSwitch(test_shell::kPlaybackMode); |
| 159 bool record_mode = | 160 bool record_mode = |
| 160 parsed_command_line.HasSwitch(test_shell::kRecordMode); | 161 parsed_command_line.HasSwitch(test_shell::kRecordMode); |
| 161 | 162 |
| 162 if (playback_mode) | 163 if (playback_mode) |
| 163 cache_mode = net::HttpCache::PLAYBACK; | 164 cache_mode = net::HttpCache::PLAYBACK; |
| 164 else if (record_mode) | 165 else if (record_mode) |
| 165 cache_mode = net::HttpCache::RECORD; | 166 cache_mode = net::HttpCache::RECORD; |
| 166 | 167 |
| 167 if (layout_test_mode || | 168 if (layout_test_mode || |
| 168 parsed_command_line.HasSwitch(test_shell::kEnableFileCookies)) | 169 parsed_command_line.HasSwitch(test_shell::kEnableFileCookies)) |
| 169 net::CookieMonster::EnableFileScheme(); | 170 net::CookieMonster::EnableFileScheme(); |
| 170 | 171 |
| 171 std::wstring cache_path = | 172 std::wstring cache_path = |
| 172 parsed_command_line.GetSwitchValue(test_shell::kCacheDir); | 173 parsed_command_line.GetSwitchValue(test_shell::kCacheDir); |
| 173 if (cache_path.empty()) { | 174 if (cache_path.empty()) { |
| 174 PathService::Get(base::DIR_EXE, &cache_path); | 175 PathService::Get(base::DIR_EXE, &cache_path); |
| 175 file_util::AppendToPath(&cache_path, L"cache"); | 176 file_util::AppendToPath(&cache_path, L"cache"); |
| 176 } | 177 } |
| 177 | 178 |
| 178 // Initializing with a default context, which means no on-disk cookie DB, | 179 // Initializing with a default context, which means no on-disk cookie DB, |
| 179 // and no support for directory listings. | 180 // and no support for directory listings. |
| 180 SimpleResourceLoaderBridge::Init( | 181 SimpleResourceLoaderBridge::Init( |
| 181 new TestShellRequestContext(cache_path, cache_mode)); | 182 new TestShellRequestContext(cache_path, cache_mode)); |
| 182 | 183 |
| 183 // Load ICU data tables | 184 // Load ICU data tables |
| 184 icu_util::Initialize(); | 185 icu_util::Initialize(); |
| 185 | 186 |
| 186 // Config the network module so it has access to a limited set of resources. | 187 // Config the network module so it has access to a limited set of resources. |
| 187 net::NetModule::SetResourceProvider(NetResourceProvider); | 188 net::NetModule::SetResourceProvider(NetResourceProvider); |
| 188 | 189 |
| 189 INITCOMMONCONTROLSEX InitCtrlEx; | 190 INITCOMMONCONTROLSEX InitCtrlEx; |
| 190 | 191 |
| 191 InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); | 192 InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); |
| 192 InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; | 193 InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; |
| 193 InitCommonControlsEx(&InitCtrlEx); | 194 InitCommonControlsEx(&InitCtrlEx); |
| 194 | 195 |
| 195 bool interactive = !layout_test_mode; | 196 bool interactive = !layout_test_mode; |
| 196 TestShell::InitializeTestShell(interactive); | 197 TestShell::InitializeTestShell(interactive); |
| 197 | 198 |
| 198 if (parsed_command_line.HasSwitch(test_shell::kAllowScriptsToCloseWindows)) | 199 if (parsed_command_line.HasSwitch(test_shell::kAllowScriptsToCloseWindows)) |
| 199 TestShell::SetAllowScriptsToCloseWindows(); | 200 TestShell::SetAllowScriptsToCloseWindows(); |
| 200 | 201 |
| 201 // Disable user themes for layout tests so pixel tests are consistent. | 202 // Disable user themes for layout tests so pixel tests are consistent. |
| 202 if (!interactive) | 203 if (!interactive) |
| 203 gfx::NativeTheme::instance()->DisableTheming(); | 204 gfx::NativeTheme::instance()->DisableTheming(); |
| 204 | 205 |
| 205 if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) { | 206 if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) { |
| 206 const std::wstring timeout_str = parsed_command_line.GetSwitchValue( | 207 const std::wstring timeout_str = parsed_command_line.GetSwitchValue( |
| 207 test_shell::kTestShellTimeOut); | 208 test_shell::kTestShellTimeOut); |
| 208 int timeout_ms = static_cast<int>(StringToInt64(timeout_str.c_str())); | 209 int timeout_ms = static_cast<int>(StringToInt64(timeout_str.c_str())); |
| 209 if (timeout_ms > 0) | 210 if (timeout_ms > 0) |
| 210 TestShell::SetFileTestTimeout(timeout_ms); | 211 TestShell::SetFileTestTimeout(timeout_ms); |
| 211 } | 212 } |
| 212 | 213 |
| 213 // Initialize global strings | 214 // Initialize global strings |
| 214 TestShell::RegisterWindowClass(); | 215 TestShell::RegisterWindowClass(); |
| 215 | 216 |
| 216 // Treat the first loose value as the initial URL to open. | 217 // Treat the first loose value as the initial URL to open. |
| 217 std::wstring uri; | 218 std::wstring uri; |
| 218 | 219 |
| 219 // Default to a homepage if we're interactive. | 220 // Default to a homepage if we're interactive. |
| 220 if (interactive) { | 221 if (interactive) { |
| 221 PathService::Get(base::DIR_SOURCE_ROOT, &uri); | 222 PathService::Get(base::DIR_SOURCE_ROOT, &uri); |
| 222 file_util::AppendToPath(&uri, L"webkit"); | 223 file_util::AppendToPath(&uri, L"webkit"); |
| 223 file_util::AppendToPath(&uri, L"data"); | 224 file_util::AppendToPath(&uri, L"data"); |
| 224 file_util::AppendToPath(&uri, L"test_shell"); | 225 file_util::AppendToPath(&uri, L"test_shell"); |
| 225 file_util::AppendToPath(&uri, L"index.html"); | 226 file_util::AppendToPath(&uri, L"index.html"); |
| 226 } | 227 } |
| 227 | 228 |
| 228 if (parsed_command_line.GetLooseValueCount() > 0) { | 229 if (parsed_command_line.GetLooseValueCount() > 0) { |
| 229 CommandLine::LooseValueIterator iter = parsed_command_line.GetLooseValue
sBegin(); | 230 CommandLine::LooseValueIterator iter( |
| 230 uri = *iter; | 231 parsed_command_line.GetLooseValuesBegin()); |
| 231 } | 232 uri = *iter; |
| 232 | 233 } |
| 233 if (parsed_command_line.HasSwitch(test_shell::kCrashDumps)) { | 234 |
| 234 std::wstring dir = parsed_command_line.GetSwitchValue(test_shell::kCrash
Dumps); | 235 if (parsed_command_line.HasSwitch(test_shell::kCrashDumps)) { |
| 235 new google_breakpad::ExceptionHandler(dir, 0, &MinidumpCallback, 0, true
); | 236 std::wstring dir( |
| 236 } | 237 parsed_command_line.GetSwitchValue(test_shell::kCrashDumps)); |
| 237 | 238 new google_breakpad::ExceptionHandler(dir, 0, &MinidumpCallback, 0, true); |
| 238 std::wstring js_flags = | 239 } |
| 239 parsed_command_line.GetSwitchValue(test_shell::kJavaScriptFlags); | 240 |
| 240 // Test shell always exposes the GC. | 241 std::wstring js_flags = |
| 241 CommandLine::AppendSwitch(&js_flags, L"expose-gc"); | 242 parsed_command_line.GetSwitchValue(test_shell::kJavaScriptFlags); |
| 242 webkit_glue::SetJavaScriptFlags(js_flags); | 243 // Test shell always exposes the GC. |
| 243 | 244 CommandLine::AppendSwitch(&js_flags, L"expose-gc"); |
| 244 // load and initialize the stats table. | 245 webkit_glue::SetJavaScriptFlags(js_flags); |
| 245 StatsTable *table = new StatsTable(kStatsFile, kStatsFileThreads, kStatsFile
Counters); | 246 |
| 246 StatsTable::set_current(table); | 247 // load and initialize the stats table. |
| 247 | 248 StatsTable *table = new StatsTable(kStatsFile, kStatsFileThreads, kStatsFileCo
unters); |
| 248 TestShell* shell; | 249 StatsTable::set_current(table); |
| 249 if (TestShell::CreateNewWindow(uri, &shell)) { | 250 |
| 250 if (record_mode || playback_mode) { | 251 TestShell* shell; |
| 251 // Move the window to the upper left corner for consistent | 252 if (TestShell::CreateNewWindow(uri, &shell)) { |
| 252 // record/playback mode. For automation, we want this to work | 253 if (record_mode || playback_mode) { |
| 253 // on build systems where the script invoking us is a background | 254 // Move the window to the upper left corner for consistent |
| 254 // process. So for this case, make our window the topmost window | 255 // record/playback mode. For automation, we want this to work |
| 255 // as well. | 256 // on build systems where the script invoking us is a background |
| 256 ForegroundHelper::SetForeground(shell->mainWnd()); | 257 // process. So for this case, make our window the topmost window |
| 257 ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); | 258 // as well. |
| 258 // Tell webkit as well. | 259 ForegroundHelper::SetForeground(shell->mainWnd()); |
| 259 webkit_glue::SetRecordPlaybackMode(true); | 260 ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); |
| 261 // Tell webkit as well. |
| 262 webkit_glue::SetRecordPlaybackMode(true); |
| 263 } |
| 264 |
| 265 shell->Show(shell->webView(), NEW_WINDOW); |
| 266 |
| 267 if (parsed_command_line.HasSwitch(test_shell::kDumpStatsTable)) |
| 268 shell->DumpStatsTableOnExit(); |
| 269 |
| 270 bool no_events = parsed_command_line.HasSwitch(test_shell::kNoEvents); |
| 271 if ((record_mode || playback_mode) && !no_events) { |
| 272 std::wstring script_path = cache_path; |
| 273 // Create the cache directory in case it doesn't exist. |
| 274 file_util::CreateDirectory(cache_path); |
| 275 file_util::AppendToPath(&script_path, L"script.log"); |
| 276 if (record_mode) |
| 277 base::EventRecorder::current()->StartRecording(script_path); |
| 278 if (playback_mode) |
| 279 base::EventRecorder::current()->StartPlayback(script_path); |
| 280 } |
| 281 |
| 282 if (parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse)) { |
| 283 base::MemoryDebug::SetMemoryInUseEnabled(true); |
| 284 // Dump all in use memory at startup |
| 285 base::MemoryDebug::DumpAllMemoryInUse(); |
| 286 } |
| 287 |
| 288 // See if we need to run the tests. |
| 289 if (layout_test_mode) { |
| 290 webkit_glue::SetLayoutTestMode(true); |
| 291 |
| 292 // Set up for the kind of test requested. |
| 293 TestShell::TestParams params; |
| 294 if (parsed_command_line.HasSwitch(test_shell::kDumpPixels)) { |
| 295 // The pixel test flag also gives the image file name to use. |
| 296 params.dump_pixels = true; |
| 297 params.pixel_file_name = parsed_command_line.GetSwitchValue( |
| 298 test_shell::kDumpPixels); |
| 299 if (params.pixel_file_name.size() == 0) { |
| 300 fprintf(stderr, "No file specified for pixel tests"); |
| 301 exit(1); |
| 260 } | 302 } |
| 261 | 303 } |
| 262 shell->Show(shell->webView(), NEW_WINDOW); | 304 if (parsed_command_line.HasSwitch(test_shell::kNoTree)) { |
| 263 | 305 params.dump_tree = false; |
| 264 if (parsed_command_line.HasSwitch(test_shell::kDumpStatsTable)) | 306 } |
| 265 shell->DumpStatsTableOnExit(); | 307 |
| 266 | 308 if (uri.length() == 0) { |
| 267 bool no_events = parsed_command_line.HasSwitch(test_shell::kNoEvents); | 309 // Watch stdin for URLs. |
| 268 if ((record_mode || playback_mode) && !no_events) { | 310 char filenameBuffer[2048]; |
| 269 std::wstring script_path = cache_path; | 311 while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { |
| 270 // Create the cache directory in case it doesn't exist. | 312 char *newLine = strchr(filenameBuffer, '\n'); |
| 271 file_util::CreateDirectory(cache_path); | 313 if (newLine) |
| 272 file_util::AppendToPath(&script_path, L"script.log"); | 314 *newLine = '\0'; |
| 273 if (record_mode) | 315 if (!*filenameBuffer) |
| 274 base::EventRecorder::current()->StartRecording(script_path); | 316 continue; |
| 275 if (playback_mode) | 317 |
| 276 base::EventRecorder::current()->StartPlayback(script_path); | 318 SetCurrentTestName(filenameBuffer); |
| 319 |
| 320 if (!TestShell::RunFileTest(filenameBuffer, params)) |
| 321 break; |
| 277 } | 322 } |
| 278 | 323 } else { |
| 279 if (parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse)) { | 324 TestShell::RunFileTest(WideToUTF8(uri).c_str(), params); |
| 280 base::MemoryDebug::SetMemoryInUseEnabled(true); | 325 } |
| 281 // Dump all in use memory at startup | 326 |
| 282 base::MemoryDebug::DumpAllMemoryInUse(); | 327 shell->CallJSGC(); |
| 283 } | 328 shell->CallJSGC(); |
| 284 | 329 if (shell) delete shell; |
| 285 // See if we need to run the tests. | 330 } else { |
| 286 if (layout_test_mode) { | 331 MessageLoop::current()->Run(); |
| 287 webkit_glue::SetLayoutTestMode(true); | 332 } |
| 288 | 333 |
| 289 // Set up for the kind of test requested. | 334 // Flush any remaining messages. This ensures that any accumulated |
| 290 TestShell::TestParams params; | 335 // Task objects get destroyed before we exit, which avoids noise in |
| 291 if (parsed_command_line.HasSwitch(test_shell::kDumpPixels)) { | 336 // purify leak-test results. |
| 292 // The pixel test flag also gives the image file name to use. | 337 MessageLoop::current()->RunAllPending(); |
| 293 params.dump_pixels = true; | 338 |
| 294 params.pixel_file_name = parsed_command_line.GetSwitchValue( | 339 if (record_mode) |
| 295 test_shell::kDumpPixels); | 340 base::EventRecorder::current()->StopRecording(); |
| 296 if (params.pixel_file_name.size() == 0) { | 341 if (playback_mode) |
| 297 fprintf(stderr, "No file specified for pixel tests"); | 342 base::EventRecorder::current()->StopPlayback(); |
| 298 exit(1); | 343 } |
| 299 } | 344 |
| 300 } | 345 TestShell::ShutdownTestShell(); |
| 301 if (parsed_command_line.HasSwitch(test_shell::kNoTree)) { | 346 TestShell::CleanupLogging(); |
| 302 params.dump_tree = false; | 347 |
| 303 } | 348 // Tear down shared StatsTable; prevents unit_tests from leaking it. |
| 304 | 349 StatsTable::set_current(NULL); |
| 305 if (uri.length() == 0) { | 350 delete table; |
| 306 // Watch stdin for URLs. | |
| 307 char filenameBuffer[2048]; | |
| 308 while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { | |
| 309 char *newLine = strchr(filenameBuffer, '\n'); | |
| 310 if (newLine) | |
| 311 *newLine = '\0'; | |
| 312 if (!*filenameBuffer) | |
| 313 continue; | |
| 314 | |
| 315 SetCurrentTestName(filenameBuffer); | |
| 316 | |
| 317 if (!TestShell::RunFileTest(filenameBuffer, params)) | |
| 318 break; | |
| 319 } | |
| 320 } else { | |
| 321 TestShell::RunFileTest(WideToUTF8(uri).c_str(), params); | |
| 322 } | |
| 323 | |
| 324 shell->CallJSGC(); | |
| 325 shell->CallJSGC(); | |
| 326 if (shell) delete shell; | |
| 327 } else { | |
| 328 MessageLoop::current()->Run(); | |
| 329 } | |
| 330 | |
| 331 // Flush any remaining messages. This ensures that any accumulated | |
| 332 // Task objects get destroyed before we exit, which avoids noise in | |
| 333 // purify leak-test results. | |
| 334 MessageLoop::current()->RunAllPending(); | |
| 335 | |
| 336 if (record_mode) | |
| 337 base::EventRecorder::current()->StopRecording(); | |
| 338 if (playback_mode) | |
| 339 base::EventRecorder::current()->StopPlayback(); | |
| 340 } | |
| 341 | |
| 342 TestShell::ShutdownTestShell(); | |
| 343 TestShell::CleanupLogging(); | |
| 344 | |
| 345 // Tear down shared StatsTable; prevents unit_tests from leaking it. | |
| 346 StatsTable::set_current(NULL); | |
| 347 delete table; | |
| 348 | 351 |
| 349 #ifdef _CRTDBG_MAP_ALLOC | 352 #ifdef _CRTDBG_MAP_ALLOC |
| 350 _CrtDumpMemoryLeaks(); | 353 _CrtDumpMemoryLeaks(); |
| 351 #endif | 354 #endif |
| 352 return 0; | 355 return 0; |
| 353 } | 356 } |
| 354 | |
| 355 | |
| OLD | NEW |