| 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 | 12 import sys |
| 13 import uuid | 13 import uuid |
| 14 | 14 |
| 15 # This script needs the utils.py and fuzzy_types.py modules in order | 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 | 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. | 17 # next to this code, so we need to disable the style warning. |
| 18 # pylint: disable=F0401 | 18 # pylint: disable=F0401 |
| 19 from resources import utils | 19 from resources import utils |
| 20 from resources import fuzzy_types | 20 from resources import fuzzy_types |
| 21 | 21 |
| 22 import gatt_aliases | 22 import gatt_aliases |
| 23 import wbt_fakes |
| 23 | 24 |
| 24 | 25 |
| 25 # List of services that are included in our fake adapters. | 26 # Strings that are used to generate the beginning of a test. The replacement |
| 26 FAKE_SERVICES = [ | 27 # fields are replaced by Get*Base() functions below to generate valid test |
| 27 'generic_access', | 28 # cases. |
| 28 'glucose', | 29 BASIC_BASE = \ |
| 29 'heart_rate', | 30 ' return setBluetoothFakeAdapter({fake_adapter_name})\n'\ |
| 30 'battery_service', | 31 ' .then(() => {{\n' |
| 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 | 32 |
| 38 # List of available fake adapters. | 33 DEVICE_DISCOVERY_BASE = BASIC_BASE + \ |
| 39 FAKE_ADAPTERS = [ | 34 ' return requestDeviceWithKeyDown({{\n'\ |
| 40 'BaseAdapter', | 35 ' filters: [{{services: [{service_uuid}]}}]}});\n'\ |
| 41 'NotPresentAdapter', | 36 ' }})\n'\ |
| 42 'NotPoweredAdapter', | 37 ' .then(device => {{\n' |
| 43 'EmptyAdapter', | 38 |
| 44 'FailStartDiscoveryAdapter', | 39 CONNECTABLE_BASE = DEVICE_DISCOVERY_BASE + \ |
| 45 'GlucoseHeartRateAdapter', | 40 ' return device.gatt.connect();\n'\ |
| 46 'UnicodeDeviceAdapter', | 41 ' }})\n'\ |
| 47 'MissingServiceHeartRateAdapter', | 42 ' .then(gatt => {{\n' |
| 48 'MissingCharacteristicHeartRateAdapter', | 43 |
| 49 'HeartRateAdapter', | 44 SERVICE_RETRIEVED_BASE = CONNECTABLE_BASE + \ |
| 50 'TwoHeartRateServicesAdapter', | 45 ' return gatt.getPrimaryService({service_uuid});\n'\ |
| 51 'DisconnectingHeartRateAdapter', | 46 ' }})\n'\ |
| 52 'BlacklistTestAdapter', | 47 ' .then(service => {{\n' |
| 53 'FailingConnectionsAdapter', | |
| 54 'FailingGATTOperationsAdapter', | |
| 55 'DelayedServicesDiscoveryAdapter', | |
| 56 ] | |
| 57 | 48 |
| 58 | 49 |
| 59 def _ToJsStr(s): | 50 def _ToJsStr(s): |
| 60 return u'\'{}\''.format(s) | 51 return u'\'{}\''.format(s) |
| 61 | 52 |
| 62 | 53 |
| 63 def GetFakeAdapter(): | |
| 64 return _ToJsStr(random.choice(FAKE_ADAPTERS)) | |
| 65 | |
| 66 | |
| 67 def _GetFuzzedJsString(s): | 54 def _GetFuzzedJsString(s): |
| 68 """Returns a fuzzed string based on |s|. | 55 """Returns a fuzzed string based on |s|. |
| 69 | 56 |
| 70 Args: | 57 Args: |
| 71 s: The base string to fuzz. | 58 s: The base string to fuzz. |
| 72 Returns: | 59 Returns: |
| 73 A single line string surrounded by quotes. | 60 A single line string surrounded by quotes. |
| 74 """ | 61 """ |
| 75 while True: | 62 while True: |
| 76 fuzzed_string = fuzzy_types.FuzzyString(s) | 63 fuzzed_string = fuzzy_types.FuzzyString(s) |
| 77 try: | 64 try: |
| 78 fuzzed_string = fuzzed_string.decode('utf8') | 65 fuzzed_string = fuzzed_string.decode('utf8') |
| 79 except UnicodeDecodeError: | 66 except UnicodeDecodeError: |
| 80 print 'Can\'t decode fuzzed string. Trying again.' | 67 print 'Can\'t decode fuzzed string. Trying again.' |
| 81 else: | 68 else: |
| 82 fuzzed_string = '\\n'.join(fuzzed_string.split()) | 69 fuzzed_string = '\\n'.join(fuzzed_string.split()) |
| 83 fuzzed_string = fuzzed_string.replace('\'', r'\'') | 70 fuzzed_string = fuzzed_string.replace('\'', r'\'') |
| 84 return _ToJsStr(fuzzed_string) | 71 return _ToJsStr(fuzzed_string) |
| 85 | 72 |
| 86 | 73 |
| 87 def GetServiceUUIDFromFakes(): | 74 def GetAdvertisedServiceUUIDFromFakes(): |
| 88 """Returns a random service string from the list of fake services.""" | 75 """Returns a random service string from the list of fake services.""" |
| 89 return _ToJsStr(random.choice(FAKE_SERVICES)) | 76 return _ToJsStr(random.choice(wbt_fakes.ADVERTISED_SERVICES)) |
| 90 | 77 |
| 91 | 78 |
| 92 def GetValidServiceAlias(): | 79 def GetValidServiceAlias(): |
| 93 """Returns a valid service alias from the list of services aliases.""" | 80 """Returns a valid service alias from the list of services aliases.""" |
| 94 return _ToJsStr(random.choice(gatt_aliases.SERVICES)) | 81 return _ToJsStr(random.choice(gatt_aliases.SERVICES)) |
| 95 | 82 |
| 96 | 83 |
| 97 def GetRandomUUID(): | 84 def GetRandomUUID(): |
| 98 """Returns a random UUID, a random number or a fuzzed uuid or alias.""" | 85 """Returns a random UUID, a random number or a fuzzed uuid or alias.""" |
| 99 choice = random.choice(['uuid', 'number', 'fuzzed string']) | 86 choice = random.choice(['uuid', 'number', 'fuzzed string']) |
| 100 if choice == 'uuid': | 87 if choice == 'uuid': |
| 101 return _ToJsStr(uuid.uuid4()) | 88 return _ToJsStr(uuid.uuid4()) |
| 102 elif choice == 'number': | 89 elif choice == 'number': |
| 103 return utils.UniformExpoInteger(0, sys.maxsize.bit_length() + 1) | 90 return utils.UniformExpoInteger(0, sys.maxsize.bit_length() + 1) |
| 104 elif choice == 'fuzzed string': | 91 elif choice == 'fuzzed string': |
| 105 choice2 = random.choice(['uuid', 'alias']) | 92 choice2 = random.choice(['uuid', 'alias']) |
| 106 if choice2 == 'uuid': | 93 if choice2 == 'uuid': |
| 107 random_uuid = str(uuid.uuid4()) | 94 random_uuid = str(uuid.uuid4()) |
| 108 return _GetFuzzedJsString(random_uuid) | 95 return _GetFuzzedJsString(random_uuid) |
| 109 elif choice2 == 'alias': | 96 elif choice2 == 'alias': |
| 110 alias = random.choice(gatt_aliases.SERVICES) | 97 alias = random.choice(gatt_aliases.SERVICES) |
| 111 return _GetFuzzedJsString(alias) | 98 return _GetFuzzedJsString(alias) |
| 112 | 99 |
| 113 | 100 |
| 114 def GetServiceUUID(): | 101 def GetAdvertisedServiceUUID(): |
| 115 """Generates a random Service UUID from a set of functions. | 102 """Generates a random Service UUID from a set of functions. |
| 116 | 103 |
| 117 See GetServiceUUIDFromFakes(), GetValidServiceAlias() and GetRandomUUID() | 104 See GetServiceUUIDFromFakes(), GetValidServiceAlias() and GetRandomUUID() |
| 118 for the different values this function can return. | 105 for the different values this function can return. |
| 119 | 106 |
| 120 This function weights GetServiceUUIDFromFakes() more heavily to increase the | 107 This function weights GetServiceUUIDFromFakes() more heavily to increase the |
| 121 probability of generating test pages that can interact with the fake | 108 probability of generating test pages that can interact with the fake |
| 122 adapters. | 109 adapters. |
| 123 | 110 |
| 124 Returns: | 111 Returns: |
| 125 A string or a number that can be used as a Service UUID by the Web | 112 A string or a number that can be used as a Service UUID by the Web |
| 126 Bluetooth API. | 113 Bluetooth API. |
| 127 """ | 114 """ |
| 128 roll = random.random() | 115 roll = random.random() |
| 129 if roll < 0.8: | 116 if roll < 0.8: |
| 130 return GetServiceUUIDFromFakes() | 117 return GetAdvertisedServiceUUIDFromFakes() |
| 131 elif roll < 0.9: | 118 elif roll < 0.9: |
| 132 return GetValidServiceAlias() | 119 return GetValidServiceAlias() |
| 133 else: | 120 else: |
| 134 return GetRandomUUID() | 121 return GetRandomUUID() |
| 135 | 122 |
| 136 | 123 |
| 137 def GetRequestDeviceOptions(): | 124 def GetRequestDeviceOptions(): |
| 138 """Returns an object used by navigator.bluetooth.requestDevice.""" | 125 """Returns an object used by navigator.bluetooth.requestDevice.""" |
| 139 # TODO(ortuno): Randomize the members, number of filters, services, etc. | 126 # TODO(ortuno): Randomize the members, number of filters, services, etc. |
| 140 | 127 |
| 141 return '{filters: [{services: [ %s ]}]}' % GetServiceUUID() | 128 return '{filters: [{services: [ %s ]}]}' % GetAdvertisedServiceUUID() |
| 129 |
| 130 |
| 131 def GetBasicBase(): |
| 132 """Returns a string that sets a random fake adapter.""" |
| 133 adapter = _ToJsStr(random.choice(wbt_fakes.ALL_ADAPTERS)) |
| 134 return BASIC_BASE.format(fake_adapter_name=adapter) |
| 135 |
| 136 |
| 137 def GetDeviceDiscoveryBase(): |
| 138 """Generates a string that contains all steps to find a device.""" |
| 139 adapter, services = random.choice(wbt_fakes.ADAPTERS_WITH_DEVICES) |
| 140 return DEVICE_DISCOVERY_BASE.format( |
| 141 fake_adapter_name=_ToJsStr(adapter), |
| 142 service_uuid=_ToJsStr(random.choice(services))) |
| 143 |
| 144 |
| 145 def GetConnectableBase(): |
| 146 """Generates a string that contains all steps to connect to a device. |
| 147 |
| 148 Returns: A string that: |
| 149 1. Sets an adapter to a fake adapter with a connectable device. |
| 150 2. Looks for the connectable device. |
| 151 3. Connects to it. |
| 152 """ |
| 153 adapter, services = random.choice(wbt_fakes.ADAPTERS_WITH_DEVICES) |
| 154 return DEVICE_DISCOVERY_BASE.format( |
| 155 fake_adapter_name=_ToJsStr(adapter), |
| 156 service_uuid=_ToJsStr(random.choice(services))) |
| 157 |
| 158 |
| 159 def GetServiceRetrievedBase(): |
| 160 """Returns a string that contains all steps to retrieve a service. |
| 161 |
| 162 Returns: A string that: |
| 163 1. Sets an adapter to a fake adapter with a connectable device with |
| 164 services. |
| 165 2. Use one of the device's services to look for that device. |
| 166 3. Connects to it. |
| 167 4. Retrieve the device's service used in 2. |
| 168 """ |
| 169 adapter, services = random.choice(wbt_fakes.ADAPTERS_WITH_SERVICES) |
| 170 return SERVICE_RETRIEVED_BASE.format( |
| 171 fake_adapter_name=_ToJsStr(adapter), |
| 172 service_uuid=_ToJsStr(random.choice(services))) |
| OLD | NEW |