15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function $(id) { 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return document.getElementById(id); 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function createNaClEmbed(args) { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fallback = function(value, default_value) { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value !== undefined ? value : default_value; 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var embed = document.createElement('embed'); 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embed.id = args.id; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embed.src = args.src; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embed.type = fallback(args.type, 'application/x-nacl'); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JavaScript inconsistency: this is equivalent to class=... in HTML. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embed.className = fallback(args.className, 'naclModule'); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embed.width = fallback(args.width, 0); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embed.height = fallback(args.height, 0); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return embed; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function decodeURIArgs(encoded) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var args = {}; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoded.length > 0) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var pairs = encoded.replace(/\+/g, ' ').split('&'); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var p = 0; p < pairs.length; p++) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var pair = pairs[p].split('='); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pair.length != 2) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw "Malformed argument key/value pair: '" + pairs[p] + "'"; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return args; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function addDefaultsToArgs(defaults, args) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var key in defaults) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(key in args)) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args[key] = defaults[key]; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return a dictionary of arguments for the test. These arguments are passed 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the query string of the main page's URL. Any time this function is used, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// default values should be provided for every argument. In some cases a test 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// may be run without an expected query string (manual testing, for example.) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Careful: all the keys and values in the dictionary are strings. You will 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// need to manually parse any non-string values you wish to use. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function getTestArguments(defaults) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var encoded = window.location.search.substring(1); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var args = decodeURIArgs(encoded); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (defaults !== undefined) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addDefaultsToArgs(defaults, args); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return args; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function exceptionToLogText(e) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof e == 'object' && 'message' in e && 'stack' in e) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return e.message + '\n' + e.stack.toString(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (typeof(e) == 'string') { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return e; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return toString(e) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Logs test results to the server using URL-encoded RPC. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Also logs the same test results locally into the DOM. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function RPCWrapper() { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Work around how JS binds 'this' 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var this_ = this; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is assumed RPC will work unless proven otherwise. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rpc_available = true; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set to true if any test fails. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.ever_failed = false; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Async calls can make it faster, but it can also change order of events. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.async = false; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called if URL-encoded RPC gets a 404, can't find the server, etc. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function handleRPCFailure(name, message) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This isn't treated as a testing error - the test can be run without a 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // web server that understands RPC. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.logLocal('RPC failure for ' + name + ': ' + message + ' - If you ' + 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'are running this test manually, this is not a problem.', 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'gray'); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.disableRPC(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function handleRPCResponse(name, req) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req.status == 200) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req.responseText == 'Die, please') { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(eugenis): this does not end the browser process on Mac. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.close(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (req.responseText != 'OK') { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.logLocal('Unexpected RPC response to ' + name + ': \'' + 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req.responseText + '\' - If you are running this test ' + 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'manually, this is not a problem.', 'gray'); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.disableRPC(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleRPCFailure(name, req.status.toString()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Performs a URL-encoded RPC call, given a function name and a dictionary 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (actually just an object - it's a JS idiom) of parameters. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function rpcCall(name, params) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window.domAutomationController !== undefined) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Running as a Chrome browser_test. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var msg = {type: name}; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var pname in params) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg[pname] = params[pname]; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domAutomationController.setAutomationId(0); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domAutomationController.send(JSON.stringify(msg)); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (this_.rpc_available) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct the URL for the RPC request. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var args = []; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var pname in params) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pvalue = params[pname]; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push(encodeURIComponent(pname) + '=' + encodeURIComponent(pvalue)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var url = '/TESTER/' + name + '?' + args.join('&'); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var req = new XMLHttpRequest(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Async result handler 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this_.async) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req.onreadystatechange = function() { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req.readyState == XMLHttpRequest.DONE) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleRPCResponse(name, req); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req.open('GET', url, this_.async); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req.send(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this_.async) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleRPCResponse(name, req); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (err) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleRPCFailure(name, err.toString()); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pretty prints an error into the DOM. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLocalError = function(message) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLocal(message, 'red'); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.visualError(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If RPC isn't working, disable it to stop error message spam. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.disableRPC = function() { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.rpc_available) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rpc_available = false; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLocal('Disabling RPC', 'gray'); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.startup = function() { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(ncbray) move into test runner 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.num_passed = 0; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.num_failed = 0; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.num_errors = 0; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log('[STARTUP]'); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.shutdown = function() { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.num_passed == 0 && this.num_failed == 0 && this.num_errors == 0) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.client_error('No tests were run. This may be a bug.'); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = '[SHUTDOWN] '; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) full_message += this.num_passed + ' passed'; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) full_message += ', ' + this.num_failed + ' failed'; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) full_message += ', ' + this.num_errors + ' errors'; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLocal(full_message); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpcCall('Shutdown', {message: full_message, passed: !this.ever_failed}); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.ever_failed) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput.style.border = '2px solid #FF0000'; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput.style.border = '2px solid #00FF00'; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.ping = function() { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpcCall('Ping', {}); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.heartbeat = function() { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpcCall('JavaScriptIsAlive', {}); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.client_error = function(message) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.num_errors += 1; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.visualError(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = '\n[CLIENT_ERROR] ' + exceptionToLogText(message) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The client error could have been generated by logging - be careful. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(full_message, 'red'); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (err) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's not much that can be done, at this point. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.begin = function(test_name) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = '[' + test_name + ' BEGIN]' 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(full_message, 'blue'); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log = function(message, color, from_completed_test) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof(message) != 'string') { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message = toString(message); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For event-driven tests, output may come after the test has finished. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Display this in a special way to assist debugging. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (from_completed_test) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color = 'orange'; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message = 'completed test: ' + message; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLocal(message, color); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpcCall('TestLog', {message: message}); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.log = function(test_name, message, from_completed_test) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message == undefined) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a log message that is not assosiated with a test. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // What we though was the test name is actually the message. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(test_name); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof(message) != 'string') { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message = toString(message); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = '[' + test_name + ' LOG] ' + message; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(full_message, 'black', from_completed_test); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fail = function(test_name, message, from_completed_test) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.num_failed += 1; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.visualError(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = '[' + test_name + ' FAIL] ' + message 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(full_message, 'red', from_completed_test); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.exception = function(test_name, err, from_completed_test) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.num_errors += 1; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.visualError(); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var message = exceptionToLogText(err); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = '[' + test_name + ' EXCEPTION] ' + message; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(full_message, 'purple', from_completed_test); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pass = function(test_name, from_completed_test) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.num_passed += 1; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = '[' + test_name + ' PASS]'; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(full_message, 'green', from_completed_test); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.blankLine = function() { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._log(''); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allows users to log time data that will be parsed and re-logged 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for chrome perf-bot graphs / performance regression testing. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See: native_client/tools/process_perf_output.py 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logTimeData = function(event, timeMS) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.log('NaClPerf [' + event + '] ' + timeMS + ' millisecs'); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.visualError = function() { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Changing the color is defered until testing is done 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.ever_failed = true; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLineLocal = function(text, color) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text = text.replace(/\s+$/, ''); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text == '') { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput.appendChild(document.createElement('br')); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mNode = document.createTextNode(text); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var div = document.createElement('div'); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Preserve whitespace formatting. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) div.style['white-space'] = 'pre'; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (color != undefined) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) div.style.color = color; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) div.appendChild(mNode); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput.appendChild(div); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLocal = function(message, color) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lines = message.split('\n'); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < lines.length; i++) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.logLineLocal(lines[i], color); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a place in the page to output test results 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput = document.createElement('div'); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput.id = 'testresults'; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput.style.border = '2px solid #0000FF'; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.localOutput.style.padding = '10px'; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document.body.appendChild(this.localOutput); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BEGIN functions for testing 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function fail(message, info, test_status) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parts = []; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message != undefined) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts.push(message); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info != undefined) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts.push('(' + info + ')'); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var full_message = parts.join(' '); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (test_status !== undefined) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // New-style test 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_status.fail(full_message); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Old-style test 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw {type: 'test_fail', message: full_message}; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function assert(condition, message, test_status) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!condition) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fail(message, toString(condition), test_status); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is accepted best practice for checking if an object is an array. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function isArray(obj) { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Object.prototype.toString.call(obj) === '[object Array]'; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function toString(obj) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof(obj) == 'string') { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\'' + obj + '\''; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return obj.toString(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (err) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Arrays should do this automatically, but there is a known bug where 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NaCl gets array types wrong. .toString will fail on these objects. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return obj.join(','); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (err) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (obj == undefined) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'undefined'; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is no way to create a textual representation of this object. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '[UNPRINTABLE]'; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Old-style, but new-style tests use it indirectly. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (The use of the "test" parameter indicates a new-style test. This is a 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temporary hack to avoid code duplication.) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function assertEqual(a, b, message, test_status) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isArray(a) && isArray(b)) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assertArraysEqual(a, b, message, test_status); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (a !== b) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fail(message, toString(a) + ' != ' + toString(b), test_status); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Old-style, but new-style tests use it indirectly. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (The use of the "test" parameter indicates a new-style test. This is a 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temporary hack to avoid code duplication.) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function assertArraysEqual(a, b, message, test_status) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dofail = function() { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fail(message, toString(a) + ' != ' + toString(b), test_status); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a.length != b.length) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dofail(); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < a.length; i++) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a[i] !== b[i]) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dofail(); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ideally there'd be some way to identify what exception was thrown, but JS 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exceptions are fairly ad-hoc. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(ncbray) allow manual validation of exception types? 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function assertRaises(func, message, test_status) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) func(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (err) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fail(message, 'did not raise', test_status); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// END functions for testing 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function haltAsyncTest() { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw {type: 'test_halt'}; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function begins_with(s, prefix) { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (s.length >= prefix.length) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s.substr(0, prefix.length) == prefix; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function ends_with(s, suffix) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (s.length >= suffix.length) { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s.substr(s.length - suffix.length, suffix.length) == suffix; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function embed_name(embed) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (embed.name != undefined) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (embed.id != undefined) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return embed.name + ' / ' + embed.id; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return embed.name; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (embed.id != undefined) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return embed.id; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '[no name]'; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 469d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Write data to the filesystem. This will only work if the browser_tester was 470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// initialized with --output_dir. 471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)function outputFile(name, data, onload, onerror) { 472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) var xhr = new XMLHttpRequest(); 473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) xhr.onload = onload; 474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) xhr.onerror = onerror; 475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) xhr.open('POST', name, true); 476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) xhr.send(data); 477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Webkit Bug Workaround 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SHOULD BE REMOVED WHEN Webkit IS FIXED 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/nativeclient/issues/detail?id=2428 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/chromium/issues/detail?id=103588 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function ForcePluginLoadOnTimeout(elem, tester, timeout) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tester.log('Registering ForcePluginLoadOnTimeout ' + 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '(Bugs: NaCl 2428, Chrome 103588)'); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var started_loading = elem.readyState !== undefined; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remember that the plugin started loading - it may be unloaded by the time 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the callback fires. 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elem.addEventListener('load', function() { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_loading = true; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, true); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the plugin has at least started to load after "timeout" seconds, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise reload the page. 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(function() { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_loading) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ForceNaClPluginReload(elem, tester); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, timeout); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function ForceNaClPluginReload(elem, tester) { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (elem.readyState === undefined) { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tester.log('WARNING: WebKit plugin-not-loading error detected; reloading.'); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.location.reload(); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function NaClWaiter(body_element) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Work around how JS binds 'this' 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var this_ = this; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var embedsToWaitFor = []; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // embedsLoaded contains list of embeds that have dispatched the 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'loadend' progress event. 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.embedsLoaded = []; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.is_loaded = function(embed) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this_.embedsLoaded.length; ++i) { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this_.embedsLoaded[i] === embed) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (embed.readyState == 4) && !this_.has_errored(embed); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.has_errored = function(embed) { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var msg = embed.lastError; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return embed.lastError != undefined && embed.lastError != ''; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an argument was passed, it is the body element for registering 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // event listeners for the 'loadend' event type. 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (body_element != undefined) { 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var eventListener = function(e) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.type == 'loadend') { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.embedsLoaded.push(e.target); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) body_element.addEventListener('loadend', eventListener, true); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Takes an arbitrary number of arguments. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waitFor = function() { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i< arguments.length; i++) { 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embedsToWaitFor.push(arguments[i]); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.run = function(doneCallback, pingCallback) { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.doneCallback = doneCallback; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pingCallback = pingCallback; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for up to forty seconds for the nexes to load. 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(ncbray) use error handling mechanisms (when they are implemented) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rather than a timeout. 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.totalWait = 0; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.maxTotalWait = 40000; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.retryWait = 10; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waitForPlugins(); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waitForPlugins = function() { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var errored = []; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var loaded = []; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var waiting = []; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < embedsToWaitFor.length; i++) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var e = embedsToWaitFor[i]; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.has_errored(e)) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errored.push(e); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (this.is_loaded(e)) { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loaded.push(e); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting.push(e); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch(err) { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the module is badly horked, touching lastError, etc, may except. 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errored.push(err); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.totalWait += this.retryWait; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (waiting.length == 0) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.doneCallback(loaded, errored); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (this.totalWait >= this.maxTotalWait) { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Timeouts are considered errors. 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.doneCallback(loaded, errored.concat(waiting)); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(function() { this_.waitForPlugins(); }, this.retryWait); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Capped exponential backoff 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.retryWait += this.retryWait/2; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Paranoid: does setTimeout like floating point numbers? 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.retryWait = Math.round(this.retryWait); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.retryWait > 100) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.retryWait = 100; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent the server from thinking the test has died. 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pingCallback) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pingCallback(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfunction logLoadStatus(rpc, load_errors_are_test_errors, 6127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch exit_cleanly_is_an_error, loaded, waiting) { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < loaded.length; i++) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpc.log(embed_name(loaded[i]) + ' loaded'); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Be careful when interacting with horked nexes. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var getCarefully = function (callback) { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return callback(); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (err) { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '<exception>'; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var errored = false; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var j = 0; j < waiting.length; j++) { 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Workaround for WebKit layout bug that caused the NaCl plugin to not 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // load. If we see that the plugin is not loaded after a timeout, we 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // forcibly reload the page, thereby triggering layout. Re-running 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // layout should make WebKit instantiate the plugin. NB: this could 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make the JavaScript-based code go into an infinite loop if the 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WebKit bug becomes deterministic or the NaCl plugin fails after 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loading, but the browser_tester.py code will timeout the test. 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://code.google.com/p/nativeclient/issues/detail?id=2428 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (waiting[j].readyState == undefined) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // alert('Woot'); // -- for manual debugging 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpc.log('WARNING: WebKit plugin-not-loading error detected; reloading.'); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.location.reload(); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw "reload NOW"; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var name = getCarefully(function(){ 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return embed_name(waiting[j]); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ready = getCarefully(function(){ 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var readyStateString = 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ['UNSENT', 'OPENED', 'HEADERS_RECEIVED', 'LOADING', 'DONE']; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An undefined index value will return and undefined result. 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return readyStateString[waiting[j].readyState]; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var last = getCarefully(function(){ 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return toString(waiting[j].lastError); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 6557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!exit_cleanly_is_an_error) { 6567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // For some tests (e.g. the NaCl SDK examples) it is OK if the test 6577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // exits cleanly when we are waiting for it to load. 6587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 6597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // In this case, "exiting cleanly" means returning 0 from main, or 6607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // calling exit(0). When this happens, the module "crashes" by posting 6617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // the "crash" message, but it also assigns an exitStatus. 6627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 6637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // A real crash produces an exitStatus of -1, and if the module is still 6647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // running its exitStatus will be undefined. 6657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var exitStatus = getCarefully(function() { 6667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ready === 'DONE') { 6677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return waiting[j].exitStatus; 6687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else { 6697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return -1; 6707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 6717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch }); 6727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 6737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (exitStatus === 0) { 6747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch continue; 6757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 6767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var msg = (name + ' did not load. Status: ' + ready + ' / ' + last); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (load_errors_are_test_errors) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpc.client_error(msg); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errored = true; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpc.log(msg); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return errored; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains the state for a single test. 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function TestStatus(tester, name, async) { 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Work around how JS binds 'this' 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var this_ = this; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester = tester; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.name = name; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.async = async; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.running = true; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.log = function(message) { 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester.rpc.log(this.name, toString(message), !this.running); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pass = function() { 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO raise if not running. 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester.rpc.pass(this.name, !this.running); 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done(); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) haltAsyncTest(); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fail = function(message) { 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester.rpc.fail(this.name, message, !this.running); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done(); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) haltAsyncTest(); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done = function() { 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.running) { 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.running = false; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester.testDone(this); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.assert = function(condition, message) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(condition, message, this); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.assertEqual = function(a, b, message) { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assertEqual(a, b, message, this); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.callbackWrapper = function(callback, args) { 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A stale callback? 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.running) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (args === undefined) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args = []; 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.apply(undefined, args); 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (err) { 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof err == 'object' && 'type' in err) { 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err.type == 'test_halt') { 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // New-style test 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we get this exception, we can assume any callbacks or next 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tests have already been scheduled. 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (err.type == 'test_fail') { 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Old-style test 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A special exception that terminates the test with a failure 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester.rpc.fail(this.name, err.message, !this.running); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done(); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is not a special type of exception, it is an error. 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester.rpc.exception(this.name, err, !this.running); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done(); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A normal exit. Should we move on to the next test? 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Async tests do not move on without an explicit pass. 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.async) { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tester.rpc.pass(this.name); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done(); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Async callbacks should be wrapped so the tester can catch unexpected 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exceptions. 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrap = function(callback) { 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function() { 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.callbackWrapper(callback, arguments); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setTimeout = function(callback, time) { 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(this.wrap(callback), time); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waitForCallback = function(callbackName, expectedCalls) { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.log('Waiting for ' + expectedCalls + ' invocations of callback: ' 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + callbackName); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var gotCallbacks = 0; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deliberately global - this is what the nexe expects. 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(ncbray): consider returning this function, so the test has more 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flexibility. For example, in the test one could count to N 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using a different callback before calling _this_ callback, and 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // continuing the test. Also, consider calling user-supplied callback 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when done waiting. 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window[callbackName] = this.wrap(function() { 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++gotCallbacks; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.log('Received callback ' + gotCallbacks); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gotCallbacks == expectedCalls) { 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.log("Done waiting"); 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.pass(); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HACK 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) haltAsyncTest(); 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HACK if this function is used in a non-async test, make sure we don't 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // spuriously pass. Throwing this exception forces us to behave like an 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // async test. 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) haltAsyncTest(); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function takes an array of messages and asserts that the nexe 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calls PostMessage with each of these messages, in order. 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Arguments: 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // plugin - The DOM object for the NaCl plugin 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // messages - An array of expected responses 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callback - An optional callback function that takes the current message 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string as an argument 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.expectMessageSequence = function(plugin, messages, callback) { 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.assert(messages.length > 0, 'Must provide at least one message'); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var local_messages = messages.slice(); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listener = function(message) { 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message.data.indexOf('@:') == 0) { 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // skip debug messages 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.log('DEBUG: ' + message.data.substr(2)); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.assertEqual(message.data, local_messages.shift()); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (callback !== undefined) { 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback(message.data); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (local_messages.length == 0) { 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.pass(); 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.expectEvent(plugin, 'message', listener); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.expectEvent(plugin, 'message', listener); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.expectEvent = function(src, event_type, listener) { 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var wrapper = this.wrap(function(e) { 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src.removeEventListener(event_type, wrapper, false); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener(e); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src.addEventListener(event_type, wrapper, false); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function Tester(body_element) { 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Work around how JS binds 'this' 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var this_ = this; 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The tests being run. 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tests = []; 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rpc = new RPCWrapper(); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waiter = new NaClWaiter(body_element); 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var load_errors_are_test_errors = true; 8587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var exit_cleanly_is_an_error = true; 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var parallel = false; 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // BEGIN public interface 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.loadErrorsAreOK = function() { 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_errors_are_test_errors = false; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.exitCleanlyIsOK = function() { 8717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch exit_cleanly_is_an_error = false; 8727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch }; 8737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.log = function(message) { 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rpc.log(message); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this kind of test exits cleanly, it passes 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addTest = function(name, testFunction) { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tests.push({name: name, callback: testFunction, async: false}); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This kind of test does not pass until "pass" is explicitly called. 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addAsyncTest = function(name, testFunction) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tests.push({name: name, callback: testFunction, async: true}); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.run = function() { 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rpc.startup(); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.startHeartbeat(); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waiter.run( 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function(loaded, waiting) { 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var errored = logLoadStatus(this_.rpc, load_errors_are_test_errors, 8947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch exit_cleanly_is_an_error, 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loaded, waiting); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errored) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.rpc.blankLine(); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.rpc.log('A nexe load error occured, aborting testing.'); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_._done(); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.startTesting(); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function() { 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.rpc.ping(); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.runParallel = function() { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parallel = true; 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.run(); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Takes an arbitrary number of arguments. 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waitFor = function() { 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i< arguments.length; i++) { 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.waiter.waitFor(arguments[i]); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // END public interface 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.startHeartbeat = function() { 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rpc = this.rpc; 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var heartbeat = function() { 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rpc.heartbeat(); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(heartbeat, 500); 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heartbeat(); 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.launchTest = function(testIndex) { 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var testDecl = tests[testIndex]; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var currentTest = new TestStatus(this, testDecl.name, testDecl.async); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(currentTest.wrap(function() { 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.rpc.blankLine(); 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this_.rpc.begin(currentTest.name); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testDecl.callback(currentTest); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }), 0); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done = function() { 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rpc.blankLine(); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rpc.shutdown(); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.startTesting = function() { 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tests.length == 0) { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No tests specified. 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done(); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.testCount = 0; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parallel) { 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch all tests. 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < tests.length; i++) { 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.launchTest(i); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the first test. 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.launchTest(0); 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.testDone = function(test) { 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.testCount += 1; 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.testCount < tests.length) { 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parallel) { 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move on to the next test if they're being run one at a time. 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.launchTest(this.testCount); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this._done(); 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 981