346 строки
14 KiB
Python
346 строки
14 KiB
Python
import BaseHTTPServer
|
|
import hashlib
|
|
import httplib
|
|
import json
|
|
import os
|
|
import pickle
|
|
import signal
|
|
import sys
|
|
import urllib
|
|
import urlparse
|
|
|
|
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
|
from SocketServer import ThreadingMixIn
|
|
|
|
import utils
|
|
utils.config.init("awfy.config")
|
|
translates = utils.config.benchmarkTranslates()
|
|
|
|
class FakeHandler(SimpleHTTPRequestHandler):
|
|
|
|
def handle_one_request(self):
|
|
""" This sometimes times out. Don't block """
|
|
with utils.Handler(signal.SIGALRM, utils.timeout_handler):
|
|
try:
|
|
signal.alarm(20)
|
|
SimpleHTTPRequestHandler.handle_one_request(self)
|
|
except utils.TimeException:
|
|
print "timeout"
|
|
finally:
|
|
signal.alarm(0)
|
|
|
|
def do_GET(self):
|
|
if self.remoteBenchmark():
|
|
return
|
|
|
|
parsedParams = urlparse.urlparse(self.path)
|
|
if self.localBenchmark(parsedParams.query):
|
|
return
|
|
|
|
self.send_error(404, "File not found")
|
|
|
|
def do_POST(self):
|
|
length = int(self.headers.getheader('content-length', 0))
|
|
postdata = self.rfile.read(length)
|
|
|
|
if self.remoteBenchmark(postdata):
|
|
return
|
|
|
|
if self.localBenchmark(postdata):
|
|
return
|
|
|
|
self.send_error(404, "File not found")
|
|
|
|
def localBenchmark(self, query = None):
|
|
if self.path.startswith("/submit"):
|
|
return self.captureResults(query)
|
|
else:
|
|
return self.retrieveOffline();
|
|
|
|
def retrieveOffline(self):
|
|
path = self.translate_path(self.path)
|
|
if os.path.isdir(path) and not self.path.endswith('/'):
|
|
# redirect browser - doing basically what apache does
|
|
self.send_response(301)
|
|
self.send_header("Location", self.path + "/")
|
|
self.end_headers()
|
|
return True
|
|
else:
|
|
f = None
|
|
# try to load index.html / index.htm
|
|
if os.path.isdir(path):
|
|
for index in "index.html", "index.htm":
|
|
index = os.path.join(path, index)
|
|
if os.path.exists(index):
|
|
path = index
|
|
break
|
|
else:
|
|
# list directory
|
|
f = self.list_directory(path)
|
|
return True
|
|
# load file
|
|
ctype = self.guess_type(path)
|
|
try:
|
|
# Always read in binary mode. Opening files in text mode may cause
|
|
# newline translations, making the actual size of the content
|
|
# transmitted *less* than the content-length!
|
|
f = open(path, 'rb')
|
|
except IOError:
|
|
self.send_error(404, "File not found")
|
|
return True
|
|
|
|
content = f.read()
|
|
content = self.injectData("localhost", self.path, content)
|
|
|
|
self.send_response(200)
|
|
self.send_header("Content-type", ctype)
|
|
fs = os.fstat(f.fileno())
|
|
self.send_header("Content-Length", len(content))
|
|
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
|
|
self.end_headers()
|
|
|
|
self.wfile.write(bytes(content))
|
|
f.close()
|
|
return True
|
|
|
|
def captureResults(self, query):
|
|
queryParsed = urlparse.parse_qs(query)
|
|
fp = open("slave/results", "w");
|
|
fp.write(queryParsed["results"][0]);
|
|
fp.close()
|
|
return False
|
|
|
|
def translatePath(self, host, path):
|
|
global translates
|
|
translated = False
|
|
for url in translates:
|
|
if host.startswith(url):
|
|
host = translates[url]
|
|
translated = True
|
|
|
|
if host.startswith("massive."):
|
|
if path == "" or path == "/":
|
|
path = "/Massive/?autoRun=true,postToURL=http://localhost:8000/submit"
|
|
return "kripken.github.io", path
|
|
elif host.startswith("octane."):
|
|
if path == "" or path == "/":
|
|
path = "/octane/index.html"
|
|
return "chromium.github.io", path
|
|
elif host.startswith("jetstream."):
|
|
if path == "" or path == "/":
|
|
path = "/JetStream/"
|
|
return "browserbench.org", path
|
|
elif host.startswith("speedometer."):
|
|
if path == "" or path == "/":
|
|
path = "/Speedometer/"
|
|
return "browserbench.org", path
|
|
elif host.startswith("kraken."):
|
|
if path == "" or path == "/":
|
|
path = "/kraken-1.1/driver.html"
|
|
return "krakenbenchmark.mozilla.org", path
|
|
elif host.startswith("sunspider."):
|
|
if path == "" or path == "/":
|
|
path = "/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html"
|
|
return "www.webkit.org", path
|
|
elif host.startswith("browsermark."):
|
|
return "browsermark.local", path
|
|
elif host.startswith("dromaeo."):
|
|
return "dromaeo.com", path
|
|
if translated:
|
|
return host, path
|
|
return None, None
|
|
|
|
def remoteBenchmark(self, postdata=None):
|
|
host = self.headers.get("Host", "")
|
|
url, path = self.translatePath(host, self.path)
|
|
if not url and not path:
|
|
return False
|
|
|
|
if self.path != path:
|
|
self.send_response(301)
|
|
self.send_header('Location', 'http://' + host + path)
|
|
self.end_headers()
|
|
return True
|
|
|
|
status, headers, data = self.retrieve(url, path, postdata)
|
|
data = self.injectData(host, path, data)
|
|
|
|
if status == 301 or status == 302:
|
|
for i in range(len(headers)):
|
|
if headers[i][0] == "Location" or headers[i][0] == "location":
|
|
location = headers[i][1].split("/", 4)
|
|
if len(location) == 3:
|
|
location = "/"
|
|
else:
|
|
location = location[4]
|
|
print location
|
|
headers[i] = ("Location", "http://" + host + location)
|
|
self.send_response(status)
|
|
for name, header in headers:
|
|
if name == "content-length" or name == "accept-ranges" or name == "connection" or name == "transfer-encoding":
|
|
pass
|
|
else:
|
|
self.send_header(name, header)
|
|
self.send_header("content-length", len(data))
|
|
self.send_header("connection", "close")
|
|
self.end_headers()
|
|
self.wfile.write(bytes(data))
|
|
return True
|
|
|
|
def retrieve(self, host, path, postdata):
|
|
hash_object = hashlib.sha1(host+path)
|
|
hex_dig = hash_object.hexdigest()
|
|
if os.path.exists("cache/"+host+"/"+hex_dig):
|
|
fp = open("cache/"+host+"/"+hex_dig, "rb")
|
|
status, headers, data = pickle.load(fp)
|
|
fp.close()
|
|
else:
|
|
status, headers, data = self.retrieveOnline(host, path, postdata)
|
|
|
|
if not os.path.exists("cache"):
|
|
os.mkdir("cache")
|
|
if not os.path.exists("cache/"+host):
|
|
os.mkdir("cache/"+host)
|
|
fp = open("cache/"+host+"/"+hex_dig, "wb")
|
|
pickle.dump([status, headers, data], fp)
|
|
fp.close()
|
|
|
|
return status, headers, data
|
|
|
|
def retrieveOnline(self, host, path, postdata):
|
|
conn = httplib.HTTPConnection(host)
|
|
if not postdata:
|
|
conn.request("GET", path, headers = {
|
|
"Cache-Control": self.headers.get("Cache-Control", ""),
|
|
"Accept": self.headers.get("Accept", ""),
|
|
"User-Agent": self.headers.get("User-Agent", ""),
|
|
"Accept-Language": self.headers.get("Accept-Language", ""),
|
|
})
|
|
else:
|
|
conn.request("POST", path, postdata, headers = {
|
|
"Cache-Control": self.headers.get("Cache-Control", ""),
|
|
"Accept": self.headers.get("Accept", ""),
|
|
"User-Agent": self.headers.get("User-Agent", ""),
|
|
"Content-Length": len(postdata),
|
|
"Accept-Language": self.headers.get("Accept-Language", ""),
|
|
})
|
|
response = conn.getresponse()
|
|
headers = response.getheaders()
|
|
|
|
data = response.read()
|
|
conn.close()
|
|
|
|
return response.status, headers, data
|
|
|
|
def injectData(self, host, path, data):
|
|
if host.startswith("massive."):
|
|
if path == "/Massive/driver.js":
|
|
return data.replace("job.calculate().toFixed(3)","normalize(job)")
|
|
if host.startswith("octane."):
|
|
if path == "/octane/index.html":
|
|
return data.replace("</body>",
|
|
"<script>"
|
|
" window.setTimeout(Run, 10000);"
|
|
" var oldAddResult = AddResult;"
|
|
" var results = {};"
|
|
" AddScore = function(score) {"
|
|
" results['total'] = score;"
|
|
" location.href = 'http://localhost:8000/submit?results=' + "
|
|
" encodeURIComponent(JSON.stringify(results))"
|
|
" };"
|
|
" AddResult = function(name, result) {"
|
|
" results[name] = result;"
|
|
" oldAddResult(name, result);"
|
|
" };"
|
|
"</script>"
|
|
"</body>");
|
|
if host.startswith("jetstream."):
|
|
if path == "/JetStream/":
|
|
return data.replace("</body>",
|
|
"<script>"
|
|
" window.setTimeout(JetStream.start, 10000);"
|
|
"</script>"
|
|
"</body>");
|
|
if path == "/JetStream/JetStreamDriver.js":
|
|
return data.replace("function end()",
|
|
"function end()"
|
|
"{"
|
|
" location.href = 'http://localhost:8000/submit?results=' + "
|
|
" encodeURIComponent(JSON.stringify(computeRawResults()))"
|
|
"} "
|
|
"function foo()");
|
|
if host.startswith("speedometer."):
|
|
if path == "/Speedometer/":
|
|
return data.replace("</body>",
|
|
"""
|
|
<script defer>
|
|
window.setTimeout(function() {
|
|
startTest()
|
|
benchmarkClient._updateGaugeNeedle = function (rpm) {
|
|
location.href = 'http://localhost:8000/submit?results=' +
|
|
encodeURIComponent(JSON.stringify([{'name': '__total__', 'time': rpm}]));
|
|
};
|
|
}, 10000);
|
|
</script>
|
|
</body>""");
|
|
if host.startswith("kraken."):
|
|
if path == "/kraken-1.1/driver.html":
|
|
return data.replace('location = "results.html?" + encodeURI(outputString);',
|
|
'location.href = "http://localhost:8000/submit?results=" + encodeURI(outputString);');
|
|
if host.startswith("sunspider."):
|
|
if path == "/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html":
|
|
return data.replace('location = "results.html?" + encodeURI(outputString);',
|
|
'location.href = "http://localhost:8000/submit?results=" + encodeURI(outputString);');
|
|
if host == "localhost":
|
|
if path == "/benchmarks/misc-desktop/hosted/assorted/driver.html":
|
|
return data.replace('location = "results.html?" + encodeURI(outputString);',
|
|
'location.href = "http://localhost:8000/submit?results=" + encodeURI(outputString);');
|
|
if path == "/benchmarks/webaudio/webaudio-bench.js":
|
|
return data.replace('xhr.open("POST", "/results", true);',
|
|
'xhr.open("POST", "/submit", true);');
|
|
if path == "/benchmarks/unity-webgl/Data/mozbench.js":
|
|
return data.replace('xmlHttp.open("POST", "/results", true);',
|
|
'xmlHttp.open("POST", "/submit", true);');
|
|
if host.startswith("dromaeo."):
|
|
if path == "/webrunner.js":
|
|
data = data.replace('function init(){',
|
|
"""
|
|
function init(){
|
|
setTimeout(function () {
|
|
interval = true;
|
|
dequeue();
|
|
}, 10000);
|
|
""")
|
|
return data.replace('} else if ( queue.length == 0 ) {',
|
|
"""
|
|
} else if ( queue.length == 0 ) {;
|
|
var results = {};
|
|
for (var i=0; i<dataStore.length; i++) {
|
|
results[dataStore[i].curID] = dataStore[i].mean
|
|
}
|
|
var summary = (runStyle === "runs/s" ? Math.pow(Math.E, maxTotal / maxTotalNum) : maxTotal).toFixed(2);
|
|
results["total"] = summary;
|
|
location.href = "http://localhost:8000/submit?results="+encodeURIComponent(JSON.stringify(results))
|
|
""")
|
|
return data
|
|
|
|
class ThreadedHTTPServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
|
pass
|
|
|
|
HandlerClass = FakeHandler
|
|
ServerClass = ThreadedHTTPServer
|
|
ServerClass = BaseHTTPServer.HTTPServer
|
|
Protocol = "HTTP/1.0"
|
|
Port = 8000
|
|
ServerAddress = ('', Port)
|
|
|
|
path = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
|
|
with utils.FolderChanger(path):
|
|
HandlerClass.protocol_version = Protocol
|
|
httpd = ServerClass(ServerAddress, HandlerClass)
|
|
|
|
sa = httpd.socket.getsockname()
|
|
print "Serving HTTP on", sa[0], "port", sa[1], "..."
|
|
|
|
httpd.serve_forever()
|