Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for additional services #365

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ignore:
- "grizzly/services/webtransport/wpt_h3_server"
codecov:
ci:
- community-tc.services.mozilla.com
1 change: 1 addition & 0 deletions grizzly/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
def session_setup(mocker):
mocker.patch("grizzly.main.FuzzManagerReporter", autospec=True)
mocker.patch("grizzly.main.Sapphire", autospec_set=True)
mocker.patch("grizzly.main.WebServices", autospec_set=True)
adapter_cls = mocker.Mock(spec_set=Adapter)
adapter_cls.return_value.RELAUNCH = Adapter.RELAUNCH
adapter_cls.return_value.TIME_LIMIT = Adapter.TIME_LIMIT
Expand Down
8 changes: 8 additions & 0 deletions grizzly/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
package_version,
time_limits,
)
from .services import WebServices
from .session import LogRate, Session
from .target import Target, TargetLaunchError, TargetLaunchTimeout

Expand Down Expand Up @@ -52,6 +53,7 @@ def main(args: Namespace) -> int:
adapter: Optional[Adapter] = None
certs: Optional[CertificateBundle] = None
complete_with_results = False
ext_services = None
pyoor marked this conversation as resolved.
Show resolved Hide resolved
target: Optional[Target] = None
try:
LOG.debug("initializing Adapter %r", args.adapter)
Expand Down Expand Up @@ -121,6 +123,9 @@ def main(args: Namespace) -> int:
# launch http server used to serve test cases
LOG.debug("starting Sapphire server")
with Sapphire(auto_close=1, timeout=timeout, certs=certs) as server:
if certs is not None:
ext_services = WebServices.start_services(certs.host, certs.key)

target.reverse(server.port, server.port)
LOG.debug("initializing the Session")
with Session(
Expand Down Expand Up @@ -149,6 +154,7 @@ def main(args: Namespace) -> int:
log_rate=log_rate,
launch_attempts=args.launch_attempts,
post_launch_delay=args.post_launch_delay,
services=ext_services,
)
complete_with_results = session.status.results.total > 0

