Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: build/android/pylib/instrumentation/test_runner.py

Issue 794923003: [Android] Implement instrumentation tests in platform mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 """Class for running instrumentation tests on a single device.""" 5 """Class for running instrumentation tests on a single device."""
6 6
7 import logging 7 import logging
8 import os 8 import os
9 import re 9 import re
10 import sys 10 import sys
11 import time 11 import time
12 12
13 from pylib import constants 13 from pylib import constants
14 from pylib import flag_changer 14 from pylib import flag_changer
15 from pylib import valgrind_tools 15 from pylib import valgrind_tools
16 from pylib.base import base_test_result 16 from pylib.base import base_test_result
17 from pylib.base import base_test_runner 17 from pylib.base import base_test_runner
18 from pylib.device import device_errors 18 from pylib.device import device_errors
19 from pylib.instrumentation import instrumentation_test_instance
19 from pylib.instrumentation import json_perf_parser 20 from pylib.instrumentation import json_perf_parser
20 from pylib.instrumentation import test_result 21 from pylib.instrumentation import test_result
22 from pylib.local.device import local_device_instrumentation_test_run
21 23
22 sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 24 sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib',
23 'common')) 25 'common'))
24 import perf_tests_results_helper # pylint: disable=F0401 26 import perf_tests_results_helper # pylint: disable=F0401
25 27
26 28
27 _PERF_TEST_ANNOTATION = 'PerfTest' 29 _PERF_TEST_ANNOTATION = 'PerfTest'
28 30
29 31
30 class TestRunner(base_test_runner.BaseTestRunner): 32 class TestRunner(base_test_runner.BaseTestRunner):
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 314
313 Returns: 315 Returns:
314 The raw output of am instrument as a list of lines. 316 The raw output of am instrument as a list of lines.
315 """ 317 """
316 extras = self._GetInstrumentationArgs() 318 extras = self._GetInstrumentationArgs()
317 extras['class'] = test 319 extras['class'] = test
318 return self.device.StartInstrumentation( 320 return self.device.StartInstrumentation(
319 '%s/%s' % (self.test_pkg.GetPackageName(), self.options.test_runner), 321 '%s/%s' % (self.test_pkg.GetPackageName(), self.options.test_runner),
320 raw=True, extras=extras, timeout=timeout, retries=0) 322 raw=True, extras=extras, timeout=timeout, retries=0)
321 323
322 @staticmethod
323 def _ParseAmInstrumentRawOutput(raw_output):
324 """Parses the output of an |am instrument -r| call.
325
326 Args:
327 raw_output: the output of an |am instrument -r| call as a list of lines
328 Returns:
329 A 3-tuple containing:
330 - the instrumentation code as an integer
331 - the instrumentation result as a list of lines
332 - the instrumentation statuses received as a list of 2-tuples
333 containing:
334 - the status code as an integer
335 - the bundle dump as a dict mapping string keys to a list of
336 strings, one for each line.
337 """
338 INSTR_STATUS = 'INSTRUMENTATION_STATUS: '
339 INSTR_STATUS_CODE = 'INSTRUMENTATION_STATUS_CODE: '
340 INSTR_RESULT = 'INSTRUMENTATION_RESULT: '
341 INSTR_CODE = 'INSTRUMENTATION_CODE: '
342
343 last = None
344 instr_code = None
345 instr_result = []
346 instr_statuses = []
347 bundle = {}
348 for line in raw_output:
349 if line.startswith(INSTR_STATUS):
350 instr_var = line[len(INSTR_STATUS):]
351 if '=' in instr_var:
352 k, v = instr_var.split('=', 1)
353 bundle[k] = [v]
354 last = INSTR_STATUS
355 last_key = k
356 else:
357 logging.debug('Unknown "%s" line: %s' % (INSTR_STATUS, line))
358
359 elif line.startswith(INSTR_STATUS_CODE):
360 instr_status = line[len(INSTR_STATUS_CODE):]
361 instr_statuses.append((int(instr_status), bundle))
362 bundle = {}
363 last = INSTR_STATUS_CODE
364
365 elif line.startswith(INSTR_RESULT):
366 instr_result.append(line[len(INSTR_RESULT):])
367 last = INSTR_RESULT
368
369 elif line.startswith(INSTR_CODE):
370 instr_code = int(line[len(INSTR_CODE):])
371 last = INSTR_CODE
372
373 elif last == INSTR_STATUS:
374 bundle[last_key].append(line)
375
376 elif last == INSTR_RESULT:
377 instr_result.append(line)
378
379 return (instr_code, instr_result, instr_statuses)
380
381 def _GenerateTestResult(self, test, instr_statuses, start_ms, duration_ms):
382 """Generate the result of |test| from |instr_statuses|.
383
384 Args:
385 instr_statuses: A list of 2-tuples containing:
386 - the status code as an integer
387 - the bundle dump as a dict mapping string keys to string values
388 Note that this is the same as the third item in the 3-tuple returned by
389 |_ParseAmInstrumentRawOutput|.
390 start_ms: The start time of the test in milliseconds.
391 duration_ms: The duration of the test in milliseconds.
392 Returns:
393 An InstrumentationTestResult object.
394 """
395 INSTR_STATUS_CODE_START = 1
396 INSTR_STATUS_CODE_OK = 0
397 INSTR_STATUS_CODE_ERROR = -1
398 INSTR_STATUS_CODE_FAIL = -2
399
400 log = ''
401 result_type = base_test_result.ResultType.UNKNOWN
402
403 for status_code, bundle in instr_statuses:
404 if status_code == INSTR_STATUS_CODE_START:
405 pass
406 elif status_code == INSTR_STATUS_CODE_OK:
407 bundle_test = '%s#%s' % (
408 ''.join(bundle.get('class', [''])),
409 ''.join(bundle.get('test', [''])))
410 skipped = ''.join(bundle.get('test_skipped', ['']))
411
412 if (test == bundle_test and
413 result_type == base_test_result.ResultType.UNKNOWN):
414 result_type = base_test_result.ResultType.PASS
415 elif skipped.lower() in ('true', '1', 'yes'):
416 result_type = base_test_result.ResultType.SKIP
417 logging.info('Skipped ' + test)
418 else:
419 if status_code not in (INSTR_STATUS_CODE_ERROR,
420 INSTR_STATUS_CODE_FAIL):
421 logging.info('Unrecognized status code %d. Handling as an error.',
422 status_code)
423 result_type = base_test_result.ResultType.FAIL
424 if 'stack' in bundle:
425 log = '\n'.join(bundle['stack'])
426 # Dismiss any error dialogs. Limit the number in case we have an error
427 # loop or we are failing to dismiss.
428 for _ in xrange(10):
429 package = self.device.old_interface.DismissCrashDialogIfNeeded()
430 if not package:
431 break
432 # Assume test package convention of ".test" suffix
433 if package in self.test_pkg.GetPackageName():
434 result_type = base_test_result.ResultType.CRASH
435 break
436
437 return test_result.InstrumentationTestResult(
438 test, result_type, start_ms, duration_ms, log=log)
439
440 #override 324 #override
441 def RunTest(self, test): 325 def RunTest(self, test):
442 results = base_test_result.TestRunResults() 326 results = base_test_result.TestRunResults()
443 timeout = (self._GetIndividualTestTimeoutSecs(test) * 327 timeout = (self._GetIndividualTestTimeoutSecs(test) *
444 self._GetIndividualTestTimeoutScale(test) * 328 self._GetIndividualTestTimeoutScale(test) *
445 self.tool.GetTimeoutScale()) 329 self.tool.GetTimeoutScale())
446 if (self.device.build_version_sdk 330 if (self.device.build_version_sdk
447 < constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN): 331 < constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN):
448 timeout *= 10 332 timeout *= 10
449 333
450 start_ms = 0 334 start_ms = 0
451 duration_ms = 0 335 duration_ms = 0
452 try: 336 try:
453 self.TestSetup(test) 337 self.TestSetup(test)
454 338
455 time_ms = lambda: int(time.time() * 1000) 339 time_ms = lambda: int(time.time() * 1000)
456 start_ms = time_ms() 340 start_ms = time_ms()
457 raw_output = self._RunTest(test, timeout) 341 raw_output = self._RunTest(test, timeout)
458 duration_ms = time_ms() - start_ms 342 duration_ms = time_ms() - start_ms
459 343
460 # Parse the test output 344 # Parse the test output
461 _, _, statuses = self._ParseAmInstrumentRawOutput(raw_output) 345 _, _, statuses = (
462 result = self._GenerateTestResult(test, statuses, start_ms, duration_ms) 346 instrumentation_test_instance.ParseAmInstrumentRawOutput(raw_output))
347 result = instrumentation_test_instance.GenerateTestResult(
348 test, statuses, start_ms, duration_ms)
349 if local_device_instrumentation_test_run.DidPackageCrashOnDevice(
350 self.test_pkg.GetPackageName(), self.device):
351 result.SetType(base_test_result.ResultType.CRASH)
463 results.AddResult(result) 352 results.AddResult(result)
464 except device_errors.CommandTimeoutError as e: 353 except device_errors.CommandTimeoutError as e:
465 results.AddResult(test_result.InstrumentationTestResult( 354 results.AddResult(test_result.InstrumentationTestResult(
466 test, base_test_result.ResultType.TIMEOUT, start_ms, duration_ms, 355 test, base_test_result.ResultType.TIMEOUT, start_ms, duration_ms,
467 log=str(e) or 'No information')) 356 log=str(e) or 'No information'))
468 except device_errors.DeviceUnreachableError as e: 357 except device_errors.DeviceUnreachableError as e:
469 results.AddResult(test_result.InstrumentationTestResult( 358 results.AddResult(test_result.InstrumentationTestResult(
470 test, base_test_result.ResultType.CRASH, start_ms, duration_ms, 359 test, base_test_result.ResultType.CRASH, start_ms, duration_ms,
471 log=str(e) or 'No information')) 360 log=str(e) or 'No information'))
472 self.TestTeardown(test, results) 361 self.TestTeardown(test, results)
473 return (results, None if results.DidRunPass() else test) 362 return (results, None if results.DidRunPass() else test)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698