Home | History | Annotate | Download | only in tests
      1 <html><head>
      2 <meta http-equiv="Pragma" content="no-cache" />
      3 <meta http-equiv="Expires" content="-1" />
      4 <link rel="stylesheet" href="test_page.css">
      5 <script>
      6 function AdjustHeight(frameWin) {
      7   var div = frameWin.document.getElementsByTagName("div")[0];
      8   var height = frameWin.getComputedStyle(div).height;
      9   frameWin.frameElement.style.height = height;
     10 }
     11 
     12 // Called when the tests are completed. |result| should be "PASS" if the test(s)
     13 // passed, or information about the failure if the test(s) did not pass.
     14 function DidExecuteTests(result) {
     15   var plugin = document.getElementById("plugin");
     16   if (plugin.removePlugin) {
     17     plugin.parentNode.removeChild(plugin);
     18     plugin = undefined;
     19   }
     20   if (CheckPostConditions())
     21     sendAutomationMessage(result);
     22 
     23   if (window == top)
     24     return;
     25 
     26   // Otherwise, we are in a subframe, so we can use this opportunity to resize
     27   // ourselves.
     28   AdjustHeight(window);
     29 }
     30 
     31 function AppendFrame(testcase, i) {
     32   var p = document.createElement("P");
     33   p.setAttribute("class", "frame-container");
     34 
     35   var title = document.createElement("H2");
     36   title.appendChild(document.createTextNode(testcase));
     37   p.appendChild(title);
     38 
     39   var frame = document.createElement("IFRAME");
     40   var mode = ExtractSearchParameter("mode");
     41   var websocket_host = ExtractSearchParameter("websocket_host");
     42   var websocket_port = ExtractSearchParameter("websocket_port");
     43   var ssl_server_port = ExtractSearchParameter("ssl_server_port");
     44   var src = "?testcase=" + testcase;
     45   if (mode == "nacl")
     46     src += "&mode=nacl";
     47   if (websocket_host != "")
     48     src += "&websocket_host=" + websocket_host;
     49   if (websocket_port != "")
     50     src += "&websocket_port=" + websocket_port;
     51   if (ssl_server_port != "")
     52     src += "&ssl_server_port=" + ssl_server_port;
     53   frame.setAttribute("src", src);
     54 
     55   frame.setAttribute("onload", "LoadNext(" + (i + 1) + ")");
     56   p.appendChild(frame);
     57 
     58   document.body.appendChild(p);
     59 }
     60 
     61 function LoadNext(i) {
     62   var links = document.links;
     63   if (links.length > i)
     64     AppendFrame(links[i].firstChild.nodeValue, i);
     65 }
     66 
     67 function RunAll() {
     68   // Remove any existing frames.
     69   var existing = document.getElementsByClassName("frame-container");
     70   while (existing.length)
     71     existing[0].parentNode.removeChild(existing[0]);
     72 
     73   // Add new frames for each test, but do so one frame at a time.
     74   LoadNext(0);
     75 }
     76 
     77 function ExtractSearchParameter(name) {
     78   var nameIndex = location.search.indexOf(name + "=");
     79   if (nameIndex != -1) {
     80     var value = location.search.substring(nameIndex + name.length + 1);
     81     var endIndex = value.indexOf("&");
     82     if (endIndex != -1)
     83       value = value.substring(0, endIndex);
     84     return value;
     85   }
     86   return "";
     87 }
     88 
     89 // Parses the message, looking for strings of the form:
     90 // TESTING_MESSAGE:<message_type>:<message_contents>
     91 //
     92 // If the message_data is not a string or does not match the above format, then
     93 // undefined is returned.
     94 //
     95 // Otherwise, returns an array containing 2 items. The 0th element is the
     96 // message_type, one of:
     97 //  - AddPostCondition
     98 //  - ClearConsole
     99 //  - DidExecuteTests
    100 //  - EvalScript
    101 //  - LogHTML
    102 //  - RemovePluginWhenFinished
    103 //  - ReportProgress
    104 // The second item is the verbatim message_contents.
    105 function ParseTestingMessage(message_data) {
    106   if (typeof(message_data) != "string")
    107     return undefined;
    108   var testing_message_prefix = "TESTING_MESSAGE";
    109   var delim_str = ":";
    110   var delim1 = message_data.indexOf(delim_str);
    111   if (message_data.substring(0, delim1) !== testing_message_prefix)
    112     return undefined;
    113   var delim2 = message_data.indexOf(delim_str, delim1 + 1);
    114   if (delim2 == -1)
    115     delim2 = message_data.length;
    116   var message_type = message_data.substring(delim1 + 1, delim2);
    117   var message_contents = message_data.substring(delim2 + 1);
    118   return [message_type, message_contents];
    119 }
    120 
    121 function ClearConsole() {
    122   window.document.getElementById("console").innerHTML = "";
    123 }
    124 
    125 function LogHTML(html) {
    126   window.document.getElementById("console").innerHTML += html;
    127 }
    128 
    129 function RemovePluginWhenFinished() {
    130   window.document.getElementById("plugin").removePlugin = true;
    131 }
    132 
    133 function sendAutomationMessage(msg) {
    134   if (window.domAutomationController) {
    135     window.domAutomationController.setAutomationId(0);
    136     window.domAutomationController.send(msg);
    137   }
    138 }
    139 
    140 // If something goes really wrong, the test running inside the plugin may not
    141 // terminate.  For example, if the plugin does not load, the test will never
    142 // send "PASS" to the browser.  In this case we should explicitly use the
    143 // automation controller to terminate the test.
    144 function InternalError(msg) {
    145   LogHTML("<p>" + msg);
    146   sendAutomationMessage(msg);
    147 }
    148 
    149 function EvalScript(script) {
    150   try {
    151     eval(script);
    152   } catch(ex) {
    153   }
    154 }
    155 
    156 var conditions = [];
    157 // Add a "PostCondition". These are bits of script that are run after the plugin
    158 // is destroyed. If they evaluate to false or throw an exception, it's
    159 // considered a failure.
    160 function AddPostCondition(script) {
    161   conditions.push(script);
    162 }
    163 // Update the HTML to show the failure and update cookies so that ui_tests
    164 // doesn't count this as a pass.
    165 function ConditionFailed(error) {
    166   error_string = "Post condition check failed: " + error;
    167   InternalError(error_string);
    168 }
    169 // Iterate through the post conditions defined in |conditions| and check that
    170 // they all pass.
    171 function CheckPostConditions() {
    172   var success = true;
    173   for (var i = 0; i < conditions.length; ++i) {
    174     var script = conditions[i];
    175     try {
    176       if (!eval(script)) {
    177         ConditionFailed("\"" + script + "\"");
    178         success = false;
    179       }
    180     } catch (ex) {
    181       ConditionFailed("\"" + script + "\"" + " failed with exception: " +
    182                       "\"" + ex.toString() + "\"");
    183       success = false;
    184     }
    185   }
    186   return success;
    187 }
    188 
    189 function IsTestingMessage(message_data) {
    190   return (ParseTestingMessage(message_data) != undefined);
    191 }
    192 
    193 function handleTestingMessage(message_event) {
    194   var type_contents_tuple = ParseTestingMessage(message_event.data);
    195   if (type_contents_tuple) {
    196     var type = type_contents_tuple[0];
    197     var contents = type_contents_tuple[1];
    198     if (type === "AddPostCondition")
    199       AddPostCondition(contents);
    200     else if (type === "ClearConsole")
    201       ClearConsole();
    202     else if (type === "DidExecuteTests")
    203       DidExecuteTests(contents);
    204     else if (type === "EvalScript")
    205       EvalScript(contents);
    206     else if (type === "LogHTML")
    207       LogHTML(contents);
    208     else if (type === "RemovePluginWhenFinished")
    209       RemovePluginWhenFinished();
    210     else if (type === "ReportProgress")
    211       sendAutomationMessage(contents);
    212   }
    213 }
    214 
    215 function sendProgress() {
    216   // We send "..." to signal that we're still working. See
    217   // ppapi/tests/testing_instance.h for how this works.
    218   sendAutomationMessage("...");
    219 }
    220 
    221 onload = function() {
    222   var testcase = ExtractSearchParameter("testcase");
    223   var mode = ExtractSearchParameter("mode");
    224   document.title = 'Test ' + testcase;
    225   var obj;
    226   if (mode == "nacl_newlib") {
    227     obj = document.createElement("EMBED");
    228     obj.setAttribute("src", "ppapi_nacl_tests_newlib.nmf");
    229     obj.setAttribute("type", "application/x-nacl");
    230     obj.setAttribute("mode", mode);
    231   } else if (mode == "nacl_glibc") {
    232     obj = document.createElement("EMBED");
    233     obj.setAttribute("src", "ppapi_nacl_tests_glibc.nmf");
    234     obj.setAttribute("type", "application/x-nacl");
    235     obj.setAttribute("mode", mode);
    236   } else if (mode == "nacl_pnacl") {
    237     obj = document.createElement("EMBED");
    238     obj.setAttribute("src", "ppapi_nacl_tests_pnacl.nmf");
    239     obj.setAttribute("type", "application/x-nacl");
    240     obj.setAttribute("mode", mode);
    241   } else {
    242     var mimeType = "application/x-ppapi-tests";
    243     if (mimeType in navigator.mimeTypes) {
    244       obj = document.createElement("EMBED");
    245       obj.setAttribute("src", "http://a.b.c/test");
    246       obj.setAttribute("type", mimeType);
    247     } else {
    248       document.getElementById("console").innerHTML =
    249           '<span class="fail">FAIL</span>: ' +
    250           '<span class="err_msg">Test plug-in is not registered.</span>';
    251     }
    252   }
    253   if (obj) {
    254     obj.setAttribute("width", 80);
    255     obj.setAttribute("height", 80);
    256     obj.setAttribute("style",
    257                      "background-color:#AAAAAA;border:1px solid black;");
    258     obj.setAttribute("id", "plugin");
    259     obj.setAttribute("testcase", testcase);
    260     obj.setAttribute("protocol", window.location.protocol);
    261     var websocket_host = ExtractSearchParameter("websocket_host");
    262     if (websocket_host != "")
    263       obj.setAttribute("websocket_host", websocket_host);
    264     var websocket_port = ExtractSearchParameter("websocket_port");
    265     if (websocket_port != "")
    266       obj.setAttribute("websocket_port", websocket_port);
    267     var ssl_server_port = ExtractSearchParameter("ssl_server_port");
    268     if (ssl_server_port != "")
    269       obj.setAttribute("ssl_server_port", ssl_server_port);
    270 
    271     var container = document.getElementById("container");
    272     container.addEventListener("message", handleTestingMessage, true);
    273 
    274     // "error" and "crash" events will only fire for NaCl, but adding these
    275     // listeners doesn't hurt in the non-NaCl cases.
    276     obj.addEventListener("error", function() {
    277       InternalError("Plugin did not load. '" + obj.lastError + "'");
    278     }, true);
    279     obj.addEventListener("crash", function() {
    280       InternalError("Plugin crashed. '" + obj.lastError + "'");
    281     }, true);
    282 
    283     // NaCl sends progress events while loading. When we get one, notify the
    284     // domAutomationController so that it knows we're still working.
    285     obj.addEventListener("loadstart", sendProgress, true);
    286     obj.addEventListener("progress", sendProgress, true);
    287     obj.addEventListener("load", sendProgress, true);
    288     obj.addEventListener("loadend", sendProgress, true);
    289 
    290     // Register a bad dispatchEvent to make sure it isn't used. See 'EVIL' note
    291     // below.
    292     var original = obj.dispatchEvent;
    293     obj.dispatchEvent = function() {
    294       // TODO(dmichael): NaCl triggers this; take out the special case for NaCl
    295       //                 when crbug.com/109775 is fixed.
    296       if (mode.indexOf("nacl") !== 0)
    297         InternalError("Bad dispatchEvent called!");
    298 
    299       // Pass it on anyways, we need the event to detect load progress and
    300       // errors.
    301       return original.apply(obj, arguments);
    302     }
    303     container.appendChild(obj);
    304   }
    305 }
    306 
    307 // EVIL Note:
    308 // This part of the script does some nefarious things to make sure that it
    309 // doesn't affect the behavior of PostMessage (on which all the tests rely). In
    310 // particular, we replace document.createEvent, MessageEvent.initMessageEvent,
    311 // and the MessageEvent constructor. Previous versions of the PostMessage
    312 // implementation made use of these and would fail (http://crbug.com/82604).
    313 // The NaCl plugin uses dispatchEvent for progress events, hence we are careful
    314 // to make that still pass for NaCl (see above, and see crbug.com/109775).
    315 document.createEvent = function() {
    316   InternalError("Bad document.createEvent called!");
    317 }
    318 function MessageEvent() {
    319   InternalError("Bad MessageEvent constructor called!");
    320 }
    321 MessageEvent.prototype.initMessageEvent = function() {
    322   InternalError("Bad MessageEvent.initMessageEvent called!");
    323 }
    324 
    325 </script>
    326 </head><body>
    327 <div>
    328   <div id="container"></div>
    329   <div id="console"><span class="load_msg">loading...</span></div>
    330 </div>
    331 </body></html>
    332