summaryrefslogtreecommitdiff
path: root/chromium/build/android/pylib/instrumentation
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/build/android/pylib/instrumentation')
-rw-r--r--chromium/build/android/pylib/instrumentation/instrumentation_parser.py2
-rw-r--r--chromium/build/android/pylib/instrumentation/instrumentation_test_instance.py79
-rwxr-xr-xchromium/build/android/pylib/instrumentation/instrumentation_test_instance_test.py92
-rw-r--r--chromium/build/android/pylib/instrumentation/test_result.py8
4 files changed, 114 insertions, 67 deletions
diff --git a/chromium/build/android/pylib/instrumentation/instrumentation_parser.py b/chromium/build/android/pylib/instrumentation/instrumentation_parser.py
index 8605178924f..d38f6a5551c 100644
--- a/chromium/build/android/pylib/instrumentation/instrumentation_parser.py
+++ b/chromium/build/android/pylib/instrumentation/instrumentation_parser.py
@@ -20,6 +20,8 @@ STATUS_CODE_SKIP = -3
# http://junit.org/junit4/javadoc/4.12/org/junit/AssumptionViolatedException.html
STATUS_CODE_ASSUMPTION_FAILURE = -4
+STATUS_CODE_TEST_DURATION = 1337
+
# http://developer.android.com/reference/android/app/Activity.html
RESULT_CODE_OK = -1
RESULT_CODE_CANCELED = 0
diff --git a/chromium/build/android/pylib/instrumentation/instrumentation_test_instance.py b/chromium/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 3b61977278e..a30334c6d09 100644
--- a/chromium/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/chromium/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -61,6 +61,23 @@ _PARAMETERIZED_COMMAND_LINE_FLAGS_SWITCHES = (
_NATIVE_CRASH_RE = re.compile('(process|native) crash', re.IGNORECASE)
_PICKLE_FORMAT_VERSION = 12
+# The ID of the bundle value Instrumentation uses to report which test index the
+# results are for in a collection of tests. Note that this index is 1-based.
+_BUNDLE_CURRENT_ID = 'current'
+# The ID of the bundle value Instrumentation uses to report the test class.
+_BUNDLE_CLASS_ID = 'class'
+# The ID of the bundle value Instrumentation uses to report the test name.
+_BUNDLE_TEST_ID = 'test'
+# The ID of the bundle value Instrumentation uses to report if a test was
+# skipped.
+_BUNDLE_SKIPPED_ID = 'test_skipped'
+# The ID of the bundle value Instrumentation uses to report the crash stack, if
+# the test crashed.
+_BUNDLE_STACK_ID = 'stack'
+
+# The ID of the bundle value Chrome uses to report the test duration.
+_BUNDLE_DURATION_ID = 'duration_ms'
+
class MissingSizeAnnotationError(test_exception.TestException):
def __init__(self, class_name):
@@ -103,9 +120,8 @@ def ParseAmInstrumentRawOutput(raw_output):
return (code, bundle, statuses)
-def GenerateTestResults(
- result_code, result_bundle, statuses, start_ms, duration_ms, device_abi,
- symbolizer):
+def GenerateTestResults(result_code, result_bundle, statuses, duration_ms,
+ device_abi, symbolizer):
"""Generate test results from |statuses|.
Args:
@@ -116,7 +132,6 @@ def GenerateTestResults(
- the bundle dump as a dict mapping string keys to string values
Note that this is the same as the third item in the 3-tuple returned by
|_ParseAmInstrumentRawOutput|.
- start_ms: The start time of the test in milliseconds.
duration_ms: The duration of the test in milliseconds.
device_abi: The device_abi, which is needed for symbolization.
symbolizer: The symbolizer used to symbolize stack.
@@ -129,10 +144,21 @@ def GenerateTestResults(
results = []
current_result = None
+ cumulative_duration = 0
for status_code, bundle in statuses:
- test_class = bundle.get('class', '')
- test_method = bundle.get('test', '')
+ if status_code == instrumentation_parser.STATUS_CODE_TEST_DURATION:
+ # For the first result, duration will be set below to the difference
+ # between the reported and actual durations to account for overhead like
+ # starting instrumentation.
+ if len(results) > 1:
+ current_duration = int(bundle.get(_BUNDLE_DURATION_ID, duration_ms))
+ current_result.SetDuration(current_duration)
+ cumulative_duration += current_duration
+ continue
+
+ test_class = bundle.get(_BUNDLE_CLASS_ID, '')
+ test_method = bundle.get(_BUNDLE_TEST_ID, '')
if test_class and test_method:
test_name = '%s#%s' % (test_class, test_method)
else:
@@ -142,10 +168,10 @@ def GenerateTestResults(
if current_result:
results.append(current_result)
current_result = test_result.InstrumentationTestResult(
- test_name, base_test_result.ResultType.UNKNOWN, start_ms, duration_ms)
+ test_name, base_test_result.ResultType.UNKNOWN, duration_ms)
else:
if status_code == instrumentation_parser.STATUS_CODE_OK:
- if bundle.get('test_skipped', '').lower() in ('true', '1', 'yes'):
+ if bundle.get(_BUNDLE_SKIPPED_ID, '').lower() in ('true', '1', 'yes'):
current_result.SetType(base_test_result.ResultType.SKIP)
elif current_result.GetType() == base_test_result.ResultType.UNKNOWN:
current_result.SetType(base_test_result.ResultType.PASS)
@@ -159,15 +185,13 @@ def GenerateTestResults(
logging.error('Unrecognized status code %d. Handling as an error.',
status_code)
current_result.SetType(base_test_result.ResultType.FAIL)
- if 'stack' in bundle:
+ if _BUNDLE_STACK_ID in bundle:
if symbolizer and device_abi:
- current_result.SetLog(
- '%s\n%s' % (
- bundle['stack'],
- '\n'.join(symbolizer.ExtractAndResolveNativeStackTraces(
- bundle['stack'], device_abi))))
+ current_result.SetLog('%s\n%s' % (bundle[_BUNDLE_STACK_ID], '\n'.join(
+ symbolizer.ExtractAndResolveNativeStackTraces(
+ bundle[_BUNDLE_STACK_ID], device_abi))))
else:
- current_result.SetLog(bundle['stack'])
+ current_result.SetLog(bundle[_BUNDLE_STACK_ID])
if current_result:
if current_result.GetType() == base_test_result.ResultType.UNKNOWN:
@@ -179,6 +203,9 @@ def GenerateTestResults(
results.append(current_result)
+ if results:
+ results[0].SetDuration(duration_ms - cumulative_duration)
+
return results
@@ -521,6 +548,8 @@ class InstrumentationTestInstance(test_instance.TestInstance):
self._skia_gold_properties = None
self._initializeSkiaGoldAttributes(args)
+ self._wpr_enable_record = args.wpr_enable_record
+
self._external_shard_index = args.test_launcher_shard_index
self._total_external_shards = args.test_launcher_total_shards
@@ -731,7 +760,7 @@ class InstrumentationTestInstance(test_instance.TestInstance):
self._use_webview_provider = args.use_webview_provider
def _initializeSkiaGoldAttributes(self, args):
- self._skia_gold_properties = gold_utils.SkiaGoldProperties(args)
+ self._skia_gold_properties = gold_utils.AndroidSkiaGoldProperties(args)
@property
def additional_apks(self):
@@ -865,6 +894,14 @@ class InstrumentationTestInstance(test_instance.TestInstance):
def wait_for_java_debugger(self):
return self._wait_for_java_debugger
+ @property
+ def wpr_record_mode(self):
+ return self._wpr_enable_record
+
+ @property
+ def wpr_replay_mode(self):
+ return not self._wpr_enable_record
+
#override
def TestType(self):
return 'instrumentation'
@@ -930,7 +967,8 @@ class InstrumentationTestInstance(test_instance.TestInstance):
'class': c['class'],
'method': m['method'],
'annotations': a,
- 'is_junit4': c['superclass'] == 'java.lang.Object'
+ # TODO(https://crbug.com/1084729): Remove is_junit4.
+ 'is_junit4': True
})
return inflated_tests
@@ -1005,11 +1043,10 @@ class InstrumentationTestInstance(test_instance.TestInstance):
return ParseAmInstrumentRawOutput(raw_output)
@staticmethod
- def GenerateTestResults(
- result_code, result_bundle, statuses, start_ms, duration_ms,
- device_abi, symbolizer):
+ def GenerateTestResults(result_code, result_bundle, statuses, duration_ms,
+ device_abi, symbolizer):
return GenerateTestResults(result_code, result_bundle, statuses,
- start_ms, duration_ms, device_abi, symbolizer)
+ duration_ms, device_abi, symbolizer)
#override
def TearDown(self):
diff --git a/chromium/build/android/pylib/instrumentation/instrumentation_test_instance_test.py b/chromium/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
index d3003b8239e..fdb4114a63d 100755
--- a/chromium/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
+++ b/chromium/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
@@ -12,11 +12,9 @@ import tempfile
import unittest
from pylib.base import base_test_result
-from pylib.constants import host_paths
from pylib.instrumentation import instrumentation_test_instance
-with host_paths.SysPath(host_paths.PYMOCK_PATH):
- import mock # pylint: disable=import-error
+import mock # pylint: disable=import-error
_INSTRUMENTATION_TEST_INSTANCE_PATH = (
'pylib.instrumentation.instrumentation_test_instance.%s')
@@ -497,15 +495,17 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
]
expected_tests = [
- {
- 'annotations': {
- 'Feature': {'value': ['Foo']},
- 'MediumTest': None,
+ {
+ 'annotations': {
+ 'Feature': {
+ 'value': ['Foo']
+ },
+ 'MediumTest': None,
+ },
+ 'class': 'org.chromium.test.SampleTest',
+ 'is_junit4': True,
+ 'method': 'testMethod2',
},
- 'class': 'org.chromium.test.SampleTest',
- 'is_junit4': False,
- 'method': 'testMethod2',
- },
]
o._excluded_annotations = [('SmallTest', None)]
@@ -556,16 +556,18 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
]
expected_tests = [
- {
- 'annotations': {
- 'Feature': {'value': ['Foo']},
- 'SmallTest': None,
- 'TestValue': '1',
+ {
+ 'annotations': {
+ 'Feature': {
+ 'value': ['Foo']
+ },
+ 'SmallTest': None,
+ 'TestValue': '1',
+ },
+ 'class': 'org.chromium.test.SampleTest',
+ 'is_junit4': True,
+ 'method': 'testMethod1',
},
- 'class': 'org.chromium.test.SampleTest',
- 'is_junit4': False,
- 'method': 'testMethod1',
- },
]
o._annotations = [('TestValue', '1')]
@@ -724,24 +726,28 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
]
expected_tests = [
- {
- 'annotations': {
- 'Feature': {'value': ['Baz']},
- 'MediumTest': None,
+ {
+ 'annotations': {
+ 'Feature': {
+ 'value': ['Baz']
+ },
+ 'MediumTest': None,
+ },
+ 'class': 'org.chromium.test.SampleTest',
+ 'is_junit4': True,
+ 'method': 'testMethod2',
},
- 'class': 'org.chromium.test.SampleTest',
- 'is_junit4': False,
- 'method': 'testMethod2',
- },
- {
- 'annotations': {
- 'Feature': {'value': ['Bar']},
- 'SmallTest': None,
+ {
+ 'annotations': {
+ 'Feature': {
+ 'value': ['Bar']
+ },
+ 'SmallTest': None,
+ },
+ 'class': 'org.chromium.test.SampleTest2',
+ 'is_junit4': True,
+ 'method': 'testMethod1',
},
- 'class': 'org.chromium.test.SampleTest2',
- 'is_junit4': False,
- 'method': 'testMethod1',
- },
]
o._annotations = [('Feature', 'Bar'), ('Feature', 'Baz')]
@@ -753,7 +759,7 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
def testGenerateTestResults_noStatus(self):
results = instrumentation_test_instance.GenerateTestResults(
- None, None, [], 0, 1000, None, None)
+ None, None, [], 1000, None, None)
self.assertEqual([], results)
def testGenerateTestResults_testPassed(self):
@@ -768,7 +774,7 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
}),
]
results = instrumentation_test_instance.GenerateTestResults(
- None, None, statuses, 0, 1000, None, None)
+ None, None, statuses, 1000, None, None)
self.assertEqual(1, len(results))
self.assertEqual(base_test_result.ResultType.PASS, results[0].GetType())
@@ -789,7 +795,7 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
}),
]
results = instrumentation_test_instance.GenerateTestResults(
- None, None, statuses, 0, 1000, None, None)
+ None, None, statuses, 1000, None, None)
self.assertEqual(1, len(results))
self.assertEqual(base_test_result.ResultType.SKIP, results[0].GetType())
@@ -808,7 +814,7 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
}),
]
results = instrumentation_test_instance.GenerateTestResults(
- None, None, statuses, 0, 1000, None, None)
+ None, None, statuses, 1000, None, None)
self.assertEqual(1, len(results))
self.assertEqual(base_test_result.ResultType.PASS, results[0].GetType())
@@ -824,7 +830,7 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
}),
]
results = instrumentation_test_instance.GenerateTestResults(
- None, None, statuses, 0, 1000, None, None)
+ None, None, statuses, 1000, None, None)
self.assertEqual(1, len(results))
self.assertEqual(base_test_result.ResultType.FAIL, results[0].GetType())
@@ -842,7 +848,7 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
}),
]
results = instrumentation_test_instance.GenerateTestResults(
- None, None, statuses, 0, 1000, None, None)
+ None, None, statuses, 1000, None, None)
self.assertEqual(1, len(results))
self.assertEqual(base_test_result.ResultType.FAIL, results[0].GetType())
self.assertEqual(stacktrace, results[0].GetLog())
@@ -859,7 +865,7 @@ class InstrumentationTestInstanceTest(unittest.TestCase):
}),
]
results = instrumentation_test_instance.GenerateTestResults(
- None, None, statuses, 0, 1000, None, None)
+ None, None, statuses, 1000, None, None)
self.assertEqual(1, len(results))
self.assertEqual(base_test_result.ResultType.SKIP, results[0].GetType())
diff --git a/chromium/build/android/pylib/instrumentation/test_result.py b/chromium/build/android/pylib/instrumentation/test_result.py
index 24e80a8e5fb..a1c7307fce9 100644
--- a/chromium/build/android/pylib/instrumentation/test_result.py
+++ b/chromium/build/android/pylib/instrumentation/test_result.py
@@ -8,13 +8,12 @@ from pylib.base import base_test_result
class InstrumentationTestResult(base_test_result.BaseTestResult):
"""Result information for a single instrumentation test."""
- def __init__(self, full_name, test_type, start_date, dur, log=''):
+ def __init__(self, full_name, test_type, dur, log=''):
"""Construct an InstrumentationTestResult object.
Args:
full_name: Full name of the test.
test_type: Type of the test result as defined in ResultType.
- start_date: Date in milliseconds when the test began running.
dur: Duration of the test run in milliseconds.
log: A string listing any errors.
"""
@@ -27,4 +26,7 @@ class InstrumentationTestResult(base_test_result.BaseTestResult):
else:
self._class_name = full_name
self._test_name = full_name
- self._start_date = start_date
+
+ def SetDuration(self, duration):
+ """Set the test duration."""
+ self._duration = duration