summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorthomasvl@chromium.org <thomasvl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-25 23:58:13 +0000
committerthomasvl@chromium.org <thomasvl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-25 23:58:13 +0000
commite10de0038ade2c7b4f80745484947bb0229700ed (patch)
treef441aa73fbf8b0ba3ad6b7f6d091f0486bd60e91 /webkit
parentc3a42ad4daeb22da04a91dc5a1d7d4b64d114be7 (diff)
downloadchromium_src-e10de0038ade2c7b4f80745484947bb0229700ed.zip
chromium_src-e10de0038ade2c7b4f80745484947bb0229700ed.tar.gz
chromium_src-e10de0038ade2c7b4f80745484947bb0229700ed.tar.bz2
make the color profile manage work with multiple test shells
make the helper exit on signals make the helper exit on any input on stdin make the helper change the profile on launch, and restore on exit. remove the color profile mgmt code from test shell remove the signal handlers from test shell update the script that runs the tests to start the helper before any test shells and stop it when done. make the helper a dep of test_shell so it's built. BUG=11173 TEST=run the layout tests with pixel diffs, the color profile should still be changed. Review URL: http://codereview.chromium.org/149036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19314 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/tools/layout_tests/layout_package/path_utils.py10
-rw-r--r--webkit/tools/layout_tests/layout_package/platform_utils_mac.py3
-rwxr-xr-xwebkit/tools/layout_tests/run_webkit_tests.py30
-rw-r--r--webkit/tools/test_shell/mac/layout_test_helper.mm87
-rw-r--r--webkit/tools/test_shell/test_shell.gyp19
-rw-r--r--webkit/tools/test_shell/test_shell_platform_delegate_mac.mm98
6 files changed, 148 insertions, 99 deletions
diff --git a/webkit/tools/layout_tests/layout_package/path_utils.py b/webkit/tools/layout_tests/layout_package/path_utils.py
index 5a4adf0..2e0e464 100644
--- a/webkit/tools/layout_tests/layout_package/path_utils.py
+++ b/webkit/tools/layout_tests/layout_package/path_utils.py
@@ -187,6 +187,16 @@ def TestShellBinaryPath(target):
raise PathNotFound('unable to find test_shell at %s' % full_path)
return full_path
+def LayoutTestHelperBinaryPath(target):
+ """Gets the full path to the layout test helper binary for the target build
+ configuration. Raises PathNotFound if the file doesn't exist"""
+ platform_util = platform_utils.PlatformUtility('')
+ # try output directory from either Xcode or chrome.sln
+ full_path = platform_util.LayoutTestHelperBinaryPath(target)
+ if not os.path.exists(full_path):
+ raise PathNotFound('unable to find layout_test_helper at %s' % full_path)
+ return full_path
+
def RelativeTestFilename(filename):
"""Provide the filename of the test relative to the layout data
directory as a unix style path (a/b/c)."""
diff --git a/webkit/tools/layout_tests/layout_package/platform_utils_mac.py b/webkit/tools/layout_tests/layout_package/platform_utils_mac.py
index cb2e87e..386d7e6 100644
--- a/webkit/tools/layout_tests/layout_package/platform_utils_mac.py
+++ b/webkit/tools/layout_tests/layout_package/platform_utils_mac.py
@@ -158,6 +158,9 @@ class PlatformUtility(object):
def ImageCompareExecutablePath(self, target):
return PathFromBase('xcodebuild', target, 'image_diff')
+ def LayoutTestHelperBinaryPath(self, target):
+ return PathFromBase('xcodebuild', target, 'layout_test_helper')
+
def TestShellBinary(self):
"""The name of the binary for TestShell."""
return 'TestShell'
diff --git a/webkit/tools/layout_tests/run_webkit_tests.py b/webkit/tools/layout_tests/run_webkit_tests.py
index 83b302d..8465800 100755
--- a/webkit/tools/layout_tests/run_webkit_tests.py
+++ b/webkit/tools/layout_tests/run_webkit_tests.py
@@ -473,6 +473,14 @@ class TestRunner:
return threads
+ def _StopLayoutTestHelper(self, proc):
+ """Stop the layout test helper and closes it down."""
+ if proc:
+ logging.info("Stopping layout test helper")
+ proc.stdin.write("x\n")
+ proc.stdin.close()
+ proc.wait()
+
def Run(self):
"""Run all our tests on all our test files.
@@ -501,6 +509,22 @@ class TestRunner:
# Create the output directory if it doesn't already exist.
google.path_utils.MaybeMakeDirectory(self._options.results_directory)
+ # Start up any helper needed
+ layout_test_helper_proc = None
+ if sys.platform in ('darwin'):
+ # Mac uses a helper for manging the color sync profile for pixel tests.
+ if not options.no_pixel_tests:
+ helper_path = \
+ path_utils.LayoutTestHelperBinaryPath(self._options.target)
+ logging.info("Starting layout helper %s" % helper_path)
+ layout_test_helper_proc = subprocess.Popen([helper_path],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=None)
+ is_ready = layout_test_helper_proc.stdout.readline()
+ if is_ready != 'ready\n':
+ logging.error("layout_test_helper failed to be ready")
+
threads = self._InstantiateTestShellThreads(test_shell_binary)
# Wait for the threads to finish and collect test failures.
@@ -521,7 +545,9 @@ class TestRunner:
except KeyboardInterrupt:
for thread in threads:
thread.Cancel()
+ self._StopLayoutTestHelper(layout_test_helper_proc)
raise
+ self._StopLayoutTestHelper(layout_test_helper_proc)
for thread in threads:
# Check whether a TestShellThread died before normal completion.
exception_info = thread.GetExceptionInfo()
@@ -961,12 +987,12 @@ def main(options, args):
# TODO(ojan): Use cpus+1 once we flesh out the flakiness.
options.num_test_shells = cpus
-
+
logging.info("Running %s test_shells in parallel" % options.num_test_shells)
if not options.time_out_ms:
if options.num_test_shells > 1:
- options.time_out_ms = str(2 * TestRunner.DEFAULT_TEST_TIMEOUT_MS)
+ options.time_out_ms = str(2 * TestRunner.DEFAULT_TEST_TIMEOUT_MS)
else:
options.time_out_ms = str(TestRunner.DEFAULT_TEST_TIMEOUT_MS)
diff --git a/webkit/tools/test_shell/mac/layout_test_helper.mm b/webkit/tools/test_shell/mac/layout_test_helper.mm
new file mode 100644
index 0000000..17ab3fd
--- /dev/null
+++ b/webkit/tools/test_shell/mac/layout_test_helper.mm
@@ -0,0 +1,87 @@
+// 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.
+
+#import <AppKit/AppKit.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// This is a simple helper app that changes the color sync profile to the
+// generic profile and back when done. This program is managed by the layout
+// test script, so it can do the job for multiple test shells while they are
+// running layout tests.
+
+static CMProfileRef gUsersColorProfile = NULL;
+
+static void SaveCurrentColorProfile(void) {
+ CGDirectDisplayID displayID = CGMainDisplayID();
+ CMProfileRef previousProfile;
+ CMError error = CMGetProfileByAVID((UInt32)displayID, &previousProfile);
+ if (error) {
+ NSLog(@"failed to get the current color profile, pixmaps won't match. "
+ @"Error: %d", (int)error);
+ } else {
+ gUsersColorProfile = previousProfile;
+ }
+}
+
+static void InstallLayoutTestColorProfile(void) {
+ // To make sure we get consistent colors (not dependent on the Main display),
+ // we force the generic rgb color profile. This cases a change the user can
+ // see.
+
+ CGDirectDisplayID displayID = CGMainDisplayID();
+ NSColorSpace *genericSpace = [NSColorSpace genericRGBColorSpace];
+ CMProfileRef genericProfile = (CMProfileRef)[genericSpace colorSyncProfile];
+ CMError error = CMSetProfileByAVID((UInt32)displayID, genericProfile);
+ if (error) {
+ NSLog(@"failed install the generic color profile, pixmaps won't match. "
+ @"Error: %d", (int)error);
+ }
+}
+
+static void RestoreUsersColorProfile(void) {
+ if (gUsersColorProfile) {
+ CGDirectDisplayID displayID = CGMainDisplayID();
+ CMError error = CMSetProfileByAVID((UInt32)displayID, gUsersColorProfile);
+ CMCloseProfile(gUsersColorProfile);
+ if (error) {
+ NSLog(@"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 the color profile and try to go down cleanly
+ RestoreUsersColorProfile();
+ exit(128 + sig);
+}
+
+int main(int argc, char *argv[]) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ // Hooks the ways we might get told to clean up...
+ signal(SIGINT, SimpleSignalHandler);
+ signal(SIGHUP, SimpleSignalHandler);
+ signal(SIGTERM, SimpleSignalHandler);
+
+ // Save off the current profile, and then install the layout test profile.
+ SaveCurrentColorProfile();
+ InstallLayoutTestColorProfile();
+
+ // Let the script know we're ready
+ printf("ready\n");
+ fflush(stdout);
+
+ // Wait for any key (or signal)
+ getchar();
+
+ // Restore the profile
+ RestoreUsersColorProfile();
+
+ [pool release];
+ return 0;
+}
diff --git a/webkit/tools/test_shell/test_shell.gyp b/webkit/tools/test_shell/test_shell.gyp
index e28e690..17bdc34 100644
--- a/webkit/tools/test_shell/test_shell.gyp
+++ b/webkit/tools/test_shell/test_shell.gyp
@@ -243,6 +243,7 @@
}],
['OS=="mac"', {
'product_name': 'TestShell',
+ 'dependencies': ['layout_test_helper'],
'variables': {
'repack_path': '../../../tools/data_pack/repack.py',
},
@@ -613,5 +614,23 @@
},
],
}],
+ ['OS=="mac"', {
+ 'targets': [
+ {
+ # Helper application that manages the color sync profile on mac
+ # for the test shells run by the layout tests.
+ 'target_name': 'layout_test_helper',
+ 'type': 'executable',
+ 'sources': [
+ 'mac/layout_test_helper.mm',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/AppKit.framework',
+ ],
+ },
+ },
+ ]
+ }],
],
}
diff --git a/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm b/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm
index fdb276d..cb2f5df 100644
--- a/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm
+++ b/webkit/tools/test_shell/test_shell_platform_delegate_mac.mm
@@ -8,10 +8,6 @@
// #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"
@@ -90,74 +86,6 @@ static void ClearAnyDefaultsForLayoutTests(void) {
[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;
-
- // Currently, layout test mode implies suppressing errors in
- // test_shell_main.cc. So we call SuppressErrorReporting() and install all the
- // appropriate signal handlers. If that ever changes we should find a way to
- // restore the color profile on crashes without suppressing errors.
- atexit(RestoreUsersColorProfile);
-}
-
#if OBJC_API_VERSION == 2
static void SwizzleAllMethods(Class imposter, Class original) {
unsigned int imposterMethodCount = 0;
@@ -229,9 +157,6 @@ TestShellPlatformDelegate::TestShellPlatformDelegate(
}
TestShellPlatformDelegate::~TestShellPlatformDelegate() {
- // if we have changed the user's display color profile for pixel tests,
- // restore it.
- RestoreUsersColorProfile();
[gTestShellAutoreleasePool release];
}
@@ -259,15 +184,11 @@ void TestShellPlatformDelegate::SetWindowPositionForRecording(TestShell *) {
void TestShellPlatformDelegate::SelectUnifiedTheme() {
SetDefaultsToLayoutTestValues();
SwizzleNSPasteboard();
-
- if (command_line_.HasSwitch(test_shell::kDumpPixels)) {
- InstallLayoutTestColorProfile();
- }
}
void TestShellPlatformDelegate::SuppressErrorReporting() {
const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
-
+
// If we die during tests, we don't want to be spamming the user's crash
// reporter. Set our exception port to null and add signal handlers.
// Both of these are necessary to avoid the crash reporter. Although, we do
@@ -276,21 +197,4 @@ void TestShellPlatformDelegate::SuppressErrorReporting() {
task_set_exception_ports(mach_task_self(), EXC_MASK_ALL, MACH_PORT_NULL,
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
}
-
- // 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
}