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