summaryrefslogtreecommitdiffstats
path: root/Tools/WebKitTestRunner
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/WebKitTestRunner')
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp14
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h3
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp2
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp12
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp7
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h4
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm43
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro17
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundleQt.cpp34
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/win/InjectedBundleWin.cpp57
-rw-r--r--Tools/WebKitTestRunner/TestController.cpp38
-rw-r--r--Tools/WebKitTestRunner/TestController.h5
-rw-r--r--Tools/WebKitTestRunner/TestInvocation.cpp52
-rw-r--r--Tools/WebKitTestRunner/TestInvocation.h14
-rw-r--r--Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj8
-rw-r--r--Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm2
-rw-r--r--Tools/WebKitTestRunner/mac/TestInvocationMac.mm156
-rw-r--r--Tools/WebKitTestRunner/qt/TestInvocationQt.cpp34
-rw-r--r--Tools/WebKitTestRunner/qt/WebKitTestRunner.pro9
-rw-r--r--Tools/WebKitTestRunner/win/InjectedBundle.vcproj4
-rw-r--r--Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp1
-rw-r--r--Tools/WebKitTestRunner/win/TestControllerWin.cpp66
-rw-r--r--Tools/WebKitTestRunner/win/TestInvocationWin.cpp34
-rw-r--r--Tools/WebKitTestRunner/win/WebKitTestRunner.vcproj4
24 files changed, 566 insertions, 54 deletions
diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
index d042431..00933bd 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
@@ -72,7 +72,7 @@ void InjectedBundle::didReceiveMessage(WKBundleRef bundle, WKStringRef messageNa
static_cast<InjectedBundle*>(const_cast<void*>(clientInfo))->didReceiveMessage(messageName, messageBody);
}
-void InjectedBundle::initialize(WKBundleRef bundle)
+void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUserData)
{
m_bundle = bundle;
@@ -86,6 +86,8 @@ void InjectedBundle::initialize(WKBundleRef bundle)
};
WKBundleSetClient(m_bundle, &client);
+ platformInitialize(initializationUserData);
+
activateFonts();
WKBundleActivateMacFontAscentHack(m_bundle);
}
@@ -173,7 +175,15 @@ void InjectedBundle::done()
setTopLoadingFrame(0);
WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done"));
- WKRetainPtr<WKStringRef> doneMessageBody(AdoptWK, WKStringCreateWithUTF8CString(m_outputStream.str().c_str()));
+ WKRetainPtr<WKMutableDictionaryRef> doneMessageBody(AdoptWK, WKMutableDictionaryCreate());
+
+ WKRetainPtr<WKStringRef> textOutputKey(AdoptWK, WKStringCreateWithUTF8CString("TextOutput"));
+ WKRetainPtr<WKStringRef> textOutput(AdoptWK, WKStringCreateWithUTF8CString(m_outputStream.str().c_str()));
+ WKDictionaryAddItem(doneMessageBody.get(), textOutputKey.get(), textOutput.get());
+
+ WKRetainPtr<WKStringRef> textOnlyKey(AdoptWK, WKStringCreateWithUTF8CString("TextOnly"));
+ WKRetainPtr<WKBooleanRef> textOnly(AdoptWK, WKBooleanCreate(!m_layoutTestController->shouldDumpPixels()));
+ WKDictionaryAddItem(doneMessageBody.get(), textOnlyKey.get(), textOnly.get());
WKBundlePostMessage(m_bundle, doneMessageName.get(), doneMessageBody.get());
diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
index 741ade4..41b1b31 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
@@ -45,7 +45,7 @@ public:
static InjectedBundle& shared();
// Initialize the InjectedBundle.
- void initialize(WKBundleRef);
+ void initialize(WKBundleRef, WKTypeRef initializationUserData);
WKBundleRef bundle() const { return m_bundle; }
WKBundlePageGroupRef pageGroup() const { return m_pageGroup; }
@@ -82,6 +82,7 @@ private:
void didInitializePageGroup(WKBundlePageGroupRef);
void didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody);
+ void platformInitialize(WKTypeRef initializationUserData);
void resetLocalSettings();
void beginTesting();
diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp
index c4cf892..4e7f58b 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp
@@ -33,5 +33,5 @@ extern "C"
#endif
void WKBundleInitialize(WKBundleRef bundle, WKTypeRef initializationUserData)
{
- WTR::InjectedBundle::shared().initialize(bundle);
+ WTR::InjectedBundle::shared().initialize(bundle, initializationUserData);
}
diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
index 739da3b..3ce081e 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
@@ -256,6 +256,8 @@ void InjectedBundlePage::reset()
WKBundlePageSetTextZoomFactor(m_page, 1);
m_previousTestBackForwardListItem = adoptWK(WKBundleBackForwardListCopyItemAtIndex(WKBundlePageGetBackForwardList(m_page), 0));
+
+ WKBundleFrameClearOpener(WKBundlePageGetMainFrame(m_page));
}
// Loader Client Callbacks
@@ -493,6 +495,15 @@ void InjectedBundlePage::dump()
InjectedBundle::shared().layoutTestController()->invalidateWaitToDumpWatchdogTimer();
+ // Force a paint before dumping. This matches DumpRenderTree on Windows. (DumpRenderTree on Mac
+ // does this at a slightly different time.) See <http://webkit.org/b/55469> for details.
+ WKBundlePageForceRepaint(m_page);
+
+ WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
+ string url = toSTD(adoptWK(WKURLCopyString(adoptWK(WKBundleFrameCopyURL(frame)).get())));
+ if (strstr(url.c_str(), "dumpAsText/"))
+ InjectedBundle::shared().layoutTestController()->dumpAsText();
+
switch (InjectedBundle::shared().layoutTestController()->whatToDump()) {
case LayoutTestController::RenderTree: {
WKRetainPtr<WKStringRef> text(AdoptWK, WKBundlePageCopyRenderTreeExternalRepresentation(m_page));
@@ -635,6 +646,7 @@ WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef, WKB
return 0;
}
+ WKRetain(request);
return request;
}
diff --git a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp
index 4707ed8..96a0d47 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp
@@ -94,6 +94,7 @@ LayoutTestController::LayoutTestController()
, m_dumpEditingCallbacks(false)
, m_dumpStatusCallbacks(false)
, m_dumpTitleChanges(false)
+ , m_dumpPixels(true)
, m_waitToDump(false)
, m_testRepaint(false)
, m_testRepaintSweepHorizontally(false)
@@ -116,6 +117,12 @@ void LayoutTestController::display()
// FIXME: actually implement, once we want pixel tests
}
+void LayoutTestController::dumpAsText()
+{
+ m_whatToDump = MainFrameText;
+ m_dumpPixels = false;
+}
+
void LayoutTestController::waitUntilDone()
{
m_waitToDump = true;
diff --git a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h
index 9271124..6733380 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h
@@ -55,7 +55,7 @@ public:
void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception);
// The basics.
- void dumpAsText() { m_whatToDump = MainFrameText; }
+ void dumpAsText();
void dumpChildFramesAsText() { m_whatToDump = AllFramesText; }
void waitUntilDone();
void notifyDone();
@@ -114,6 +114,7 @@ public:
bool shouldDumpMainFrameScrollPosition() const { return m_whatToDump == RenderTree; }
bool shouldDumpStatusCallbacks() const { return m_dumpStatusCallbacks; }
bool shouldDumpTitleChanges() const { return m_dumpTitleChanges; }
+ bool shouldDumpPixels() const { return m_dumpPixels; }
bool waitToDump() const { return m_waitToDump; }
void waitToDumpWatchdogTimerFired();
@@ -154,6 +155,7 @@ private:
bool m_dumpEditingCallbacks;
bool m_dumpStatusCallbacks;
bool m_dumpTitleChanges;
+ bool m_dumpPixels;
bool m_waitToDump; // True if waitUntilDone() has been called, but notifyDone() has not yet been called.
bool m_testRepaint;
bool m_testRepaintSweepHorizontally;
diff --git a/Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm b/Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm
new file mode 100644
index 0000000..7cb8dfa
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/mac/InjectedBundleMac.mm
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "InjectedBundle.h"
+
+namespace WTR {
+
+void InjectedBundle::platformInitialize(WKTypeRef)
+{
+ NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger:4], @"AppleAntiAliasingThreshold",
+ [NSNumber numberWithInteger:0], @"AppleFontSmoothing",
+ [NSNumber numberWithBool:NO], @"AppleScrollAnimationEnabled",
+ [NSNumber numberWithBool:NO], @"NSOverlayScrollersEnabled",
+ @"Always", @"AppleShowScrollBars",
+ nil];
+
+ [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
+}
+
+} // namespace WTR
diff --git a/Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro b/Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro
index 24db4b8..6838205 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro
+++ b/Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundle.pro
@@ -24,6 +24,7 @@ SOURCES += \
../LayoutTestController.h \
../Bindings/JSWrapper.cpp \
ActivateFontsQt.cpp \
+ InjectedBundleQt.cpp \
LayoutTestControllerQt.cpp \
$$GENERATED_SOURCES_DIR/JSEventSendingController.cpp \
$$GENERATED_SOURCES_DIR/JSGCController.cpp \
@@ -45,27 +46,29 @@ HEADERS += \
include(../../../../Source/WebKit.pri)
include(../../../../Source/JavaScriptCore/JavaScriptCore.pri)
-addJavaScriptCoreLib(../../../JavaScriptCore)
+prependJavaScriptCoreLib(../../../JavaScriptCore)
include(../../../../Source/WebKit2/WebKit2.pri)
-addWebKit2Lib(../../../WebKit2)
+prependWebKit2Lib(../../../WebKit2)
-INCLUDEPATH += \
+INCLUDEPATH = \
$$PWD \
$$PWD/.. \
$$PWD/../.. \
$$PWD/../Bindings \
+ $$PWD/../../../../Source \
$$PWD/../../../../Source/JavaScriptCore \
- $$PWD/../../../../Source/JavaScriptCore/wtf \
+ $$PWD/../../../../Source/JavaScriptCore/ForwardingHeaders \
+ $$PWD/../../../../Source/JavaScriptCore/wtf/unicode \
$$PWD/../../../../Source/WebCore \
$$PWD/../../../../Source/WebCore/platform/text \
$$PWD/../../../../Source/WebKit2 \
$$PWD/../../../../Source/WebKit2/Shared \
- $$GENERATED_SOURCES_DIR
-
-INCLUDEPATH += \
+ $$OUTPUT_DIR/include/QtWebKit \
$$OUTPUT_DIR/include \
+ $$GENERATED_SOURCES_DIR \
$$WC_GENERATED_SOURCES_DIR
+
PREFIX_HEADER = $$PWD/../../WebKitTestRunnerPrefix.h
*-g++*:QMAKE_CXXFLAGS += "-include $$PREFIX_HEADER"
diff --git a/Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundleQt.cpp b/Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundleQt.cpp
new file mode 100644
index 0000000..52502ed
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/qt/InjectedBundleQt.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "InjectedBundle.h"
+
+namespace WTR {
+
+void InjectedBundle::platformInitialize(WKTypeRef)
+{
+}
+
+} // namespace WTR
diff --git a/Tools/WebKitTestRunner/InjectedBundle/win/InjectedBundleWin.cpp b/Tools/WebKitTestRunner/InjectedBundle/win/InjectedBundleWin.cpp
new file mode 100644
index 0000000..af8eaed
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/win/InjectedBundleWin.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "InjectedBundle.h"
+
+namespace WTR {
+
+static HANDLE webProcessCrashingEvent;
+
+static LONG WINAPI exceptionFilter(EXCEPTION_POINTERS*)
+{
+ // Let the UI process know right away that we crashed. It might take a long time for us to
+ // finish crashing if a crash log is being saved.
+ ::SetEvent(webProcessCrashingEvent);
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+void InjectedBundle::platformInitialize(WKTypeRef initializationUserData)
+{
+ ::SetUnhandledExceptionFilter(exceptionFilter);
+
+ ASSERT_ARG(initializationUserData, initializationUserData);
+ ASSERT_ARG(initializationUserData, WKGetTypeID(initializationUserData) == WKStringGetTypeID());
+
+ WKStringRef string = static_cast<WKStringRef>(initializationUserData);
+ Vector<char> buffer(WKStringGetMaximumUTF8CStringSize(string));
+ WKStringGetUTF8CString(string, buffer.data(), buffer.size());
+
+ // The UI process should already have created this event. We're just getting another HANDLE to it.
+ webProcessCrashingEvent = ::CreateEventA(0, FALSE, FALSE, buffer.data());
+ ASSERT(webProcessCrashingEvent);
+}
+
+} // namespace WTR
diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp
index 6f5b9a7..d12fff6 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -63,6 +63,8 @@ TestController::TestController(int argc, const char* argv[])
, m_doneResetting(false)
, m_longTimeout(defaultLongTimeout)
, m_shortTimeout(defaultShortTimeout)
+ , m_didPrintWebProcessCrashedMessage(false)
+ , m_shouldExitWhenWebProcessCrashes(true)
{
initialize(argc, argv);
controller = this;
@@ -327,7 +329,8 @@ void TestController::initialize(int argc, const char* argv[])
0, // didBecomeUnresponsive
0, // didBecomeResponsive
processDidCrash, // processDidCrash
- 0 // didChangeBackForwardList
+ 0, // didChangeBackForwardList
+ 0 // shouldGoToBackForwardListItem
};
WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
}
@@ -383,8 +386,20 @@ bool TestController::runTest(const char* test)
return false;
}
+ std::string pathOrURL(test);
+ std::string expectedPixelHash;
+ size_t separatorPos = pathOrURL.find("'");
+ if (separatorPos != std::string::npos) {
+ pathOrURL = std::string(std::string(test), 0, separatorPos);
+ expectedPixelHash = std::string(std::string(test), separatorPos + 1);
+ }
+
m_state = RunningTest;
- m_currentInvocation.set(new TestInvocation(test));
+
+ m_currentInvocation.set(new TestInvocation(pathOrURL));
+ if (m_dumpPixels)
+ m_currentInvocation->setIsPixelTest(expectedPixelHash);
+
m_currentInvocation->invoke();
m_currentInvocation.clear();
@@ -395,7 +410,7 @@ void TestController::runTestingServerLoop()
{
char filenameBuffer[2048];
while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
- char *newLineCharacter = strchr(filenameBuffer, '\n');
+ char* newLineCharacter = strchr(filenameBuffer, '\n');
if (newLineCharacter)
*newLineCharacter = '\0';
@@ -417,7 +432,6 @@ void TestController::run()
break;
}
}
-
}
void TestController::runUntil(bool& done, TimeoutDuration timeoutDuration)
@@ -458,7 +472,7 @@ void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKT
void TestController::processDidCrash(WKPageRef page, const void* clientInfo)
{
- static_cast<TestController*>(const_cast<void*>(clientInfo))->processDidCrash(page);
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->processDidCrash();
}
void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
@@ -477,10 +491,18 @@ void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
shared().notifyDone();
}
-void TestController::processDidCrash(WKPageRef page)
+void TestController::processDidCrash()
{
- fputs("#CRASHED - WebProcess\n", stderr);
- fflush(stderr);
+ // This function can be called multiple times when crash logs are being saved on Windows, so
+ // ensure we only print the crashed message once.
+ if (!m_didPrintWebProcessCrashedMessage) {
+ fputs("#CRASHED - WebProcess\n", stderr);
+ fflush(stderr);
+ m_didPrintWebProcessCrashedMessage = true;
+ }
+
+ if (m_shouldExitWhenWebProcessCrashes)
+ exit(1);
}
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/TestController.h b/Tools/WebKitTestRunner/TestController.h
index fe37952..0630e2b 100644
--- a/Tools/WebKitTestRunner/TestController.h
+++ b/Tools/WebKitTestRunner/TestController.h
@@ -83,7 +83,7 @@ private:
void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame);
static void processDidCrash(WKPageRef, const void* clientInfo);
- void processDidCrash(WKPageRef);
+ void processDidCrash();
static WKPageRef createOtherPage(WKPageRef oldPage, WKDictionaryRef, WKEventModifiers, WKEventMouseButton, const void*);
@@ -117,6 +117,9 @@ private:
double m_longTimeout;
double m_shortTimeout;
+
+ bool m_didPrintWebProcessCrashedMessage;
+ bool m_shouldExitWhenWebProcessCrashes;
};
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp
index 3af184a..3227be9 100644
--- a/Tools/WebKitTestRunner/TestInvocation.cpp
+++ b/Tools/WebKitTestRunner/TestInvocation.cpp
@@ -30,6 +30,7 @@
#include "TestController.h"
#include <climits>
#include <cstdio>
+#include <WebKit2/WKDictionary.h>
#include <WebKit2/WKContextPrivate.h>
#include <WebKit2/WKInspector.h>
#include <WebKit2/WKRetainPtr.h>
@@ -57,7 +58,8 @@ static WKURLRef createWKURL(const char* pathOrURL)
if (!length)
return 0;
- const char* filePrefix = "file://";
+ // FIXME: Remove the "localhost/" suffix once <http://webkit.org/b/55683> is fixed.
+ const char* filePrefix = "file://localhost/";
static const size_t prefixLength = strlen(filePrefix);
#if OS(WINDOWS)
const char separator = '\\';
@@ -85,18 +87,25 @@ static WKURLRef createWKURL(const char* pathOrURL)
return WKURLCreateWithUTF8CString(buffer.get());
}
-TestInvocation::TestInvocation(const char* pathOrURL)
- : m_url(AdoptWK, createWKURL(pathOrURL))
- , m_pathOrURL(fastStrDup(pathOrURL))
+TestInvocation::TestInvocation(const std::string& pathOrURL)
+ : m_url(AdoptWK, createWKURL(pathOrURL.c_str()))
+ , m_pathOrURL(pathOrURL)
+ , m_dumpPixels(false)
, m_gotInitialResponse(false)
, m_gotFinalMessage(false)
+ , m_gotRepaint(false)
, m_error(false)
{
}
TestInvocation::~TestInvocation()
{
- fastFree(m_pathOrURL);
+}
+
+void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash)
+{
+ m_dumpPixels = true;
+ m_expectedPixelHash = expectedPixelHash;
}
static const unsigned w3cSVGWidth = 480;
@@ -104,7 +113,7 @@ static const unsigned w3cSVGHeight = 360;
static const unsigned normalWidth = 800;
static const unsigned normalHeight = 600;
-static void sizeWebViewForCurrentTest(char* pathOrURL)
+static void sizeWebViewForCurrentTest(const char* pathOrURL)
{
bool isSVGW3CTest = strstr(pathOrURL, "svg/W3C-SVG-1.1") || strstr(pathOrURL, "svg\\W3C-SVG-1.1");
@@ -116,12 +125,12 @@ static void sizeWebViewForCurrentTest(char* pathOrURL)
static bool shouldOpenWebInspector(const char* pathOrURL)
{
- return strstr(pathOrURL, "inspector/");
+ return strstr(pathOrURL, "inspector/") || strstr(pathOrURL, "inspector\\");
}
void TestInvocation::invoke()
{
- sizeWebViewForCurrentTest(m_pathOrURL);
+ sizeWebViewForCurrentTest(m_pathOrURL.c_str());
WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("BeginTest"));
WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
@@ -136,7 +145,7 @@ void TestInvocation::invoke()
return;
}
- if (shouldOpenWebInspector(m_pathOrURL))
+ if (shouldOpenWebInspector(m_pathOrURL.c_str()))
WKInspectorShow(WKPageGetInspector(TestController::shared().mainWebView()->page()));
WKPageLoadURL(TestController::shared().mainWebView()->page(), m_url.get());
@@ -156,11 +165,7 @@ void TestInvocation::dump(const char* stringToDump)
printf("%s", stringToDump);
fputs("#EOF\n", stdout);
- fputs("#EOF\n", stdout);
fputs("#EOF\n", stderr);
-
- fflush(stdout);
- fflush(stderr);
}
void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
@@ -187,11 +192,26 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
}
if (WKStringIsEqualToUTF8CString(messageName, "Done")) {
- ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
- WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody);
+ ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+ WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+
+ WKRetainPtr<WKStringRef> textOutputKey(AdoptWK, WKStringCreateWithUTF8CString("TextOutput"));
+ WKStringRef textOutput = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, textOutputKey.get()));
+
+ WKRetainPtr<WKStringRef> textOnlyKey(AdoptWK, WKStringCreateWithUTF8CString("TextOnly"));
+ bool textOnly = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, textOnlyKey.get())));
+
+ // Dump text.
+ dump(toSTD(textOutput).c_str());
- dump(toSTD(messageBodyString).c_str());
+ // Dump pixels (if necessary).
+ if (m_dumpPixels && !textOnly)
+ dumpPixelsAndCompareWithExpected();
+ fputs("#EOF\n", stdout);
+ fflush(stdout);
+ fflush(stderr);
+
m_gotFinalMessage = true;
TestController::shared().notifyDone();
return;
diff --git a/Tools/WebKitTestRunner/TestInvocation.h b/Tools/WebKitTestRunner/TestInvocation.h
index efc6635..d5a4af9 100644
--- a/Tools/WebKitTestRunner/TestInvocation.h
+++ b/Tools/WebKitTestRunner/TestInvocation.h
@@ -26,6 +26,7 @@
#ifndef TestInvocation_h
#define TestInvocation_h
+#include <string>
#include <WebKit2/WKRetainPtr.h>
#include <wtf/Noncopyable.h>
@@ -34,22 +35,29 @@ namespace WTR {
class TestInvocation {
WTF_MAKE_NONCOPYABLE(TestInvocation);
public:
- TestInvocation(const char*);
+ TestInvocation(const std::string& pathOrURL);
~TestInvocation();
+ void setIsPixelTest(const std::string& expectedPixelHash);
+
void invoke();
void didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody);
WKRetainPtr<WKTypeRef> didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody);
private:
void dump(const char*);
-
+ void dumpPixelsAndCompareWithExpected();
+
WKRetainPtr<WKURLRef> m_url;
- char* m_pathOrURL;
+ std::string m_pathOrURL;
+
+ bool m_dumpPixels;
+ std::string m_expectedPixelHash;
// Invocation state
bool m_gotInitialResponse;
bool m_gotFinalMessage;
+ bool m_gotRepaint;
bool m_error;
};
diff --git a/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj b/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj
index 8428403..62105cd 100644
--- a/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj
+++ b/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj
@@ -47,6 +47,8 @@
BC7934AC1190658C005EA8E2 /* WebKit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC7934AB1190658C005EA8E2 /* WebKit2.framework */; };
BC7934E811906846005EA8E2 /* PlatformWebViewMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC7934E711906846005EA8E2 /* PlatformWebViewMac.mm */; };
BC8C795C11D2785D004535A1 /* TestControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC8C795B11D2785D004535A1 /* TestControllerMac.mm */; };
+ BC8DAD5D1315C0EC00EC96FC /* TestInvocationMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC8DAD5B1315C0EC00EC96FC /* TestInvocationMac.mm */; };
+ BC8DAD7B1316D91000EC96FC /* InjectedBundleMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC8DAD771316D7B900EC96FC /* InjectedBundleMac.mm */; };
BC8FD8CA120E527F00F3E71A /* EventSendingController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC8FD8C9120E527F00F3E71A /* EventSendingController.cpp */; };
BC8FD8D2120E545B00F3E71A /* JSEventSendingController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC8FD8D0120E545B00F3E71A /* JSEventSendingController.cpp */; };
BC952C0D11F3B965003398B4 /* JSWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC952C0C11F3B965003398B4 /* JSWrapper.cpp */; };
@@ -113,6 +115,8 @@
BC7934DD119066EC005EA8E2 /* PlatformWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformWebView.h; sourceTree = "<group>"; };
BC7934E711906846005EA8E2 /* PlatformWebViewMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformWebViewMac.mm; sourceTree = "<group>"; };
BC8C795B11D2785D004535A1 /* TestControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestControllerMac.mm; sourceTree = "<group>"; };
+ BC8DAD5B1315C0EC00EC96FC /* TestInvocationMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestInvocationMac.mm; sourceTree = "<group>"; };
+ BC8DAD771316D7B900EC96FC /* InjectedBundleMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InjectedBundleMac.mm; sourceTree = "<group>"; };
BC8FD8C8120E527F00F3E71A /* EventSendingController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventSendingController.h; sourceTree = "<group>"; };
BC8FD8C9120E527F00F3E71A /* EventSendingController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventSendingController.cpp; sourceTree = "<group>"; };
BC8FD8CB120E52B000F3E71A /* EventSendingController.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EventSendingController.idl; sourceTree = "<group>"; };
@@ -218,6 +222,7 @@
isa = PBXGroup;
children = (
65EB859F11EC67CC0034D300 /* ActivateFonts.mm */,
+ BC8DAD771316D7B900EC96FC /* InjectedBundleMac.mm */,
);
path = mac;
sourceTree = "<group>";
@@ -278,6 +283,7 @@
BC7933FF118F7C84005EA8E2 /* main.mm */,
BC7934E711906846005EA8E2 /* PlatformWebViewMac.mm */,
BC8C795B11D2785D004535A1 /* TestControllerMac.mm */,
+ BC8DAD5B1315C0EC00EC96FC /* TestInvocationMac.mm */,
);
path = mac;
sourceTree = "<group>";
@@ -440,6 +446,7 @@
BC793431118F7F19005EA8E2 /* TestController.cpp in Sources */,
BC7934E811906846005EA8E2 /* PlatformWebViewMac.mm in Sources */,
BCD7D2F811921278006DB7EE /* TestInvocation.cpp in Sources */,
+ BC8DAD5D1315C0EC00EC96FC /* TestInvocationMac.mm in Sources */,
BC8C795C11D2785D004535A1 /* TestControllerMac.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -457,6 +464,7 @@
BC952F1F11F3C652003398B4 /* JSLayoutTestController.cpp in Sources */,
BC14E4DB120E02D000826C0C /* GCController.cpp in Sources */,
BC14E4EA120E03D800826C0C /* JSGCController.cpp in Sources */,
+ BC8DAD7B1316D91000EC96FC /* InjectedBundleMac.mm in Sources */,
BC8FD8CA120E527F00F3E71A /* EventSendingController.cpp in Sources */,
BC8FD8D2120E545B00F3E71A /* JSEventSendingController.cpp in Sources */,
C0CE720B1247C93300BC0EC4 /* LayoutTestControllerMac.mm in Sources */,
diff --git a/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm b/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm
index b68f6a3..8415692 100644
--- a/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm
+++ b/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm
@@ -34,7 +34,7 @@ PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGro
NSRect windowRect = NSOffsetRect(rect, -10000, [[[NSScreen screens] objectAtIndex:0] frame].size.height - rect.size.height + 10000);
m_window = [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
- [m_window setColorSpace:[[NSScreen mainScreen] colorSpace]];
+ [m_window setColorSpace:[NSColorSpace genericRGBColorSpace]];
[[m_window contentView] addSubview:m_view];
[m_window orderBack:nil];
[m_window setAutodisplay:NO];
diff --git a/Tools/WebKitTestRunner/mac/TestInvocationMac.mm b/Tools/WebKitTestRunner/mac/TestInvocationMac.mm
new file mode 100644
index 0000000..13a0295
--- /dev/null
+++ b/Tools/WebKitTestRunner/mac/TestInvocationMac.mm
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "TestInvocation.h"
+
+#include "PlatformWebView.h"
+#include "TestController.h"
+#include <ImageIO/CGImageDestination.h>
+#include <LaunchServices/UTCoreTypes.h>
+#include <WebKit2/WKPage.h>
+#include <wtf/RetainPtr.h>
+
+#define COMMON_DIGEST_FOR_OPENSSL
+#include <CommonCrypto/CommonDigest.h>
+
+namespace WTR {
+
+static CGContextRef createCGContextFromPlatformView(PlatformWebView* platformWebView)
+{
+ WKView* view = platformWebView->platformView();
+ [view display];
+
+ NSSize webViewSize = [view frame].size;
+ size_t pixelsWide = static_cast<size_t>(webViewSize.width);
+ size_t pixelsHigh = static_cast<size_t>(webViewSize.height);
+ size_t rowBytes = (4 * pixelsWide + 63) & ~63;
+ void* buffer = calloc(pixelsHigh, rowBytes);
+
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGContextRef context = CGBitmapContextCreate(buffer, pixelsWide, pixelsHigh, 8, rowBytes, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
+ CGColorSpaceRelease(colorSpace);
+
+ CGImageRef image = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, [[view window] windowNumber], kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque);
+ CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
+ CGImageRelease(image);
+
+ return context;
+}
+
+void computeMD5HashStringForContext(CGContextRef bitmapContext, char hashString[33])
+{
+ ASSERT(CGBitmapContextGetBitsPerPixel(bitmapContext) == 32); // ImageDiff assumes 32 bit RGBA, we must as well.
+ size_t pixelsHigh = CGBitmapContextGetHeight(bitmapContext);
+ size_t pixelsWide = CGBitmapContextGetWidth(bitmapContext);
+ size_t bytesPerRow = CGBitmapContextGetBytesPerRow(bitmapContext);
+
+ // We need to swap the bytes to ensure consistent hashes independently of endianness
+ MD5_CTX md5Context;
+ MD5_Init(&md5Context);
+ unsigned char* bitmapData = static_cast<unsigned char*>(CGBitmapContextGetData(bitmapContext));
+ if ((CGBitmapContextGetBitmapInfo(bitmapContext) & kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Big) {
+ for (unsigned row = 0; row < pixelsHigh; row++) {
+ uint32_t buffer[pixelsWide];
+ for (unsigned column = 0; column < pixelsWide; column++)
+ buffer[column] = OSReadLittleInt32(bitmapData, 4 * column);
+ MD5_Update(&md5Context, buffer, 4 * pixelsWide);
+ bitmapData += bytesPerRow;
+ }
+ } else {
+ for (unsigned row = 0; row < pixelsHigh; row++) {
+ MD5_Update(&md5Context, bitmapData, 4 * pixelsWide);
+ bitmapData += bytesPerRow;
+ }
+ }
+
+ unsigned char hash[16];
+ MD5_Final(hash, &md5Context);
+
+ hashString[0] = '\0';
+ for (int i = 0; i < 16; i++)
+ snprintf(hashString, 33, "%s%02x", hashString, hash[i]);
+}
+
+static void dumpBitmap(CGContextRef bitmapContext)
+{
+ RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(bitmapContext));
+ RetainPtr<CFMutableDataRef> imageData(AdoptCF, CFDataCreateMutable(0, 0));
+ RetainPtr<CGImageDestinationRef> imageDest(AdoptCF, CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0));
+ CGImageDestinationAddImage(imageDest.get(), image.get(), 0);
+ CGImageDestinationFinalize(imageDest.get());
+
+ const unsigned char* data = CFDataGetBytePtr(imageData.get());
+ const size_t dataLength = CFDataGetLength(imageData.get());
+
+
+ fprintf(stdout, "Content-Type: %s\n", "image/png");
+ fprintf(stdout, "Content-Length: %lu\n", static_cast<unsigned long>(dataLength));
+
+ const size_t bytesToWriteInOneChunk = 1 << 15;
+ size_t dataRemainingToWrite = dataLength;
+ while (dataRemainingToWrite) {
+ size_t bytesToWriteInThisChunk = std::min(dataRemainingToWrite, bytesToWriteInOneChunk);
+ size_t bytesWritten = fwrite(data, 1, bytesToWriteInThisChunk, stdout);
+ if (bytesWritten != bytesToWriteInThisChunk)
+ break;
+ dataRemainingToWrite -= bytesWritten;
+ data += bytesWritten;
+ }
+}
+
+static void forceRepaintFunction(WKErrorRef, void* context)
+{
+ *static_cast<bool*>(context) = true;
+}
+
+void TestInvocation::dumpPixelsAndCompareWithExpected()
+{
+ WKPageForceRepaint(TestController::shared().mainWebView()->page(), &m_gotRepaint, forceRepaintFunction);
+ TestController::shared().runUntil(m_gotRepaint, TestController::LongTimeout);
+
+ CGContextRef context = createCGContextFromPlatformView(TestController::shared().mainWebView());
+
+ // Compute the hash of the bitmap context pixels
+ char actualHash[33];
+ computeMD5HashStringForContext(context, actualHash);
+ fprintf(stdout, "\nActualHash: %s\n", actualHash);
+
+ // Check the computed hash against the expected one and dump image on mismatch
+ bool hashesMatch = false;
+ if (m_expectedPixelHash.length() > 0) {
+ ASSERT(m_expectedPixelHash.length() == 32);
+
+ fprintf(stdout, "\nExpectedHash: %s\n", m_expectedPixelHash.c_str());
+
+ // FIXME: Do case insensitive compare.
+ if (m_expectedPixelHash == actualHash)
+ hashesMatch = true;
+ }
+
+ if (!hashesMatch)
+ dumpBitmap(context);
+}
+
+} // namespace WTR
diff --git a/Tools/WebKitTestRunner/qt/TestInvocationQt.cpp b/Tools/WebKitTestRunner/qt/TestInvocationQt.cpp
new file mode 100644
index 0000000..b5fbda4
--- /dev/null
+++ b/Tools/WebKitTestRunner/qt/TestInvocationQt.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "TestInvocation.h"
+
+namespace WTR {
+
+void TestInvocation::dumpPixelsAndCompareWithExpected()
+{
+}
+
+} // namespace WTR
diff --git a/Tools/WebKitTestRunner/qt/WebKitTestRunner.pro b/Tools/WebKitTestRunner/qt/WebKitTestRunner.pro
index de648ea..d6579a4 100644
--- a/Tools/WebKitTestRunner/qt/WebKitTestRunner.pro
+++ b/Tools/WebKitTestRunner/qt/WebKitTestRunner.pro
@@ -8,12 +8,6 @@ GENERATED_SOURCES_DIR = ../generated
include(../../../Source/WebKit.pri)
-!CONFIG(release, debug|release) {
- OBJECTS_DIR = obj/debug
-} else { # Release
- OBJECTS_DIR = obj/release
-}
-
DEFINES += USE_SYSTEM_MALLOC=1
INCLUDEPATH += \
@@ -48,6 +42,7 @@ SOURCES = \
main.cpp \
PlatformWebViewQt.cpp \
TestControllerQt.cpp \
+ TestInvocationQt.cpp \
$$BASEDIR/TestController.cpp \
$$BASEDIR/TestInvocation.cpp \
@@ -68,4 +63,4 @@ linux-* {
}
include(../../../Source/JavaScriptCore/JavaScriptCore.pri)
-addJavaScriptCoreLib(../../JavaScriptCore)
+prependJavaScriptCoreLib(../../JavaScriptCore)
diff --git a/Tools/WebKitTestRunner/win/InjectedBundle.vcproj b/Tools/WebKitTestRunner/win/InjectedBundle.vcproj
index f615d50..eec770b 100644
--- a/Tools/WebKitTestRunner/win/InjectedBundle.vcproj
+++ b/Tools/WebKitTestRunner/win/InjectedBundle.vcproj
@@ -439,6 +439,10 @@
>
</File>
<File
+ RelativePath="..\InjectedBundle\win\InjectedBundleWin.cpp"
+ >
+ </File>
+ <File
RelativePath="..\InjectedBundle\EventSendingController.cpp"
>
</File>
diff --git a/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp b/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp
index c132275..e75ccc8 100644
--- a/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp
+++ b/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp
@@ -54,6 +54,7 @@ PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGro
RECT viewRect = {0, 0, 800, 600};
m_window = CreateWindowExW(0, hostWindowClassName, L"WebKitTestRunner", WS_OVERLAPPEDWINDOW, 0 /*XOFFSET*/, 0 /*YOFFSET*/, viewRect.right, viewRect.bottom, 0, 0, GetModuleHandle(0), 0);
m_view = WKViewCreate(viewRect, contextRef, pageGroupRef, m_window);
+ WKViewSetIsInWindow(m_view, true);
}
PlatformWebView::~PlatformWebView()
diff --git a/Tools/WebKitTestRunner/win/TestControllerWin.cpp b/Tools/WebKitTestRunner/win/TestControllerWin.cpp
index 5af5503..6201cf7 100644
--- a/Tools/WebKitTestRunner/win/TestControllerWin.cpp
+++ b/Tools/WebKitTestRunner/win/TestControllerWin.cpp
@@ -38,6 +38,13 @@ using namespace std;
namespace WTR {
+static HANDLE webProcessCrashingEvent;
+static const char webProcessCrashingEventName[] = "WebKitTestRunner.WebProcessCrashing";
+// This is the longest we'll wait (in seconds) for the web process to finish crashing and a crash
+// log to be saved. This interval should be just a tiny bit longer than it will ever reasonably
+// take to save a crash log.
+static const double maximumWaitForWebProcessToCrash = 60;
+
#ifdef DEBUG_ALL
const LPWSTR testPluginDirectoryName = L"TestNetscapePlugin_Debug";
const char* injectedBundleDLL = "\\InjectedBundle_debug.dll";
@@ -96,6 +103,11 @@ void TestController::notifyDone()
void TestController::platformInitialize()
{
+ // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
+ // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
+ // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
+ ::SetErrorMode(0);
+
::SetUnhandledExceptionFilter(exceptionFilter);
_setmode(1, _O_BINARY);
@@ -104,6 +116,8 @@ void TestController::platformInitialize()
// Add the QuickTime dll directory to PATH or QT 7.6 will fail to initialize on systems
// linked with older versions of qtmlclientlib.dll.
addQTDirToPATH();
+
+ webProcessCrashingEvent = ::CreateEventA(0, FALSE, FALSE, webProcessCrashingEventName);
}
void TestController::initializeInjectedBundlePath()
@@ -124,19 +138,26 @@ void TestController::initializeTestPluginDirectory()
m_testPluginDirectory.adopt(WKStringCreateWithCFString(testPluginDirectoryPath.get()));
}
-void TestController::platformRunUntil(bool& done, double timeout)
+enum RunLoopResult { TimedOut, ObjectSignaled, ConditionSatisfied };
+
+static RunLoopResult runRunLoopUntil(bool& condition, HANDLE object, double timeout)
{
DWORD end = ::GetTickCount() + timeout * 1000;
- while (!done) {
+ while (!condition) {
DWORD now = ::GetTickCount();
if (now > end)
- return;
+ return TimedOut;
- DWORD result = ::MsgWaitForMultipleObjectsEx(0, 0, end - now, QS_ALLINPUT, 0);
+ DWORD objectCount = object ? 1 : 0;
+ const HANDLE* objects = object ? &object : 0;
+ DWORD result = ::MsgWaitForMultipleObjectsEx(objectCount, objects, end - now, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
if (result == WAIT_TIMEOUT)
- return;
+ return TimedOut;
- ASSERT(result == WAIT_OBJECT_0);
+ if (objectCount && result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + objectCount)
+ return ObjectSignaled;
+
+ ASSERT(result == WAIT_OBJECT_0 + objectCount);
// There are messages in the queue. Process them.
MSG msg;
while (::PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) {
@@ -144,12 +165,45 @@ void TestController::platformRunUntil(bool& done, double timeout)
::DispatchMessageW(&msg);
}
}
+
+ return ConditionSatisfied;
+}
+
+void TestController::platformRunUntil(bool& done, double timeout)
+{
+ RunLoopResult result = runRunLoopUntil(done, webProcessCrashingEvent, timeout);
+ if (result == TimedOut || result == ConditionSatisfied)
+ return;
+ ASSERT(result == ObjectSignaled);
+
+ // The web process is crashing. A crash log might be being saved, which can take a long
+ // time, and we don't want to time out while that happens.
+
+ // First, let the test harness know this happened so it won't think we've hung. But
+ // make sure we don't exit just yet!
+ m_shouldExitWhenWebProcessCrashes = false;
+ processDidCrash();
+ m_shouldExitWhenWebProcessCrashes = true;
+
+ // Then spin a run loop until it finishes crashing to give time for a crash log to be saved. If
+ // it takes too long for a crash log to be saved, we'll just give up.
+ bool neverSetCondition = false;
+ result = runRunLoopUntil(neverSetCondition, 0, maximumWaitForWebProcessToCrash);
+ ASSERT_UNUSED(result, result == TimedOut);
+ exit(1);
+}
+
+static WKRetainPtr<WKStringRef> toWK(const char* string)
+{
+ return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithUTF8CString(string));
}
void TestController::platformInitializeContext()
{
// FIXME: Make DRT pass with Windows native controls. <http://webkit.org/b/25592>
WKContextSetShouldPaintNativeControls(m_context.get(), false);
+
+ WKContextSetInitializationUserDataForInjectedBundle(m_context.get(), toWK(webProcessCrashingEventName).get());
}
void TestController::runModal(PlatformWebView*)
diff --git a/Tools/WebKitTestRunner/win/TestInvocationWin.cpp b/Tools/WebKitTestRunner/win/TestInvocationWin.cpp
new file mode 100644
index 0000000..b5fbda4
--- /dev/null
+++ b/Tools/WebKitTestRunner/win/TestInvocationWin.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "TestInvocation.h"
+
+namespace WTR {
+
+void TestInvocation::dumpPixelsAndCompareWithExpected()
+{
+}
+
+} // namespace WTR
diff --git a/Tools/WebKitTestRunner/win/WebKitTestRunner.vcproj b/Tools/WebKitTestRunner/win/WebKitTestRunner.vcproj
index 09dea95..e12338a 100644
--- a/Tools/WebKitTestRunner/win/WebKitTestRunner.vcproj
+++ b/Tools/WebKitTestRunner/win/WebKitTestRunner.vcproj
@@ -401,6 +401,10 @@
RelativePath=".\TestControllerWin.cpp"
>
</File>
+ <File
+ RelativePath=".\TestInvocationWin.cpp"
+ >
+ </File>
</Filter>
<File
RelativePath="..\PlatformWebView.h"