Expand All @@ -169,6 +175,8 @@ def main(args: Namespace) -> int:
if adapter is not None:
LOG.debug("calling adapter.cleanup()")
adapter.cleanup()
if ext_services is not None:
ext_services.cleanup()
if certs is not None:
certs.cleanup()
LOG.info("Done.")
Expand Down
14 changes: 14 additions & 0 deletions grizzly/reduce/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
time_limits,
)
from ..replay import ReplayManager, ReplayResult
from ..services import WebServices
from ..target import AssetManager, Target, TargetLaunchError, TargetLaunchTimeout
from .exceptions import GrizzlyReduceBaseException, NotReproducible
from .strategies import STRATEGIES
Expand Down Expand Up @@ -90,6 +91,7 @@ def __init__(
relaunch: int = 1,
report_period: Optional[int] = None,
report_to_fuzzmanager: bool = False,
services: Optional[WebServices] = None,
signature: Optional[CrashSignature] = None,
signature_desc: Optional[str] = None,
static_timeout: bool = False,
Expand All @@ -115,6 +117,7 @@ def __init__(
Target should be relaunched.
report_period: Periodically report best results for long-running strategies.
report_to_fuzzmanager: Report to FuzzManager rather than filesystem.
services: WebServices instance.
signature: Signature for accepting crashes.
signature_desc: Short description of the given signature.
static_timeout: Use only specified timeouts (`--timeout` and
Expand Down Expand Up @@ -153,6 +156,7 @@ def __init__(
)
self._use_analysis = use_analysis
self._use_harness = use_harness
self._services = services

def __enter__(self) -> "ReduceManager":
return self
Expand Down Expand Up @@ -322,6 +326,7 @@ def run_reliability_analysis(self) -> Tuple[int, int]:
idle_delay=self._idle_delay,
idle_threshold=self._idle_threshold,
on_iteration_cb=self._on_replay_iteration,
services=self._services,
)
try:
crashes = sum(x.count for x in results if x.expected)
Expand Down Expand Up @@ -525,6 +530,7 @@ def run(
repeat=repeat,
on_iteration_cb=self._on_replay_iteration,
post_launch_delay=post_launch_delay,
services=self._services,
)
self._status.attempts += 1
self.update_timeout(results)
Expand Down Expand Up @@ -777,6 +783,7 @@ def main(cls, args: Namespace) -> int:

asset_mgr: Optional[AssetManager] = None
certs = None
ext_services = None
signature = None
signature_desc = None
target: Optional[Target] = None
Expand Down Expand Up @@ -846,6 +853,10 @@ def main(cls, args: Namespace) -> int:
LOG.debug("starting sapphire server")
# launch HTTP server used to serve test cases
with Sapphire(auto_close=1, timeout=timeout, certs=certs) as server:
if certs is not None:
LOG.debug("starting additional web services")
ext_services = WebServices.start_services(certs.host, certs.key)

target.reverse(server.port, server.port)
with ReduceManager(
set(args.ignore),
Expand All @@ -868,6 +879,7 @@ def main(cls, args: Namespace) -> int:
tool=args.tool,
use_analysis=not args.no_analysis,
use_harness=not args.no_harness,
services=ext_services,
) as mgr:
return_code = mgr.run(
repeat=args.repeat,
Expand Down Expand Up @@ -910,4 +922,6 @@ def main(cls, args: Namespace) -> int:
asset_mgr.cleanup()
if certs is not None:
certs.cleanup()
if ext_services is not None:
ext_services.cleanup()
LOG.info("Done.")
14 changes: 14 additions & 0 deletions grizzly/replay/replay.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
package_version,
time_limits,
)
from ..services import WebServices
from ..target import (
AssetManager,
Result,
Expand Down Expand Up @@ -294,6 +295,7 @@ def run(
launch_attempts: int = 3,
on_iteration_cb: Optional[Callable[[], None]] = None,
post_launch_delay: int = -1,
services: Optional[WebServices] = None,
) -> List[ReplayResult]:
"""Run testcase replay.

Expand All @@ -314,6 +316,7 @@ def run(
on_iteration_cb: Called every time a single iteration is run.
post_launch_delay: Number of seconds to wait before continuing after the
browser is launched. A negative number skips redirect.
services: WebServices instance.

Returns:
ReplayResults that were found running provided testcases.
Expand Down Expand Up @@ -349,6 +352,9 @@ def harness_fn(_: str) -> bytes: # pragma: no cover
)
server_map.set_redirect("grz_start", "grz_harness", required=False)

if services:
services.map_locations(server_map)

# track unprocessed results
reports: Dict[str, ReplayResult] = {}
try:
Expand Down Expand Up @@ -629,6 +635,7 @@ def main(cls, args: Namespace) -> int:
certs = None
results: Optional[List[ReplayResult]] = None
target: Optional[Target] = None
ext_services = None
try:
# check if hangs are expected
expect_hang = cls.expect_hang(args.ignore, signature, testcases)
Expand Down Expand Up @@ -682,6 +689,10 @@ def main(cls, args: Namespace) -> int:
LOG.debug("starting sapphire server")
# launch HTTP server used to serve test cases
with Sapphire(auto_close=1, timeout=timeout, certs=certs) as server:
if certs is not None:
LOG.debug("starting additional web services")
ext_services = WebServices.start_services(certs.host, certs.key)

target.reverse(server.port, server.port)
with cls(
set(args.ignore),
Expand All @@ -702,6 +713,7 @@ def main(cls, args: Namespace) -> int:
min_results=args.min_crashes,
post_launch_delay=args.post_launch_delay,
repeat=repeat,
services=ext_services,
)
# handle results
success = any(x.expected for x in results)
Expand Down Expand Up @@ -754,4 +766,6 @@ def main(cls, args: Namespace) -> int:
asset_mgr.cleanup()
if certs is not None:
certs.cleanup()
if ext_services is not None:
ext_services.cleanup()
LOG.info("Done.")
7 changes: 7 additions & 0 deletions grizzly/replay/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def test_main_01(mocker, server, tmp_path):
# Of the four attempts only the first and third will 'reproduce' the result
# and the forth attempt should be skipped.
mocker.patch("grizzly.common.runner.sleep", autospec=True)
mocker.patch("grizzly.replay.replay.WebServices", autospec=True)
server.serve_path.return_value = (Served.ALL, {"test.html": "/fake/path"})
# setup Target
load_target = mocker.patch("grizzly.replay.replay.load_plugin", autospec=True)
Expand Down Expand Up @@ -151,6 +152,7 @@ def test_main_02(mocker, server, tmp_path, repro_results):
test_index=[],
time_limit=10,
timeout=None,
use_https=False,
valgrind=False,
)
assert ReplayManager.main(args) == Exit.FAILURE
Expand Down Expand Up @@ -215,6 +217,7 @@ def test_main_03(mocker, load_plugin, load_testcases, signature, result):
test_index=[],
time_limit=10,
timeout=None,
use_https=False,
valgrind=False,
)
asset_mgr = load_testcases[1] if isinstance(load_testcases, tuple) else None
Expand Down Expand Up @@ -256,6 +259,7 @@ def test_main_04(mocker, tmp_path):
test_index=[],
time_limit=10,
timeout=None,
use_https=False,
valgrind=False,
)
# target launch error
Expand Down Expand Up @@ -317,6 +321,7 @@ def test_main_05(mocker, server, tmp_path):
test_index=[],
time_limit=1,
timeout=None,
use_https=False,
valgrind=False,
)
# build a test case
Expand Down Expand Up @@ -385,6 +390,7 @@ def test_main_06(
test_index=[],
time_limit=10,
timeout=None,
use_https=False,
valgrind=valgrind,
)
# maximum one debugger allowed at a time
Expand Down Expand Up @@ -438,6 +444,7 @@ def test_main_07(mocker, server, tmp_path):
time_limit=10,
timeout=None,
tool=None,
use_https=False,
valgrind=False,
)
assert ReplayManager.main(args) == Exit.SUCCESS
Expand Down
11 changes: 11 additions & 0 deletions grizzly/services/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
__all__ = (
"ServiceName",
"WebServices",
"WebTransportServer",
)

from .core import ServiceName, WebServices
from .webtransport.core import WebTransportServer
30 changes: 30 additions & 0 deletions grizzly/services/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
from abc import ABC, abstractmethod


class BaseService(ABC):
"""Base service class"""

@property
@abstractmethod
def location(self) -> str:
"""Location to use with Sapphire.set_dynamic_response"""

@property
@abstractmethod
def port(self) -> int:
"""The port on which the server is listening"""

@abstractmethod
def url(self, _query: str) -> bytes:
"""Returns the URL of the server."""

@abstractmethod
async def is_ready(self) -> None:
"""Wait until the service is ready"""

@abstractmethod
def cleanup(self) -> None:
"""Stop the server."""
Loading
Loading