mirror of
https://github.com/servo/servo.git
synced 2025-08-20 12:55:33 +01:00
Update web-platform-tests to revision 5e3ea8f49fee68c327388bfd1dd1375a8ce12a0e.
This commit is contained in:
parent
12195a5c4a
commit
bfb96b9448
1166 changed files with 35123 additions and 900 deletions
|
@ -121,6 +121,7 @@
|
|||
<th>Failed
|
||||
<th>Timeouts
|
||||
<th>Errors
|
||||
<th>Not Run</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -129,6 +130,7 @@
|
|||
<td class='FAIL'>0
|
||||
<td class='TIMEOUT'>0
|
||||
<td class='ERROR'>0
|
||||
<td class='NOTRUN'>0
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -153,6 +153,10 @@ td.TIMEOUT {
|
|||
color: #f6bb42;
|
||||
}
|
||||
|
||||
td.NOTRUN {
|
||||
color: #00c;
|
||||
}
|
||||
|
||||
td.ERROR {
|
||||
color: #da4453;
|
||||
font-weight: bold;
|
||||
|
|
|
@ -145,7 +145,8 @@ VisualOutput.prototype = {
|
|||
this.result_count = {"PASS":0,
|
||||
"FAIL":0,
|
||||
"ERROR":0,
|
||||
"TIMEOUT":0};
|
||||
"TIMEOUT":0,
|
||||
"NOTRUN":0};
|
||||
for (var p in this.result_count) {
|
||||
if (this.result_count.hasOwnProperty(p)) {
|
||||
this.elem.querySelector("td." + p).textContent = 0;
|
||||
|
@ -183,12 +184,19 @@ VisualOutput.prototype = {
|
|||
var subtest_pass_count = subtests.reduce(function(prev, current) {
|
||||
return (current.status === "PASS") ? prev + 1 : prev;
|
||||
}, 0);
|
||||
|
||||
var subtest_notrun_count = subtests.reduce(function(prev, current) {
|
||||
return (current.status === "NOTRUN") ? prev +1 : prev;
|
||||
}, 0);
|
||||
|
||||
var subtests_count = subtests.length;
|
||||
|
||||
var test_status;
|
||||
if (subtest_pass_count === subtests_count &&
|
||||
(status == "OK" || status == "PASS")) {
|
||||
test_status = "PASS";
|
||||
} else if (subtest_notrun_count == subtests_count) {
|
||||
test_status = "NOTRUN";
|
||||
} else if (subtests_count > 0 && status === "OK") {
|
||||
test_status = "FAIL";
|
||||
} else {
|
||||
|
@ -225,7 +233,7 @@ VisualOutput.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
var status_arr = ["PASS", "FAIL", "ERROR", "TIMEOUT"];
|
||||
var status_arr = ["PASS", "FAIL", "ERROR", "TIMEOUT", "NOTRUN"];
|
||||
for (var i = 0; i < status_arr.length; i++) {
|
||||
this.elem.querySelector("td." + status_arr[i]).textContent = this.result_count[status_arr[i]];
|
||||
}
|
||||
|
@ -707,7 +715,7 @@ function setup() {
|
|||
}
|
||||
|
||||
window.completion_callback = function(tests, status) {
|
||||
var harness_status_map = {0:"OK", 1:"ERROR", 2:"TIMEOUT"};
|
||||
var harness_status_map = {0:"OK", 1:"ERROR", 2:"TIMEOUT", 3:"NOTRUN"};
|
||||
var subtest_status_map = {0:"PASS", 1:"FAIL", 2:"TIMEOUT", 3:"NOTRUN"};
|
||||
|
||||
// this ugly hack is because IE really insists on holding on to the objects it creates in
|
||||
|
|
|
@ -17,6 +17,7 @@ from .. import localpaths
|
|||
|
||||
import sslutils
|
||||
from wptserve import server as wptserve, handlers
|
||||
from wptserve import stash
|
||||
from wptserve.logger import set_logger
|
||||
from mod_pywebsocket import standalone as pywebsocket
|
||||
|
||||
|
@ -356,7 +357,6 @@ def get_ssl_config(config, external_domains, ssl_environment):
|
|||
"cert_path": cert_path,
|
||||
"encrypt_after_connect": config["ssl"]["encrypt_after_connect"]}
|
||||
|
||||
|
||||
def start(config, ssl_environment, routes, **kwargs):
|
||||
host = config["host"]
|
||||
domains = get_subdomains(host)
|
||||
|
@ -485,12 +485,13 @@ def main():
|
|||
|
||||
setup_logger(config["log_level"])
|
||||
|
||||
with get_ssl_environment(config) as ssl_env:
|
||||
config_, servers = start(config, ssl_env, default_routes(), **kwargs)
|
||||
with stash.StashServer((config["host"], get_port()), authkey=str(uuid.uuid4())):
|
||||
with get_ssl_environment(config) as ssl_env:
|
||||
config_, servers = start(config, ssl_env, default_routes(), **kwargs)
|
||||
|
||||
try:
|
||||
while any(item.is_alive() for item in iter_procs(servers)):
|
||||
for item in iter_procs(servers):
|
||||
item.join(1)
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Shutting down")
|
||||
try:
|
||||
while any(item.is_alive() for item in iter_procs(servers)):
|
||||
for item in iter_procs(servers):
|
||||
item.join(1)
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Shutting down")
|
||||
|
|
30
tests/wpt/web-platform-tests/tools/wptserve/LICENSE
Normal file
30
tests/wpt/web-platform-tests/tools/wptserve/LICENSE
Normal file
|
@ -0,0 +1,30 @@
|
|||
W3C 3-clause BSD License
|
||||
|
||||
http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of works must retain the original copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the original copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the W3C nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this work without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,6 +1,7 @@
|
|||
import base64
|
||||
import cgi
|
||||
import Cookie
|
||||
import os
|
||||
import StringIO
|
||||
import tempfile
|
||||
import urlparse
|
||||
|
@ -27,7 +28,15 @@ class Server(object):
|
|||
config = None
|
||||
|
||||
def __init__(self, request):
|
||||
self.stash = stash.Stash(request.url_parts.path)
|
||||
self._stash = None
|
||||
self._request = request
|
||||
|
||||
@property
|
||||
def stash(self):
|
||||
if self._stash is None:
|
||||
address, authkey = stash.load_env_config()
|
||||
self._stash = stash.Stash(self._request.url_parts.path, address, authkey)
|
||||
return self._stash
|
||||
|
||||
|
||||
class InputFile(object):
|
||||
|
|
|
@ -1,17 +1,76 @@
|
|||
import base64
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
from multiprocessing import Process
|
||||
from multiprocessing.managers import BaseManager, DictProxy
|
||||
|
||||
class ServerDictManager(BaseManager):
|
||||
shared_data = {}
|
||||
|
||||
def _get_shared():
|
||||
return ServerDictManager.shared_data
|
||||
|
||||
ServerDictManager.register("get_dict",
|
||||
callable=_get_shared,
|
||||
proxytype=DictProxy)
|
||||
|
||||
class ClientDictManager(BaseManager):
|
||||
pass
|
||||
|
||||
ClientDictManager.register("get_dict")
|
||||
|
||||
class StashServer(object):
|
||||
def __init__(self, address=None, authkey=None):
|
||||
self.address = address
|
||||
self.authkey = authkey
|
||||
self.manager = None
|
||||
|
||||
def __enter__(self):
|
||||
self.manager, self.address, self.authkey = start_server(self.address, self.authkey)
|
||||
store_env_config(self.address, self.authkey)
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
if self.manager is not None:
|
||||
self.manager.shutdown()
|
||||
|
||||
def load_env_config():
|
||||
address, authkey = json.loads(os.environ["WPT_STASH_CONFIG"])
|
||||
if isinstance(address, list):
|
||||
address = tuple(address)
|
||||
else:
|
||||
address = str(address)
|
||||
authkey = base64.decodestring(authkey)
|
||||
return address, authkey
|
||||
|
||||
def store_env_config(address, authkey):
|
||||
authkey = base64.encodestring(authkey)
|
||||
os.environ["WPT_STASH_CONFIG"] = json.dumps((address, authkey))
|
||||
|
||||
def start_server(address=None, authkey=None):
|
||||
manager = ServerDictManager(address, authkey)
|
||||
manager.start()
|
||||
|
||||
return (manager, manager._address, manager._authkey)
|
||||
|
||||
|
||||
#TODO: Consider expiring values after some fixed time for long-running
|
||||
#servers
|
||||
|
||||
# TODO(kristijanburnik): Provide shared Stash support for WebSockets.
|
||||
|
||||
class Stash(object):
|
||||
"""Key-value store for persisting data across HTTP requests.
|
||||
"""Key-value store for persisting data across HTTP/S requests.
|
||||
|
||||
This data store specifically designed for persisting data across
|
||||
HTTP requests. It is entirely in-memory so data will not be
|
||||
persisted across server restarts.
|
||||
This data store is specifically designed for persisting data across
|
||||
HTTP and HTTPS requests. The synchronization model is usually done by using
|
||||
the SyncManager from the multiprocessing module.
|
||||
|
||||
This has several unusual properties. Keys are of the form (path,
|
||||
Stash can be used interchangeably between HTTP and HTTPS requests as both
|
||||
processes are accessing the same resource (e.g. a Manager.dict).
|
||||
The WS and WSS servers are currently not supported.
|
||||
|
||||
The store has several unusual properties. Keys are of the form (path,
|
||||
uuid), where path is, by default, the path in the HTTP request and
|
||||
uuid is a unique id. In addition, the store is write-once, read-once,
|
||||
i.e. the value associated with a particular key cannot be changed once
|
||||
|
@ -19,66 +78,66 @@ class Stash(object):
|
|||
these properties make it difficult for data to accidentally leak
|
||||
between different resources or different requests for the same
|
||||
resource.
|
||||
|
||||
"""
|
||||
|
||||
data = {}
|
||||
_proxy = None
|
||||
|
||||
def __init__(self, default_path):
|
||||
def __init__(self, default_path, address=None, authkey=None):
|
||||
self.default_path = default_path
|
||||
self.data = self._get_proxy(address, authkey)
|
||||
|
||||
def _get_proxy(self, address=None, authkey=None):
|
||||
if address is None and authkey is None:
|
||||
Stash._proxy = {}
|
||||
|
||||
if Stash._proxy is None:
|
||||
manager = ClientDictManager(address, authkey)
|
||||
manager.connect()
|
||||
Stash._proxy = manager.get_dict()
|
||||
|
||||
return Stash._proxy
|
||||
|
||||
def _wrap_key(self, key, path):
|
||||
if path is None:
|
||||
path = self.default_path
|
||||
# This key format is required to support using the path. Since the data
|
||||
# passed into the stash can be a DictProxy which wouldn't detect changes
|
||||
# when writing to a subdict.
|
||||
return (str(path), str(uuid.UUID(key)))
|
||||
|
||||
def put(self, key, value, path=None):
|
||||
"""Place a value in the stash.
|
||||
"""Place a value in the shared stash.
|
||||
|
||||
:param key: A UUID to use as the data's key.
|
||||
:param value: The data to store. This can be any python object.
|
||||
:param path: The path that has access to read the data (by default
|
||||
the current request path)"""
|
||||
if path is None:
|
||||
path = self.default_path
|
||||
if path not in self.data:
|
||||
self.data[path] = PathStash(path)
|
||||
|
||||
self.data[path][key] = value
|
||||
if value is None:
|
||||
raise ValueError("SharedStash value may not be set to None")
|
||||
internal_key = self._wrap_key(key, path)
|
||||
if internal_key in self.data:
|
||||
raise StashError("Tried to overwrite existing shared stash value "
|
||||
"for key %s (old value was %s, new value is %s)" %
|
||||
(internal_key, self[str(internal_key)], value))
|
||||
else:
|
||||
self.data[internal_key] = value
|
||||
|
||||
def take(self, key, path=None):
|
||||
"""Remove a value from the stash and return it.
|
||||
"""Remove a value from the shared stash and return it.
|
||||
|
||||
:param key: A UUID to use as the data's key.
|
||||
:param path: The path that has access to read the data (by default
|
||||
the current request path)"""
|
||||
if path is None:
|
||||
path = self.default_path
|
||||
internal_key = self._wrap_key(key, path)
|
||||
value = self.data.get(internal_key, None)
|
||||
if not value is None:
|
||||
try:
|
||||
self.data.pop(internal_key)
|
||||
except KeyError:
|
||||
# Silently continue when pop error occurs.
|
||||
pass
|
||||
|
||||
if path in self.data:
|
||||
value = self.data[path][key]
|
||||
else:
|
||||
value = None
|
||||
return value
|
||||
|
||||
|
||||
class PathStash(dict):
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
key = uuid.UUID(key)
|
||||
if value is None:
|
||||
raise ValueError("Stash value may not be set to None")
|
||||
if key in self:
|
||||
raise StashError("Tried to overwrite existing stash value "
|
||||
"for path %s and key %s (old value was %s, new value is %s)" %
|
||||
(self.path, key, self[str(key)], value))
|
||||
else:
|
||||
dict.__setitem__(self, key, value)
|
||||
|
||||
def __getitem__(self, key):
|
||||
key = uuid.UUID(key)
|
||||
rv = dict.get(self, key, None)
|
||||
if rv is not None:
|
||||
del self[key]
|
||||
return rv
|
||||
|
||||
|
||||
class StashError(Exception):
|
||||
pass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue