[GTK] Remove unnecessary GLIB_CHECK_VERSION #ifdefs
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / gtk / tests / TestInspectorServer.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics Ltd. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "WebViewTest.h"
28 #include <wtf/gobject/GRefPtr.h>
29 #include <wtf/text/WTFString.h>
30
31 // Name of the test server application creating the webView object.
32 static const char* gTestServerAppName = "InspectorTestServer";
33
34 // Max seconds to wait for the test server before inspecting it.
35 static const int gMaxWaitForChild = 5;
36
37 // The PID for the test server running, so we can kill it if needed.
38 static GPid gChildProcessPid = 0;
39
40 // Whether the child has replied and it's ready.
41 static bool gChildIsReady = false;
42
43 static void stopTestServer()
44 {
45     // Do nothing if there's no server running.
46     if (!gChildProcessPid)
47         return;
48
49     g_spawn_close_pid(gChildProcessPid);
50     kill(gChildProcessPid, SIGTERM);
51     gChildProcessPid = 0;
52 }
53
54 static void sigAbortHandler(int sigNum)
55 {
56     // Just stop the test server if SIGABRT was received.
57     stopTestServer();
58 }
59
60 static gpointer testServerMonitorThreadFunc(gpointer)
61 {
62     // Wait for the specified timeout to happen.
63     g_usleep(gMaxWaitForChild * G_USEC_PER_SEC);
64
65     // Kill the child process if not ready yet.
66     if (!gChildIsReady)
67         stopTestServer();
68
69     g_thread_exit(0);
70     return 0;
71 }
72
73 static void startTestServerMonitor()
74 {
75     gChildIsReady = false;
76     g_thread_new("TestServerMonitor", testServerMonitorThreadFunc, 0);
77 }
78
79 static void startTestServer()
80 {
81     // Prepare argv[] for spawning the server process.
82     GOwnPtr<char> testServerPath(g_build_filename(WEBKIT_EXEC_PATH, "WebKit2APITests", gTestServerAppName, NULL));
83
84     // We install a handler to ensure that we kill the child process
85     // if the parent dies because of whatever the reason is.
86     signal(SIGABRT, sigAbortHandler);
87
88     char* testServerArgv[2];
89     testServerArgv[0] = testServerPath.get();
90     testServerArgv[1] = 0;
91
92     // Spawn the server, getting its stdout file descriptor to set a
93     // communication channel, so we know when it's ready.
94     int childStdout = 0;
95     g_assert(g_spawn_async_with_pipes(0, testServerArgv, 0, static_cast<GSpawnFlags>(0), 0, 0,
96         &gChildProcessPid, 0, &childStdout, 0, 0));
97
98     // Start monitoring the test server (in a separate thread) to
99     // ensure we don't block on the child process more than a timeout.
100     startTestServerMonitor();
101
102     char msg[2];
103     GIOChannel* ioChannel = g_io_channel_unix_new(childStdout);
104     if (g_io_channel_read_chars(ioChannel, msg, 2, 0, 0) == G_IO_STATUS_NORMAL) {
105         // Check whether the server sent a message saying it's ready
106         // and store the result globally, so the monitor can see it.
107         gChildIsReady = msg[0] == 'O' && msg[1] == 'K';
108     }
109     g_io_channel_unref(ioChannel);
110     close(childStdout);
111
112     // The timeout was reached and the server is not ready yet, so
113     // stop it inmediately, and let the unit tests fail.
114     if (!gChildIsReady)
115         stopTestServer();
116 }
117
118 class InspectorServerTest: public WebViewTest {
119 public:
120     MAKE_GLIB_TEST_FIXTURE(InspectorServerTest);
121
122     InspectorServerTest()
123         : WebViewTest()
124     {
125     }
126
127     bool getPageList()
128     {
129         loadHtml("<script type=\"text/javascript\">\n"
130             "var pages;\n"
131             "var xhr = new XMLHttpRequest;\n"
132             "xhr.open(\"GET\", \"/pagelist.json\");\n"
133             "xhr.onload = function(e) {\n"
134                 "if (xhr.status == 200) {\n"
135                     "pages = JSON.parse(xhr.responseText);\n"
136                     "document.title = \"OK\";\n"
137                 "} else \n"
138                     "document.title = \"FAIL\";\n"
139                 "}\n"
140             "xhr.send();\n"
141             "</script>\n",
142             "http://127.0.0.1:2999/");
143
144         waitUntilTitleChanged();
145
146         if (!strcmp(webkit_web_view_get_title(m_webView), "OK"))
147             return true;
148
149         return false;
150     }
151
152     ~InspectorServerTest()
153     {
154     }
155 };
156
157 // Test to get inspector server page list from the test server.
158 // Should contain only one entry pointing to http://127.0.0.1:2999/webinspector/inspector.html?page=1
159 static void testInspectorServerPageList(InspectorServerTest* test, gconstpointer)
160 {
161     GOwnPtr<GError> error;
162
163     test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
164     g_assert(test->getPageList());
165
166     WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("pages.length;", &error.outPtr());
167     g_assert(javascriptResult);
168     g_assert(!error.get());
169     g_assert_cmpint(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 1);
170
171     javascriptResult = test->runJavaScriptAndWaitUntilFinished("pages[0].id;", &error.outPtr());
172     g_assert(javascriptResult);
173     g_assert(!error.get());
174     int pageId = WebViewTest::javascriptResultToNumber(javascriptResult);
175
176     GOwnPtr<char> valueString;
177     javascriptResult = test->runJavaScriptAndWaitUntilFinished("pages[0].url;", &error.outPtr());
178     g_assert(javascriptResult);
179     g_assert(!error.get());
180     valueString.set(WebViewTest::javascriptResultToCString(javascriptResult));
181     g_assert_cmpstr(valueString.get(), ==, "http://127.0.0.1:2999/");
182
183     javascriptResult = test->runJavaScriptAndWaitUntilFinished("pages[0].inspectorUrl;", &error.outPtr());
184     g_assert(javascriptResult);
185     g_assert(!error.get());
186     valueString.set(WebViewTest::javascriptResultToCString(javascriptResult));
187     String validInspectorURL = String("/webinspector/inspector.html?page=") + String::number(pageId);
188     ASSERT_CMP_CSTRING(valueString.get(), ==, validInspectorURL.utf8());
189 }
190
191 // Test sending a raw remote debugging message through our web socket server.
192 // For this specific message see: http://code.google.com/chrome/devtools/docs/protocol/tot/runtime.html#command-evaluate
193 static void testRemoteDebuggingMessage(InspectorServerTest* test, gconstpointer)
194 {
195     test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
196
197     test->loadHtml("<script type=\"text/javascript\">\n"
198         "var socket = new WebSocket('ws://127.0.0.1:2999/devtools/page/1');\n"
199         "socket.onmessage = function(message) {\n"
200             "var response = JSON.parse(message.data);\n"
201             "if (response.id === 1)\n"
202                 "document.title = response.result.result.value;\n"
203             "else\n"
204                 "document.title = \"FAIL\";\n"
205             "}\n"
206             "socket.onopen = function() {\n"
207             "socket.send('{\"id\": 1, \"method\": \"Runtime.evaluate\", \"params\": {\"expression\": \"2 + 2\" } }');\n"
208         "}\n"
209         "</script>",
210         "http://127.0.0.1:2999/");
211     test->waitUntilTitleChanged();
212
213     g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, "4");
214 }
215
216 static void openRemoteDebuggingSession(InspectorServerTest* test, gconstpointer)
217 {
218     // To test the whole pipeline this exploits a behavior of the inspector front-end which won't provide any title unless the
219     // debugging session was established correctly through web socket. It should be something like "Web Inspector - <Page URL>".
220     // In our case page URL should be http://127.0.0.1:2999/
221     // So this test case will fail if:
222     // - The page list didn't return a valid inspector URL
223     // - Or the front-end couldn't be loaded through the inspector HTTP server
224     // - Or the web socket connection couldn't be established between the front-end and the page through the inspector server
225     // Let's see if this test isn't raising too many false positives, in which case we should use a better predicate if available.
226
227     test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
228
229     g_assert(test->getPageList());
230
231     GOwnPtr<GError> error;
232     WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("pages[0].inspectorUrl;", &error.outPtr());
233     g_assert(javascriptResult);
234     g_assert(!error.get());
235
236     String resolvedURL = String("http://127.0.0.1:2999/") + String::fromUTF8(WebViewTest::javascriptResultToCString(javascriptResult));
237     test->loadURI(resolvedURL.utf8().data());
238     test->waitUntilTitleChanged();
239
240     g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, "Web Inspector - http://127.0.0.1:2999/");
241 }
242
243
244 void beforeAll()
245 {
246     // Overwrite WEBKIT_INSPECTOR_SERVER variable with default IP address but different port to avoid conflict with the test inspector server page.
247     g_setenv("WEBKIT_INSPECTOR_SERVER", "127.0.0.1:2998", TRUE);
248
249     startTestServer();
250     InspectorServerTest::add("WebKitWebInspectorServer", "test-page-list", testInspectorServerPageList);
251     InspectorServerTest::add("WebKitWebInspectorServer", "test-remote-debugging-message", testRemoteDebuggingMessage);
252     InspectorServerTest::add("WebKitWebInspectorServer", "test-open-debugging-session", openRemoteDebuggingSession);
253
254 }
255
256 void afterAll()
257 {
258     stopTestServer();
259 }