| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Module to get random numbers, strings, etc. | 5 """Module to get random numbers, strings, etc. |
| 6 | 6 |
| 7 The values returned by the various functions can be replaced in | 7 The values returned by the various functions can be replaced in |
| 8 templates to generate test cases. | 8 templates to generate test cases. |
| 9 """ | 9 """ |
| 10 | 10 |
| 11 import random | 11 import random |
| 12 import sys |
| 13 import uuid |
| 14 |
| 15 # This script needs the utils.py and fuzzy_types.py modules in order |
| 16 # to work. This files are copied by the setup.py script and not checked-in |
| 17 # next to this code, so we need to disable the style warning. |
| 18 # pylint: disable=F0401 |
| 19 from resources import utils |
| 20 from resources import fuzzy_types |
| 21 |
| 22 import gatt_aliases |
| 12 | 23 |
| 13 | 24 |
| 14 def GetValidUUIDString(): | 25 # List of services that are included in our fake adapters. |
| 15 """Constructs a valid UUID string. | 26 FAKE_SERVICES = [ |
| 27 'generic_access', |
| 28 'glucose', |
| 29 'heart_rate', |
| 30 'battery_service', |
| 31 'human_interface_device', |
| 32 '000000a0-97e5-4cd7-b9f1-f5a427670c59', # Error UUID |
| 33 'device_information', |
| 34 '611c954a-263b-4f4a-aab6-01ddb953f985', # Blacklisted |
| 35 '01d7d889-7451-419f-aeb8-d65e7b9277af', # Request Disconnection |
| 36 ] |
| 37 |
| 38 # List of available fake adapters. |
| 39 FAKE_ADAPTERS = [ |
| 40 'BaseAdapter', |
| 41 'NotPresentAdapter', |
| 42 'NotPoweredAdapter', |
| 43 'EmptyAdapter', |
| 44 'FailStartDiscoveryAdapter', |
| 45 'GlucoseHeartRateAdapter', |
| 46 'UnicodeDeviceAdapter', |
| 47 'MissingServiceHeartRateAdapter', |
| 48 'MissingCharacteristicHeartRateAdapter', |
| 49 'HeartRateAdapter', |
| 50 'TwoHeartRateServicesAdapter', |
| 51 'DisconnectingHeartRateAdapter', |
| 52 'BlacklistTestAdapter', |
| 53 'FailingConnectionsAdapter', |
| 54 'FailingGATTOperationsAdapter', |
| 55 'DelayedServicesDiscoveryAdapter', |
| 56 ] |
| 57 |
| 58 |
| 59 def _ToJsStr(s): |
| 60 return u'\'{}\''.format(s) |
| 61 |
| 62 |
| 63 def GetFakeAdapter(): |
| 64 return _ToJsStr(random.choice(FAKE_ADAPTERS)) |
| 65 |
| 66 |
| 67 def _GetFuzzedJsString(s): |
| 68 """Returns a fuzzed string based on |s|. |
| 69 |
| 70 Args: |
| 71 s: The base string to fuzz. |
| 72 Returns: |
| 73 A single line string surrounded by quotes. |
| 74 """ |
| 75 while True: |
| 76 fuzzed_string = fuzzy_types.FuzzyString(s) |
| 77 try: |
| 78 fuzzed_string = fuzzed_string.decode('utf8') |
| 79 except UnicodeDecodeError: |
| 80 print 'Can\'t decode fuzzed string. Trying again.' |
| 81 else: |
| 82 fuzzed_string = '\\n'.join(fuzzed_string.split()) |
| 83 fuzzed_string = fuzzed_string.replace('\'', r'\'') |
| 84 return _ToJsStr(fuzzed_string) |
| 85 |
| 86 |
| 87 def GetServiceUUIDFromFakes(): |
| 88 """Returns a random service string from the list of fake services.""" |
| 89 return _ToJsStr(random.choice(FAKE_SERVICES)) |
| 90 |
| 91 |
| 92 def GetValidServiceAlias(): |
| 93 """Returns a valid service alias from the list of services aliases.""" |
| 94 return _ToJsStr(random.choice(gatt_aliases.SERVICES)) |
| 95 |
| 96 |
| 97 def GetRandomUUID(): |
| 98 """Returns a random UUID, a random number or a fuzzed uuid or alias.""" |
| 99 choice = random.choice(['uuid', 'number', 'fuzzed string']) |
| 100 if choice == 'uuid': |
| 101 return _ToJsStr(uuid.uuid4()) |
| 102 elif choice == 'number': |
| 103 return utils.UniformExpoInteger(0, sys.maxsize.bit_length() + 1) |
| 104 elif choice == 'fuzzed string': |
| 105 choice2 = random.choice(['uuid', 'alias']) |
| 106 if choice2 == 'uuid': |
| 107 random_uuid = str(uuid.uuid4()) |
| 108 return _GetFuzzedJsString(random_uuid) |
| 109 elif choice2 == 'alias': |
| 110 alias = random.choice(gatt_aliases.SERVICES) |
| 111 return _GetFuzzedJsString(alias) |
| 112 |
| 113 |
| 114 def GetServiceUUID(): |
| 115 """Generates a random Service UUID from a set of functions. |
| 116 |
| 117 See GetServiceUUIDFromFakes(), GetValidServiceAlias() and GetRandomUUID() |
| 118 for the different values this function can return. |
| 119 |
| 120 This function weights GetServiceUUIDFromFakes() more heavily to increase the |
| 121 probability of generating test pages that can interact with the fake |
| 122 adapters. |
| 16 | 123 |
| 17 Returns: | 124 Returns: |
| 18 A string representating a valid UUID according to: | 125 A string or a number that can be used as a Service UUID by the Web |
| 19 https://webbluetoothcg.github.io/web-bluetooth/#valid-uuid | 126 Bluetooth API. |
| 20 """ | 127 """ |
| 21 | 128 roll = random.random() |
| 22 return '\'{:08x}-{:04x}-{:04x}-{:04x}-{:012x}\''.format( | 129 if roll < 0.8: |
| 23 random.getrandbits(32), | 130 return GetServiceUUIDFromFakes() |
| 24 random.getrandbits(16), | 131 elif roll < 0.9: |
| 25 random.getrandbits(16), | 132 return GetValidServiceAlias() |
| 26 random.getrandbits(16), | 133 else: |
| 27 random.getrandbits(48)) | 134 return GetRandomUUID() |
| 28 | 135 |
| 29 | 136 |
| 30 def GetRequestDeviceOptions(): | 137 def GetRequestDeviceOptions(): |
| 31 """Returns an object used by navigator.bluetooth.requestDevice.""" | 138 """Returns an object used by navigator.bluetooth.requestDevice.""" |
| 32 # TODO(ortuno): Randomize the members, number of filters, services, etc. | 139 # TODO(ortuno): Randomize the members, number of filters, services, etc. |
| 33 | 140 |
| 34 return '{filters: [{services: [ %s ]}]}' % GetValidUUIDString() | 141 return '{filters: [{services: [ %s ]}]}' % GetServiceUUID() |
| OLD | NEW |