Skip to content

Commit

Permalink
[replay] Add --post-launch-delay argument
Browse files Browse the repository at this point in the history
This adds the ability to schedule a delay after the browser
is launched but before a test is loaded to allow time to
attach debuggers, etc.
  • Loading branch information
tysmith committed Sep 8, 2022
1 parent 1dd39eb commit 9e13457
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 4 deletions.
62 changes: 62 additions & 0 deletions grizzly/common/post_launch_delay.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html>
<meta charset=UTF-8>
<title>Grizzly &sdot; Post Launch Delay</title>
<head>
<script>
const args = window.location.search.replace('?', '')
const target = args ? `/grz_continue?${args}` : '/grz_continue'
let countInterval = null

// parse args
let limit = 300
if (args) {
for (let kv of args.split('&')) {
let [k, v] = kv.split('=')
if (k === 'post_launch_delay') {
limit = Math.max(Number.parseInt(v), 0)
break
}
}
}
let remaining = limit

function countDown() {
remaining -= 1
setTimeout(updateDisplay, 0)
if (remaining <= 0)
setTimeout(next, 0)
}

function next() {
if (countInterval) {
clearInterval(countInterval)
}
setTimeout(() => {
window.location = target
}, 0)
}

function updateDisplay() {
remainingSeconds = Math.max(remaining, 0)
let o = document.getElementById('msg')
o.innerText = `Test will run automatically in: ${remainingSeconds}s`
}

window.onload = () => {
setTimeout(updateDisplay, 0)
if (remaining) {
countInterval = setInterval(countDown, 1000)
}
else {
setTimeout(countDown, 0)
}
}
</script>
</head>
<body style='background-color:#E5E4E2'>
<div>Connect debugger, etc...</div>
<div id='msg'></div>
<button onclick='next()'>Run Test</button>
</body>
</html>
46 changes: 44 additions & 2 deletions grizzly/common/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from logging import getLogger
from pathlib import Path
from time import sleep, time

from sapphire import Served
from sapphire import Served, ServerMap

from ..target import Result, TargetLaunchError, TargetLaunchTimeout
from .storage import TestCase

__all__ = ("Runner", "RunResult")
__author__ = "Tyson Smith"
Expand Down Expand Up @@ -148,13 +150,16 @@ def launch(self, location, max_retries=3, retry_delay=0):
break

@staticmethod
def location(srv_path, srv_port, close_after=None, time_limit=None):
def location(
srv_path, srv_port, close_after=None, post_launch_delay=None, time_limit=None
):
"""Build a valid URL to pass to a browser.
Args:
srv_path (str): Path segment of the URL
srv_port (int): Server listening port
close_after (int): Harness argument.
post_launch_delay (int): Post-launch delay page argument.
time_limit (int): Harness argument.
Returns:
Expand All @@ -169,6 +174,9 @@ def location(srv_path, srv_port, close_after=None, time_limit=None):
if time_limit:
assert time_limit > 0
args.append("time_limit=%d" % (time_limit * 1000,))
if post_launch_delay is not None:
assert post_launch_delay >= 0
args.append("post_launch_delay=%d" % (post_launch_delay,))
if args:
return "?".join((location, "&".join(args)))
return location
Expand All @@ -185,6 +193,40 @@ def initial(self):
"""
return self._tests_run < 2

def post_launch(self, delay=None):
"""Perform actions after launching browser before loading test cases.
Args:
post_launch_delay (int): Amount of time in seconds before the target will
redirect to test case.
Returns:
None
"""
if delay is not None and not self.startup_failure:
assert delay >= 0
with TestCase("post_launch_delay.html", None, "None") as content:
content.add_from_file(
Path(__file__).parent / "post_launch_delay.html",
content.landing_page,
copy=True,
)
srv_map = ServerMap()
srv_map.set_redirect("grz_start", content.landing_page, required=False)
srv_map.set_redirect("grz_continue", "grz_start", required=True)
# temporarily disable server timeout
srv_timeout = self._server.timeout
self._server.timeout = 0
LOG.info("Browser launched, continuing in %ds...", delay)
# serve prompt page
self._server.serve_path(
content.data_path,
continue_cb=self._target.monitor.is_healthy,
server_map=srv_map,
)
# re-enable server timeout
self._server.timeout = srv_timeout

def run(
self,
ignore,
Expand Down
15 changes: 15 additions & 0 deletions grizzly/common/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ def test_runner_08():
assert result == "http://127.0.0.1:9999/a.html?time_limit=60000"
result = Runner.location("a.html", 9999, close_after=10, time_limit=60)
assert result == "http://127.0.0.1:9999/a.html?close_after=10&time_limit=60000"
result = Runner.location("a.html", 9999, post_launch_delay=10)
assert result == "http://127.0.0.1:9999/a.html?post_launch_delay=10"


def test_runner_09(mocker):
Expand Down Expand Up @@ -329,6 +331,19 @@ def test_runner_10(mocker, tmp_path):
assert "test/inc_file3.txt" in tcase.contents


def test_runner_11(mocker):
"""test Runner.post_launch()"""
server = mocker.Mock(spec_set=Sapphire, timeout=1)
target = mocker.Mock(spec_set=Target, launch_timeout=30)
runner = Runner(server, target)
# successful launch
runner.launch("http://a/")
runner.post_launch(delay=10)
assert target.launch.call_count == 1
assert server.timeout == 1
assert server.serve_path.call_count == 1


def test_idle_check_01(mocker):
"""test simple _IdleChecker"""
fake_time = mocker.patch("grizzly.common.runner.time", autospec=True)
Expand Down
11 changes: 11 additions & 0 deletions grizzly/replay/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ def __init__(self):
"0 == Oldest, n-1 == Newest (default: run all testcases)",
)

