739d405fe9f19546dda9476a12a4aad7346e81b4
[WebKit-https.git] / WebKitTools / WebKitTestRunner / TestController.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "TestController.h"
27
28 #include "PlatformWebView.h"
29 #include "StringFunctions.h"
30 #include "TestInvocation.h"
31 #include <WebKit2/WKContextPrivate.h>
32 #include <WebKit2/WKPreferencesPrivate.h>
33 #include <wtf/PassOwnPtr.h>
34
35 namespace WTR {
36
37 static TestController* controller;
38
39 TestController& TestController::shared()
40 {
41     ASSERT(controller);
42     return *controller;
43 }
44
45 TestController::TestController(int argc, const char* argv[])
46     : m_dumpPixels(false)
47     , m_verbose(false)
48     , m_printSeparators(false)
49     , m_usingServerMode(false)
50     , m_state(Initial)
51     , m_doneResetting(false)
52 {
53     initialize(argc, argv);
54     controller = this;
55     run();
56     controller = 0;
57 }
58
59 TestController::~TestController()
60 {
61 }
62
63 static void closeOtherPage(WKPageRef page, const void* clientInfo)
64 {
65     WKPageClose(page);
66     const PlatformWebView* view = static_cast<const PlatformWebView*>(clientInfo);
67     delete view;
68 }
69
70 static WKPageRef createOtherPage(WKPageRef oldPage, const void*)
71 {
72     PlatformWebView* view = new PlatformWebView(WKPageGetPageNamespace(oldPage));
73     WKPageRef newPage = view->page();
74
75     view->resizeTo(800, 600);
76
77     WKPageUIClient otherPageUIClient = {
78         0,
79         view,
80         createOtherPage,
81         0,
82         closeOtherPage,
83         0,
84         0,
85         0,
86         0,
87         0,
88         0,
89         0
90     };
91     WKPageSetPageUIClient(newPage, &otherPageUIClient);
92
93     WKRetain(newPage);
94     return newPage;
95 }
96
97 void TestController::initialize(int argc, const char* argv[])
98 {
99     platformInitialize();
100
101     bool printSupportedFeatures = false;
102
103     for (int i = 1; i < argc; ++i) {
104         std::string argument(argv[i]);
105
106         if (argument == "--pixel-tests") {
107             m_dumpPixels = true;
108             continue;
109         }
110         if (argument == "--verbose") {
111             m_verbose = true;
112             continue;
113         }
114         if (argument == "--print-supported-features") {
115             printSupportedFeatures = true;
116             break;
117         }
118
119         // Skip any other arguments that begin with '--'.
120         if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-')
121             continue;
122
123         m_paths.push_back(argument);
124     }
125
126     if (printSupportedFeatures) {
127         // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
128         // transforms and accelerated compositing. When we support those features, we
129         // should match DRT's behavior.
130         exit(0);
131     }
132
133     m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
134     if (m_usingServerMode)
135         m_printSeparators = true;
136     else
137         m_printSeparators = m_paths.size() > 1;
138
139     initializeInjectedBundlePath();
140     initializeTestPluginDirectory();
141
142     m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
143     platformInitializeContext();
144
145     WKContextInjectedBundleClient injectedBundleClient = {
146         0,
147         this,
148         didReceiveMessageFromInjectedBundle,
149         0
150     };
151     WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);
152
153     _WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());
154
155     m_pageNamespace.adopt(WKPageNamespaceCreate(m_context.get()));
156     m_mainWebView = adoptPtr(new PlatformWebView(m_pageNamespace.get()));
157
158     WKPageUIClient pageUIClient = {
159         0,
160         this,
161         createOtherPage,
162         0,
163         0,
164         0,
165         0,
166         0,
167         0,
168         0,
169         0,
170         0
171     };
172     WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);
173
174     WKPageLoaderClient pageLoaderClient = {
175         0,
176         this,
177         0,
178         0,
179         0,
180         0,
181         0,
182         didFinishLoadForFrame,
183         0,
184         0,
185         0,
186         0,
187         0,
188         0,
189         0,
190         0,
191         0,
192         0,
193         0,
194         0
195     };
196     WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
197 }
198
199 void TestController::resetStateToConsistentValues()
200 {
201     m_state = Resetting;
202
203     // FIXME: This function should also ensure that there is only one page open.
204
205     // Reset preferences
206     WKPreferencesRef preferences = WKContextGetPreferences(m_context.get());
207     WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true);
208     WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing);
209     WKPreferencesSetXSSAuditorEnabled(preferences, false);
210
211     static WKStringRef standardFontFamily = WKStringCreateWithUTF8CString("Times");
212     static WKStringRef cursiveFontFamily = WKStringCreateWithUTF8CString("Apple Chancery");
213     static WKStringRef fantasyFontFamily = WKStringCreateWithUTF8CString("Papyrus");
214     static WKStringRef fixedFontFamily = WKStringCreateWithUTF8CString("Courier");
215     static WKStringRef sansSerifFontFamily = WKStringCreateWithUTF8CString("Helvetica");
216     static WKStringRef serifFontFamily = WKStringCreateWithUTF8CString("Times");
217
218     WKPreferencesSetStandardFontFamily(preferences, standardFontFamily);
219     WKPreferencesSetCursiveFontFamily(preferences, cursiveFontFamily);
220     WKPreferencesSetFantasyFontFamily(preferences, fantasyFontFamily);
221     WKPreferencesSetFixedFontFamily(preferences, fixedFontFamily);
222     WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily);
223     WKPreferencesSetSerifFontFamily(preferences, serifFontFamily);
224
225     m_mainWebView->focus();
226
227     // Reset main page back to about:blank
228     m_doneResetting = false;
229
230     WKRetainPtr<WKURLRef> url(AdoptWK, createWKURL("about:blank"));
231     WKPageLoadURL(m_mainWebView->page(), url.get());
232     TestController::runUntil(m_doneResetting);
233 }
234
235 void TestController::runTest(const char* test)
236 {
237     resetStateToConsistentValues();
238
239     m_state = RunningTest;
240     m_currentInvocation.set(new TestInvocation(test));
241     m_currentInvocation->invoke();
242     m_currentInvocation.clear();
243 }
244
245 void TestController::runTestingServerLoop()
246 {
247     char filenameBuffer[2048];
248     while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
249         char *newLineCharacter = strchr(filenameBuffer, '\n');
250         if (newLineCharacter)
251             *newLineCharacter = '\0';
252
253         if (strlen(filenameBuffer) == 0)
254             continue;
255
256         runTest(filenameBuffer);
257     }
258 }
259
260 void TestController::run()
261 {
262     if (m_usingServerMode)
263         runTestingServerLoop();
264     else {
265         for (size_t i = 0; i < m_paths.size(); ++i)
266             runTest(m_paths[i].c_str());
267     }
268 }
269
270 // WKContextInjectedBundleClient
271
272 void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
273 {
274     static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
275 }
276
277 void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
278 {
279     m_currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
280 }
281
282 // WKPageLoaderClient
283
284 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
285 {
286     static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
287 }
288
289 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
290 {
291     if (m_state != Resetting)
292         return;
293
294     if (!WKFrameIsMainFrame(frame))
295         return;
296
297     WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
298     WKRetainPtr<WKStringRef> wkURLString(AdoptWK, copyURLString(wkURL.get()));
299     if (!WKStringIsEqualToUTF8CString(wkURLString.get(), "about:blank"))
300         return;
301
302     m_doneResetting = true;
303 }
304
305 } // namespace WTR