2010-10-07 Balazs Kelemen <kbalazs@webkit.org>
[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 WKURLRef blankURL()
38 {
39     static staticBlankURL = WKURLCreateWithUTF8CString("about:blank");
40     retun staticBlankURL;
41 }
42
43 static TestController* controller;
44
45 TestController& TestController::shared()
46 {
47     ASSERT(controller);
48     return *controller;
49 }
50
51 TestController::TestController(int argc, const char* argv[])
52     : m_dumpPixels(false)
53     , m_verbose(false)
54     , m_printSeparators(false)
55     , m_usingServerMode(false)
56     , m_state(Initial)
57     , m_doneResetting(false)
58 {
59     initialize(argc, argv);
60     controller = this;
61     run();
62     controller = 0;
63 }
64
65 TestController::~TestController()
66 {
67 }
68
69 static void closeOtherPage(WKPageRef page, const void* clientInfo)
70 {
71     WKPageClose(page);
72     const PlatformWebView* view = static_cast<const PlatformWebView*>(clientInfo);
73     delete view;
74 }
75
76 static WKPageRef createOtherPage(WKPageRef oldPage, const void*)
77 {
78     PlatformWebView* view = new PlatformWebView(WKPageGetPageNamespace(oldPage));
79     WKPageRef newPage = view->page();
80
81     view->resizeTo(800, 600);
82
83     WKPageUIClient otherPageUIClient = {
84         0,
85         view,
86         createOtherPage,
87         0,
88         closeOtherPage,
89         0,
90         0,
91         0,
92         0,
93         0,
94         0,
95         0
96     };
97     WKPageSetPageUIClient(newPage, &otherPageUIClient);
98
99     WKRetain(newPage);
100     return newPage;
101 }
102
103 void TestController::initialize(int argc, const char* argv[])
104 {
105     platformInitialize();
106
107     bool printSupportedFeatures = false;
108
109     for (int i = 1; i < argc; ++i) {
110         std::string argument(argv[i]);
111
112         if (argument == "--pixel-tests") {
113             m_dumpPixels = true;
114             continue;
115         }
116         if (argument == "--verbose") {
117             m_verbose = true;
118             continue;
119         }
120         if (argument == "--print-supported-features") {
121             printSupportedFeatures = true;
122             break;
123         }
124
125         // Skip any other arguments that begin with '--'.
126         if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-')
127             continue;
128
129         m_paths.push_back(argument);
130     }
131
132     if (printSupportedFeatures) {
133         // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
134         // transforms and accelerated compositing. When we support those features, we
135         // should match DRT's behavior.
136         exit(0);
137     }
138
139     m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
140     if (m_usingServerMode)
141         m_printSeparators = true;
142     else
143         m_printSeparators = m_paths.size() > 1;
144
145     initializeInjectedBundlePath();
146     initializeTestPluginDirectory();
147
148     m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
149     platformInitializeContext();
150
151     WKContextInjectedBundleClient injectedBundleClient = {
152         0,
153         this,
154         didReceiveMessageFromInjectedBundle,
155         0
156     };
157     WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);
158
159     _WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());
160
161     m_pageNamespace.adopt(WKPageNamespaceCreate(m_context.get()));
162     m_mainWebView = adoptPtr(new PlatformWebView(m_pageNamespace.get()));
163
164     WKPageUIClient pageUIClient = {
165         0,
166         this,
167         createOtherPage,
168         0,
169         0,
170         0,
171         0,
172         0,
173         0,
174         0,
175         0,
176         0
177     };
178     WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);
179
180     WKPageLoaderClient pageLoaderClient = {
181         0,
182         this,
183         0,
184         0,
185         0,
186         0,
187         0,
188         didFinishLoadForFrame,
189         0,
190         0,
191         0,
192         0,
193         0,
194         0,
195         0,
196         0,
197         0,
198         0,
199         0,
200         0
201     };
202     WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
203 }
204
205 void TestController::resetStateToConsistentValues()
206 {
207     m_state = Resetting;
208
209     // FIXME: This function should also ensure that there is only one page open.
210
211     // Reset preferences
212     WKPreferencesRef preferences = WKContextGetPreferences(m_context.get());
213     WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true);
214     WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing);
215     WKPreferencesSetXSSAuditorEnabled(preferences, false);
216
217     static WKStringRef standardFontFamily = WKStringCreateWithUTF8CString("Times");
218     static WKStringRef cursiveFontFamily = WKStringCreateWithUTF8CString("Apple Chancery");
219     static WKStringRef fantasyFontFamily = WKStringCreateWithUTF8CString("Papyrus");
220     static WKStringRef fixedFontFamily = WKStringCreateWithUTF8CString("Courier");
221     static WKStringRef sansSerifFontFamily = WKStringCreateWithUTF8CString("Helvetica");
222     static WKStringRef serifFontFamily = WKStringCreateWithUTF8CString("Times");
223
224     WKPreferencesSetStandardFontFamily(preferences, standardFontFamily);
225     WKPreferencesSetCursiveFontFamily(preferences, cursiveFontFamily);
226     WKPreferencesSetFantasyFontFamily(preferences, fantasyFontFamily);
227     WKPreferencesSetFixedFontFamily(preferences, fixedFontFamily);
228     WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily);
229     WKPreferencesSetSerifFontFamily(preferences, serifFontFamily);
230
231     m_mainWebView->focus();
232
233     // Reset main page back to about:blank
234     m_doneResetting = false;
235
236     WKPageLoadURL(m_mainWebView->page(), blankURL());
237     TestController::runUntil(m_doneResetting);
238 }
239
240 void TestController::runTest(const char* test)
241 {
242     resetStateToConsistentValues();
243
244     m_state = RunningTest;
245     m_currentInvocation.set(new TestInvocation(test));
246     m_currentInvocation->invoke();
247     m_currentInvocation.clear();
248 }
249
250 void TestController::runTestingServerLoop()
251 {
252     char filenameBuffer[2048];
253     while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
254         char *newLineCharacter = strchr(filenameBuffer, '\n');
255         if (newLineCharacter)
256             *newLineCharacter = '\0';
257
258         if (strlen(filenameBuffer) == 0)
259             continue;
260
261         runTest(filenameBuffer);
262     }
263 }
264
265 void TestController::run()
266 {
267     if (m_usingServerMode)
268         runTestingServerLoop();
269     else {
270         for (size_t i = 0; i < m_paths.size(); ++i)
271             runTest(m_paths[i].c_str());
272     }
273 }
274
275 // WKContextInjectedBundleClient
276
277 void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
278 {
279     static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
280 }
281
282 void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
283 {
284     m_currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
285 }
286
287 // WKPageLoaderClient
288
289 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
290 {
291     static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
292 }
293
294 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
295 {
296     if (m_state != Resetting)
297         return;
298
299     if (!WKFrameIsMainFrame(frame))
300         return;
301
302     WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
303     if (!WKURLIsEqual(wkURL.get(), blankURL()))
304         return;
305
306     m_doneResetting = true;
307 }
308
309 } // namespace WTR