OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 """Base class for linker-specific test cases. | 5 """Base class for linker-specific test cases. |
6 | 6 |
7 The custom dynamic linker can only be tested through a custom test case | 7 The custom dynamic linker can only be tested through a custom test case |
8 for various technical reasons: | 8 for various technical reasons: |
9 | 9 |
10 - It's an 'invisible feature', i.e. it doesn't expose a new API or | 10 - It's an 'invisible feature', i.e. it doesn't expose a new API or |
(...skipping 19 matching lines...) Expand all Loading... |
30 To build and run the linker tests, do the following: | 30 To build and run the linker tests, do the following: |
31 | 31 |
32 ninja -C out/Debug content_linker_test_apk | 32 ninja -C out/Debug content_linker_test_apk |
33 build/android/test_runner.py linker | 33 build/android/test_runner.py linker |
34 | 34 |
35 """ | 35 """ |
36 | 36 |
37 import logging | 37 import logging |
38 import os | 38 import os |
39 import re | 39 import re |
40 import StringIO | |
41 import subprocess | |
42 import tempfile | |
43 import time | 40 import time |
44 | 41 |
45 from pylib import constants | 42 from pylib import constants |
46 from pylib import android_commands | 43 from pylib import android_commands |
47 from pylib import flag_changer | |
48 from pylib.base import base_test_result | 44 from pylib.base import base_test_result |
49 | 45 |
50 ResultType = base_test_result.ResultType | 46 ResultType = base_test_result.ResultType |
51 | 47 |
52 _PACKAGE_NAME='org.chromium.content_linker_test_apk' | 48 _PACKAGE_NAME = 'org.chromium.content_linker_test_apk' |
53 _ACTIVITY_NAME='.ContentLinkerTestActivity' | 49 _ACTIVITY_NAME = '.ContentLinkerTestActivity' |
54 _COMMAND_LINE_FILE='/data/local/tmp/content-linker-test-command-line' | 50 _COMMAND_LINE_FILE = '/data/local/tmp/content-linker-test-command-line' |
55 | 51 |
56 # Path to the Linker.java source file. | 52 # Path to the Linker.java source file. |
57 _LINKER_JAVA_SOURCE_PATH = \ | 53 _LINKER_JAVA_SOURCE_PATH = ( |
58 'content/public/android/java/src/org/chromium/content/app/Linker.java' | 54 'content/public/android/java/src/org/chromium/content/app/Linker.java') |
59 | 55 |
60 # A regular expression used to extract the browser shared RELRO configuration | 56 # A regular expression used to extract the browser shared RELRO configuration |
61 # from the Java source file above. | 57 # from the Java source file above. |
62 _RE_LINKER_BROWSER_CONFIG = \ | 58 _RE_LINKER_BROWSER_CONFIG = re.compile( |
63 re.compile(r'.*BROWSER_SHARED_RELRO_CONFIG\s+=\s+' + \ | 59 r'.*BROWSER_SHARED_RELRO_CONFIG\s+=\s+' + |
64 'BROWSER_SHARED_RELRO_CONFIG_(\S+)\s*;.*', | 60 'BROWSER_SHARED_RELRO_CONFIG_(\S+)\s*;.*', |
65 re.MULTILINE | re.DOTALL) | 61 re.MULTILINE | re.DOTALL) |
66 | 62 |
67 # Logcat filters used during each test. Only the 'chromium' one is really | 63 # Logcat filters used during each test. Only the 'chromium' one is really |
68 # needed, but the logs are added to the TestResult in case of error, and | 64 # needed, but the logs are added to the TestResult in case of error, and |
69 # it is handy to have the 'content_android_linker' ones as well when | 65 # it is handy to have the 'content_android_linker' ones as well when |
70 # troubleshooting. | 66 # troubleshooting. |
71 _LOGCAT_FILTERS = [ '*:s', 'chromium:v', 'content_android_linker:v' ] | 67 _LOGCAT_FILTERS = [ '*:s', 'chromium:v', 'content_android_linker:v' ] |
72 #_LOGCAT_FILTERS = [ '*:v' ] ## DEBUG | 68 #_LOGCAT_FILTERS = [ '*:v' ] ## DEBUG |
73 | 69 |
74 # Regular expression used to match status lines in logcat. | 70 # Regular expression used to match status lines in logcat. |
75 re_status_line = re.compile(r'(BROWSER|RENDERER)_LINKER_TEST: (FAIL|SUCCESS)') | 71 re_status_line = re.compile(r'(BROWSER|RENDERER)_LINKER_TEST: (FAIL|SUCCESS)') |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 else: | 139 else: |
144 assert False, 'Invalid process type ' + process_type | 140 assert False, 'Invalid process type ' + process_type |
145 | 141 |
146 if browser_found and renderer_found: | 142 if browser_found and renderer_found: |
147 return (True, browser_success, renderer_success) | 143 return (True, browser_success, renderer_success) |
148 | 144 |
149 # Didn't find anything. | 145 # Didn't find anything. |
150 return (False, None, None) | 146 return (False, None, None) |
151 | 147 |
152 | 148 |
153 def _WaitForLinkerTestStatus(adb, timeout): | 149 def _WaitForLinkerTestStatus(_adb, _timeout): |
154 """Wait up to |timeout| seconds until the full linker test status lines appear | 150 """Wait up to |timeout| seconds until the full linker test status lines appear |
155 in the logcat being recorded with |adb|. | 151 in the logcat being recorded with |adb|. |
156 Args: | 152 Args: |
157 adb: An AndroidCommands instance. This assumes adb.StartRecordingLogcat() | 153 adb: An AndroidCommands instance. This assumes adb.StartRecordingLogcat() |
158 was called previously. | 154 was called previously. |
159 timeout: Timeout in seconds. | 155 timeout: Timeout in seconds. |
160 Returns: | 156 Returns: |
161 ResultType.TIMEOUT in case of timeout, ResulType.PASS if both status lines | 157 ResultType.TIMEOUT in case of timeout, ResulType.PASS if both status lines |
162 report 'SUCCESS', or ResulType.FAIL otherwise. | 158 report 'SUCCESS', or ResulType.FAIL otherwise. |
163 """ | 159 """ |
| 160 pass |
164 | 161 |
165 | 162 |
166 def _StartActivityAndWaitForLinkerTestStatus(adb, timeout): | 163 def _StartActivityAndWaitForLinkerTestStatus(adb, timeout): |
167 """Force-start an activity and wait up to |timeout| seconds until the full | 164 """Force-start an activity and wait up to |timeout| seconds until the full |
168 linker test status lines appear in the logcat, recorded through |adb|. | 165 linker test status lines appear in the logcat, recorded through |adb|. |
169 Args: | 166 Args: |
170 adb: An AndroidCommands instance. | 167 adb: An AndroidCommands instance. |
171 timeout: Timeout in seconds | 168 timeout: Timeout in seconds |
172 Returns: | 169 Returns: |
173 A (status, logs) tuple, where status is a ResultType constant, and logs | 170 A (status, logs) tuple, where status is a ResultType constant, and logs |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 for lib_map in lib_map_list: | 266 for lib_map in lib_map_list: |
270 for lib_name, lib_address in lib_map.iteritems(): | 267 for lib_name, lib_address in lib_map.iteritems(): |
271 if lib_name not in lib_addr_map: | 268 if lib_name not in lib_addr_map: |
272 lib_addr_map[lib_name] = AddressList() | 269 lib_addr_map[lib_name] = AddressList() |
273 lib_addr_map[lib_name].append(lib_address) | 270 lib_addr_map[lib_name].append(lib_address) |
274 | 271 |
275 logging.info('%s library load map: %s', process_type, lib_addr_map) | 272 logging.info('%s library load map: %s', process_type, lib_addr_map) |
276 | 273 |
277 # For each library, check the randomness of its load addresses. | 274 # For each library, check the randomness of its load addresses. |
278 bad_libs = {} | 275 bad_libs = {} |
279 success = True | |
280 for lib_name, lib_address_list in lib_addr_map.iteritems(): | 276 for lib_name, lib_address_list in lib_addr_map.iteritems(): |
281 # If all addresses are different, skip to next item. | 277 # If all addresses are different, skip to next item. |
282 lib_address_set = set(lib_address_list) | 278 lib_address_set = set(lib_address_list) |
283 # Consider that if there is more than one pair of identical addresses in | 279 # Consider that if there is more than one pair of identical addresses in |
284 # the list, then randomization is broken. | 280 # the list, then randomization is broken. |
285 if len(lib_address_set) < len(lib_address_list) - 1: | 281 if len(lib_address_set) < len(lib_address_list) - 1: |
286 bad_libs[lib_name] = lib_address_list | 282 bad_libs[lib_name] = lib_address_list |
287 | 283 |
288 | 284 |
289 if bad_libs: | 285 if bad_libs: |
290 return False, '%s libraries failed randomization: %s' % \ | 286 return False, '%s libraries failed randomization: %s' % \ |
291 (process_type, bad_libs) | 287 (process_type, bad_libs) |
292 | 288 |
293 return True, '%s libraries properly randomized: %s' % \ | 289 return True, '%s libraries properly randomized: %s' % \ |
294 (process_type, lib_addr_map) | 290 (process_type, lib_addr_map) |
295 | 291 |
296 | 292 |
297 class LinkerTestCaseBase(object): | 293 class LinkerTestCaseBase(object): |
298 """Base class for linker test cases.""" | 294 """Base class for linker test cases.""" |
299 | 295 |
300 def __init__(self, is_low_memory=False): | 296 def __init__(self, is_low_memory=False): |
301 """Create a test case. | 297 """Create a test case. |
302 Args: | 298 Args: |
303 is_low_memory: True to simulate a low-memory device, False otherwise. | 299 is_low_memory: True to simulate a low-memory device, False otherwise. |
304 """ | 300 """ |
305 self.is_low_memory = is_low_memory | 301 self.is_low_memory = is_low_memory |
306 if is_low_memory: | 302 if is_low_memory: |
307 test_suffix = 'ForLowMemoryDevice' | 303 test_suffix = 'ForLowMemoryDevice' |
308 else: | 304 else: |
309 test_suffix = 'ForRegularDevice' | 305 test_suffix = 'ForRegularDevice' |
310 class_name = self.__class__.__name__ | 306 class_name = self.__class__.__name__ |
311 self.qualified_name = '%s.%s' % (class_name, test_suffix) | 307 self.qualified_name = '%s.%s' % (class_name, test_suffix) |
312 self.tagged_name = self.qualified_name | 308 self.tagged_name = self.qualified_name |
313 | 309 |
314 def _RunTest(self, adb): | 310 def _RunTest(self, _adb): |
315 """Run the test, must be overriden. | 311 """Run the test, must be overriden. |
316 Args: | 312 Args: |
317 adb: An AndroidCommands instance to the device. | 313 _adb: An AndroidCommands instance to the device. |
318 Returns: | 314 Returns: |
319 A (status, log) tuple, where <status> is a ResultType constant, and <log> | 315 A (status, log) tuple, where <status> is a ResultType constant, and <log> |
320 is the logcat output captured during the test in case of error, or None | 316 is the logcat output captured during the test in case of error, or None |
321 in case of success. | 317 in case of success. |
322 """ | 318 """ |
323 return ResultType.FAIL, 'Unimplemented _RunTest() method!' | 319 return ResultType.FAIL, 'Unimplemented _RunTest() method!' |
324 | 320 |
325 def Run(self, device): | 321 def Run(self, device): |
326 """Run the test on a given device. | 322 """Run the test on a given device. |
327 Args: | 323 Args: |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 In theory, two successive runs could (very rarely) use the same load | 488 In theory, two successive runs could (very rarely) use the same load |
493 address, so loop 5 times and compare the values there. It is assumed | 489 address, so loop 5 times and compare the values there. It is assumed |
494 that if there are more than one pair of identical addresses, then the | 490 that if there are more than one pair of identical addresses, then the |
495 load addresses are not random enough for this test. | 491 load addresses are not random enough for this test. |
496 """ | 492 """ |
497 def _RunTest(self, adb): | 493 def _RunTest(self, adb): |
498 max_loops = 5 | 494 max_loops = 5 |
499 browser_lib_map_list = [] | 495 browser_lib_map_list = [] |
500 renderer_lib_map_list = [] | 496 renderer_lib_map_list = [] |
501 logs_list = [] | 497 logs_list = [] |
502 for loop in range(max_loops): | 498 for _loop in range(max_loops): |
503 # Start the activity. | 499 # Start the activity. |
504 result, logs = _StartActivityAndWaitForLinkerTestStatus(adb, timeout=30) | 500 result, logs = _StartActivityAndWaitForLinkerTestStatus(adb, timeout=30) |
505 if result == ResultType.TIMEOUT: | 501 if result == ResultType.TIMEOUT: |
506 # Something bad happened. Return immediately. | 502 # Something bad happened. Return immediately. |
507 return result, logs | 503 return result, logs |
508 | 504 |
509 # Collect library addresses. | 505 # Collect library addresses. |
510 browser_libs, renderer_libs = _ExtractLibraryLoadAddressesFromLogcat(logs) | 506 browser_libs, renderer_libs = _ExtractLibraryLoadAddressesFromLogcat(logs) |
511 browser_lib_map_list.append(browser_libs) | 507 browser_lib_map_list.append(browser_libs) |
512 renderer_lib_map_list.append(renderer_libs) | 508 renderer_lib_map_list.append(renderer_libs) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 # Note that this behaviour doesn't seem to happen when starting an | 543 # Note that this behaviour doesn't seem to happen when starting an |
548 # application 'normally', i.e. when using the application launcher to | 544 # application 'normally', i.e. when using the application launcher to |
549 # start the activity. | 545 # start the activity. |
550 logging.info('Ignoring system\'s low randomization of browser libraries' + | 546 logging.info('Ignoring system\'s low randomization of browser libraries' + |
551 ' for regular devices') | 547 ' for regular devices') |
552 | 548 |
553 if not renderer_status: | 549 if not renderer_status: |
554 return ResultType.FAIL, renderer_logs | 550 return ResultType.FAIL, renderer_logs |
555 | 551 |
556 return ResultType.PASS, logs | 552 return ResultType.PASS, logs |
OLD | NEW |