mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Devtools: add more test cases (#36910)
This patch adds test cases for Debugger > Sources with inline module scripts and external classic scripts. We also fix the big test case in #36401 to receive and assert the worker script URLs. Testing: this patch improves test coverage for the Debugger > Sources feature Part of: #36325 --------- Signed-off-by: Delan Azabani <dazabani@igalia.com> Signed-off-by: atbrakhi <atbrakhi@igalia.com> Co-authored-by: atbrakhi <atbrakhi@igalia.com>
This commit is contained in:
parent
063bfc761e
commit
c6f61e6b6e
1 changed files with 83 additions and 26 deletions
|
@ -25,6 +25,10 @@ from typing import Optional
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
# Set this to true to log requests in the internal web servers.
|
||||||
|
LOG_REQUESTS = False
|
||||||
|
|
||||||
|
|
||||||
class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
||||||
# /path/to/servo/python/servo
|
# /path/to/servo/python/servo
|
||||||
script_path = None
|
script_path = None
|
||||||
|
@ -36,23 +40,49 @@ class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
||||||
self.web_server = None
|
self.web_server = None
|
||||||
self.web_server_thread = None
|
self.web_server_thread = None
|
||||||
|
|
||||||
|
# Classic script vs module script:
|
||||||
|
# - <https://html.spec.whatwg.org/multipage/#classic-script>
|
||||||
|
# - <https://html.spec.whatwg.org/multipage/#module-script>
|
||||||
|
# Worker scripts can be classic or module:
|
||||||
|
# - <https://html.spec.whatwg.org/multipage/#fetch-a-classic-worker-script>
|
||||||
|
# - <https://html.spec.whatwg.org/multipage/#fetch-a-module-worker-script-tree>
|
||||||
|
# Non-worker(?) script sources can be inline, external, or blob.
|
||||||
|
# Worker script sources can be external or blob.
|
||||||
def test_sources_list(self):
|
def test_sources_list(self):
|
||||||
self.run_servoshell(test_dir=os.path.join(DevtoolsTests.script_path, "devtools_tests/sources"))
|
self.start_web_server(test_dir=os.path.join(DevtoolsTests.script_path, "devtools_tests/sources"))
|
||||||
self.assert_sources_list([f"{self.base_url}/classic.js", f"{self.base_url}/test.html", "https://servo.org/js/load-table.js"])
|
self.run_servoshell()
|
||||||
|
self.assert_sources_list(2, set([
|
||||||
|
tuple([f"{self.base_url}/classic.js", f"{self.base_url}/test.html", "https://servo.org/js/load-table.js"]),
|
||||||
|
tuple([f"{self.base_url}/worker.js"]),
|
||||||
|
]))
|
||||||
|
|
||||||
def test_sources_list_with_data_no_scripts(self):
|
def test_sources_list_with_data_no_scripts(self):
|
||||||
self.run_servoshell(url="data:text/html,")
|
self.run_servoshell(url="data:text/html,")
|
||||||
self.assert_sources_list([])
|
self.assert_sources_list(1, set([tuple()]))
|
||||||
|
|
||||||
def test_sources_list_with_data_empty_inline_script(self):
|
def test_sources_list_with_data_empty_inline_classic_script(self):
|
||||||
self.run_servoshell(url="data:text/html,<script></script>")
|
self.run_servoshell(url="data:text/html,<script></script>")
|
||||||
self.assert_sources_list([])
|
self.assert_sources_list(1, set([tuple()]))
|
||||||
|
|
||||||
def test_sources_list_with_data_inline_script(self):
|
def test_sources_list_with_data_inline_classic_script(self):
|
||||||
self.run_servoshell(url="data:text/html,<script>;</script>")
|
self.run_servoshell(url="data:text/html,<script>;</script>")
|
||||||
self.assert_sources_list(["data:text/html,<script>;</script>"])
|
self.assert_sources_list(1, set([tuple(["data:text/html,<script>;</script>"])]))
|
||||||
|
|
||||||
def run_servoshell(self, *, test_dir=None, url=None):
|
def test_sources_list_with_data_external_classic_script(self):
|
||||||
|
self.start_web_server(test_dir=os.path.join(DevtoolsTests.script_path, "devtools_tests/sources"))
|
||||||
|
self.run_servoshell(url=f"data:text/html,<script src=\"{self.base_url}/classic.js\"></script>")
|
||||||
|
self.assert_sources_list(1, set([tuple([f"{self.base_url}/classic.js"])]))
|
||||||
|
|
||||||
|
def test_sources_list_with_data_empty_inline_module_script(self):
|
||||||
|
self.run_servoshell(url="data:text/html,<script type=module></script>")
|
||||||
|
self.assert_sources_list(1, set([tuple()]))
|
||||||
|
|
||||||
|
def test_sources_list_with_data_inline_module_script(self):
|
||||||
|
self.run_servoshell(url="data:text/html,<script type=module>;</script>")
|
||||||
|
self.assert_sources_list(1, set([tuple(["data:text/html,<script type=module>;</script>"])]))
|
||||||
|
|
||||||
|
# Sets `base_url` and `web_server` and `web_server_thread`.
|
||||||
|
def start_web_server(self, *, test_dir=None):
|
||||||
if test_dir is None:
|
if test_dir is None:
|
||||||
test_dir = os.path.join(DevtoolsTests.script_path, "devtools_tests")
|
test_dir = os.path.join(DevtoolsTests.script_path, "devtools_tests")
|
||||||
base_url = Future()
|
base_url = Future()
|
||||||
|
@ -62,9 +92,8 @@ class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
||||||
super().__init__(*args, directory=test_dir, **kwargs)
|
super().__init__(*args, directory=test_dir, **kwargs)
|
||||||
|
|
||||||
def log_message(self, format, *args):
|
def log_message(self, format, *args):
|
||||||
# Uncomment this to log requests.
|
if LOG_REQUESTS:
|
||||||
# return super().log_message(format, *args)
|
return super().log_message(format, *args)
|
||||||
pass
|
|
||||||
|
|
||||||
def server_thread():
|
def server_thread():
|
||||||
self.web_server = socketserver.TCPServer(("0.0.0.0", 0), Handler)
|
self.web_server = socketserver.TCPServer(("0.0.0.0", 0), Handler)
|
||||||
|
@ -76,6 +105,8 @@ class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
||||||
self.web_server_thread.start()
|
self.web_server_thread.start()
|
||||||
self.base_url = base_url.result(1)
|
self.base_url = base_url.result(1)
|
||||||
|
|
||||||
|
# Sets `servoshell`.
|
||||||
|
def run_servoshell(self, *, url=None):
|
||||||
# Change this setting if you want to debug Servo.
|
# Change this setting if you want to debug Servo.
|
||||||
os.environ["RUST_LOG"] = "error,devtools=warn"
|
os.environ["RUST_LOG"] = "error,devtools=warn"
|
||||||
|
|
||||||
|
@ -89,13 +120,21 @@ class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# Terminate servoshell.
|
# Terminate servoshell.
|
||||||
self.servoshell.terminate()
|
if self.servoshell is not None:
|
||||||
|
self.servoshell.terminate()
|
||||||
|
self.servoshell = None
|
||||||
|
|
||||||
# Stop the web server.
|
# Stop the web server.
|
||||||
self.web_server.shutdown()
|
if self.web_server is not None:
|
||||||
self.web_server_thread.join()
|
self.web_server.shutdown()
|
||||||
|
self.web_server = None
|
||||||
|
if self.web_server_thread is not None:
|
||||||
|
self.web_server_thread.join()
|
||||||
|
self.web_server_thread = None
|
||||||
|
if self.base_url is not None:
|
||||||
|
self.base_url = None
|
||||||
|
|
||||||
def assert_sources_list(self, expected_urls):
|
def assert_sources_list(self, expected_targets: int, expected_urls_by_target: set[tuple[str]]):
|
||||||
client = RDPClient()
|
client = RDPClient()
|
||||||
client.connect("127.0.0.1", 6080)
|
client.connect("127.0.0.1", 6080)
|
||||||
root = RootActor(client)
|
root = RootActor(client)
|
||||||
|
@ -105,41 +144,59 @@ class DevtoolsTests(unittest.IsolatedAsyncioTestCase):
|
||||||
watcher = tab.get_watcher()
|
watcher = tab.get_watcher()
|
||||||
watcher = WatcherActor(client, watcher["actor"])
|
watcher = WatcherActor(client, watcher["actor"])
|
||||||
|
|
||||||
target = Future()
|
done = Future()
|
||||||
|
targets = []
|
||||||
|
|
||||||
def on_target(data):
|
def on_target(data):
|
||||||
if data["target"]["browsingContextID"] == tab_dict["browsingContextID"]:
|
try:
|
||||||
target.set_result(data["target"])
|
targets.append(data["target"])
|
||||||
|
if len(targets) == expected_targets:
|
||||||
|
done.set_result(None)
|
||||||
|
except Exception as e:
|
||||||
|
# Raising here does nothing, for some reason.
|
||||||
|
# Send the exception back so it can be raised.
|
||||||
|
done.set_result(e)
|
||||||
|
|
||||||
client.add_event_listener(
|
client.add_event_listener(
|
||||||
watcher.actor_id, Events.Watcher.TARGET_AVAILABLE_FORM, on_target,
|
watcher.actor_id, Events.Watcher.TARGET_AVAILABLE_FORM, on_target,
|
||||||
)
|
)
|
||||||
watcher.watch_targets(WatcherActor.Targets.FRAME)
|
watcher.watch_targets(WatcherActor.Targets.FRAME)
|
||||||
|
watcher.watch_targets(WatcherActor.Targets.WORKER)
|
||||||
|
|
||||||
|
result: Optional[Exception] = done.result(1)
|
||||||
|
if result:
|
||||||
|
raise result
|
||||||
done = Future()
|
done = Future()
|
||||||
target = target.result(1)
|
# NOTE: breaks if two targets have the same list of source urls.
|
||||||
|
# This should really be a multiset, but Python does not have multisets.
|
||||||
|
actual_urls_by_target: set[tuple[str]] = set()
|
||||||
|
|
||||||
def on_source_resource(data):
|
def on_source_resource(data):
|
||||||
for [resource_type, sources] in data["array"]:
|
for [resource_type, sources] in data["array"]:
|
||||||
try:
|
try:
|
||||||
self.assertEqual(resource_type, "source")
|
self.assertEqual(resource_type, "source")
|
||||||
self.assertEqual([source["url"] for source in sources], expected_urls)
|
source_urls = tuple([source["url"] for source in sources])
|
||||||
done.set_result(None)
|
self.assertFalse(source_urls in sources) # See NOTE above
|
||||||
|
actual_urls_by_target.add(source_urls)
|
||||||
|
if len(actual_urls_by_target) == expected_targets:
|
||||||
|
done.set_result(None)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Raising here does nothing, for some reason.
|
# Raising here does nothing, for some reason.
|
||||||
# Send the exception back so it can be raised.
|
# Send the exception back so it can be raised.
|
||||||
done.set_result(e)
|
done.set_result(e)
|
||||||
|
|
||||||
client.add_event_listener(
|
for target in targets:
|
||||||
target["actor"],
|
client.add_event_listener(
|
||||||
Events.Watcher.RESOURCES_AVAILABLE_ARRAY,
|
target["actor"],
|
||||||
on_source_resource,
|
Events.Watcher.RESOURCES_AVAILABLE_ARRAY,
|
||||||
)
|
on_source_resource,
|
||||||
|
)
|
||||||
watcher.watch_resources([Resources.SOURCE])
|
watcher.watch_resources([Resources.SOURCE])
|
||||||
|
|
||||||
result: Optional[Exception] = done.result(1)
|
result: Optional[Exception] = done.result(1)
|
||||||
if result:
|
if result:
|
||||||
raise result
|
raise result
|
||||||
|
self.assertEqual(actual_urls_by_target, expected_urls_by_target)
|
||||||
client.disconnect()
|
client.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue