mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[infra] Remove obsolete webdriver/selenium support from testing
After this removal, the only thing in tools/testing is the checked-in jsshell (Mozilla command-line JavaScript runner) executable. Discussions for removing that as well have been started. Change-Id: I28505154de9fa7df3a2d5f84f3f778c596f52fcc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106087 Reviewed-by: Bob Nystrom <rnystrom@google.com>
This commit is contained in:
parent
770675b668
commit
707d3ccd14
|
@ -1,20 +0,0 @@
|
|||
# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
|
||||
import test_runner
|
||||
import utils
|
||||
|
||||
|
||||
# Constants used for test outcomes
|
||||
SKIP = 'skip'
|
||||
FAIL = 'fail'
|
||||
PASS = 'pass'
|
||||
OKAY = 'okay'
|
||||
TIMEOUT = 'timeout'
|
||||
CRASH = 'crash'
|
||||
SLOW = 'slow'
|
||||
|
||||
HOST_CPUS = utils.GuessCpus()
|
||||
USE_DEFAULT_CPUS = -1
|
|
@ -1,29 +0,0 @@
|
|||
Overview:
|
||||
These are the instructions to run a wide variety of browser tests using
|
||||
test.dart or dart/tools/testing/perf_testing/run_perf_tests.py. Currently
|
||||
the results of run_perf_tests are uploaded to
|
||||
https://dartperf.googleplex.com/.
|
||||
|
||||
========= General Browser Setup ==========
|
||||
|
||||
See instructions on:
|
||||
https://code.google.com/p/dart/wiki/BrowserTestSetup
|
||||
|
||||
========= Proceed further only if you also want to run performance tests.======
|
||||
|
||||
1) Pull down benchmarks from internal repo (Google only): goto/dartbrowsersetup
|
||||
|
||||
2) Create a directory in called appengine-python in third_party. Download the
|
||||
Linux/Other Platforms .zip file, and place the contents in the directory
|
||||
you just created.
|
||||
http://code.google.com/appengine/downloads.html#Google_App_Engine_SDK_for_Python
|
||||
|
||||
3) Run the tests! While standing in dart/tools/testing/perf_testing, run
|
||||
$> python run_perf_tests.py --forever --verbose
|
||||
to run all the tests (browser performance, language correctness in the
|
||||
browser, command line performance, and self-hosted compile time and compiled
|
||||
code size).
|
||||
|
||||
You can run individual tests by adding the particular option (such as
|
||||
--language) when running create_graph.py. Type "create_graph.py -h" for a
|
||||
full list of the options.
|
Binary file not shown.
|
@ -1,90 +0,0 @@
|
|||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* This is the background window. It can access the necessary APIs to get
|
||||
* at the console messages. It can only communicate with the content
|
||||
* window through message passing.
|
||||
*
|
||||
* There is no way to query the console messages, as such, but we can
|
||||
* set up a handler that is called when there are console messages. This
|
||||
* will be called with any console messages already present, so it can be set
|
||||
* up after the fact. However, if there are no messages it won't be called.
|
||||
* To handle the end of the messages (or no messages) we have to use a
|
||||
* sentinel message that is logged by the content page.
|
||||
*/
|
||||
var version = "1.0";
|
||||
var messages = []; // An array that we can put messages in.
|
||||
var debuggeeId; // An object that identifies the browser tab we are talking to.
|
||||
var callback; // For passing back the response to the content window.
|
||||
var timer; // To time out if no messages are available.
|
||||
|
||||
/**
|
||||
* When we have collected all the messages, we send them back to the
|
||||
* content page via the callback, turn off message collection, and
|
||||
* detach the debugger from the browser tab.
|
||||
*/
|
||||
function allDone() {
|
||||
callback(messages);
|
||||
chrome.debugger.sendCommand(debuggeeId, "Console.clearMessages", {},
|
||||
function() {
|
||||
chrome.debugger.sendCommand(debuggeeId, "Console.disable", {},
|
||||
function() {});
|
||||
chrome.debugger.detach(debuggeeId, function() {});
|
||||
});
|
||||
messages = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Debugger event handler. We only care about console.messageAdded
|
||||
* events, in which case we add a new message object with the fields
|
||||
* we care about to our messages array.
|
||||
*/
|
||||
function onEvent(debuggeeId, method, params) {
|
||||
var tabId = debuggeeId.tabId;
|
||||
if (method == "Console.messageAdded") {
|
||||
var msg = params.message;
|
||||
// More fields are available if we want them later. See
|
||||
// https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/console#type-ConsoleMessage
|
||||
if (msg.text == 'getMessages/end') {
|
||||
allDone();
|
||||
} else {
|
||||
messages.push({"source":msg.url, "line": msg.line,
|
||||
"category":msg.source, "message":msg.text });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle requests sent by the content script. We save the callback,
|
||||
* get the window and tab that is currently active, attach the
|
||||
* debugger to that tab, and then turn on console message event
|
||||
* handling, which will result in onEvent calls for each console
|
||||
* message, including the ones that are already present in the console.
|
||||
*/
|
||||
function onRequest(request, sender, sendResponse) {
|
||||
if (request.command == "getMessages") {
|
||||
callback = sendResponse;
|
||||
chrome.windows.getCurrent(function(win) {
|
||||
chrome.tabs.getSelected(win.id, function(tab) {
|
||||
debuggeeId = {tabId:tab.id};
|
||||
chrome.debugger.attach(debuggeeId, version, function() {
|
||||
if (chrome.extension.lastError) {
|
||||
// Attach failed; send an empty response.
|
||||
callback([]);
|
||||
} else {
|
||||
chrome.debugger.sendCommand(debuggeeId, "Console.enable", {},
|
||||
function() {});
|
||||
//timer = setTimeout(allDone, 1000);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the general handler for debug events.
|
||||
chrome.debugger.onEvent.addListener(onEvent);
|
||||
// Listen for the content script to send a message to the background page.
|
||||
chrome.extension.onRequest.addListener(onRequest);
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* This is the content page script. This runs in the context of the browser
|
||||
* page, and communicates with the background page by relaying a getMessages
|
||||
* request, and the forwarding the messages back to the browser page as a
|
||||
* gotMessages message.
|
||||
*/
|
||||
window.addEventListener("message", function(event) {
|
||||
if (event.source == window && event.data == "getMessages") {
|
||||
// Log a special sentinel message to mark the end of the messages.
|
||||
console.log('getMessages/end');
|
||||
chrome.extension.sendRequest({command: "getMessages"}, function(messages) {
|
||||
window.postMessage({ "type": "gotMessages", "messages" : messages}, "*");
|
||||
});
|
||||
}
|
||||
}, false);
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"name": "Console Collector",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
"description": "Allow querying of the Javascript console.",
|
||||
"browser_action": {
|
||||
"name": "ConsoleCollector"
|
||||
},
|
||||
"background": {
|
||||
"scripts": ["background.js"],
|
||||
"persistent": true
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["http://*/*", "file://*" ],
|
||||
"js": [ "content.js" ]
|
||||
}
|
||||
],
|
||||
"permissions": [
|
||||
"tabs", "http://*/*", "file://*", "debugger"
|
||||
]
|
||||
}
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
|||
../ConsoleCollector.xpi: chrome.manifest install.rdf chrome/content/console.js chrome/content/overlay.xul
|
||||
zip -r ../ConsoleCollector.xpi chrome.manifest install.rdf chrome/content/console.js chrome/content/overlay.xul
|
|
@ -1,2 +0,0 @@
|
|||
content ConsoleCollector chrome/content/
|
||||
overlay chrome://browser/content/browser.xul chrome://ConsoleCollector/content/overlay.xul
|
|
@ -1,104 +0,0 @@
|
|||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// This Firefox add-on exposes the Javascript console contents to Javascript
|
||||
// running in the browser. Once this is installed there will be a new
|
||||
// window.ConsoleCollector object with read() and clear() functions.
|
||||
|
||||
var ConsoleCollector = {};
|
||||
|
||||
(function() {
|
||||
// An array for collecting the messages.
|
||||
var messages = [];
|
||||
|
||||
// Add a console message to the collection.
|
||||
this.add = function(message) {
|
||||
messages.push(message);
|
||||
};
|
||||
|
||||
// Read the message collection. As a side effect we clear the message list.
|
||||
this.read = function(type) {
|
||||
var rtn = [];
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
var message = messages[i];
|
||||
if (message.errorMessage) {
|
||||
rtn.push({ 'time' : message.timeStamp,
|
||||
'source' : message.sourceName,
|
||||
'line': message.lineNumber,
|
||||
'column': message.columnNumber,
|
||||
'category': message.category,
|
||||
'message' : message.errorMessage });
|
||||
}
|
||||
}
|
||||
messages = [];
|
||||
return rtn;
|
||||
};
|
||||
|
||||
// Clear the message list.
|
||||
this.clear = function() {
|
||||
messages = [];
|
||||
};
|
||||
}).apply(ConsoleCollector);
|
||||
|
||||
// A Console Listener.
|
||||
// See https://developer.mozilla.org/en-US/docs/Console_service for
|
||||
// details.
|
||||
(function() {
|
||||
|
||||
var consoleService;
|
||||
|
||||
var consoleListener = {
|
||||
observe: function(e) {
|
||||
try {
|
||||
var message = e.QueryInterface(Components.interfaces.nsIScriptError);
|
||||
ConsoleCollector.add(message);
|
||||
} catch (exception) {
|
||||
ConsoleCollector.add(e);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: function (iid) {
|
||||
if (!iid.equals(Components.interfaces.nsIConsoleListener) &&
|
||||
!iid.equals(Components.interfaces.nsISupports)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
// Start collecting console messages.
|
||||
function initialize(event) {
|
||||
consoleService = Components.classes['@mozilla.org/consoleservice;1']
|
||||
.getService(Components.interfaces.nsIConsoleService);
|
||||
if (consoleService) {
|
||||
consoleService.registerListener(consoleListener);
|
||||
}
|
||||
// Add the handler for hooking in to each page's DOM. This handler
|
||||
// is for each "gBrowser", representing a tab/window.
|
||||
window.getBrowser().addEventListener("load", onPageLoad, true);
|
||||
}
|
||||
|
||||
// Stop collecting console messages.
|
||||
function shutdown(event) {
|
||||
window.getBrowser().removeEventListener("load", onPageLoad);
|
||||
consoleService.unregisterListener(consoleListener);
|
||||
ConsoleCollector.clear();
|
||||
}
|
||||
|
||||
// Hook the ConsoleCollector into the DOM as window.ConsoleCollector.
|
||||
var onPageLoad = function(e) {
|
||||
var win = e.originalTarget.defaultView;
|
||||
if (win) {
|
||||
win.wrappedJSObject.ConsoleCollector = ConsoleCollector;
|
||||
}
|
||||
};
|
||||
|
||||
// Add the handlers to initialize the add-on and shut it down.
|
||||
// These handlers are for the application as a whole.
|
||||
window.addEventListener('load', initialize, false);
|
||||
window.addEventListener('unload', shutdown, false);
|
||||
}());
|
||||
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<overlay id="ConsoleCollector-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="console.js"/>
|
||||
</overlay>
|
|
@ -1,20 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>ConsoleCollector@google.com</em:id>
|
||||
<em:name>Console collector</em:name>
|
||||
<em:version>0.2</em:version>
|
||||
<em:description>Exposes the Javascript console to each browser window.
|
||||
</em:description>
|
||||
<em:creator>Graham Wheeler</em:creator>
|
||||
<em:homepageURL>http://www.dartlang.org</em:homepageURL>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
|
||||
<em:minVersion>3.0</em:minVersion>
|
||||
<em:maxVersion>15.0</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
|
@ -1,390 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
#
|
||||
|
||||
"""Script to actually open a browser and perform the test, and reports back with
|
||||
the result. It uses Selenium WebDriver when possible for running the tests. It
|
||||
uses Selenium RC for Safari.
|
||||
|
||||
If started with --batch this script runs a batch of in-browser tests in
|
||||
the same browser process.
|
||||
|
||||
Normal mode:
|
||||
$ python run_selenium.py --browser=ff --timeout=60 path/to/test.html
|
||||
|
||||
Exit code indicates pass or fail
|
||||
|
||||
Batch mode:
|
||||
$ python run_selenium.py --batch
|
||||
stdin: --browser=ff --timeout=60 path/to/test.html
|
||||
stdout: >>> TEST PASS
|
||||
stdin: --browser=ff --timeout=60 path/to/test2.html
|
||||
stdout: >>> TEST FAIL
|
||||
stdin: --terminate
|
||||
$
|
||||
"""
|
||||
|
||||
import os
|
||||
import optparse
|
||||
import platform
|
||||
import selenium
|
||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import urllib2
|
||||
import threading
|
||||
|
||||
TIMEOUT_ERROR_MSG = 'FAIL (timeout)'
|
||||
CRASH_ERROR_MSG = 'CRASH'
|
||||
|
||||
def correctness_test_done(source):
|
||||
"""Checks if test has completed."""
|
||||
return ('PASS' in source) or ('FAIL' in source)
|
||||
|
||||
def perf_test_done(source):
|
||||
"""Tests to see if our performance test is done by printing a score."""
|
||||
#This code is written this way to work around a current instability in the
|
||||
# python webdriver bindings if you call driver.get_element_by_id.
|
||||
#TODO(efortuna): Access these elements in a nicer way using DOM parser.
|
||||
string = '<div id="status">'
|
||||
index = source.find(string)
|
||||
end_index = source.find('</div>', index+1)
|
||||
source = source[index + len(string):end_index]
|
||||
return 'Score:' in source
|
||||
|
||||
# TODO(vsm): Ideally, this wouldn't live in this file.
|
||||
CONFIGURATIONS = {
|
||||
'correctness': correctness_test_done,
|
||||
'perf': perf_test_done
|
||||
}
|
||||
|
||||
def run_test_in_browser(browser, html_out, timeout, mode, refresh):
|
||||
"""Run the desired test in the browser using Selenium 2.0 WebDriver syntax,
|
||||
and wait for the test to complete. This is the newer syntax, that currently
|
||||
supports Firefox, Chrome, IE, Opera (and some mobile browsers)."""
|
||||
|
||||
if isinstance(browser, selenium.selenium):
|
||||
return run_test_in_browser_selenium_rc(browser, html_out, timeout, mode,
|
||||
refresh)
|
||||
|
||||
browser.get(html_out)
|
||||
if refresh:
|
||||
browser.refresh()
|
||||
try:
|
||||
def pythonTimeout():
|
||||
# The builtin quit call for chrome will call close on the RemoteDriver
|
||||
# which may hang. Explicitly call browser.service.stop()
|
||||
if (type(browser) is selenium.webdriver.chrome.webdriver.WebDriver):
|
||||
# Browser may be dead
|
||||
try:
|
||||
browser.service.stop()
|
||||
except:
|
||||
print("Trying to close browser that has already been closed")
|
||||
# If the browser is crashing selenium may not time out.
|
||||
# Explicitly catch this case with a python timer.
|
||||
t = threading.Timer(timeout, pythonTimeout)
|
||||
t.start()
|
||||
test_done = CONFIGURATIONS[mode]
|
||||
element = WebDriverWait(browser, float(timeout)).until(
|
||||
lambda driver: test_done(driver.page_source))
|
||||
t.cancel()
|
||||
return browser.page_source
|
||||
except selenium.common.exceptions.TimeoutException:
|
||||
return TIMEOUT_ERROR_MSG
|
||||
except:
|
||||
return CRASH_ERROR_MSG
|
||||
|
||||
def run_test_in_browser_selenium_rc(sel, html_out, timeout, mode, refresh):
|
||||
""" Run the desired test in the browser using Selenium 1.0 syntax, and wait
|
||||
for the test to complete. This is used for Safari, since it is not currently
|
||||
supported on Selenium 2.0."""
|
||||
sel.open(html_out)
|
||||
if refresh:
|
||||
sel.refresh()
|
||||
source = sel.get_html_source()
|
||||
end_condition = CONFIGURATIONS[mode]
|
||||
|
||||
elapsed = 0
|
||||
while (not end_condition(source)) and elapsed <= timeout:
|
||||
sec = .25
|
||||
time.sleep(sec)
|
||||
elapsed += sec
|
||||
source = sel.get_html_source()
|
||||
return source
|
||||
|
||||
def parse_args(args=None):
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('--out', dest='out',
|
||||
help = 'The path for html output file that we will running our test from',
|
||||
action = 'store', default = '')
|
||||
parser.add_option('--browser', dest='browser',
|
||||
help = 'The browser type (default = chrome)',
|
||||
action = 'store', default = 'chrome')
|
||||
parser.add_option('--executable', dest='executable',
|
||||
help = 'The browser executable path (only for browser=dartium)',
|
||||
action = 'store', default = None)
|
||||
# TODO(efortuna): Put this back up to be more than the default timeout in
|
||||
# test.dart. Right now it needs to be less than 60 so that when test.dart
|
||||
# times out, this script also closes the browser windows.
|
||||
parser.add_option('--timeout', dest = 'timeout',
|
||||
help = 'Amount of time (seconds) to wait before timeout', type = 'int',
|
||||
action = 'store', default=58)
|
||||
parser.add_option('--mode', dest = 'mode',
|
||||
help = 'The type of test we are running',
|
||||
action = 'store', default='correctness')
|
||||
parser.add_option('--force-refresh', dest='refresh',
|
||||
help='Force the browser to refresh before getting results from this test '
|
||||
'(used for browser multitests).', action='store_true', default=False)
|
||||
args, _ = parser.parse_args(args=args)
|
||||
args.out = args.out.strip('"')
|
||||
if args.executable and args.browser != 'dartium':
|
||||
print 'Executable path only supported when browser=dartium.'
|
||||
sys.exit(1)
|
||||
return (args.out, args.browser, args.executable, args.timeout, args.mode,
|
||||
args.refresh)
|
||||
|
||||
def print_server_error():
|
||||
"""Provide the user an informative error message if we attempt to connect to
|
||||
the Selenium remote control server, but cannot access it. Then exit the
|
||||
program."""
|
||||
print ('ERROR: Could not connect to Selenium RC server. Are you running'
|
||||
' java -jar tools/testing/selenium-server-standalone-*.jar? If not, '
|
||||
'start it before running this test.')
|
||||
sys.exit(1)
|
||||
|
||||
def start_browser(browser, executable_path, html_out):
|
||||
if browser == 'chrome' or browser == 'dartium':
|
||||
# Note: you need ChromeDriver *in your path* to run Chrome, in addition to
|
||||
# installing Chrome. Also note that the build bot runs have a different path
|
||||
# from a normal user -- check the build logs.
|
||||
options = selenium.webdriver.chrome.options.Options()
|
||||
if browser == 'dartium':
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
dartium_dir = os.path.join(script_dir, '..', '..', 'client', 'tests',
|
||||
'dartium')
|
||||
# enable ShadowDOM and style scoped for Dartium
|
||||
options.add_argument('--enable-shadow-dom')
|
||||
options.add_argument('--enable-style-scoped')
|
||||
if executable_path is not None:
|
||||
options.binary_location = executable_path
|
||||
elif platform.system() == 'Windows':
|
||||
options.binary_location = os.path.join(dartium_dir, 'chrome.exe')
|
||||
elif platform.system() == 'Darwin':
|
||||
options.binary_location = os.path.join(dartium_dir, 'Chromium.app',
|
||||
'Contents', 'MacOS', 'Chromium')
|
||||
else:
|
||||
options.binary_location = os.path.join(dartium_dir, 'chrome')
|
||||
return selenium.webdriver.Chrome(chrome_options=options)
|
||||
elif browser == 'ff':
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
profile = selenium.webdriver.firefox.firefox_profile.FirefoxProfile()
|
||||
profile.set_preference('dom.max_script_run_time', 0)
|
||||
profile.set_preference('dom.max_chrome_script_run_time', 0)
|
||||
profile.set_preference('app.update.auto', True)
|
||||
profile.set_preference('app.update.enabled', True)
|
||||
return selenium.webdriver.Firefox(firefox_profile=profile)
|
||||
elif ((browser == 'ie9' or browser == 'ie10') and
|
||||
platform.system() == 'Windows'):
|
||||
return selenium.webdriver.Ie()
|
||||
elif browser == 'safari' and platform.system() == 'Darwin':
|
||||
# TODO(efortuna): Ensure our preferences (no pop-up blocking) file is the
|
||||
# same (Safari auto-deletes when it has too many "crashes," or in our case,
|
||||
# timeouts). Come up with a less hacky way to do this.
|
||||
backup_safari_prefs = os.path.dirname(__file__) + '/com.apple.Safari.plist'
|
||||
if os.path.exists(backup_safari_prefs):
|
||||
shutil.copy(backup_safari_prefs,
|
||||
'/Library/Preferences/com.apple.Safari.plist')
|
||||
sel = selenium.selenium('localhost', 4444, "*safari", html_out)
|
||||
try:
|
||||
sel.start()
|
||||
return sel
|
||||
except socket.error:
|
||||
print_server_error()
|
||||
elif browser == 'opera':
|
||||
try:
|
||||
driver = RemoteWebDriver(desired_capabilities=DesiredCapabilities.OPERA)
|
||||
# By default, Opera sets their script timeout (the amount of time they
|
||||
# expect to hear back from the JavaScript file) to be 10 seconds. We just
|
||||
# make it an impossibly large number so that it doesn't time out for this
|
||||
# reason, so it behaves like all of the other browser drivers.
|
||||
driver.set_script_timeout(9000)
|
||||
# If the webpage contains document.onreadystatechanged = function() {...}
|
||||
# page load event does not correctly get fired and caught (OperaDriver
|
||||
# bug). This is a band-aid.
|
||||
driver.set_page_load_timeout(1)
|
||||
return driver
|
||||
except urllib2.URLError:
|
||||
print_server_error()
|
||||
else:
|
||||
raise Exception('Incompatible browser and platform combination.')
|
||||
|
||||
def close_browser(browser):
|
||||
if browser is None:
|
||||
return
|
||||
if isinstance(browser, selenium.selenium):
|
||||
browser.stop()
|
||||
return
|
||||
|
||||
# A timeout exception is thrown if nothing happens within the time limit.
|
||||
if (type(browser) is not selenium.webdriver.chrome.webdriver.WebDriver and
|
||||
type(browser) is not selenium.webdriver.ie.webdriver.WebDriver):
|
||||
browser.close()
|
||||
|
||||
browser.quit()
|
||||
|
||||
def report_results(mode, source, browser):
|
||||
if mode != 'correctness':
|
||||
# We're running a performance test.
|
||||
print source.encode('utf8')
|
||||
sys.stdout.flush()
|
||||
if 'NaN' in source:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
else:
|
||||
# We're running a correctness test. Mark test as passing if all individual
|
||||
# test cases pass.
|
||||
if 'FAIL' not in source and 'PASS' in source:
|
||||
print 'Content-Type: text/plain\nPASS'
|
||||
return 0
|
||||
else:
|
||||
#The hacky way to get document.getElementById('body').innerHTML for this
|
||||
# webpage, without the JavaScript.
|
||||
#TODO(efortuna): Access these elements in a nicer way using DOM parser.
|
||||
index = source.find('<body>')
|
||||
index += len('<body>')
|
||||
end_index = source.find('</body')
|
||||
print unicode(source[index : end_index]).encode("utf-8")
|
||||
return 1
|
||||
|
||||
|
||||
def run_batch_tests():
|
||||
'''
|
||||
Runs a batch of in-browser tests in the same browser process. Batching
|
||||
gives faster throughput and makes tests less subject to browser starting
|
||||
flakiness, issues with too many browser processes running, etc.
|
||||
|
||||
When running this function, stdin/stdout is used to communicate with the test
|
||||
framework. See BatchRunnerProcess in test_runner.dart for the other side of
|
||||
this communication channel
|
||||
|
||||
Example of usage:
|
||||
$ python run_selenium.py --batch
|
||||
stdin: --browser=ff --timeout=60 path/to/test.html
|
||||
stdout: >>> TEST PASS
|
||||
stdin: --browser=ff --timeout=60 path/to/test2.html
|
||||
stdout: >>> TEST FAIL
|
||||
stdin: --terminate
|
||||
$
|
||||
'''
|
||||
|
||||
print '>>> BATCH START'
|
||||
browser = None
|
||||
current_browser_name = None
|
||||
|
||||
# TODO(jmesserly): It'd be nice to shutdown gracefully in the event of a
|
||||
# SIGTERM. Unfortunately dart:io cannot send SIGTERM, see dartbug.com/1756.
|
||||
signal.signal(signal.SIGTERM, lambda number, frame: close_browser(browser))
|
||||
|
||||
try:
|
||||
try:
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if line == '--terminate\n':
|
||||
print("Terminating selenium driver")
|
||||
break
|
||||
|
||||
(html_out, browser_name, executable_path,
|
||||
timeout, mode, refresh) = parse_args(line.split())
|
||||
|
||||
# Sanity checks that test.dart is passing flags we can handle.
|
||||
if mode != 'correctness':
|
||||
print 'Batch test runner not compatible with perf testing'
|
||||
return 1
|
||||
if browser and current_browser_name != browser_name:
|
||||
print('Batch test runner got multiple browsers: %s and %s'
|
||||
% (current_browser_name, browser_name))
|
||||
return 1
|
||||
|
||||
# Start the browser on the first run
|
||||
if browser is None:
|
||||
current_browser_name = browser_name
|
||||
browser = start_browser(browser_name, executable_path, html_out)
|
||||
|
||||
source = run_test_in_browser(browser, html_out, timeout, mode, refresh)
|
||||
|
||||
# Test is done. Write end token to stderr and flush.
|
||||
sys.stderr.write('>>> EOF STDERR\n')
|
||||
sys.stderr.flush()
|
||||
|
||||
# print one of:
|
||||
# >>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}
|
||||
status = report_results(mode, source, browser)
|
||||
if status == 0:
|
||||
print '>>> TEST PASS'
|
||||
elif source == TIMEOUT_ERROR_MSG:
|
||||
print '>>> TEST TIMEOUT'
|
||||
elif source == CRASH_ERROR_MSG:
|
||||
print '>>> TEST CRASH'
|
||||
# The browser crashed, set the browser to None so that we will
|
||||
# create a new instance on next iteration.
|
||||
browser = None
|
||||
else:
|
||||
print '>>> TEST FAIL'
|
||||
sys.stdout.flush()
|
||||
except:
|
||||
type, value, traceback = sys.exc_info()
|
||||
print "run_selenium.py: Unexpected exception occured: "
|
||||
print " type: ", type
|
||||
print " value: ", value
|
||||
print " traceback: ", traceback
|
||||
raise
|
||||
finally:
|
||||
sys.stdin.close()
|
||||
print("Closing browser");
|
||||
|
||||
def close_output_streams():
|
||||
sys.stdout.flush()
|
||||
sys.stdout.close()
|
||||
sys.stderr.flush()
|
||||
sys.stderr.close()
|
||||
|
||||
def close_and_exit():
|
||||
print("Timed out waiting for browser to close")
|
||||
close_output_streams()
|
||||
exit(1)
|
||||
|
||||
timer = threading.Timer(5.0, close_and_exit)
|
||||
timer.start()
|
||||
try:
|
||||
close_browser(browser)
|
||||
timer.cancel()
|
||||
finally:
|
||||
close_output_streams()
|
||||
|
||||
def main(args):
|
||||
# Run in batch mode if the --batch flag is passed.
|
||||
# TODO(jmesserly): reconcile with the existing args parsing
|
||||
if '--batch' in args:
|
||||
return run_batch_tests()
|
||||
|
||||
# Run a single test
|
||||
html_out, browser_name, executable_path, timeout, mode, refresh = parse_args()
|
||||
browser = start_browser(browser_name, executable_path, html_out)
|
||||
|
||||
try:
|
||||
output = run_test_in_browser(browser, html_out, timeout, mode, refresh)
|
||||
return report_results(mode, output, browser)
|
||||
finally:
|
||||
close_browser(browser)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
|
@ -1,434 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
# Run to install the necessary components to run webdriver on the buildbots or
|
||||
# on your local machine.
|
||||
# Note: The setup steps can be done fairly easily by hand. This script is
|
||||
# intended to simply and reduce the time for setup since there are a fair number
|
||||
# of steps.
|
||||
|
||||
# TODO(efortuna): Rewrite this script in Dart when the Process module has a
|
||||
# better high level API.
|
||||
import HTMLParser
|
||||
import optparse
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib
|
||||
import urllib2
|
||||
import zipfile
|
||||
|
||||
def run_cmd(cmd, stdin=None):
|
||||
"""Run the command on the command line in the shell. We print the output of
|
||||
the command.
|
||||
"""
|
||||
print cmd
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
stdin=subprocess.PIPE, shell=True)
|
||||
output, stderr = p.communicate(input=stdin)
|
||||
if output:
|
||||
print output
|
||||
if stderr:
|
||||
print stderr
|
||||
|
||||
def parse_args():
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('--firefox', '-f', dest='firefox',
|
||||
help="Don't install Firefox", action='store_true', default=False)
|
||||
parser.add_option('--opera', '-o', dest='opera', default=False,
|
||||
help="Don't install Opera", action='store_true')
|
||||
parser.add_option('--chromedriver', '-c', dest='chromedriver',
|
||||
help="Don't install chromedriver.", action='store_true', default=False)
|
||||
parser.add_option('--iedriver', '-i', dest='iedriver',
|
||||
help="Don't install iedriver (only used on Windows).",
|
||||
action='store_true', default=False)
|
||||
parser.add_option('--seleniumrc', '-s', dest='seleniumrc',
|
||||
help="Don't install the Selenium RC server (used for Safari and Opera "
|
||||
"tests).", action='store_true', default=False)
|
||||
parser.add_option('--python', '-p', dest='python',
|
||||
help="Don't install Selenium python bindings.", action='store_true',
|
||||
default=False)
|
||||
parser.add_option('--buildbot', '-b', dest='buildbot', action='store_true',
|
||||
help='Perform a buildbot selenium setup (buildbots have a different' +
|
||||
'location for their python executable).', default=False)
|
||||
args, _ = parser.parse_args()
|
||||
return args
|
||||
|
||||
def find_depot_tools_location(is_buildbot):
|
||||
"""Depot_tools is our default install location for chromedriver, so we find
|
||||
its location on the filesystem.
|
||||
Arguments:
|
||||
is_buildbot - True if we are running buildbot machine setup (we can't detect
|
||||
this automatically because this script is not run at build time).
|
||||
"""
|
||||
if is_buildbot:
|
||||
depot_tools = os.sep + os.path.join('b', 'depot_tools')
|
||||
if 'win32' in sys.platform or 'cygwin' in sys.platform:
|
||||
depot_tools = os.path.join('e:', depot_tools)
|
||||
return depot_tools
|
||||
else:
|
||||
path = os.environ['PATH'].split(os.pathsep)
|
||||
for loc in path:
|
||||
if 'depot_tools' in loc:
|
||||
return loc
|
||||
raise Exception("Could not find depot_tools in your path.")
|
||||
|
||||
class GoogleBasedInstaller(object):
|
||||
"""Install a project from a Google source, pulling latest version."""
|
||||
|
||||
def __init__(self, project_name, destination, download_path_func):
|
||||
"""Create an object that will install the project.
|
||||
Arguments:
|
||||
project_name - Google code name of the project, such as "selenium" or
|
||||
"chromedriver."
|
||||
destination - Where to download the desired file on our filesystem.
|
||||
download_path_func - A function that takes a dictionary (currently with keys
|
||||
"os" and "version", but more can be added) that calculates the string
|
||||
representing the path of the download we want.
|
||||
"""
|
||||
self.project_name = project_name
|
||||
self.destination = destination
|
||||
self.download_path_func = download_path_func
|
||||
|
||||
@property
|
||||
def get_os_str(self):
|
||||
"""The strings to indicate what OS a download is for."""
|
||||
os_str = 'win'
|
||||
if 'darwin' in sys.platform:
|
||||
os_str = 'mac'
|
||||
elif 'linux' in sys.platform:
|
||||
os_str = 'linux32'
|
||||
if '64bit' in platform.architecture()[0]:
|
||||
os_str = 'linux64'
|
||||
if self.project_name == 'chromedriver' and (
|
||||
os_str == 'mac' or os_str == 'win'):
|
||||
os_str += '32'
|
||||
return os_str
|
||||
|
||||
def run(self):
|
||||
"""Download and install the project."""
|
||||
print 'Installing %s' % self.project_name
|
||||
os_str = self.get_os_str
|
||||
version = self.find_latest_version()
|
||||
download_path = self.download_path_func({'os': os_str, 'version': version})
|
||||
download_name = os.path.basename(download_path)
|
||||
urllib.urlretrieve(os.path.join(self.source_path(), download_path),
|
||||
os.path.join(self.destination, download_name))
|
||||
if download_name.endswith('.zip'):
|
||||
if platform.system() != 'Windows':
|
||||
# The Python zip utility does not preserve executable permissions, but
|
||||
# this does not seem to be a problem for Windows, which does not have a
|
||||
# built in zip utility. :-/
|
||||
run_cmd('unzip -u %s -d %s' % (os.path.join(self.destination,
|
||||
download_name), self.destination), stdin='y')
|
||||
else:
|
||||
z = zipfile.ZipFile(os.path.join(self.destination, download_name))
|
||||
z.extractall(self.destination)
|
||||
z.close()
|
||||
os.remove(os.path.join(self.destination, download_name))
|
||||
chrome_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'orig-chromedriver')
|
||||
if self.project_name == 'chromedriver' and os.path.exists(chrome_path):
|
||||
# We have one additional location to make sure chromedriver is updated.
|
||||
# TODO(efortuna): Remove this. See move_chrome_driver_if_needed in
|
||||
# perf_testing/run_perf_tests.py
|
||||
driver = 'chromedriver'
|
||||
if platform.system() == 'Windows':
|
||||
driver += '.exe'
|
||||
shutil.copy(os.path.join(self.destination, driver),
|
||||
os.path.join(chrome_path, driver))
|
||||
|
||||
class ChromeDriverInstaller(GoogleBasedInstaller):
|
||||
"""Install chromedriver from Google Storage."""
|
||||
|
||||
def __init__(self, destination):
|
||||
"""Create an object to install ChromeDriver
|
||||
destination - Where to download the desired file on our filesystem.
|
||||
"""
|
||||
super(ChromeDriverInstaller, self).__init__('chromedriver', destination,
|
||||
lambda x: '%(version)s/chromedriver_%(os)s.zip' % x)
|
||||
|
||||
def find_latest_version(self):
|
||||
"""Find the latest version number of ChromeDriver."""
|
||||
source_page = urllib2.urlopen(self.source_path())
|
||||
source_text = source_page.read()
|
||||
regex = re.compile('(?:<Key>)(\d+\.\d+)')
|
||||
latest = max(regex.findall(source_text))
|
||||
return latest
|
||||
|
||||
def source_path(self):
|
||||
return 'http://chromedriver.storage.googleapis.com'
|
||||
|
||||
class GoogleCodeInstaller(GoogleBasedInstaller):
|
||||
"""Install a project from Google Code."""
|
||||
|
||||
def google_code_downloads_page(self):
|
||||
return 'http://code.google.com/p/%s/downloads/list' % self.project_name
|
||||
|
||||
def find_latest_version(self):
|
||||
"""Find the latest version number of some code available for download on a
|
||||
Google code page. This was unfortunately done in an ad hoc manner because
|
||||
Google Code does not seem to have an API for their list of current
|
||||
downloads(!).
|
||||
"""
|
||||
google_code_site = self.google_code_downloads_page()
|
||||
f = urllib2.urlopen(google_code_site)
|
||||
latest = ''
|
||||
|
||||
download_regex_str = self.download_path_func({'os': self.get_os_str,
|
||||
'version': '.+'})
|
||||
|
||||
for line in f.readlines():
|
||||
if re.search(download_regex_str, line):
|
||||
suffix_index = line.find(
|
||||
download_regex_str[download_regex_str.rfind('.'):])
|
||||
name_end = download_regex_str.rfind('.+')
|
||||
name = self.download_path_func({'os': self.get_os_str, 'version': ''})
|
||||
name = name[:name.rfind('.')]
|
||||
version_str = line[line.find(name) + len(name) : suffix_index]
|
||||
orig_version_str = version_str
|
||||
if version_str.count('.') == 0:
|
||||
version_str = version_str.replace('_', '.')
|
||||
version_str = re.compile(r'[^\d.]+').sub('', version_str)
|
||||
if latest == '':
|
||||
latest = '0.' * version_str.count('.')
|
||||
latest += '0'
|
||||
orig_latest_str = latest
|
||||
else:
|
||||
orig_latest_str = latest
|
||||
latest = latest.replace('_', '.')
|
||||
latest = re.compile(r'[^\d.]+').sub('', latest)
|
||||
nums = version_str.split('.')
|
||||
latest_nums = latest.split('.')
|
||||
for (num, latest_num) in zip(nums, latest_nums):
|
||||
if int(num) > int(latest_num):
|
||||
latest = orig_version_str
|
||||
break
|
||||
else:
|
||||
latest = orig_latest_str
|
||||
if latest == '':
|
||||
raise Exception("Couldn't find the desired download on " + \
|
||||
' %s.' % google_code_site)
|
||||
return latest
|
||||
|
||||
def source_path(self):
|
||||
return 'http://%s.googlecode.com/files/' % self.project_name
|
||||
|
||||
|
||||
class FirefoxInstaller(object):
|
||||
"""Installs the latest version of Firefox on the machine."""
|
||||
|
||||
def ff_download_site(self, os_name):
|
||||
return 'http://releases.mozilla.org/pub/mozilla.org/firefox/releases/' + \
|
||||
'latest/%s/en-US/' % os_name
|
||||
|
||||
@property
|
||||
def get_os_str(self):
|
||||
"""Returns the string that Mozilla uses to denote which operating system a
|
||||
Firefox binary is for."""
|
||||
os_str = ('win32', '.exe')
|
||||
if 'darwin' in sys.platform:
|
||||
os_str = ('mac', '.dmg')
|
||||
elif 'linux' in sys.platform:
|
||||
os_str = ('linux-i686', '.tar.bz2')
|
||||
if '64bit' in platform.architecture()[0]:
|
||||
os_str = ('linux-x86_64', '.tar.bz2')
|
||||
return os_str
|
||||
|
||||
def get_download_url(self):
|
||||
"""Parse the html on the page to determine what is the latest download
|
||||
appropriate for our system."""
|
||||
f = urllib2.urlopen(self.ff_download_site(self.get_os_str[0]))
|
||||
download_name = ''
|
||||
for line in f.readlines():
|
||||
suffix = self.get_os_str[1]
|
||||
if (suffix + '"') in line:
|
||||
link_str = '<a href="'
|
||||
download_name = line[line.find(link_str) + len(link_str) : \
|
||||
line.find(suffix) + len(suffix)]
|
||||
break
|
||||
return '%s%s' % (self.ff_download_site(self.get_os_str[0]), download_name)
|
||||
|
||||
def run(self):
|
||||
print 'Installing Firefox'
|
||||
if 'darwin' in sys.platform:
|
||||
urllib.urlretrieve(self.get_download_url(), 'firefox.dmg')
|
||||
run_cmd('hdiutil mount firefox.dmg')
|
||||
run_cmd('sudo cp -R /Volumes/firefox/Firefox.app /Applications')
|
||||
run_cmd('hdiutil unmount /Volumes/firefox/')
|
||||
elif 'win' in sys.platform:
|
||||
urllib.urlretrieve(self.get_download_url(), 'firefox_install.exe')
|
||||
run_cmd('firefox_install.exe -ms')
|
||||
else:
|
||||
run_cmd('wget -O - %s | tar -C ~ -jxv' % self.get_download_url())
|
||||
|
||||
|
||||
class SeleniumBindingsInstaller(object):
|
||||
"""Install the Selenium Webdriver bindings for Python."""
|
||||
|
||||
SETUPTOOLS_SITE = 'http://python-distribute.org/distribute_setup.py'
|
||||
PIP_SITE = 'https://raw.github.com/pypa/pip/master/contrib/get-pip.py'
|
||||
def __init__(self, is_buildbot):
|
||||
self.is_buildbot = is_buildbot
|
||||
|
||||
def run(self):
|
||||
print 'Installing Selenium Python Bindings'
|
||||
admin_keyword = ''
|
||||
python_cmd = 'python'
|
||||
pip_cmd = 'pip'
|
||||
if 'win32' not in sys.platform and 'cygwin' not in sys.platform:
|
||||
admin_keyword = 'sudo'
|
||||
pip_cmd = '/usr/local/bin/pip'
|
||||
else:
|
||||
# The python installation is "special" on Windows buildbots.
|
||||
if self.is_buildbot:
|
||||
python_loc = os.path.join(
|
||||
find_depot_tools_location(self.is_buildbot), 'python_bin')
|
||||
python_cmd = os.path.join(python_loc, 'python')
|
||||
pip_cmd = os.path.join(python_loc, 'Scripts', pip_cmd)
|
||||
else:
|
||||
path = os.environ['PATH'].split(os.pathsep)
|
||||
for loc in path:
|
||||
if 'python' in loc or 'Python' in loc:
|
||||
pip_cmd = os.path.join(loc, 'Scripts', pip_cmd)
|
||||
break
|
||||
page = urllib2.urlopen(self.SETUPTOOLS_SITE)
|
||||
run_cmd('%s %s' % (admin_keyword, python_cmd), page.read())
|
||||
page = urllib2.urlopen(self.PIP_SITE)
|
||||
run_cmd('%s %s' % (admin_keyword, python_cmd), page.read())
|
||||
run_cmd('%s %s install -U selenium' % (admin_keyword, pip_cmd))
|
||||
|
||||
class OperaHtmlParser(HTMLParser.HTMLParser):
|
||||
"""A helper class to parse Opera pages listing available downloads to find the
|
||||
correct download we want."""
|
||||
|
||||
def initialize(self, rejection_func, accept_func):
|
||||
"""Initialize some state for our parser.
|
||||
Arguments:
|
||||
rejection_func: A function that accepts the value of the URL and determines
|
||||
if it is of the type we are looking for.
|
||||
accept_func: A function that takes the URL and the "current best" URL and
|
||||
determines if it is better than our current download url."""
|
||||
self.latest = 0
|
||||
self.rejection_func = rejection_func
|
||||
self.accept_func = accept_func
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
"""Find the latest version."""
|
||||
if (tag == 'a' and attrs[0][0] == 'href' and
|
||||
self.rejection_func(attrs[0][1])):
|
||||
self.latest = self.accept_func(attrs[0][1], self.latest)
|
||||
|
||||
class OperaInstaller(object):
|
||||
"""Install from the Opera FTP website."""
|
||||
|
||||
def find_latest_version(self, download_page, rejection_func, accept_func):
|
||||
"""Get the latest non-beta version.
|
||||
Arguments:
|
||||
download_page: The initial page that lists all the download options.
|
||||
rejection_func: A function that accepts the value of the URL and determines
|
||||
if it is of the type we are looking for.
|
||||
accept_func: A function that takes the URL and the "current best" URL and
|
||||
determines if it is better than our current download url."""
|
||||
f = urllib2.urlopen(download_page)
|
||||
parser = OperaHtmlParser()
|
||||
parser.initialize(rejection_func, accept_func)
|
||||
parser.feed(f.read())
|
||||
return str(parser.latest)
|
||||
|
||||
def run(self):
|
||||
"""Download and install Opera."""
|
||||
print 'Installing Opera'
|
||||
os_str = self.get_os_str
|
||||
download_name = 'http://ftp.opera.com/pub/opera/%s/' % os_str
|
||||
|
||||
def higher_revision(new_version_str, current):
|
||||
version_string = new_version_str[:-1]
|
||||
if int(version_string) > current:
|
||||
return int(version_string)
|
||||
return current
|
||||
|
||||
version = self.find_latest_version(
|
||||
download_name,
|
||||
lambda x: x[0] in string.digits and 'b' not in x and 'rc' not in x,
|
||||
higher_revision)
|
||||
download_name += version
|
||||
if ('linux' in sys.platform and
|
||||
platform.linux_distribution()[0] == 'Ubuntu'):
|
||||
# Last time I tried, the .deb file you download directly from opera was
|
||||
# not installing correctly on Ubuntu. This installs Opera more nicely.
|
||||
os.system("sudo sh -c 'wget -O - http://deb.opera.com/archive.key | "
|
||||
"apt-key add -'")
|
||||
os.system("""sudo sh -c 'echo "deb http://deb.opera.com/opera/ """
|
||||
"""stable non-free" > /etc/apt/sources.list.d/opera.list'""")
|
||||
run_cmd('sudo apt-get update')
|
||||
run_cmd('sudo apt-get install opera', stdin='y')
|
||||
else:
|
||||
if 'darwin' in sys.platform:
|
||||
dotted_version = '%s.%s' % (version[:2], version[2:])
|
||||
download_name += '/Opera_%s_Setup_Intel.dmg' % dotted_version
|
||||
urllib.urlretrieve(download_name, 'opera.dmg')
|
||||
run_cmd('hdiutil mount opera.dmg', stdin='qY\n')
|
||||
run_cmd('sudo cp -R /Volumes/Opera/Opera.app /Applications')
|
||||
run_cmd('hdiutil unmount /Volumes/Opera/')
|
||||
elif 'win' in sys.platform:
|
||||
download_name += '/en/Opera_%s_en_Setup.exe' % version
|
||||
urllib.urlretrieve(download_name, 'opera_install.exe')
|
||||
run_cmd('opera_install.exe -ms')
|
||||
else:
|
||||
# For all other flavors of linux, download the tar.
|
||||
download_name += '/'
|
||||
extension = '.tar.bz2'
|
||||
if '64bit' in platform.architecture()[0]:
|
||||
platform_str = '.x86_64'
|
||||
else:
|
||||
platform_str = '.i386'
|
||||
def get_acceptable_file(new_version_str, current):
|
||||
return new_version_str
|
||||
latest = self.find_latest_version(
|
||||
download_name,
|
||||
lambda x: x.startswith('opera') and x.endswith(extension)
|
||||
and platform_str in x,
|
||||
get_acceptable_file)
|
||||
download_name += latest
|
||||
run_cmd('wget -O - %s | tar -C ~ -jxv' % download_name)
|
||||
print ('PLEASE MANUALLY RUN "~/%s/install" TO COMPLETE OPERA '
|
||||
'INSTALLATION' %
|
||||
download_name[download_name.rfind('/') + 1:-len(extension)])
|
||||
|
||||
@property
|
||||
def get_os_str(self):
|
||||
"""The strings to indicate what OS a download is."""
|
||||
os_str = 'win'
|
||||
if 'darwin' in sys.platform:
|
||||
os_str = 'mac'
|
||||
elif 'linux' in sys.platform:
|
||||
os_str = 'linux'
|
||||
return os_str
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
if not args.python:
|
||||
SeleniumBindingsInstaller(args.buildbot).run()
|
||||
if not args.chromedriver:
|
||||
ChromeDriverInstaller(find_depot_tools_location(args.buildbot)).run()
|
||||
if not args.seleniumrc:
|
||||
GoogleCodeInstaller('selenium', os.path.dirname(os.path.abspath(__file__)),
|
||||
lambda x: 'selenium-server-standalone-%(version)s.jar' % x).run()
|
||||
if not args.iedriver and platform.system() == 'Windows':
|
||||
GoogleCodeInstaller('selenium', find_depot_tools_location(args.buildbot),
|
||||
lambda x: 'IEDriverServer_Win32_%(version)s.zip' % x).run()
|
||||
if not args.firefox:
|
||||
FirefoxInstaller().run()
|
||||
if not args.opera:
|
||||
OperaInstaller().run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in a new issue