Chromium Code Reviews| Index: third_party/WebKit/Source/modules/bluetooth/web_bluetooth_fuzzer/constraints.py |
| diff --git a/third_party/WebKit/Source/modules/bluetooth/web_bluetooth_fuzzer/constraints.py b/third_party/WebKit/Source/modules/bluetooth/web_bluetooth_fuzzer/constraints.py |
| index 6bc36dd58a53bc2ef2fa18eafffa690a63481250..b633bde3259eabb955b3692f10d7084f47eab39d 100644 |
| --- a/third_party/WebKit/Source/modules/bluetooth/web_bluetooth_fuzzer/constraints.py |
| +++ b/third_party/WebKit/Source/modules/bluetooth/web_bluetooth_fuzzer/constraints.py |
| @@ -8,27 +8,143 @@ |
| templates to generate test cases. |
| """ |
| +import os |
| import random |
| +import sys |
| +import uuid |
| +import gatt_aliases |
| -def GetValidUUIDString(): |
| - """Constructs a valid UUID string. |
| +# This file is uploaded next to 'common' to ClusterFuzz so we try to import |
| +# the necessary modules from there. If we fail then we try the parent directory, |
| +# where common is usually located when developing locally. |
| +try: |
| + # pylint: disable=E0611 |
| + from common import utils |
| + from common import fuzzy_types |
| +except ImportError: |
| + sys.path.append(os.pardir) |
|
ortuno
2016/07/21 21:35:24
Now the setup.py script copies these files.
|
| + # pylint: disable=E0611 |
| + from common import utils |
| + from common import fuzzy_types |
| + |
| +# List of services that are included in our fake adapters. |
|
ortuno
2016/07/21 21:35:24
Done.
|
| +FAKE_SERVICES = [ |
| + 'generic_access', |
| + 'glucose', |
| + 'heart_rate', |
| + 'battery_service', |
| + 'human_interface_device', |
| + '000000a0-97e5-4cd7-b9f1-f5a427670c59', # Error UUID |
| + 'device_information', |
| + '611c954a-263b-4f4a-aab6-01ddb953f985', # Blacklist |
| + '01d7d889-7451-419f-aeb8-d65e7b9277af', # Request Disconnection |
| +] |
| + |
| +# List of available fake adapters. |
| +FAKE_ADAPTERS = [ |
| + 'BaseAdapter', |
| + 'NotPresentAdapter', |
| + 'NotPoweredAdapter', |
| + 'EmptyAdapter', |
| + 'FailStartDiscoveryAdapter', |
| + 'GlucoseHeartRateAdapter', |
| + 'UnicodeDeviceAdapter', |
| + 'MissingServiceHeartRateAdapter', |
| + 'MissingCharacteristicHeartRateAdapter', |
| + 'HeartRateAdapter', |
| + 'TwoHeartRateServicesAdapter', |
| + 'DisconnectingHeartRateAdapter', |
| + 'BlacklistTestAdapter', |
| + 'FailingConnectionsAdapter', |
| + 'FailingGATTOperationsAdapter', |
| + 'DelayedServicesDiscoveryAdapter', |
| +] |
| + |
| + |
| +def _ToJsStr(s): |
| + return u'\'{}\''.format(s) |
| + |
| + |
| +def GetFakeAdapter(): |
| + return _ToJsStr(random.choice(FAKE_ADAPTERS)) |
| + |
| + |
| +def _GetFuzzedJsString(s): |
| + """Returns a fuzzed string based on |s|. |
| + |
| + Args: |
| + s: The base string to fuzz. |
| Returns: |
| - A string representating a valid UUID according to: |
| - https://webbluetoothcg.github.io/web-bluetooth/#valid-uuid |
| + A single line string surrounded by quotes. |
| """ |
| + while True: |
| + fuzzed_string = fuzzy_types.FuzzyString(s) |
| + try: |
| + fuzzed_string = fuzzed_string.decode('utf8') |
| + except UnicodeDecodeError: |
| + print 'Can\'t decode fuzzed string. Trying again.' |
| + else: |
| + fuzzed_string = '\\n'.join(fuzzed_string.split()) |
| + fuzzed_string = fuzzed_string.replace('\'', r'\'') |
| + return _ToJsStr(fuzzed_string) |
| + |
| + |
| +def GetServiceUUIDFromFakes(): |
| + """Returns a random service string from the list of fake services.""" |
| + return _ToJsStr(random.choice(FAKE_SERVICES)) |
| - return '\'{:08x}-{:04x}-{:04x}-{:04x}-{:012x}\''.format( |
| - random.getrandbits(32), |
| - random.getrandbits(16), |
| - random.getrandbits(16), |
| - random.getrandbits(16), |
| - random.getrandbits(48)) |
| + |
| +def GetValidServiceAlias(): |
| + """Returns a valid service alias from the list of services aliases.""" |
| + return _ToJsStr(random.choice(gatt_aliases.SERVICES)) |
| + |
| + |
| +def GetRandomUUID(): |
| + """Returns a random UUID, a random number or a fuzzed uuid or alias.""" |
| + roll = random.random() |
|
ortuno
2016/07/21 21:35:24
Done.
|
| + if roll < 1 / 3: |
| + # Random UUID |
| + return _ToJsStr(uuid.uuid4()) |
| + elif roll < 2 / 3: |
| + # Random number |
| + return utils.UniformExpoInteger(0, sys.maxsize.bit_length() + 1) |
| + else: |
| + # Fuzzed UUID or alias |
| + if random.getrandbits(1): |
| + random_uuid = str(uuid.uuid4()) |
| + return _GetFuzzedJsString(random_uuid) |
| + else: |
| + alias = random.choice(gatt_aliases.SERVICES) |
| + return _GetFuzzedJsString(alias) |
| + |
| + |
| +def GetServiceUUID(): |
| + """Generates a random Service UUID from a set of functions. |
| + |
| + See GetServiceUUIDFromFakes(), GetValidServiceAlias() and GetRandomUUID() |
| + for the different values this function can return. |
| + |
| + This function weights GetServiceUUIDFromFakes() more heavily to increase the |
| + probability of generating test pages that can interact with the fake |
| + adapters. |
| + |
| + Returns: |
| + A string or a number that can be used as a Service UUID by the Web |
| + Bluetooth API. |
| + """ |
| + roll = random.random() |
| + if roll < 0.8: |
| + return GetServiceUUIDFromFakes() |
| + elif roll < 0.9: |
| + return GetValidServiceAlias() |
| + else: |
| + return GetRandomUUID() |
| def GetRequestDeviceOptions(): |
| """Returns an object used by navigator.bluetooth.requestDevice.""" |
| # TODO(ortuno): Randomize the members, number of filters, services, etc. |
| - return '{filters: [{services: [ %s ]}]}' % GetValidUUIDString() |
| + return '{filters: [{services: [ %s ]}]}' % GetServiceUUID() |