self.launcher_grp.add_argument(
"--post-launch-delay",
type=int,
default=None,
help="Number of seconds to wait after launching browser before "
" running the test. This provides an opportunity to connect debuggers. ",
)

self.reporter_grp.add_argument(
"--include-test",
action="store_true",
Expand All @@ -101,6 +109,9 @@ def sanity_check(self, args):
if args.min_crashes < 1:
self.parser.error("--min-crashes value must be positive")

if args.post_launch_delay is not None and args.post_launch_delay < 0:
self.parser.error("--post-launch-delay value must be positive")

if args.repeat < 1:
self.parser.error("--repeat value must be positive")

Expand Down
14 changes: 12 additions & 2 deletions grizzly/replay/replay.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ def run(
idle_threshold=0,
launch_attempts=3,
on_iteration_cb=None,
post_launch_delay=None,
):
"""Run testcase replay.
Expand All @@ -239,7 +240,9 @@ def run(
idle_delay (int): Number of seconds to wait before polling for idle.
idle_threshold (int): CPU usage threshold to mark the process as idle.
launch_attempts (int): Number of attempts to launch the browser.
on_iteration_cb (callable): called every time a single iteration is run
on_iteration_cb (callable): Called every time a single iteration is run.
post_launch_delay (int): Time in seconds before test case is loaded after
the browser is launched.
Returns:
list: ReplayResults that were found running testcases.
Expand Down Expand Up @@ -286,15 +289,21 @@ def run(
on_iteration_cb()
if self.target.closed:
if self._harness is None:
location = runner.location("/grz_start", self.server.port)
location = runner.location(
"/grz_start",
self.server.port,
post_launch_delay=post_launch_delay,
)
else:
location = runner.location(
"/grz_start",
self.server.port,
close_after=relaunch * test_count,
post_launch_delay=post_launch_delay,
time_limit=time_limit,
)
runner.launch(location, max_retries=launch_attempts)
runner.post_launch(delay=post_launch_delay)
# run tests
durations = list()
served = list()
Expand Down Expand Up @@ -647,6 +656,7 @@ def main(cls, args):
idle_threshold=args.idle_threshold,
launch_attempts=args.launch_attempts,
min_results=args.min_crashes,
post_launch_delay=args.post_launch_delay,
repeat=repeat,
)
# handle results
Expand Down
5 changes: 5 additions & 0 deletions grizzly/replay/test_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ def test_replay_args_01(capsys, mocker, tmp_path):
),
# test invalid min-crashes value
(["--min-crashes", "0"], "error: --min-crashes value must be positive"),
# test invalid post-launch-delay value
(
["--post-launch-delay", "-1"],
"error: --post-launch-delay value must be positive",
),
# test invalid repeat value
(["--repeat", "-1"], "error: --repeat value must be positive"),
# test running with rr without --logs set
Expand Down
7 changes: 7 additions & 0 deletions grizzly/replay/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def test_main_01(mocker, tmp_path):
min_crashes=2,
no_harness=False,
pernosco=False,
post_launch_delay=None,
relaunch=1,
repeat=4,
rr=False,
Expand Down Expand Up @@ -123,6 +124,7 @@ def test_main_02(mocker, tmp_path):
min_crashes=2,
no_harness=True,
pernosco=False,
post_launch_delay=None,
relaunch=1,
repeat=1,
rr=False,
Expand Down Expand Up @@ -154,6 +156,7 @@ def test_main_03(mocker):
min_crashes=1,
no_harness=True,
pernosco=False,
post_launch_delay=None,
relaunch=1,
repeat=1,
rr=False,
Expand Down Expand Up @@ -222,6 +225,7 @@ def test_main_04(mocker, tmp_path):
input="test",
min_crashes=1,
no_harness=True,
post_launch_delay=None,
pernosco=False,
relaunch=1,
repeat=1,
Expand Down Expand Up @@ -281,6 +285,7 @@ def test_main_05(mocker, tmp_path):
min_crashes=1,
no_harness=True,
pernosco=False,
post_launch_delay=None,
relaunch=1,
repeat=1,
rr=False,
Expand Down Expand Up @@ -368,6 +373,7 @@ def test_main_06(mocker, tmp_path, arg_timelimit, arg_timeout, test_timelimit, r
min_crashes=2,
no_harness=True,
pernosco=False,
post_launch_delay=None,
relaunch=1,
repeat=1,
rr=False,
Expand Down Expand Up @@ -425,6 +431,7 @@ def test_main_07(mocker, tmp_path, pernosco, rr, valgrind, no_harness):
min_crashes=2,
no_harness=no_harness,
pernosco=pernosco,
post_launch_delay=None,
relaunch=1,
repeat=1,
rr=rr,
Expand Down

0 comments on commit 9e13457

Please sign in to comment.