diff options
author | amanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-26 16:33:29 +0000 |
---|---|---|
committer | amanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-26 16:33:29 +0000 |
commit | 238a20d1987f93f79895a8f8710ac9912e8d60a0 (patch) | |
tree | e6650a8c0e4eeeee8f98d6d3b3a6f335e8545d15 /webkit | |
parent | 7c19b87b028f32ccb4664699fc3386f1ba97d083 (diff) | |
download | chromium_src-238a20d1987f93f79895a8f8710ac9912e8d60a0.zip chromium_src-238a20d1987f93f79895a8f8710ac9912e8d60a0.tar.gz chromium_src-238a20d1987f93f79895a8f8710ac9912e8d60a0.tar.bz2 |
Unfork test_shell_main:
- remove Mac version
- move platform-specific operations into PlatformDelegate and
remove #ifdefs
- add event recorder link stubs for use by platforms that don't
have event recording working yet
Notes:
There's a bunch of stuff in test_shell_{gtk,mac,win} that should
also be pulled into the platform delegate so that the TestShell
class can also be unforked, but those can be worked on independently
per platform after this refactoring.
Review URL: http://codereview.chromium.org/18451
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8629 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/tools/test_shell/SConscript | 2 | ||||
-rw-r--r-- | webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj | 22 | ||||
-rw-r--r-- | webkit/tools/test_shell/mac/main.mm | 348 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.vcproj | 8 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_mac.mm | 234 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_main.cc | 151 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate.h | 58 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc | 44 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate_mac.mm | 286 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_platform_delegate_win.cc | 110 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_tests.vcproj | 8 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell_win.cc | 10 |
12 files changed, 566 insertions, 715 deletions
diff --git a/webkit/tools/test_shell/SConscript b/webkit/tools/test_shell/SConscript index 8bf73b2..4bdfea9 100644 --- a/webkit/tools/test_shell/SConscript +++ b/webkit/tools/test_shell/SConscript @@ -119,6 +119,7 @@ if env.Bit('windows'): input_files.extend([ 'drag_delegate.cc', 'drop_delegate.cc', + 'test_shell_platform_delegate_win.cc', 'test_shell_win.cc', 'test_webview_delegate_win.cc', 'webview_host_win.cc', @@ -129,6 +130,7 @@ elif env.Bit('linux'): 'webview_host_gtk.cc', 'webwidget_host_gtk.cc', 'test_shell_gtk.cc', + 'test_shell_platform_delegate_gtk.cc', 'test_webview_delegate_gtk.cc', ]) diff --git a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj index 902bbf3a..655d179 100644 --- a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj +++ b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj @@ -85,6 +85,9 @@ 93AF4F350EFAFE2C0073C62D /* GKURL_unittest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4F310EFAFE2C0073C62D /* GKURL_unittest.cpp */; }; 93AF4F360EFAFE2C0073C62D /* ICOImageDecoder_unittest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4F320EFAFE2C0073C62D /* ICOImageDecoder_unittest.cpp */; }; 93AF4F370EFAFE2C0073C62D /* XBMImageDecoder_unittest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4F330EFAFE2C0073C62D /* XBMImageDecoder_unittest.cpp */; }; + AB19AC150F1BBBD000673E20 /* test_shell_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB19AC140F1BBBD000673E20 /* test_shell_main.cc */; }; + AB19AC290F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB19AC280F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm */; }; + AB19AD380F1D0AF200673E20 /* test_shell_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABA9CAE90DBC521D00CB1EFB /* test_shell_mac.mm */; }; E43A79AA0F1CE23800ABD5D1 /* textAreaResizeCorner.png in Resources */ = {isa = PBXBuildFile; fileRef = E43A79A90F1CE23800ABD5D1 /* textAreaResizeCorner.png */; }; E44662070ECCD652000B9316 /* test_webview_delegate.cc in Sources */ = {isa = PBXBuildFile; fileRef = E44662060ECCD652000B9316 /* test_webview_delegate.cc */; }; E450637E0E4100740025A81A /* test_shell_request_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = E450637D0E4100740025A81A /* test_shell_request_context.cc */; }; @@ -193,11 +196,9 @@ E456290C0E26B4FE005E4685 /* test_shell_switches.cc in Sources */ = {isa = PBXBuildFile; fileRef = ABCF253C0DB8436B00099567 /* test_shell_switches.cc */; }; E456290F0E26B4FE005E4685 /* webview_host.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8A785E0DC553EE005C27B8 /* webview_host.mm */; }; E45629100E26B4FE005E4685 /* webwidget_host.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD16F380DC6A73B0013D3AA /* webwidget_host.mm */; }; - E45629150E26B4FE005E4685 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.mm */; }; E45629160E26B4FE005E4685 /* event_sending_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8A78520DC553A8005C27B8 /* event_sending_controller.cc */; }; E45629170E26B4FE005E4685 /* layout_test_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8A77FD0DC54DD6005C27B8 /* layout_test_controller.cc */; }; E45629190E26B4FE005E4685 /* test_navigation_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB351E2E0DC7B290002F427A /* test_navigation_controller.cc */; }; - E456291A0E26B4FE005E4685 /* test_shell_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABA9CAE90DBC521D00CB1EFB /* test_shell_mac.mm */; }; E456291C0E26B4FE005E4685 /* test_webview_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8A78580DC553D7005C27B8 /* test_webview_delegate.mm */; }; E456291D0E26B4FE005E4685 /* text_input_controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB8A785B0DC553E4005C27B8 /* text_input_controller.cc */; }; E456291E0E26B4FE005E4685 /* test_shell_webview.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABA65EFE0DD50BFF003A4FC8 /* test_shell_webview.mm */; }; @@ -721,7 +722,6 @@ /* Begin PBXFileReference section */ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = "<group>"; }; - 29B97316FDCFA39411CA2CEA /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = "<group>"; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = "<group>"; }; @@ -787,6 +787,11 @@ 93AF4F310EFAFE2C0073C62D /* GKURL_unittest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GKURL_unittest.cpp; path = ../../webcore_unit_tests/GKURL_unittest.cpp; sourceTree = SOURCE_ROOT; }; 93AF4F320EFAFE2C0073C62D /* ICOImageDecoder_unittest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ICOImageDecoder_unittest.cpp; path = ../../webcore_unit_tests/ICOImageDecoder_unittest.cpp; sourceTree = SOURCE_ROOT; }; 93AF4F330EFAFE2C0073C62D /* XBMImageDecoder_unittest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XBMImageDecoder_unittest.cpp; path = ../../webcore_unit_tests/XBMImageDecoder_unittest.cpp; sourceTree = SOURCE_ROOT; }; + AB19AC140F1BBBD000673E20 /* test_shell_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_shell_main.cc; sourceTree = "<group>"; }; + AB19AC1B0F1BC29D00673E20 /* test_shell_platform_delegate_win.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_shell_platform_delegate_win.cc; sourceTree = "<group>"; }; + AB19AC1F0F1BD2D800673E20 /* test_shell_platform_delegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_shell_platform_delegate.h; sourceTree = "<group>"; }; + AB19AC280F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = test_shell_platform_delegate_mac.mm; sourceTree = "<group>"; }; + AB19AC2D0F1BD6E200673E20 /* test_shell_platform_delegate_gtk.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_shell_platform_delegate_gtk.cc; sourceTree = "<group>"; }; AB351E2E0DC7B290002F427A /* test_navigation_controller.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_navigation_controller.cc; sourceTree = "<group>"; }; AB351E2F0DC7B290002F427A /* test_navigation_controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test_navigation_controller.h; sourceTree = "<group>"; }; AB8665450DC78A5A002CE06A /* googleurl.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = googleurl.xcodeproj; path = build/googleurl.xcodeproj; sourceTree = "<group>"; }; @@ -1186,7 +1191,6 @@ F431EA490F1D141300E8D37F /* DumpRenderTreePasteboard.h */, 4D4164FA0F212E6500F2F4A0 /* KeystoneGlue.h */, 4D4164FB0F212E6500F2F4A0 /* KeystoneGlue.m */, - 29B97316FDCFA39411CA2CEA /* main.mm */, ABA65EFD0DD50BFF003A4FC8 /* test_shell_webview.h */, ABA65EFE0DD50BFF003A4FC8 /* test_shell_webview.mm */, 32CA4F630368D1EE00C91783 /* TestShell_Prefix.pch */, @@ -1277,6 +1281,11 @@ E45449360EC9FD15000DFA6E /* test_shell.cc */, ABA9CAE80DBC521D00CB1EFB /* test_shell.h */, ABA9CAE90DBC521D00CB1EFB /* test_shell_mac.mm */, + AB19AC140F1BBBD000673E20 /* test_shell_main.cc */, + AB19AC1F0F1BD2D800673E20 /* test_shell_platform_delegate.h */, + AB19AC2D0F1BD6E200673E20 /* test_shell_platform_delegate_gtk.cc */, + AB19AC280F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm */, + AB19AC1B0F1BC29D00673E20 /* test_shell_platform_delegate_win.cc */, E450637D0E4100740025A81A /* test_shell_request_context.cc */, E450637C0E4100740025A81A /* test_shell_request_context.h */, ABCF253C0DB8436B00099567 /* test_shell_switches.cc */, @@ -1941,12 +1950,10 @@ E45629160E26B4FE005E4685 /* event_sending_controller.cc in Sources */, 4D4164FC0F212E6500F2F4A0 /* KeystoneGlue.m in Sources */, E45629170E26B4FE005E4685 /* layout_test_controller.cc in Sources */, - E45629150E26B4FE005E4685 /* main.mm in Sources */, 53E50D280ECA1B21001784B4 /* simple_clipboard_impl.cc in Sources */, E456296A0E26B64D005E4685 /* simple_resource_loader_bridge.cc in Sources */, E45629190E26B4FE005E4685 /* test_navigation_controller.cc in Sources */, E45449370EC9FD15000DFA6E /* test_shell.cc in Sources */, - E456291A0E26B4FE005E4685 /* test_shell_mac.mm in Sources */, E450637E0E4100740025A81A /* test_shell_request_context.cc in Sources */, E456290C0E26B4FE005E4685 /* test_shell_switches.cc in Sources */, E456291E0E26B4FE005E4685 /* test_shell_webview.mm in Sources */, @@ -1955,6 +1962,9 @@ E456291D0E26B4FE005E4685 /* text_input_controller.cc in Sources */, E456290F0E26B4FE005E4685 /* webview_host.mm in Sources */, E45629100E26B4FE005E4685 /* webwidget_host.mm in Sources */, + AB19AC150F1BBBD000673E20 /* test_shell_main.cc in Sources */, + AB19AC290F1BD6C900673E20 /* test_shell_platform_delegate_mac.mm in Sources */, + AB19AD380F1D0AF200673E20 /* test_shell_mac.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/webkit/tools/test_shell/mac/main.mm b/webkit/tools/test_shell/mac/main.mm deleted file mode 100644 index 1f73d53..0000000 --- a/webkit/tools/test_shell/mac/main.mm +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright (c) 2008 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. - -#import <Cocoa/Cocoa.h> -#include <sys/syslimits.h> -#include <unistd.h> -#import <mach/task.h> - -#include <string> - -#include "base/at_exit.h" -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/icu_util.h" -#include "base/memory_debug.h" -#include "base/message_loop.h" -#include "base/path_service.h" -#include "base/string_util.h" -#include "net/base/cookie_monster.h" -#include "net/http/http_cache.h" -#include "webkit/glue/webkit_glue.h" -#include "webkit/tools/test_shell/simple_resource_loader_bridge.h" -#include "webkit/tools/test_shell/test_shell.h" -#include "webkit/tools/test_shell/test_shell_request_context.h" -#include "webkit/tools/test_shell/test_shell_switches.h" -#import "webkit/tools/test_shell/mac/KeystoneGlue.h" - -#include "WebSystemInterface.h" - -static char g_currentTestName[PATH_MAX]; - -static const char* kStatsFile = "testshell"; -static int kStatsFileThreads = 20; -static int kStatsFileCounters = 100; - -// Extracts the name of the test from the given path and sets the test name -// global. -static void SetCurrentTestName(char* path) { - char* lastSlash = strrchr(path, '/'); - if (lastSlash) { - ++lastSlash; - } else { - lastSlash = path; - } - - strncpy(g_currentTestName, lastSlash, PATH_MAX); - g_currentTestName[PATH_MAX-1] = '\0'; -} - -// The application delegate, used to hook application termination so that we -// can kill the TestShell object and do some other app-wide cleanup. Once we -// go into the run-loop, we never come back to main. -@interface TestShellAppDelegate : NSObject { - @private - TestShell* shell_; // strong -} -- (id)initWithShell:(TestShell*)shell; -@end - -@implementation TestShellAppDelegate -- (id)initWithShell:(TestShell*)shell { - if ((self = [super init])) { - shell_ = shell; - } - return self; -} - -- (void)dealloc { - // Flush any remaining messages. This ensures that any accumulated - // Task objects get destroyed before we exit, which avoids noise in - // purify leak-test results. - MessageLoop::current()->RunAllPending(); - - TestShell::ShutdownTestShell(); - - // get rid of the stats table last, V8 relies on it - StatsTable* table = StatsTable::current(); - StatsTable::set_current(NULL); - delete table; - - TestShell::CleanupLogging(); - - [super dealloc]; -} - -// Called because we're the NSApp's delegate. Destroy ourselves which forces -// shutdown cleanup to be called. -- (void)applicationWillTerminate:(id)sender { - // commit suicide. - [self release]; -} - -@end - -int main(const int argc, const char *argv[]) { - InitWebCoreSystemInterface(); - - // Some tests may use base::Singleton<>, thus we need to instantiate - // the AtExitManager or else we will leak objects. - base::AtExitManager at_exit_manager; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Allocate a message loop for this thread. Although it is not used - // directly, its constructor sets up some necessary state. - MessageLoop main_message_loop(MessageLoop::TYPE_UI); - - // Force AppKit to init itself, but don't start the runloop yet - [NSApplication sharedApplication]; - [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; - - // Interpret the same flags as - // the windows version, so that we can run the same test scripts. stop - // if we hit something that's not a switch (like, oh, a URL). - - CommandLine::Init(argc, argv); - const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); - - if (parsed_command_line.HasSwitch(test_shell::kCheckLayoutTestSystemDeps)) { - // Always succeed the deps check, currently just used by windows port. - exit(0); - } - - if (parsed_command_line.HasSwitch(test_shell::kStartupDialog)) { - //TODO: add alert to allow attaching via gdb before things really get going - } - - if (parsed_command_line.HasSwitch(test_shell::kCrashDumps)) { - std::wstring dir = - parsed_command_line.GetSwitchValue(test_shell::kCrashDumps); - // TODO: enable breakpad - // new google_breakpad::ExceptionHandler(dir, 0, &MinidumpCallback, 0, true); - } - - bool suppress_error_dialogs = (getenv("CHROME_HEADLESS") != NULL) || - parsed_command_line.HasSwitch(test_shell::kNoErrorDialogs) || - parsed_command_line.HasSwitch(test_shell::kLayoutTests); - bool layout_test_mode = - parsed_command_line.HasSwitch(test_shell::kLayoutTests); - - TestShell::InitLogging(suppress_error_dialogs, layout_test_mode, false); - TestShell::InitializeTestShell(layout_test_mode); - - bool no_tree = parsed_command_line.HasSwitch(test_shell::kNoTree); - - bool dump_pixels = parsed_command_line.HasSwitch(test_shell::kDumpPixels); - std::wstring pixel_file_name; - if (dump_pixels) { - pixel_file_name = - parsed_command_line.GetSwitchValue(test_shell::kDumpPixels); - if (pixel_file_name.size() == 0) { - fprintf(stderr, "No file specified for pixel tests"); - exit(1); - } - } - - if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) { - const std::wstring timeout_str = parsed_command_line.GetSwitchValue( - test_shell::kTestShellTimeOut); - int timeout_ms = static_cast<int>(StringToInt64(timeout_str.c_str())); - if (timeout_ms > 0) - TestShell::SetFileTestTimeout(timeout_ms); - } - - std::wstring javascript_flags = - parsed_command_line.GetSwitchValue(test_shell::kJavaScriptFlags); - // Test shell always exposes the GC. - javascript_flags += L" --expose-gc"; - webkit_glue::SetJavaScriptFlags(javascript_flags); - - // Load and initialize the stats table (one per process, so that multiple - // instances don't interfere with each other) - char statsfile[64]; - snprintf(statsfile, 64, "%s-%d", kStatsFile, getpid()); - StatsTable *table = - new StatsTable(statsfile, kStatsFileThreads, kStatsFileCounters); - StatsTable::set_current(table); - - net::HttpCache::Mode cache_mode = net::HttpCache::NORMAL; - bool playback_mode = - parsed_command_line.HasSwitch(test_shell::kPlaybackMode); - bool record_mode = - parsed_command_line.HasSwitch(test_shell::kRecordMode); - - if (playback_mode) - cache_mode = net::HttpCache::PLAYBACK; - else if (record_mode) - cache_mode = net::HttpCache::RECORD; - - bool dump_stats_table = - parsed_command_line.HasSwitch(test_shell::kDumpStatsTable); - - bool debug_memory_in_use = - parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse); - - if (layout_test_mode || - parsed_command_line.HasSwitch(test_shell::kEnableFileCookies)) - net::CookieMonster::EnableFileScheme(); - - std::wstring cache_path = - parsed_command_line.GetSwitchValue(test_shell::kCacheDir); - if (cache_path.empty()) { - PathService::Get(base::DIR_EXE, &cache_path); - file_util::AppendToPath(&cache_path, L"cache"); - } - - // Initializing with a default context, which means no on-disk cookie DB, - // and no support for directory listings. - SimpleResourceLoaderBridge::Init( - new TestShellRequestContext(cache_path, cache_mode, layout_test_mode)); - - // Load ICU data tables - icu_util::Initialize(); - - // Config the network module so it has access to a limited set of resources. - // NetModule::SetResourceProvider(NetResourceProvider); - - // Treat the first loose value as the initial URL to open. - std::wstring uri; - - // Default to a homepage if we're interactive - if (!layout_test_mode) { - // If Keystone is available, set it up if needed and register with it. - [KeystoneGlue registerWithKeystone]; - - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - NSString *testShellPath = - [resourcePath stringByAppendingPathComponent:@"test_shell/index.html"]; - // don't use NSURL; it puts a "localhost" bit in that freaks out our URL - // handling - NSString *testShellURL = [NSString stringWithFormat:@"file://%@", - testShellPath]; - uri = UTF8ToWide([testShellURL UTF8String]); - } - - std::vector<std::wstring> values = parsed_command_line.GetLooseValues(); - if (values.size() > 0) - uri = values[0]; - - TestShell* shell; - if (TestShell::CreateNewWindow(uri, &shell)) { -#ifdef NOTYET - if (record_mode || playback_mode) { - // Move the window to the upper left corner for consistent - // record/playback mode. For automation, we want this to work - // on build systems where the script invoking us is a background - // process. So for this case, make our window the topmost window - // as well. - // ForegroundHelper::SetForeground(shell->mainWnd()); - // ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); - // Tell webkit as well. - webkit_glue::SetRecordPlaybackMode(true); - } -#endif - shell->Show(shell->webView(), NEW_WINDOW); - - if (dump_stats_table) - shell->DumpStatsTableOnExit(); - -#ifdef NOTYET - if ((record_mode || playback_mode) && !no_events) { - std::string script_path = cache_path; - // Create the cache directory in case it doesn't exist. - file_util::CreateDirectory(cache_path); - file_util::AppendToPath(&script_path, "script.log"); - if (record_mode) - base::EventRecorder::current()->StartRecording(script_path); - if (playback_mode) - base::EventRecorder::current()->StartPlayback(script_path); - } -#endif - - if (debug_memory_in_use) { - base::MemoryDebug::SetMemoryInUseEnabled(true); - base::MemoryDebug::DumpAllMemoryInUse(); - } - - // Set up our app delegate so we can tear down the TestShell object when - // necessary. |delegate| takes ownership of |shell|, and will clean itself - // up when it receives the notification that the app is terminating. - TestShellAppDelegate* delegate = [[TestShellAppDelegate alloc] - initWithShell:shell]; - [[NSApplication sharedApplication] setDelegate:delegate]; - - if (layout_test_mode) { - // If we die during tests, we don't want to be spamming the user's crash - // reporter. Set our exception port to null. - if (task_set_exception_ports(mach_task_self(), - EXC_MASK_ALL, - MACH_PORT_NULL, - EXCEPTION_DEFAULT, - THREAD_STATE_NONE) != KERN_SUCCESS) { - return -1; - } - - // Cocoa housekeeping - [NSApp finishLaunching]; - webkit_glue::SetLayoutTestMode(true); - - // Set up for the kind of test requested. - TestShell::TestParams params; - if (dump_pixels) { - // The pixel test flag also gives the image file name to use. - params.dump_pixels = true; - params.pixel_file_name = pixel_file_name; - if (params.pixel_file_name.size() == 0) { - fprintf(stderr, "No file specified for pixel tests"); - exit(1); - } - } - if (no_tree) - params.dump_tree = false; - if (uri.length() == 0) { - // Watch stdin for URLs. - char filenameBuffer[2048]; - while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { - char *newLine = strchr(filenameBuffer, '\n'); - if (newLine) - *newLine = '\0'; - if (!*filenameBuffer) - continue; - - SetCurrentTestName(filenameBuffer); - params.test_url = filenameBuffer; - if (!TestShell::RunFileTest(params)) - break; - } - } else { - params.test_url = WideToUTF8(uri).c_str(); - TestShell::RunFileTest(params); - } - } else { - main_message_loop.Run(); - } - -#ifdef NOTYET - if (record_mode) - base::EventRecorder::current()->StopRecording(); - if (playback_mode) - base::EventRecorder::current()->StopPlayback(); -#endif - } - - [pool release]; - return 0; -} diff --git a/webkit/tools/test_shell/test_shell.vcproj b/webkit/tools/test_shell/test_shell.vcproj index b652571..c7e2d96 100644 --- a/webkit/tools/test_shell/test_shell.vcproj +++ b/webkit/tools/test_shell/test_shell.vcproj @@ -266,6 +266,14 @@ > </File> <File + RelativePath=".\test_shell_platform_delegate.h" + > + </File> + <File + RelativePath=".\test_shell_platform_delegate_win.cc" + > + </File> + <File RelativePath=".\test_shell_request_context.cc" > </File> diff --git a/webkit/tools/test_shell/test_shell_mac.mm b/webkit/tools/test_shell/test_shell_mac.mm index 789fc4e..0d004a5 100644 --- a/webkit/tools/test_shell/test_shell_mac.mm +++ b/webkit/tools/test_shell/test_shell_mac.mm @@ -48,7 +48,10 @@ #define MAX_LOADSTRING 100 +// Sizes for URL bar layout +#define BUTTON_HEIGHT 22 #define BUTTON_WIDTH 72 +#define BUTTON_MARGIN 8 #define URLBAR_HEIGHT 32 // Global Variables: @@ -157,230 +160,14 @@ void TestShell::PlatformShutdown() { [DumpRenderTreePasteboard releaseLocalPasteboards]; } -#if OBJC_API_VERSION == 2 -static void SwizzleAllMethods(Class imposter, Class original) { - unsigned int imposterMethodCount = 0; - Method* imposterMethods = class_copyMethodList(imposter, &imposterMethodCount); - - unsigned int originalMethodCount = 0; - Method* originalMethods = class_copyMethodList(original, &originalMethodCount); - - for (unsigned int i = 0; i < imposterMethodCount; i++) { - SEL imposterMethodName = method_getName(imposterMethods[i]); - - // Attempt to add the method to the original class. If it fails, the method - // already exists and we should instead exchange the implementations. - if (class_addMethod(original, - imposterMethodName, - method_getImplementation(originalMethods[i]), - method_getTypeEncoding(originalMethods[i]))) { - continue; - } - - unsigned int j = 0; - for (; j < originalMethodCount; j++) { - SEL originalMethodName = method_getName(originalMethods[j]); - if (sel_isEqual(imposterMethodName, originalMethodName)) { - break; - } - } - - // If class_addMethod failed above then the method must exist on the - // original class. - DCHECK(j < originalMethodCount) << "method wasn't found?"; - method_exchangeImplementations(imposterMethods[i], originalMethods[j]); - } - - if (imposterMethods) { - free(imposterMethods); - } - if (originalMethods) { - free(originalMethods); - } -} -#endif - -static void SwizzleNSPasteboard(void) { - // We replace NSPaseboard w/ the shim (from WebKit) that avoids having - // sideeffects w/ whatever the user does at the same time. - - Class imposterClass = objc_getClass("DumpRenderTreePasteboard"); - Class originalClass = objc_getClass("NSPasteboard"); -#if OBJC_API_VERSION == 0 - class_poseAs(imposterClass, originalClass); -#else - // Swizzle instance methods... - SwizzleAllMethods(imposterClass, originalClass); - // and then class methods. - SwizzleAllMethods(object_getClass(imposterClass), - object_getClass(originalClass)); -#endif -} - -static void SetDefaultsToLayoutTestValues(void) { - // So we can match the WebKit layout tests, we want to force a bunch of - // preferences that control appearance to match. - // (We want to do this as early as possible in application startup so - // the settings are in before any higher layers could cache values.) - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - const NSInteger kMinFontSizeCGSmoothes = 4; - const NSInteger kNoFontSmoothing = 0; - const NSInteger kBlueTintedAppearance = 1; - [defaults setInteger:kMinFontSizeCGSmoothes - forKey:@"AppleAntiAliasingThreshold"]; - [defaults setInteger:kNoFontSmoothing - forKey:@"AppleFontSmoothing"]; - [defaults setInteger:kBlueTintedAppearance - forKey:@"AppleAquaColorVariant"]; - [defaults setObject:@"0.709800 0.835300 1.000000" - forKey:@"AppleHighlightColor"]; - [defaults setObject:@"0.500000 0.500000 0.500000" - forKey:@"AppleOtherHighlightColor"]; - [defaults setObject:[NSArray arrayWithObject:@"en"] - forKey:@"AppleLanguages"]; - - // AppKit pulls scrollbar style from NSUserDefaults. HIToolbox uses - // CFPreferences, but AnyApplication, so we set it, force it to load, and - // then reset the pref to what it was (HIToolbox will cache what it loaded). - [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; - CFTypeRef initialValue - = CFPreferencesCopyValue(CFSTR("AppleScrollBarVariant"), - kCFPreferencesAnyApplication, - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), - CFSTR("DoubleMax"), - kCFPreferencesAnyApplication, - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - // Make HIToolbox read from CFPreferences - ThemeScrollBarArrowStyle style; - GetThemeScrollBarArrowStyle(&style); - if (initialValue) { - // Reset the preference to what it was - CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), - initialValue, - kCFPreferencesAnyApplication, - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - CFRelease(initialValue); - } -} - -static void ClearAnyDefaultsForLayoutTests(void) { - // Not running a test, clear the keys so the TestShell looks right to the - // running user. - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - [defaults removeObjectForKey:@"AppleAntiAliasingThreshold"]; - [defaults removeObjectForKey:@"AppleFontSmoothing"]; - [defaults removeObjectForKey:@"AppleAquaColorVariant"]; - [defaults removeObjectForKey:@"AppleHighlightColor"]; - [defaults removeObjectForKey:@"AppleOtherHighlightColor"]; - [defaults removeObjectForKey:@"AppleLanguages"]; - [defaults removeObjectForKey:@"AppleScrollBarVariant"]; -} - -static CMProfileRef gUsersColorProfile = NULL; - -static void RestoreUsersColorProfile(void) { - // This is called from the unsafe signal handers, so doing just about anything - // isn't really safe. But since we're already gonna crash, we give it a try - // anyways... (and WebKit uses this strategy...) - - if (gUsersColorProfile) { - CGDirectDisplayID displayID = CGMainDisplayID(); - CMError error = CMSetProfileByAVID((UInt32)displayID, gUsersColorProfile); - CMCloseProfile(gUsersColorProfile); - if (error) { - fprintf(stderr, "Failed to restore color profile, use System " - "Preferences -> Displays -> Color to reset. Error: %d", - (int)error); - } - gUsersColorProfile = NULL; - } -} - -static void SimpleSignalHandler(int sig) { - // Try to restore and try to go down cleanly - RestoreUsersColorProfile(); - exit(128 + sig); -} - -static void CrashSignalHandler(int sig) { - // Try to restore and get out fast... - RestoreUsersColorProfile(); - _exit(128 + sig); -} - -static void InstallLayoutTestColorProfile(void) { - // To make sure we get consisten colors (not dependent on the Main display), - // we force the generic rgb color profile. This cases a change the user can - // see. We use the same basic method as WebKit for trying to make sure we - // get the profile back if we go down in flames. - - // Save off the current - CGDirectDisplayID displayID = CGMainDisplayID(); - CMProfileRef previousProfile; - CMError error = CMGetProfileByAVID((UInt32)displayID, &previousProfile); - if (error) { - DLOG(WARNING) << "failed to get the current color profile, " - "pixmaps won't match. Error: " << (int)error; - return; - } - - // Install the generic one - NSColorSpace *genericSpace = [NSColorSpace genericRGBColorSpace]; - CMProfileRef genericProfile = (CMProfileRef)[genericSpace colorSyncProfile]; - if ((error = CMSetProfileByAVID((UInt32)displayID, genericProfile))) { - DLOG(WARNING) << "failed install the generic color profile, " - "pixmaps won't match. Error: " << (int)error; - return; - } - - // Save the starting profile, and hook in as best we can to make sure when - // we exit, it's restored (use atexit() so direct calls to exit() call us). - gUsersColorProfile = previousProfile; - atexit(RestoreUsersColorProfile); - // The less scary signals... - signal(SIGINT, SimpleSignalHandler); - signal(SIGHUP, SimpleSignalHandler); - signal(SIGTERM, SimpleSignalHandler); - // And now the scary ones... - signal(SIGILL, CrashSignalHandler); // 4: illegal instruction - signal(SIGTRAP, CrashSignalHandler); // 5: trace trap - signal(SIGEMT, CrashSignalHandler); // 7: EMT instruction - signal(SIGFPE, CrashSignalHandler); // 8: floating point exception - signal(SIGBUS, CrashSignalHandler); // 10: bus error - signal(SIGSEGV, CrashSignalHandler); // 11: segmentation violation - signal(SIGSYS, CrashSignalHandler); // 12: bad argument to system call - signal(SIGPIPE, CrashSignalHandler); // 13: write on a pipe with no reader - signal(SIGXCPU, CrashSignalHandler); // 24: exceeded CPU time limit - signal(SIGXFSZ, CrashSignalHandler); // 25: exceeded file size limit -} - // static void TestShell::InitializeTestShell(bool layout_test_mode) { // This should move to a per-process platform-specific initialization function // when one exists. - [NSApplication sharedApplication]; window_list_ = new WindowList; layout_test_mode_ = layout_test_mode; - if (layout_test_mode_) { - SwizzleNSPasteboard(); - SetDefaultsToLayoutTestValues(); - // If we could check the command line to see if we're doing pixel tests, - // then we only install the color profile in that case. - InstallLayoutTestColorProfile(); - } else { - ClearAnyDefaultsForLayoutTests(); - } - web_prefs_ = new WebPreferences; ResetWebPreferences(); @@ -450,8 +237,7 @@ bool TestShell::Initialize(const std::wstring& startingURL) { styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | - NSResizableWindowMask | - NSTexturedBackgroundWindowMask) + NSResizableWindowMask ) backing:NSBackingStoreBuffered defer:NO]; [m_mainWnd setTitle:@"TestShell"]; @@ -481,9 +267,10 @@ bool TestShell::Initialize(const std::wstring& startingURL) { // create buttons NSRect button_rect = [[m_mainWnd contentView] bounds]; - button_rect.origin.y = window_rect.size.height - 22; - button_rect.size.height = 22; - button_rect.origin.x += 16; + button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT + + (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2; + button_rect.size.height = BUTTON_HEIGHT; + button_rect.origin.x += BUTTON_MARGIN; button_rect.size.width = BUTTON_WIDTH; NSView* content = [m_mainWnd contentView]; @@ -507,9 +294,9 @@ bool TestShell::Initialize(const std::wstring& startingURL) { [button setAction:@selector(stopLoading:)]; // text field for URL - button_rect.origin.x += 16; + button_rect.origin.x += BUTTON_MARGIN; button_rect.size.width = [[m_mainWnd contentView] bounds].size.width - - button_rect.origin.x - 32; + button_rect.origin.x - BUTTON_MARGIN; m_editWnd = [[NSTextField alloc] initWithFrame:button_rect]; [[m_mainWnd contentView] addSubview:m_editWnd]; [m_editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; @@ -595,7 +382,6 @@ void TestShell::TestFinished() { puts("#TEST_TIMED_OUT\n"); puts("#EOF\n"); fflush(stdout); - RestoreUsersColorProfile(); abort(); } diff --git a/webkit/tools/test_shell/test_shell_main.cc b/webkit/tools/test_shell/test_shell_main.cc index 3a52828..e895626 100644 --- a/webkit/tools/test_shell/test_shell_main.cc +++ b/webkit/tools/test_shell/test_shell_main.cc @@ -5,25 +5,10 @@ // Creates an instance of the test_shell. #include "build/build_config.h" -#include <stdlib.h> // required by _set_abort_behavior - -#if defined(OS_WIN) -#include <windows.h> -#include <commctrl.h> -#include "base/event_recorder.h" -#include "base/gfx/native_theme.h" -#include "base/resource_util.h" -#include "base/win_util.h" -#include "webkit/tools/test_shell/foreground_helper.h" -#endif - -#if defined(OS_LINUX) -#include <gtk/gtk.h> -#endif - #include "base/at_exit.h" #include "base/basictypes.h" #include "base/command_line.h" +#include "base/event_recorder.h" #include "base/file_util.h" #include "base/icu_util.h" #include "base/memory_debug.h" @@ -43,6 +28,7 @@ #include "webkit/glue/window_open_disposition.h" #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" #include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" #include "webkit/tools/test_shell/test_shell_request_context.h" #include "webkit/tools/test_shell/test_shell_switches.h" @@ -58,93 +44,26 @@ static const char* kStatsFilePrefix = "testshell_"; static int kStatsFileThreads = 20; static int kStatsFileCounters = 200; -#if defined(OS_WIN) -// This test approximates whether you have the Windows XP theme selected by -// inspecting a couple of metrics. It does not catch all cases, but it does -// pick up on classic vs xp, and normal vs large fonts. Something it misses -// is changes to the color scheme (which will infact cause pixel test -// failures). -// -// ** Expected dependencies ** -// + Theme: Windows XP -// + Color scheme: Default (blue) -// + Font size: Normal -// + Font smoothing: off (minor impact). -// -bool HasLayoutTestThemeDependenciesWin() { - // This metric will be 17 when font size is "Normal". The size of drop-down - // menus depends on it. - if (::GetSystemMetrics(SM_CXVSCROLL) != 17) - return false; - - // Check that the system fonts RenderThemeWin relies on are Tahoma 11 pt. - NONCLIENTMETRICS metrics; - win_util::GetNonClientMetrics(&metrics); - LOGFONTW* system_fonts[] = - { &metrics.lfStatusFont, &metrics.lfMenuFont, &metrics.lfSmCaptionFont }; - - for (size_t i = 0; i < arraysize(system_fonts); ++i) { - if (system_fonts[i]->lfHeight != -11 || - 0 != wcscmp(L"Tahoma", system_fonts[i]->lfFaceName)) - return false; - } - return true; -} - -bool CheckLayoutTestSystemDependenciesWin() { - bool has_deps = HasLayoutTestThemeDependenciesWin(); - if (!has_deps) { - fprintf(stderr, - "\n" - "###############################################################\n" - "## Layout test system dependencies check failed.\n" - "## Some layout tests may fail due to unexpected theme.\n" - "##\n" - "## To fix, go to Display Properties -> Appearance, and select:\n" - "## + Windows and buttons: Windows XP style\n" - "## + Color scheme: Default (blue)\n" - "## + Font size: Normal\n" - "###############################################################\n"); - } - return has_deps; -} - -#endif - -bool CheckLayoutTestSystemDependencies() { -#if defined(OS_WIN) - return CheckLayoutTestSystemDependenciesWin(); -#else - return true; -#endif -} - } // namespace - int main(int argc, char* argv[]) { base::EnableTerminationOnHeapCorruption(); -#ifdef _CRTDBG_MAP_ALLOC - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); -#endif + // Some tests may use base::Singleton<>, thus we need to instanciate // the AtExitManager or else we will leak objects. base::AtExitManager at_exit_manager; -#if defined(OS_LINUX) - gtk_init(&argc, &argv); -#endif - - // Only parse the command line after GTK's had a crack at it. + TestShellPlatformDelegate::PreflightArgs(&argc, &argv); CommandLine::Init(argc, argv); - const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); + + TestShellPlatformDelegate platform(parsed_command_line); + if (parsed_command_line.HasSwitch(test_shell::kStartupDialog)) TestShell::ShowStartupDebuggingDialog(); if (parsed_command_line.HasSwitch(test_shell::kCheckLayoutTestSystemDeps)) { - exit(CheckLayoutTestSystemDependencies() ? 0 : 1); + exit(platform.CheckLayoutTestSystemDependencies() ? 0 : 1); } // Allocate a message loop for this thread. Although it is not used @@ -159,10 +78,8 @@ int main(int argc, char* argv[]) { parsed_command_line.HasSwitch(test_shell::kLayoutTests); bool enable_gp_fault_error_box = false; -#if defined(OS_WIN) enable_gp_fault_error_box = parsed_command_line.HasSwitch(test_shell::kGPFaultErrorBox); -#endif TestShell::InitLogging(suppress_error_dialogs, layout_test_mode, enable_gp_fault_error_box); @@ -172,11 +89,9 @@ int main(int argc, char* argv[]) { // Suppress abort message in v8 library in debugging mode. // V8 calls abort() when it hits assertion errors. -#if defined(OS_WIN) if (suppress_error_dialogs) { - _set_abort_behavior(0, _WRITE_ABORT_MSG); + platform.SuppressErrorReporting(); } -#endif if (parsed_command_line.HasSwitch(test_shell::kEnableTracing)) base::TraceLog::StartTracing(); @@ -211,16 +126,7 @@ int main(int argc, char* argv[]) { // Load ICU data tables icu_util::Initialize(); - // Config the network module so it has access to a limited set of resources. - net::NetModule::SetResourceProvider(TestShell::NetResourceProvider); - -#if defined(OS_WIN) - INITCOMMONCONTROLSEX InitCtrlEx; - - InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); - InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; - InitCommonControlsEx(&InitCtrlEx); -#endif + platform.InitializeGUI(); TestShell::InitializeTestShell(layout_test_mode); @@ -229,16 +135,7 @@ int main(int argc, char* argv[]) { // Disable user themes for layout tests so pixel tests are consistent. if (layout_test_mode) { -#if defined(OS_WIN) - gfx::NativeTheme::instance()->DisableTheming(); -#elif defined(OS_LINUX) - // Pick a theme that uses Cairo for drawing, since we: - // 1) currently don't support GTK themes that use the GDK drawing APIs, and - // 2) need to use a unified theme for layout tests anyway. - g_object_set(gtk_settings_get_default(), - "gtk-theme-name", "Mist", - NULL); -#endif + platform.SelectUnifiedTheme(); } if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) { @@ -249,11 +146,6 @@ int main(int argc, char* argv[]) { TestShell::SetFileTestTimeout(timeout_ms); } -#if defined(OS_WIN) - // Initialize global strings - TestShell::RegisterWindowClass(); -#endif - // Treat the first loose value as the initial URL to open. std::wstring uri; @@ -281,33 +173,26 @@ int main(int argc, char* argv[]) { // Load and initialize the stats table. Attempt to construct a somewhat // unique name to isolate separate instances from each other. StatsTable *table = new StatsTable( - kStatsFilePrefix + Uint64ToString(base::RandUint64()), + // truncate the random # to 32 bits for the benefit of Mac OS X, to + // avoid tripping over its maximum shared memory segment name length + kStatsFilePrefix + Uint64ToString(base::RandUint64() & 0xFFFFFFFFL), kStatsFileThreads, kStatsFileCounters); StatsTable::set_current(table); TestShell* shell; if (TestShell::CreateNewWindow(uri, &shell)) { -#if defined(OS_WIN) if (record_mode || playback_mode) { - // Move the window to the upper left corner for consistent - // record/playback mode. For automation, we want this to work - // on build systems where the script invoking us is a background - // process. So for this case, make our window the topmost window - // as well. - ForegroundHelper::SetForeground(shell->mainWnd()); - ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); + platform.SetWindowPositionForRecording(shell); // Tell webkit as well. webkit_glue::SetRecordPlaybackMode(true); } -#endif shell->Show(shell->webView(), NEW_WINDOW); if (parsed_command_line.HasSwitch(test_shell::kDumpStatsTable)) shell->DumpStatsTableOnExit(); -#if defined(OS_WIN) bool no_events = parsed_command_line.HasSwitch(test_shell::kNoEvents); if ((record_mode || playback_mode) && !no_events) { std::wstring script_path = cache_path; @@ -319,7 +204,6 @@ int main(int argc, char* argv[]) { if (playback_mode) base::EventRecorder::current()->StartPlayback(script_path); } -#endif if (parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse)) { base::MemoryDebug::SetMemoryInUseEnabled(true); @@ -382,12 +266,10 @@ int main(int argc, char* argv[]) { // purify leak-test results. MessageLoop::current()->RunAllPending(); -#if defined(OS_WIN) if (record_mode) base::EventRecorder::current()->StopRecording(); if (playback_mode) base::EventRecorder::current()->StopPlayback(); -#endif } TestShell::ShutdownTestShell(); @@ -397,8 +279,5 @@ int main(int argc, char* argv[]) { StatsTable::set_current(NULL); delete table; -#ifdef _CRTDBG_MAP_ALLOC - _CrtDumpMemoryLeaks(); -#endif return 0; } diff --git a/webkit/tools/test_shell/test_shell_platform_delegate.h b/webkit/tools/test_shell/test_shell_platform_delegate.h new file mode 100644 index 0000000..5be147a --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate.h @@ -0,0 +1,58 @@ +// Copyright (c) 2009 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. + +// TestShellPlatformDelegate isolates a variety of platform-specific +// functions so that code can invoke them by purpose without resorting to +// ifdefs or runtime platform checks. Each platform should define an +// implementation of this class. In many cases, implementation of methods +// in this class will be stubs on platforms where those functions are +// unnecessary. + +class TestShellPlatformDelegate { + public: + // The TestShellPlatformDelegate object is scoped to main(), and so + // its constructor is a good place to put per-application initialization + // (as opposed to per-test code, which should go into the TestShell class). + TestShellPlatformDelegate(const CommandLine& command_line); + ~TestShellPlatformDelegate(); + + // EnableMemoryDebugging: turn on platform memory debugging assistance + // (console messages, heap checking, leak detection, etc.). + void EnableMemoryDebugging(); + + // CheckLayoutTestSystemDependencies: check for any system dependencies that + // can't be easily overridden from within an application (for example, UI or + // display settings). Returns false if any dependencies are not met. + bool CheckLayoutTestSystemDependencies(); + + // PreflightArgs: give the platform first crack at the arguments to main() + // before we parse the command line. For example, some UI toolkits have + // runtime flags that they can pre-filter. + static void PreflightArgs(int* argc, char*** argv); + + // SuppressErrorReporting: if possible, turn off platform error reporting + // dialogs, crash dumps, etc. + void SuppressErrorReporting(); + + // InitializeGUI: do any special initialization that the UI needs before + // we start the main message loop + void InitializeGUI(); + + // SelectUnifiedTheme: override user preferences so that the UI theme matches + // what's in the baseline files. Whenever possible, override user settings + // here rather than testing them in CheckLayoutTestSystemDependencies. + void SelectUnifiedTheme(); + + // AboutToExit: give the platform delegate a last chance to restore platform + // settings. Normally called by the destructor, but also called before + // abort() (example: test timeouts). + void AboutToExit(); + + // SetWindowPositionForRecording: if the platform's implementation of + // EventRecorder requires the window to be in a particular absolute position, + // make it so. This is called by TestShell after it creates the window. + void SetWindowPositionForRecording(TestShell *shell); + private: + const CommandLine& command_line_; +}; diff --git a/webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc b/webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc new file mode 100644 index 0000000..8846f19 --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate_gtk.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2009 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 <stdlib.h> // required by _set_abort_behavior +#include <gtk/gtk.h> + +#include "base/command_line.h" +#include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" + +void TestShellPlatformDelegate::PreflightArgs(int *argc, char ***argv) { + gtk_init(argc, argv); +} + +void TestShellPlatformDelegate::SelectUnifiedTheme() { + // Pick a theme that uses Cairo for drawing, since we: + // 1) currently don't support GTK themes that use the GDK drawing APIs, and + // 2) need to use a unified theme for layout tests anyway. + g_object_set(gtk_settings_get_default(), + "gtk-theme-name", "Mist", + NULL); +} + +TestShellPlatformDelegate::TestShellPlatformDelegate( + const CommandLine& command_line) + : command_line_(command_line) { +} + +bool TestShellPlatformDelegate::CheckLayoutTestSystemDependencies() { + return true; +} + +void TestShellPlatformDelegate::SuppressErrorReporting() { +} + +void TestShellPlatformDelegate::InitializeGUI() { +} + +void TestShellPlatformDelegate::SetWindowPositionForRecording(TestShell *) { +} + +TestShellPlatformDelegate::~TestShellPlatformDelegate() { +} diff --git a/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm b/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm new file mode 100644 index 0000000..3642e35 --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm @@ -0,0 +1,286 @@ +// Copyright (c) 2006-2009 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 "build/build_config.h" + +// #include <Carbon/Carbon.h> +// #include <ApplicationServices/ApplicationServices.h> +#import <Cocoa/Cocoa.h> +#import <objc/objc-runtime.h> +#include <sys/syslimits.h> +#include <unistd.h> +#include <string> +#include <stdlib.h> +#include <mach/task.h> + +#include "base/command_line.h" +#include "base/logging.h" +#include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" +#include "webkit/tools/test_shell/test_shell_switches.h" +#include "WebSystemInterface.h" + +static NSAutoreleasePool *gTestShellAutoreleasePool = nil; + +static void SetDefaultsToLayoutTestValues(void) { + // So we can match the WebKit layout tests, we want to force a bunch of + // preferences that control appearance to match. + // (We want to do this as early as possible in application startup so + // the settings are in before any higher layers could cache values.) + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + const NSInteger kMinFontSizeCGSmoothes = 4; + const NSInteger kNoFontSmoothing = 0; + const NSInteger kBlueTintedAppearance = 1; + [defaults setInteger:kMinFontSizeCGSmoothes + forKey:@"AppleAntiAliasingThreshold"]; + [defaults setInteger:kNoFontSmoothing + forKey:@"AppleFontSmoothing"]; + [defaults setInteger:kBlueTintedAppearance + forKey:@"AppleAquaColorVariant"]; + [defaults setObject:@"0.709800 0.835300 1.000000" + forKey:@"AppleHighlightColor"]; + [defaults setObject:@"0.500000 0.500000 0.500000" + forKey:@"AppleOtherHighlightColor"]; + [defaults setObject:[NSArray arrayWithObject:@"en"] + forKey:@"AppleLanguages"]; + + // AppKit pulls scrollbar style from NSUserDefaults. HIToolbox uses + // CFPreferences, but AnyApplication, so we set it, force it to load, and + // then reset the pref to what it was (HIToolbox will cache what it loaded). + [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; + CFTypeRef initialValue = + CFPreferencesCopyValue(CFSTR("AppleScrollBarVariant"), + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), + CFSTR("DoubleMax"), + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + // Make HIToolbox read from CFPreferences + ThemeScrollBarArrowStyle style; + GetThemeScrollBarArrowStyle(&style); + if (initialValue) { + // Reset the preference to what it was + CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), + initialValue, + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + CFRelease(initialValue); + } +} + +static void ClearAnyDefaultsForLayoutTests(void) { + // Not running a test, clear the keys so the TestShell looks right to the + // running user. + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + [defaults removeObjectForKey:@"AppleAntiAliasingThreshold"]; + [defaults removeObjectForKey:@"AppleFontSmoothing"]; + [defaults removeObjectForKey:@"AppleAquaColorVariant"]; + [defaults removeObjectForKey:@"AppleHighlightColor"]; + [defaults removeObjectForKey:@"AppleOtherHighlightColor"]; + [defaults removeObjectForKey:@"AppleLanguages"]; + [defaults removeObjectForKey:@"AppleScrollBarVariant"]; +} + +static CMProfileRef gUsersColorProfile = NULL; + +static void RestoreUsersColorProfile(void) { + // This is called from the unsafe signal handers, so doing just about anything + // isn't really safe. But since we're already gonna crash, we give it a try + // anyways... (and WebKit uses this strategy...) + + if (gUsersColorProfile) { + CGDirectDisplayID displayID = CGMainDisplayID(); + CMError error = CMSetProfileByAVID((UInt32)displayID, gUsersColorProfile); + CMCloseProfile(gUsersColorProfile); + if (error) { + fprintf(stderr, "Failed to restore color profile, use System " + "Preferences -> Displays -> Color to reset. Error: %d", + (int)error); + } + gUsersColorProfile = NULL; + } +} + +static void SimpleSignalHandler(int sig) { + // Try to restore and try to go down cleanly + RestoreUsersColorProfile(); + exit(128 + sig); +} + +static void CrashSignalHandler(int sig) { + // Try to restore and get out fast... + RestoreUsersColorProfile(); + _exit(128 + sig); +} + +static void InstallLayoutTestColorProfile(void) { + // To make sure we get consisten colors (not dependent on the Main display), + // we force the generic rgb color profile. This cases a change the user can + // see. We use the same basic method as WebKit for trying to make sure we + // get the profile back if we go down in flames. + + // Save off the current + CGDirectDisplayID displayID = CGMainDisplayID(); + CMProfileRef previousProfile; + CMError error = CMGetProfileByAVID((UInt32)displayID, &previousProfile); + if (error) { + DLOG(WARNING) << "failed to get the current color profile, " + "pixmaps won't match. Error: " << (int)error; + return; + } + + // Install the generic one + NSColorSpace *genericSpace = [NSColorSpace genericRGBColorSpace]; + CMProfileRef genericProfile = (CMProfileRef)[genericSpace colorSyncProfile]; + if ((error = CMSetProfileByAVID((UInt32)displayID, genericProfile))) { + DLOG(WARNING) << "failed install the generic color profile, " + "pixmaps won't match. Error: " << (int)error; + return; + } + + // Save the starting profile, and hook in as best we can to make sure when + // we exit, it's restored (use atexit() so direct calls to exit() call us). + gUsersColorProfile = previousProfile; + atexit(RestoreUsersColorProfile); + // The less scary signals... + signal(SIGINT, SimpleSignalHandler); + signal(SIGHUP, SimpleSignalHandler); + signal(SIGTERM, SimpleSignalHandler); + // And now the scary ones... + signal(SIGABRT, CrashSignalHandler); // abort() called + signal(SIGILL, CrashSignalHandler); // 4: illegal instruction + signal(SIGTRAP, CrashSignalHandler); // 5: trace trap + signal(SIGEMT, CrashSignalHandler); // 7: EMT instruction + signal(SIGFPE, CrashSignalHandler); // 8: floating point exception + signal(SIGBUS, CrashSignalHandler); // 10: bus error + signal(SIGSEGV, CrashSignalHandler); // 11: segmentation violation + signal(SIGSYS, CrashSignalHandler); // 12: bad argument to system call + signal(SIGPIPE, CrashSignalHandler); // 13: write on a pipe with no reader + signal(SIGXCPU, CrashSignalHandler); // 24: exceeded CPU time limit + signal(SIGXFSZ, CrashSignalHandler); // 25: exceeded file size limit +} + +#if OBJC_API_VERSION == 2 +static void SwizzleAllMethods(Class imposter, Class original) { + unsigned int imposterMethodCount = 0; + Method* imposterMethods = class_copyMethodList(imposter, &imposterMethodCount); + + unsigned int originalMethodCount = 0; + Method* originalMethods = class_copyMethodList(original, &originalMethodCount); + + for (unsigned int i = 0; i < imposterMethodCount; i++) { + SEL imposterMethodName = method_getName(imposterMethods[i]); + + // Attempt to add the method to the original class. If it fails, the method + // already exists and we should instead exchange the implementations. + if (class_addMethod(original, + imposterMethodName, + method_getImplementation(originalMethods[i]), + method_getTypeEncoding(originalMethods[i]))) { + continue; + } + + unsigned int j = 0; + for (; j < originalMethodCount; j++) { + SEL originalMethodName = method_getName(originalMethods[j]); + if (sel_isEqual(imposterMethodName, originalMethodName)) { + break; + } + } + + // If class_addMethod failed above then the method must exist on the + // original class. + DCHECK(j < originalMethodCount) << "method wasn't found?"; + method_exchangeImplementations(imposterMethods[i], originalMethods[j]); + } + + if (imposterMethods) { + free(imposterMethods); + } + if (originalMethods) { + free(originalMethods); + } +} +#endif + +static void SwizzleNSPasteboard(void) { + // We replace NSPaseboard w/ the shim (from WebKit) that avoids having + // sideeffects w/ whatever the user does at the same time. + + Class imposterClass = objc_getClass("DumpRenderTreePasteboard"); + Class originalClass = objc_getClass("NSPasteboard"); +#if OBJC_API_VERSION == 0 + class_poseAs(imposterClass, originalClass); +#else + // Swizzle instance methods... + SwizzleAllMethods(imposterClass, originalClass); + // and then class methods. + SwizzleAllMethods(object_getClass(imposterClass), + object_getClass(originalClass)); +#endif +} + +TestShellPlatformDelegate::TestShellPlatformDelegate( + const CommandLine &command_line) + : command_line_(command_line) { + gTestShellAutoreleasePool = [[NSAutoreleasePool alloc] init]; + InitWebCoreSystemInterface(); + // Force AppKit to init itself, but don't start the runloop yet + [NSApplication sharedApplication]; + [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; +} + +TestShellPlatformDelegate::~TestShellPlatformDelegate() { + // if we have changed the user's display color profile for pixel tests, + // restore it. + RestoreUsersColorProfile(); + [gTestShellAutoreleasePool release]; +} + +bool TestShellPlatformDelegate::CheckLayoutTestSystemDependencies() { + return true; +} + +void TestShellPlatformDelegate::InitializeGUI() { + if (command_line_.HasSwitch(test_shell::kLayoutTests)) { + // If we're doing automated testing, we won't be using a conventional + // run loop, so tell Cocoa to finish initializing. + [NSApp finishLaunching]; + } +} + +void TestShellPlatformDelegate::PreflightArgs(int *argc, char ***argv) { +} + +void TestShellPlatformDelegate::SetWindowPositionForRecording(TestShell *) { +} + +void TestShellPlatformDelegate::SelectUnifiedTheme() { + if (command_line_.HasSwitch(test_shell::kLayoutTests)) { + SetDefaultsToLayoutTestValues(); + SwizzleNSPasteboard(); + + if (command_line_.HasSwitch(test_shell::kDumpPixels)) { + InstallLayoutTestColorProfile(); + } + } else { + ClearAnyDefaultsForLayoutTests(); + } +} + +void TestShellPlatformDelegate::SuppressErrorReporting() { + // If we die during tests, we don't want to be spamming the user's crash + // reporter. Set our exception port to null. + task_set_exception_ports(mach_task_self(), EXC_MASK_ALL, MACH_PORT_NULL, + EXCEPTION_DEFAULT, THREAD_STATE_NONE); +} + diff --git a/webkit/tools/test_shell/test_shell_platform_delegate_win.cc b/webkit/tools/test_shell/test_shell_platform_delegate_win.cc new file mode 100644 index 0000000..d03dc5f --- /dev/null +++ b/webkit/tools/test_shell/test_shell_platform_delegate_win.cc @@ -0,0 +1,110 @@ +// Copyright (c) 2006-2009 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 <windows.h> +#include <commctrl.h> +#include "base/command_line.h" +#include "base/event_recorder.h" +#include "base/gfx/native_theme.h" +#include "base/resource_util.h" +#include "base/win_util.h" +#include "webkit/tools/test_shell/foreground_helper.h" +#include "webkit/tools/test_shell/test_shell.h" +#include "webkit/tools/test_shell/test_shell_platform_delegate.h" + +TestShellPlatformDelegate::TestShellPlatformDelegate( + const CommandLine& command_line) + : command_line_(command_line) { +#ifdef _CRTDBG_MAP_ALLOC + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); +#endif +} + +TestShellPlatformDelegate::~TestShellPlatformDelegate() { +#ifdef _CRTDBG_MAP_ALLOC + _CrtDumpMemoryLeaks(); +#endif +} + +void TestShellPlatformDelegate::PreflightArgs(int *argc, char ***argv) { +} + +// This test approximates whether you have the Windows XP theme selected by +// inspecting a couple of metrics. It does not catch all cases, but it does +// pick up on classic vs xp, and normal vs large fonts. Something it misses +// is changes to the color scheme (which will infact cause pixel test +// failures). +// +// ** Expected dependencies ** +// + Theme: Windows XP +// + Color scheme: Default (blue) +// + Font size: Normal +// + Font smoothing: off (minor impact). +// +static bool HasLayoutTestThemeDependenciesWin() { + // This metric will be 17 when font size is "Normal". The size of drop-down + // menus depends on it. + if (::GetSystemMetrics(SM_CXVSCROLL) != 17) + return false; + + // Check that the system fonts RenderThemeWin relies on are Tahoma 11 pt. + NONCLIENTMETRICS metrics; + win_util::GetNonClientMetrics(&metrics); + LOGFONTW* system_fonts[] = + { &metrics.lfStatusFont, &metrics.lfMenuFont, &metrics.lfSmCaptionFont }; + + for (size_t i = 0; i < arraysize(system_fonts); ++i) { + if (system_fonts[i]->lfHeight != -11 || + 0 != wcscmp(L"Tahoma", system_fonts[i]->lfFaceName)) + return false; + } + return true; +} + +bool TestShellPlatformDelegate::CheckLayoutTestSystemDependencies() { + bool has_deps = HasLayoutTestThemeDependenciesWin(); + if (!has_deps) { + fprintf(stderr, + "\n" + "###############################################################\n" + "## Layout test system dependencies check failed.\n" + "## Some layout tests may fail due to unexpected theme.\n" + "##\n" + "## To fix, go to Display Properties -> Appearance, and select:\n" + "## + Windows and buttons: Windows XP style\n" + "## + Color scheme: Default (blue)\n" + "## + Font size: Normal\n" + "###############################################################\n"); + } + return has_deps; +} + +void TestShellPlatformDelegate::SuppressErrorReporting() { + _set_abort_behavior(0, _WRITE_ABORT_MSG); +} + +void TestShellPlatformDelegate::InitializeGUI() { + INITCOMMONCONTROLSEX InitCtrlEx; + + InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; + InitCommonControlsEx(&InitCtrlEx); + TestShell::RegisterWindowClass(); +} + +void TestShellPlatformDelegate::SelectUnifiedTheme() { + gfx::NativeTheme::instance()->DisableTheming(); +} + +void TestShellPlatformDelegate::SetWindowPositionForRecording( + TestShell *shell) { + // Move the window to the upper left corner for consistent + // record/playback mode. For automation, we want this to work + // on build systems where the script invoking us is a background + // process. So for this case, make our window the topmost window + // as well. + ForegroundHelper::SetForeground(shell->mainWnd()); + ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0); +} diff --git a/webkit/tools/test_shell/test_shell_tests.vcproj b/webkit/tools/test_shell/test_shell_tests.vcproj index 2b0bb22..3251e8c 100644 --- a/webkit/tools/test_shell/test_shell_tests.vcproj +++ b/webkit/tools/test_shell/test_shell_tests.vcproj @@ -226,6 +226,14 @@ RelativePath=".\resources\test_shell.rc" > </File> + <File + RelativePath=".\test_shell_platform_delegate.h" + > + </File> + <File + RelativePath=".\test_shell_platform_delegate_win.cc" + > + </File> <File RelativePath=".\test_shell_request_context.cc" > diff --git a/webkit/tools/test_shell/test_shell_win.cc b/webkit/tools/test_shell/test_shell_win.cc index 28fabc5..3f82fe8 100644 --- a/webkit/tools/test_shell/test_shell_win.cc +++ b/webkit/tools/test_shell/test_shell_win.cc @@ -22,6 +22,7 @@ #include "base/trace_event.h" #include "base/win_util.h" #include "breakpad/src/client/windows/handler/exception_handler.h" +#include "net/base/net_module.h" #include "net/http/http_network_layer.h" #include "net/url_request/url_request_file_job.h" #include "skia/ext/bitmap_platform_device.h" @@ -126,7 +127,7 @@ FilePath GetResourcesFilePath() { return path.AppendASCII("resources"); } -StringPiece GetRawDataResource(HMODULE module, int resource_id) { +static StringPiece GetRawDataResource(HMODULE module, int resource_id) { void* data_ptr; size_t data_size; return base::GetDataResourceFromModule(module, resource_id, &data_ptr, @@ -134,6 +135,11 @@ StringPiece GetRawDataResource(HMODULE module, int resource_id) { StringPiece(static_cast<char*>(data_ptr), data_size) : StringPiece(); } +// This is called indirectly by the network layer to access resources. +StringPiece NetResourceProvider(int key) { + return GetRawDataResource(::GetModuleHandle(NULL), key); +} + } // namespace // Initialize static member variable @@ -143,6 +149,8 @@ HINSTANCE TestShell::instance_handle_; // static methods on TestShell void TestShell::InitializeTestShell(bool layout_test_mode) { + net::NetModule::SetResourceProvider(NetResourceProvider); + // Start COM stuff. HRESULT res = OleInitialize(NULL); DCHECK(SUCCEEDED(res)); |