blob: 4e7b611bb66f5893e0702f0f24407ef689e7ac2d [file] [log] [blame]
#!/usr/bin/env python3.8
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import errno
from .args import ArgParser
from .host import Host
from .buildenv import BuildEnv
from .device import Device
from .fuzzer import Fuzzer
class Factory(object):
"""Facility for creating associated objects.
The factory can create Hosts, BuildEnvs, Devices, and
Fuzzers. More importantly, it can construct them with references to
each other, i.e. a Factory-constructed Fuzzer automatically gets a
reference to a Factory-constructed Device, which has a reference to a
Factory-constructed BuildEnv.
Attributes:
host: System interface object for user interactions.
buildenv: The associated BuildEnv object.
device: The associated Device object.
"""
def __init__(self, host=None):
if not host:
host = Host()
self._parser = None
self._host = host
self._buildenv = None
self._device = None
@property
def host(self):
"""System interface object for user interactions."""
return self._host
@property
def parser(self):
"""The associated ArgParser object."""
if self._parser:
return self._parser
parser = ArgParser()
parser.host = self.host
parser.add_parsers()
self._parser = parser
return self._parser
@property
def buildenv(self):
"""The associated BuildEnv object."""
if self._buildenv:
return self._buildenv
buildenv = BuildEnv(self)
pathname = buildenv.abspath('//.fx-build-dir')
build_dir = '//' + self.host.readfile(
pathname,
on_error=[
'Failed to read build directory from {}.'.format(pathname),
'Have you run "fx set ... --fuzz-with <sanitizer>"?'
])
buildenv.configure(build_dir)
buildenv.read_fuzzers(buildenv.abspath(build_dir, 'fuzzers.json'))
self._buildenv = buildenv
return self._buildenv
@property
def device(self):
"""The associated Device object."""
if self._device:
return self._device
pathname = '{}.device'.format(self.buildenv.build_dir)
device_name = self.host.readfile(pathname, missing_ok=True)
device = Device(self, name=device_name)
device.configure()
self._device = device
return self._device
def create_fuzzer(self, args, include_tests=False):
"""Constructs a Fuzzer from command line arguments, showing a
disambiguation menu if specified name matches more than one fuzzer."""
fuzzers = self.buildenv.fuzzers(args.name, include_tests=include_tests)
if not fuzzers:
self.host.error('No matching fuzzers found.', 'Try "fx fuzz list".')
if len(fuzzers) > 1:
choices = {}
for fuzzer in fuzzers:
choices[str(fuzzer)] = fuzzer
self.host.echo('More than one match found.')
prompt = 'Please pick one from the list'
choice = self.host.choose(prompt, sorted(choices.keys()))
fuzzer = choices[choice]
else:
fuzzer = fuzzers[0]
fuzzer.update(args)
return fuzzer