2 <meta http-equiv=
"Pragma" content=
"no-cache" />
3 <meta http-equiv=
"Expires" content=
"-1" />
4 <link rel=
"stylesheet" href=
"test_page.css">
6 // Do a deep comparison of two values. Return true if their values are
7 // identical, false otherwise.
8 function deepCompare(left
, right
) {
9 if (typeof(left
) !== typeof(right
))
11 // If their identity is the same or they're basic types with the same value,
15 // If it's a basic type and we got here, we know they're not equal.
16 if (["undefined", "boolean", "number", "string", "function"].indexOf(
20 // Use right_keys as a set containing all keys from |right| which we haven't
23 for (var key
in right
)
24 right_keys
[key
] = true;
25 for (var key
in left
) {
26 if (key
in right_keys
) {
27 if (!deepCompare(left
[key
], right
[key
]))
30 // |left| had a key that |right| didn't.
33 delete right_keys
[key
];
35 // If there are keys left in |right_keys|, it means they didn't exist in
36 // |left|, so the objects aren't equal.
37 if (Object
.keys(right_keys
).length
> 0)
42 function AdjustHeight(frameWin
) {
43 var div
= frameWin
.document
.getElementsByTagName("div")[0];
44 var height
= frameWin
.getComputedStyle(div
).height
;
45 frameWin
.frameElement
.style
.height
= height
;
48 // Called when the tests are completed. |result| should be "PASS" if the test(s)
49 // passed, or information about the failure if the test(s) did not pass.
50 function DidExecuteTests(result
) {
51 var plugin
= document
.getElementById("plugin");
52 if (plugin
.parentNode
.removePlugin
) {
53 plugin
.parentNode
.removeChild(plugin
);
56 if (CheckPostConditions())
57 sendAutomationMessage(result
);
62 // Otherwise, we are in a subframe, so we can use this opportunity to resize
67 function AppendFrame(testcase
, i
) {
68 var p
= document
.createElement("P");
69 p
.setAttribute("class", "frame-container");
71 var title
= document
.createElement("H2");
72 title
.appendChild(document
.createTextNode(testcase
));
75 var frame
= document
.createElement("IFRAME");
76 var mode
= ExtractSearchParameter("mode");
77 var websocket_host
= ExtractSearchParameter("websocket_host");
78 var websocket_port
= ExtractSearchParameter("websocket_port");
79 var ssl_server_port
= ExtractSearchParameter("ssl_server_port");
80 var src
= "?testcase=" + testcase
;
83 if (websocket_host
!= "")
84 src
+= "&websocket_host=" + websocket_host
;
85 if (websocket_port
!= "")
86 src
+= "&websocket_port=" + websocket_port
;
87 if (ssl_server_port
!= "")
88 src
+= "&ssl_server_port=" + ssl_server_port
;
89 frame
.setAttribute("src", src
);
91 frame
.setAttribute("onload", "LoadNext(" + (i
+ 1) + ")");
94 document
.body
.appendChild(p
);
97 function LoadNext(i
) {
98 var links
= document
.links
;
100 AppendFrame(links
[i
].firstChild
.nodeValue
, i
);
104 // Remove any existing frames.
105 var existing
= document
.getElementsByClassName("frame-container");
106 while (existing
.length
)
107 existing
[0].parentNode
.removeChild(existing
[0]);
109 // Add new frames for each test, but do so one frame at a time.
113 function ExtractSearchParameter(name
) {
114 var nameIndex
= location
.search
.indexOf(name
+ "=");
115 if (nameIndex
!= -1) {
116 var value
= location
.search
.substring(nameIndex
+ name
.length
+ 1);
117 var endIndex
= value
.indexOf("&");
119 value
= value
.substring(0, endIndex
);
125 // Parses the message, looking for strings of the form:
126 // TESTING_MESSAGE:<message_type>:<message_contents>
128 // If the message_data is not a string or does not match the above format, then
129 // undefined is returned.
131 // Otherwise, returns an array containing 2 items. The 0th element is the
132 // message_type, one of:
133 // - AddPostCondition
138 // - RemovePluginWhenFinished
140 // The second item is the verbatim message_contents.
141 function ParseTestingMessage(message_data
) {
142 if (typeof(message_data
) != "string")
144 var testing_message_prefix
= "TESTING_MESSAGE";
146 var delim1
= message_data
.indexOf(delim_str
);
147 if (message_data
.substring(0, delim1
) !== testing_message_prefix
)
149 var delim2
= message_data
.indexOf(delim_str
, delim1
+ 1);
151 delim2
= message_data
.length
;
152 var message_type
= message_data
.substring(delim1
+ 1, delim2
);
153 var message_contents
= message_data
.substring(delim2
+ 1);
154 return [message_type
, message_contents
];
157 function ClearConsole() {
158 window
.document
.getElementById("console").innerHTML
= "";
161 function LogHTML(html
) {
162 window
.document
.getElementById("console").innerHTML
+= html
;
165 function RemovePluginWhenFinished() {
166 window
.document
.getElementById("container").removePlugin
= true;
169 function sendAutomationMessage(msg
) {
170 if (window
.domAutomationController
) {
171 window
.domAutomationController
.setAutomationId(0);
172 window
.domAutomationController
.send(msg
);
176 function LogTestTime(test_time
) {
177 console
.log(test_time
);
180 // If something goes really wrong, the test running inside the plugin may not
181 // terminate. For example, if the plugin does not load, the test will never
182 // send "PASS" to the browser. In this case we should explicitly use the
183 // automation controller to terminate the test.
184 function InternalError(msg
) {
185 LogHTML("<p>" + msg
);
186 sendAutomationMessage(msg
);
189 function EvalScript(script
) {
197 // Add a "PostCondition". These are bits of script that are run after the plugin
198 // is destroyed. If they evaluate to false or throw an exception, it's
199 // considered a failure.
200 function AddPostCondition(script
) {
201 conditions
.push(script
);
203 // Update the HTML to show the failure and update cookies so that ui_tests
204 // doesn't count this as a pass.
205 function ConditionFailed(error
) {
206 error_string
= "Post condition check failed: " + error
;
207 InternalError(error_string
);
209 // Iterate through the post conditions defined in |conditions| and check that
211 function CheckPostConditions() {
213 for (var i
= 0; i
< conditions
.length
; ++i
) {
214 var script
= conditions
[i
];
217 ConditionFailed("\"" + script
+ "\"");
221 ConditionFailed("\"" + script
+ "\"" + " failed with exception: " +
222 "\"" + ex
.toString() + "\"");
229 function IsTestingMessage(message_data
) {
230 return (ParseTestingMessage(message_data
) != undefined);
233 function handleTestingMessage(message_event
) {
234 var type_contents_tuple
= ParseTestingMessage(message_event
.data
);
235 if (type_contents_tuple
) {
236 var type
= type_contents_tuple
[0];
237 var contents
= type_contents_tuple
[1];
238 if (type
=== "AddPostCondition")
239 AddPostCondition(contents
);
240 else if (type
=== "ClearConsole")
242 else if (type
=== "DidExecuteTests")
243 DidExecuteTests(contents
);
244 else if (type
=== "EvalScript")
245 EvalScript(contents
);
246 else if (type
=== "LogHTML")
248 else if (type
=== "RemovePluginWhenFinished")
249 RemovePluginWhenFinished();
250 else if (type
=== "ReportProgress")
251 sendAutomationMessage(contents
);
252 else if (type
=== "LogTestTime")
253 LogTestTime(contents
);
257 function sendProgress() {
258 // We send "..." to signal that we're still working. See
259 // ppapi/tests/testing_instance.h for how this works.
260 sendAutomationMessage("...");
263 onload = function() {
264 var testcase
= ExtractSearchParameter("testcase");
265 var mode
= ExtractSearchParameter("mode");
266 document
.title
= 'Test ' + testcase
;
268 if (mode
== "nacl_newlib") {
269 obj
= document
.createElement("EMBED");
270 obj
.setAttribute("src", "ppapi_nacl_tests_newlib.nmf");
271 obj
.setAttribute("type", "application/x-nacl");
272 obj
.setAttribute("mode", mode
);
273 } else if (mode
== "nacl_glibc") {
274 obj
= document
.createElement("EMBED");
275 obj
.setAttribute("src", "ppapi_nacl_tests_glibc.nmf");
276 obj
.setAttribute("type", "application/x-nacl");
277 obj
.setAttribute("mode", mode
);
278 } else if (mode
== "nacl_pnacl") {
279 obj
= document
.createElement("EMBED");
280 obj
.setAttribute("src", "ppapi_nacl_tests_pnacl.nmf");
281 obj
.setAttribute("type", "application/x-nacl");
282 obj
.setAttribute("mode", mode
);
283 } else if (mode
== "nacl_pnacl_nonsfi") {
284 obj
= document
.createElement("EMBED");
285 obj
.setAttribute("src", "ppapi_nacl_tests_pnacl_nonsfi.nmf");
286 obj
.setAttribute("type", "application/x-nacl");
287 obj
.setAttribute("mode", mode
);
288 } else if (mode
== "mojo") {
289 obj
= document
.createElement("EMBED");
290 obj
.setAttribute("src",
291 "test_data/ppapi/tests/mojo/pnacl/ppapi_tests_mojo.nmf");
292 obj
.setAttribute("type", "application/x-pnacl");
293 obj
.setAttribute("mode", mode
);
295 var mimeType
= "application/x-ppapi-tests";
296 if (mimeType
in navigator
.mimeTypes
) {
297 obj
= document
.createElement("EMBED");
298 obj
.setAttribute("src", "http://a.b.c/test");
299 obj
.setAttribute("type", mimeType
);
301 document
.getElementById("console").innerHTML
=
302 '<span class="fail">FAIL</span>: ' +
303 '<span class="err_msg">Test plug-in is not registered.</span>';
308 obj
.setAttribute("width", 80);
309 obj
.setAttribute("height", 80);
310 obj
.setAttribute("style",
311 "background-color:#AAAAAA;border:1px solid black;");
312 obj
.setAttribute("id", "plugin");
313 obj
.setAttribute("testcase", testcase
);
314 obj
.setAttribute("protocol", window
.location
.protocol
);
315 var websocket_host
= ExtractSearchParameter("websocket_host");
316 if (websocket_host
!= "")
317 obj
.setAttribute("websocket_host", websocket_host
);
318 var websocket_port
= ExtractSearchParameter("websocket_port");
319 if (websocket_port
!= "")
320 obj
.setAttribute("websocket_port", websocket_port
);
321 var ssl_server_port
= ExtractSearchParameter("ssl_server_port");
322 if (ssl_server_port
!= "")
323 obj
.setAttribute("ssl_server_port", ssl_server_port
);
325 var container
= document
.getElementById("container");
326 container
.addEventListener("message", handleTestingMessage
, true);
328 // "error" and "crash" events will only fire for NaCl, but adding these
329 // listeners doesn't hurt in the non-NaCl cases.
330 obj
.addEventListener("error", function() {
331 InternalError("Plugin did not load. '" + obj
.lastError
+ "'");
333 obj
.addEventListener("crash", function() {
334 InternalError("Plugin crashed. '" + obj
.lastError
+ "'");
337 // NaCl sends progress events while loading. When we get one, notify the
338 // domAutomationController so that it knows we're still working.
339 obj
.addEventListener("loadstart", sendProgress
, true);
340 obj
.addEventListener("progress", sendProgress
, true);
341 obj
.addEventListener("load", sendProgress
, true);
342 obj
.addEventListener("loadend", sendProgress
, true);
344 // Register a bad dispatchEvent to make sure it isn't used. See 'EVIL' note
346 var original
= obj
.dispatchEvent
;
347 obj
.dispatchEvent = function() {
348 InternalError("Bad dispatchEvent called!");
350 container
.appendChild(obj
);
355 // This part of the script does some nefarious things to make sure that it
356 // doesn't affect the behavior of PostMessage (on which all the tests rely). In
357 // particular, we replace document.createEvent, MessageEvent.initMessageEvent,
358 // and the MessageEvent constructor. Previously, the NaCl integration
359 // implementation made use of these and would fail (http://crbug.com/82604
360 // and http://crbug.com/109775).
361 document
.createEvent = function() {
362 InternalError("Bad document.createEvent called!");
364 function MessageEvent() {
365 InternalError("Bad MessageEvent constructor called!");
367 MessageEvent
.prototype.initMessageEvent = function() {
368 InternalError("Bad MessageEvent.initMessageEvent called!");
374 <div id=
"container"></div>
375 <div id=
"console"><span class=
"load_msg">loading...
</span></div>