diff options
author | slamm@google.com <slamm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-18 02:40:39 +0000 |
---|---|---|
committer | slamm@google.com <slamm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-18 02:40:39 +0000 |
commit | e8e3eea260001a067f069d8da98584c2f6fc44fa (patch) | |
tree | 8b3c882efaea296f1365c1b838e45df11c76cda0 /tools/page_cycler | |
parent | 5bd6feee0b7185ee2b07f245f7a89a74f8f2ef94 (diff) | |
download | chromium_src-e8e3eea260001a067f069d8da98584c2f6fc44fa.zip chromium_src-e8e3eea260001a067f069d8da98584c2f6fc44fa.tar.gz chromium_src-e8e3eea260001a067f069d8da98584c2f6fc44fa.tar.bz2 |
Add Web Page Replay test to page cycler.
- Add supporting WPR extension.
BUG=
TEST=
Review URL: http://codereview.chromium.org/9956045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132730 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/page_cycler')
-rw-r--r-- | tools/page_cycler/common/head.js | 10 | ||||
-rw-r--r-- | tools/page_cycler/common/report.html | 16 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/README | 15 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/extension/background.html | 2 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/extension/background.js | 328 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/extension/content.js | 14 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/extension/manifest.json | 26 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/extension/page_cycler.js | 54 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/extension/start.js | 89 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/start.html | 26 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/start.js | 123 | ||||
-rw-r--r-- | tools/page_cycler/webpagereplay/tests/2012Q2.js | 77 |
12 files changed, 771 insertions, 9 deletions
diff --git a/tools/page_cycler/common/head.js b/tools/page_cycler/common/head.js index f12fb24..dddaa7ee 100644 --- a/tools/page_cycler/common/head.js +++ b/tools/page_cycler/common/head.js @@ -26,13 +26,11 @@ function __pages() { // fetch lazily return this.data; } function __get_timings() { - if (sessionStorage == null) + if (sessionStorage != null && + sessionStorage.getItem("__pc_timings") != null) { + return sessionStorage["__pc_timings"]; + } else { return __get_cookie("__pc_timings"); - else { - if (sessionStorage.getItem("__pc_timings") == null) - return ""; - else - return sessionStorage["__pc_timings"]; } } function __set_timings(timings) { diff --git a/tools/page_cycler/common/report.html b/tools/page_cycler/common/report.html index 221d8ab..9833fbe 100644 --- a/tools/page_cycler/common/report.html +++ b/tools/page_cycler/common/report.html @@ -79,6 +79,7 @@ document.write("</table>"); r.vari = r.vari / (ary.length - 1); r.stdd = Math.sqrt(r.vari); + r.errp = r.stdd / Math.sqrt((ary.length - 1) / 2) / r.mean * 100; return r; } @@ -88,7 +89,14 @@ document.write("</table>"); if (linkify) { var anchor = doc.createElement("A"); - anchor.href = text + "/index.html?skip=true"; + if (text.indexOf('http://localhost:') == 0 || + text.indexOf('file://') == 0) { + // URLs for page cycler HTTP and file tests. + anchor.href = text + "/index.html?skip=true"; + } else { + // For Web Page Replay, URLs are same as recorded pages. + anchor.href = text; + } anchor.appendChild(doc.createTextNode(text)); td.appendChild(anchor); } @@ -113,7 +121,7 @@ document.write("</table>"); function showReport() { var tbody = document.getElementById("tbody"); - var colsums = [0,0,0,0]; + var colsums = [0,0,0,0,0]; var timeVals = getTimeVals(); for (var i = 0; i < timeVals.length; ++i) { var tr = document.createElement("TR"); @@ -125,6 +133,7 @@ document.write("</table>"); appendTableCol(tr, r.max.toFixed(2)); appendTableCol(tr, r.mean.toFixed(2)); appendTableCol(tr, r.stdd.toFixed(2)); + appendTableCol(tr, r.errp.toFixed(2)); //appendTableCol(tr, r.chi2.toFixed(2)); for (var j = 0; j < timeVals[i].length; ++j) { @@ -138,6 +147,7 @@ document.write("</table>"); colsums[1] = colsums[1] + r.max; colsums[2] = colsums[2] + r.mean; colsums[3] = colsums[3] + r.stdd; + colsums[4] = colsums[4] + r.errp; tbody.appendChild(tr); } @@ -163,6 +173,7 @@ document.write("</table>"); <th>Max</th> <th>Mean</th> <th>Std.d</th> + <th>Err %</th> <th colspan="10">Runs</th> </tr> </thead> @@ -170,4 +181,3 @@ document.write("</table>"); </table> </body> </html> - diff --git a/tools/page_cycler/webpagereplay/README b/tools/page_cycler/webpagereplay/README new file mode 100644 index 0000000..6fce3e9 --- /dev/null +++ b/tools/page_cycler/webpagereplay/README @@ -0,0 +1,15 @@ +Page Cycler Tests with Web Page Replay +--------------------------------------------------------------------------- +Web Page Replay is a proxy that can record and "play" web pages with +simulated network characteristics -- without having to edit the pages +by hand. With WPR, tests can use "real" web content, and catch +performance issues that may result from introducing network delays and +bandwidth throttling. + +The Chromium extension here is used to load URLs, record the times, +and set the appropriate cookies for src/tools/page_cycler/common/report.html. + +For more information: +https://sites.google.com/a/chromium.org/dev/developers/testing/page-cyclers-wpr +https://sites.google.com/a/chromium.org/dev/developers/testing/page-cyclers +http://code.google.com/p/web-page-replay diff --git a/tools/page_cycler/webpagereplay/extension/background.html b/tools/page_cycler/webpagereplay/extension/background.html new file mode 100644 index 0000000..61a2902 --- /dev/null +++ b/tools/page_cycler/webpagereplay/extension/background.html @@ -0,0 +1,2 @@ +<script src="background.js"></script> +<script src="page_cycler.js"></script> diff --git a/tools/page_cycler/webpagereplay/extension/background.js b/tools/page_cycler/webpagereplay/extension/background.js new file mode 100644 index 0000000..207979e --- /dev/null +++ b/tools/page_cycler/webpagereplay/extension/background.js @@ -0,0 +1,328 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// start.js sends a "start" message to set this. +window.benchmarkConfiguration = {}; + +// The callback (e.g. report writer) is set via AddBenchmarckCallback. +window.benchmarkCallback; + +// Url to load before loading target page. +var kWaitUrl = "http://wprwprwpr/web-page-replay-generate-200"; + +// Constant StatCounter Names +var kTcpReadBytes = "tcp.read_bytes"; +var kTcpWriteBytes = "tcp.write_bytes"; +var kRequestCount = "HttpNetworkTransaction.Count"; +var kConnectCount = "tcp.connect"; + +function CHECK(expr, comment) { + if (!expr) { + console.log(comment); + alert(comment); + } +} + +function Result() { + var me_ = this; + this.url = ""; + this.firstPaintTime = 0; + this.readBytesKB = 0; + this.writeBytesKB = 0; + this.numRequests = 0; + this.numConnects = 0; + this.timing = {}; // window.performance.timing + this.getTotalTime = function() { + var totalTime = 0 + if (me_.timing.navigationStart && me_.timing.loadEventEnd) { + totalTime = me_.timing.loadEventEnd - me_.timing.navigationStart; + } + CHECK(totalTime >= 0); + return totalTime; + } +} + +// Collect all the results for a session (i.e. different pages). +function ResultsCollection() { + var results_ = []; + var pages_ = []; + var pageResults_ = {}; + + this.addResult = function(result) { + results_.push(result); + var url = result.url; + if (!(url in pageResults_)) { + pages_.push(url); + pageResults_[url] = []; + } + pageResults_[url].push(result); + } + + this.getPages = function() { + return pages_; + } + + this.getResults = function() { + return results_; + } + + this.getTotalTimes = function() { + return results_.map(function (t) { return t.getTotalTime(); }); + } +} + +// Load a url in the default tab and record the time. +function PageLoader(url, resultReadyCallback) { + var me_ = this; + var url_ = url; + var resultReadyCallback_ = resultReadyCallback; + + // If it record mode, wait a little longer for lazy loaded resources. + var postLoadGraceMs_ = window.isRecordMode ? 5000 : 0; + var loadInterval_ = window.loadInterval; + var checkInterval_ = window.checkInterval; + var timeout_ = window.timeout; + var maxLoadChecks_ = window.maxLoadChecks; + + var preloadFunc_; + var timeoutId_; + var isFinished_; + var result_; + + var initialReadBytes_; + var initialWriteBytes_; + var initialRequestCount_; + var initialConnectCount_; + + this.result = function() { return result_; }; + + this.run = function() { + timeoutId_ = null; + isFinished_ = false; + result_ = null; + initialReadBytes_ = chrome.benchmarking.counter(kTcpReadBytes); + initialWriteBytes_ = chrome.benchmarking.counter(kTcpWriteBytes); + initialRequestCount_ = chrome.benchmarking.counter(kRequestCount); + initialConnectCount_ = chrome.benchmarking.counter(kConnectCount); + + if (me_.preloadFunc_) { + me_.preloadFunc_(me_.load_); + } else { + me_.load_(); + } + }; + + this.setClearAll = function() { + me_.preloadFunc_ = me_.clearAll_; + }; + + this.setClearConnections = function() { + me_.preloadFunc_ = me_.clearConnections_; + }; + + this.clearAll_ = function(callback) { + chrome.tabs.getSelected(null, function(tab) { + chrome.tabs.update(tab.id, {"url": kWaitUrl}, function() { + chrome.benchmarking.clearHostResolverCache(); + chrome.benchmarking.clearPredictorCache(); + chrome.benchmarking.closeConnections(); + var dataToRemove = { + "appcache": true, + "cache": true, + "cookies": true, + "downloads": true, + "fileSystems": true, + "formData": true, + "history": true, + "indexedDB": true, + "localStorage": true, + "passwords": true, + "pluginData": true, + "webSQL": true + }; + // Add any items new to the API. + for (var prop in chrome.browsingData) { + var dataName = prop.replace("remove", ""); + if (dataName && dataName != prop) { + dataName = dataName.charAt(0).toLowerCase() + + dataName.substr(1); + if (!dataToRemove.hasOwnProperty(dataName)) { + console.log("New browsingData API item: " + dataName); + dataToRemove[dataName] = true; + } + } + } + chrome.browsingData.remove({}, dataToRemove, callback); + }); + }); + }; + + this.clearConnections_ = function(callback) { + chrome.benchmarking.closeConnections(); + callback(); + }; + + this.load_ = function() { + console.log("LOAD started: " + url_); + setTimeout(function() { + chrome.extension.onRequest.addListener(me_.finishLoad_); + timeoutId_ = setTimeout(function() { + me_.finishLoad_({"loadTimes": null, "timing": null}); + }, timeout_); + chrome.tabs.getSelected(null, function(tab) { + chrome.tabs.update(tab.id, {"url": url_}); + }); + }, loadInterval_); + }; + + this.finishLoad_ = function(msg) { + if (!isFinished_) { + isFinished_ = true; + clearTimeout(timeoutId_); + chrome.extension.onRequest.removeListener(me_.finishLoad_); + me_.saveResult_(msg.loadTimes, msg.timing); + } + }; + + this.saveResult_ = function(loadTimes, timing) { + result_ = new Result() + result_.url = url_; + if (!loadTimes || !timing) { + console.log("LOAD INCOMPLETE: " + url_); + } else { + console.log("LOAD complete: " + url_); + result_.timing = timing; + var baseTime = timing.navigationStart; + CHECK(baseTime); + result_.firstPaintTime = Math.max(0, + Math.round((1000.0 * loadTimes.firstPaintTime) - baseTime)); + } + result_.readBytesKB = (chrome.benchmarking.counter(kTcpReadBytes) - + initialReadBytes_) / 1024; + result_.writeBytesKB = (chrome.benchmarking.counter(kTcpWriteBytes) - + initialWriteBytes_) / 1024; + result_.numRequests = (chrome.benchmarking.counter(kRequestCount) - + initialRequestCount_); + result_.numConnects = (chrome.benchmarking.counter(kConnectCount) - + initialConnectCount_); + setTimeout(function() { resultReadyCallback_(me_); }, postLoadGraceMs_); + }; +} + +// Load page sets and prepare performance results. +function SessionLoader(resultsReadyCallback) { + var me_ = this; + var resultsReadyCallback_ = resultsReadyCallback; + var pageSets_ = benchmarkConfiguration.pageSets; + var iterations_ = window.iterations; + var retries_ = window.retries; + + var pageLoaders_ = []; + var resultsCollection_ = new ResultsCollection(); + var loaderIndex_ = 0; + var retryIndex_ = 0; + var iterationIndex_ = 0; + + this.run = function() { + me_.createLoaders_(); + me_.loadPage_(); + } + + this.getResultsCollection = function() { + return resultsCollection_; + } + + this.createLoaders_ = function() { + // Each url becomes one benchmark. + for (var i = 0; i < pageSets_.length; i++) { + for (var j = 0; j < pageSets_[i].length; j++) { + // Remove extra space at the beginning or end of a url. + var url = pageSets_[i][j].trim(); + // Alert about and ignore blank page which does not get loaded. + if (url == "about:blank") { + alert("blank page loaded!"); + } else if (!url.match(/https?:\/\//)) { + // Alert about url that is not in scheme http:// or https://. + alert("Skipping url without http:// or https://: " + url); + } else { + var loader = new PageLoader(url, me_.handleResult_) + if (j == 0) { + // Clear all browser data for the first page in a sub list. + loader.setClearAll(); + } else { + // Otherwise, only clear the connections. + loader.setClearConnections(); + } + pageLoaders_.push(loader); + } + } + } + } + + this.loadPage_ = function() { + console.log("LOAD url " + (loaderIndex_ + 1) + " of " + + pageLoaders_.length + + ", iteration " + (iterationIndex_ + 1) + " of " + + iterations_); + pageLoaders_[loaderIndex_].run(); + } + + this.handleResult_ = function(loader) { + var result = loader.result(); + resultsCollection_.addResult(result); + var totalTime = result.getTotalTime(); + if (!totalTime && retryIndex_ < retries_) { + retryIndex_++; + console.log("LOAD retry, " + retryIndex_); + } else { + retryIndex_ = 0; + console.log("RESULTS url " + (loaderIndex_ + 1) + " of " + + pageLoaders_.length + + ", iteration " + (iterationIndex_ + 1) + " of " + + iterations_ + ": " + totalTime); + loaderIndex_++; + if (loaderIndex_ >= pageLoaders_.length) { + iterationIndex_++; + if (iterationIndex_ < iterations_) { + loaderIndex_ = 0; + } else { + resultsReadyCallback_(me_); + return; + } + } + } + me_.loadPage_(); + } +} + +function AddBenchmarkCallback(callback) { + window.benchmarkCallback = callback; +} + +function Run() { + window.checkInterval = 500; + window.loadInterval = 1000; + window.timeout = 20000; // max ms before killing page. + window.retries = 0; + window.isRecordMode = benchmarkConfiguration.isRecordMode; + if (window.isRecordMode) { + window.iterations = 1; + window.timeout = 40000; + window.retries = 2; + } else { + window.iterations = benchmarkConfiguration["iterations"] || 3; + } + var sessionLoader = new SessionLoader(benchmarkCallback); + console.log("pageSets: " + JSON.stringify(benchmarkConfiguration.pageSets)); + sessionLoader.run(); +} + +chrome.extension.onConnect.addListener(function(port) { + port.onMessage.addListener(function(data) { + if (data.message == "start") { + window.benchmarkConfiguration = data.benchmark; + Run() + } + }); +});
\ No newline at end of file diff --git a/tools/page_cycler/webpagereplay/extension/content.js b/tools/page_cycler/webpagereplay/extension/content.js new file mode 100644 index 0000000..69713c3 --- /dev/null +++ b/tools/page_cycler/webpagereplay/extension/content.js @@ -0,0 +1,14 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Hook onload and then add a timeout to send timing information +// after the onload has completed. +window.addEventListener('load', function() { + window.setTimeout(function() { + chrome.extension.sendRequest({ + "timing": window.performance.timing, + "loadTimes": chrome.loadTimes(), + }); + }, 0); +}, false); diff --git a/tools/page_cycler/webpagereplay/extension/manifest.json b/tools/page_cycler/webpagereplay/extension/manifest.json new file mode 100644 index 0000000..a775768 --- /dev/null +++ b/tools/page_cycler/webpagereplay/extension/manifest.json @@ -0,0 +1,26 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +{ + "name": "Chromium Page Cycler with Web Page Replay.", + "version": "1.0.0.0", + "description": "Chromium Page Cycler with Web Page Replay.", + "background_page": "background.html", + "content_scripts": [ + { "matches": ["file:///*/start.html*"], + "js": ["start.js"], + "run_at": "document_idle" + }, + { "matches": ["http://*/*", "https://*/*"], + "js": ["content.js"], + "run_at": "document_start" + } + ], + "permissions": [ + "browsingData", + "cookies", + "experimental", + "tabs", + "<all_urls>" + ] +} diff --git a/tools/page_cycler/webpagereplay/extension/page_cycler.js b/tools/page_cycler/webpagereplay/extension/page_cycler.js new file mode 100644 index 0000000..76869b2 --- /dev/null +++ b/tools/page_cycler/webpagereplay/extension/page_cycler.js @@ -0,0 +1,54 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Returns the sum of all values in the array. +Array.sum = function(array) { + var sum = 0; + for (var i = array.length - 1; i >= 0; i--) { + sum += array[i]; + } + return sum; +}; + + +function WriteReport(sessionLoader) { + var iterations = window.iterations; + var reportUrl = window.benchmarkConfiguration.reportUrl; + var resultsCollection = sessionLoader.getResultsCollection(); + var times = resultsCollection.getTotalTimes(); + var pages = resultsCollection.getPages(); + + reportUrl += "?n=" + iterations; + reportUrl += "&i=" + iterations * pages.length; // "cycles" + reportUrl += "&td=" + Array.sum(times); // total time + reportUrl += "&tf=" + 0; // fudge time + console.log('reportUrl: ' + reportUrl); + chrome.cookies.set({ + "url": reportUrl, + "name": "__pc_done", + "value": "1", + "path": "/", + }); + chrome.cookies.set({ + "url": reportUrl, + "name": "__pc_pages", + "value": pages.map(function(x) { + return x.replace(/=/g, "%3D"); + }).join(","), + "path": "/", + }); + chrome.cookies.set({ + "url": reportUrl, + "name": "__pc_timings", + "value": times.join(","), + "path": "/", + }); + + chrome.tabs.getSelected(null, function(tab) { + console.log("Navigate to the report."); + chrome.tabs.update(tab.id, {"url": reportUrl}, null); + }); +} + +AddBenchmarkCallback(WriteReport); diff --git a/tools/page_cycler/webpagereplay/extension/start.js b/tools/page_cycler/webpagereplay/extension/start.js new file mode 100644 index 0000000..3250edb --- /dev/null +++ b/tools/page_cycler/webpagereplay/extension/start.js @@ -0,0 +1,89 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +document.cookie = "__navigated_to_report=0; path=/"; +document.cookie = "__pc_done=0; path=/"; +document.cookie = "__pc_timings=; path=/"; + +function dirname(path) { + var match = path.match(/(.*)\//); + if (match) { + return match[1]; + } else { + return "."; + } +} + +function IsWprRecordMode() { + var kStatusUrl = "http://wprwprwpr/web-page-replay-command-status"; + var isRecordMode; + var xhr = new XMLHttpRequest(); + var useAsync = false; + xhr.open("GET", kStatusUrl, useAsync); + xhr.timeout = 500; + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + var status = JSON.parse(xhr.responseText); + isRecordMode = status["is_record_mode"]; + console.log("WPR record mode?: " + isRecordMode); + } + }; + try { + xhr.send(); + } catch(e) { + throw "Web Page Replay is not responding. Start WPR to continue." + } + return isRecordMode; +} + + +function TryStart() { + console.log("try start"); + var status_element = document.getElementById("status"); + + var config_json; + var config; + try { + config_json = document.getElementById("json").textContent; + config = JSON.parse(config_json); + } catch(err) { + console.log("Bad json data: " + config_json); + status_element.textContent = "Exception: " + err + "\njson data: " + + config_json; + return; + } + var isRecordMode = false; + try { + isRecordMode = IsWprRecordMode(); + } catch (err) { + status_element.textContent = err; + setTimeout(TryStart, 5000); + return; + } + + if (!config["shouldStart"]) { + status_element.textContent = + "Press 'Start' to continue (or load this page with 'auto=1')."; + return; + } + + try { + var reportDir = dirname(dirname(window.location.pathname)) + "/common"; + config["reportUrl"] = "file://" + reportDir + "/report.html"; + config["isRecordMode"] = isRecordMode; + var port = chrome.extension.connect(); + port.postMessage({message: "start", benchmark: config}); + console.log("sending start message: page count, " + + config["pageSets"].length); + } catch(err) { + console.log("TryStart retrying after exception: " + err); + status_element.textContent = "Exception: " + err; + setTimeout(TryStart, 1000); + return; + } + status_element.textContent = "STARTING"; +} + +// We wait before starting the test just to let chrome warm up better. +setTimeout(TryStart, 250); diff --git a/tools/page_cycler/webpagereplay/start.html b/tools/page_cycler/webpagereplay/start.html new file mode 100644 index 0000000..d263a35 --- /dev/null +++ b/tools/page_cycler/webpagereplay/start.html @@ -0,0 +1,26 @@ +<html> +<!-- Copyright (c) 2012 The Chromium Authors. All rights reserved. --> +<!-- Use of this source code is governed by a BSD-style license that can be --> +<!-- found in the LICENSE file. --> +<head> +<style> + .labeledtextarea * { + vertical-align: middle; + } +</style> +</head> +<body> +<h3>Page Cycler: Web Page Replay Test</h3> + +<p class=labeledtextarea> +<label for="status">Status:</label> +<textarea id=status style="width:40em;height:3em;"></textarea> +</p> + +<hr> +<p> +<div id=startform></div> +<textarea id=json style="visibility: hidden;"></textarea> +<script src="start.js"></script> +</body> +</html> diff --git a/tools/page_cycler/webpagereplay/start.js b/tools/page_cycler/webpagereplay/start.js new file mode 100644 index 0000000..6ff5e6d --- /dev/null +++ b/tools/page_cycler/webpagereplay/start.js @@ -0,0 +1,123 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// webpagereplay/start.js - Start Web Page Replay (WPR) test. +// +// This script is included by webpagereplay/start.html. +// The query parameter "test=TEST_NAME" is required to load the +// test configuration from webpagereplay/tests/TEST_NAME.js +// That JavaScript file defines a global, "pageSets", as a list of lists: +// [ [url_1, url_2], [url_3], ...], +// - Before each sublist: +// Run chrome.browingData.remove and close the connections. +// - Before each url in a sublist: +// Close the connections. +// +// These WPR tests use a Chrome extension to load the test URLs. +// The extension loads the test configuration via a DOM elemment +// (id=json). This script sets the content of that DOM element. +// +// The test runs immediately after being loaded. +// + + +var options = location.search.substring(1).split('&'); +function getopt(name) { + var r = new RegExp('^' + name + '='); + for (i = 0; i < options.length; ++i) { + if (options[i].match(r)) { + return options[i].substring(name.length + 1); + } + } + return null; +} + +function LoadTestConfigurationScript(testUrl, callback) { + var testjs = document.createElement('script'); + testjs.type = 'text/javascript'; + testjs.async = true; + testjs.src = testUrl + var s = document.getElementsByTagName('script')[0]; + testjs.addEventListener('load', callback, false); + s.parentNode.insertBefore(testjs, s); +} + +function ReloadIfStuck() { + setTimeout(function() { + var status = document.getElementById('status'); + // The status text is set to 'STARTING' by the extension. + if (status.textContent != 'STARTING') { + console.log('Benchmark stuck? Reloading.'); + window.location.reload(true); + } + }, 30000); +} + +function RenderForm() { + var form = document.createElement('FORM'); + form.setAttribute('action', 'start.html'); + + var label = document.createTextNode('Iterations: '); + form.appendChild(label); + + var input = document.createElement('INPUT'); + var iterations = getopt('iterations'); + input.setAttribute('name', 'iterations'); + input.setAttribute('value', iterations ? iterations : '5'); + form.appendChild(input); + + form.appendChild(document.createElement('P')); + + var label = document.createTextNode('Test: '); + form.appendChild(label); + + var input = document.createElement('INPUT'); + input.setAttribute('name', 'test'); + var test = getopt('test'); + input.setAttribute('value', test ? test : ''); + form.appendChild(input); + + var input = document.createElement('INPUT'); + input.setAttribute('name', 'auto'); + var auto = getopt('auto'); + input.setAttribute('value', 1); + input.setAttribute('type', 'hidden'); + form.appendChild(input); + + form.appendChild(document.createElement('P')); + + input = document.createElement('INPUT'); + input.setAttribute('type', 'submit'); + input.setAttribute('value', 'Start'); + form.appendChild(input); + + document.getElementById('startform').appendChild(form); +} + + +var iterations = getopt('iterations'); +var test_name = getopt('test'); +var is_auto_start = getopt('auto'); + +RenderForm(); +if (test_name) { + var testUrl = 'tests/' + test_name + '.js'; + LoadTestConfigurationScript(testUrl, function() { + var testConfig = {}; + if (iterations) { + testConfig['iterations'] = iterations; + } + // The pageSets global is set by test configuration script. + testConfig['pageSets'] = pageSets; + + if (is_auto_start) { + testConfig['shouldStart'] = 1; + ReloadIfStuck(); + } + // Write testConfig to "json" DOM element for the Chrome extension. + document.getElementById('json').textContent = JSON.stringify(testConfig); + }); +} else { + console.log('Need "test=TEST_NAME" query parameter.'); +} diff --git a/tools/page_cycler/webpagereplay/tests/2012Q2.js b/tools/page_cycler/webpagereplay/tests/2012Q2.js new file mode 100644 index 0000000..11bba9f --- /dev/null +++ b/tools/page_cycler/webpagereplay/tests/2012Q2.js @@ -0,0 +1,77 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/* + "pageSets" is a list of lists. + - Before each sublist: + Run chrome.browingData.remove and close the connections. + - Before each url in a sublist: + Close the connections. +*/ +var pageSets = [ + ["http://superfastpageload/web-page-replay-generate-200"], + + // Load url pairs without clearing browser data (e.g. cache) in-between. + ["http://go.com/", + "http://espn.go.com/"], + ["http://www.amazon.com/", + "http://www.amazon.com/Kindle-Fire-Amazon-Tablet/dp/B0051VVOB2/"], + ["http://www.baidu.com/", + "http://www.baidu.com/s?wd=obama"], + ["http://www.bing.com/", + "http://www.bing.com/search?q=cars"], + ["http://www.ebay.com/", + "http://fashion.ebay.com/womens-clothing"], + ["http://www.google.com/", + "http://www.google.com/search?q=dogs"], + ["http://www.yandex.ru/", + "http://yandex.ru/yandsearch?text=obama&lr=84"], + ["http://www.youtube.com", + "http://www.youtube.com/watch?v=xvN9Ri1GmuY&feature=g-sptl&cid=inp-hs-edt"], + + ["http://ameblo.jp/"], + ["http://en.rakuten.co.jp/"], + ["http://en.wikipedia.org/wiki/Lady_gaga"], + ["http://news.google.co.in"], + ["http://plus.google.com/"], // iframe error (result of no cookies?) + ["http://www.163.com/"], + ["http://www.apple.com/"], + ["http://www.bbc.co.uk/"], + ["http://www.cnet.com/"], + ["http://www.msn.com/"], + ["http://www.nytimes.com/"], + ["http://www.taobao.com/"], + ["http://www.yahoo.co.jp/"], + + // HTTPS pages. + ["https://wordpress.com/"], + ["https://www.conduit.com/"], + ["https://www.facebook.com", + "https://www.facebook.com/barackobama"], +]; + +/* + // Not included (need further investigation). + ["http://twitter.com/BarackObama", + "http://twitter.com/search?q=pizza"], // large variance on second page + ["http://www.fc2.com/"], // slow + ["http://sina.com.cn/"], // slow + ["http://www.mail.ru/"], // long load time (30s+) + ["http://www.sohu.com/"], // load does not finish (even without WPR) + + // Not included (trimmed pageSets to keep test under 10 minutes). + ["http://sfbay.craigslist.org/", + "http://sfbay.craigslist.org/search/sss?query=flowers"], + ["http://www.flickr.com/", + "http://www.flickr.com/photos/tags/flowers"], + ["http://www.linkedin.com/", + "http://www.linkedin.com/in/jeffweiner08"], + ["http://www.yahoo.com/", + "http://search.yahoo.com/search?p=disney"], + ["http://googleblog.blogspot.com/"], + ["http://www.adobe.com/reader/"], + ["http://www.cnn.com/"], + ["http://www.imdb.com/"], + ["http://www.qq.com/"], +*/ |