1# Copyright (c) 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Module containing utility functions for reporting results."""
6
7import logging
8import os
9import re
10
11from pylib import constants
12from pylib.utils import flakiness_dashboard_results_uploader
13
14
15def _LogToFile(results, test_type, suite_name):
16  """Log results to local files which can be used for aggregation later."""
17  log_file_path = os.path.join(constants.GetOutDirectory(), 'test_logs')
18  if not os.path.exists(log_file_path):
19    os.mkdir(log_file_path)
20  full_file_name = os.path.join(
21      log_file_path, re.sub('\W', '_', test_type).lower() + '.log')
22  if not os.path.exists(full_file_name):
23    with open(full_file_name, 'w') as log_file:
24      print >> log_file, '\n%s results for %s build %s:' % (
25          test_type, os.environ.get('BUILDBOT_BUILDERNAME'),
26          os.environ.get('BUILDBOT_BUILDNUMBER'))
27    logging.info('Writing results to %s.' % full_file_name)
28
29  logging.info('Writing results to %s.' % full_file_name)
30  with open(full_file_name, 'a') as log_file:
31    shortened_suite_name = suite_name[:25] + (suite_name[25:] and '...')
32    print >> log_file, '%s%s' % (shortened_suite_name.ljust(30),
33                                 results.GetShortForm())
34
35
36def _LogToFlakinessDashboard(results, test_type, test_package,
37                             flakiness_server):
38  """Upload results to the flakiness dashboard"""
39  logging.info('Upload results for test type "%s", test package "%s" to %s' %
40               (test_type, test_package, flakiness_server))
41
42  # TODO(frankf): Enable uploading for gtests.
43  if test_type != 'Instrumentation':
44    logging.warning('Invalid test type.')
45    return
46
47  try:
48    if flakiness_server == constants.UPSTREAM_FLAKINESS_SERVER:
49      assert test_package in ['ContentShellTest',
50                                'ChromeShellTest',
51                              'AndroidWebViewTest']
52      dashboard_test_type = ('%s_instrumentation_tests' %
53                             test_package.lower().rstrip('test'))
54    # Downstream server.
55    else:
56      dashboard_test_type = 'Chromium_Android_Instrumentation'
57
58    flakiness_dashboard_results_uploader.Upload(
59        results, flakiness_server, dashboard_test_type)
60  except Exception as e:
61    logging.error(e)
62
63
64def LogFull(results, test_type, test_package, annotation=None,
65            flakiness_server=None):
66  """Log the tests results for the test suite.
67
68  The results will be logged three different ways:
69    1. Log to stdout.
70    2. Log to local files for aggregating multiple test steps
71       (on buildbots only).
72    3. Log to flakiness dashboard (on buildbots only).
73
74  Args:
75    results: An instance of TestRunResults object.
76    test_type: Type of the test (e.g. 'Instrumentation', 'Unit test', etc.).
77    test_package: Test package name (e.g. 'ipc_tests' for gtests,
78                  'ContentShellTest' for instrumentation tests)
79    annotation: If instrumenation test type, this is a list of annotations
80                (e.g. ['Smoke', 'SmallTest']).
81    flakiness_server: If provider, upload the results to flakiness dashboard
82                      with this URL.
83    """
84  if not results.DidRunPass():
85    logging.critical('*' * 80)
86    logging.critical('Detailed Logs')
87    logging.critical('*' * 80)
88    for line in results.GetLogs().splitlines():
89      logging.critical(line)
90  logging.critical('*' * 80)
91  logging.critical('Summary')
92  logging.critical('*' * 80)
93  for line in results.GetGtestForm().splitlines():
94    logging.critical(line)
95  logging.critical('*' * 80)
96
97  if os.environ.get('BUILDBOT_BUILDERNAME'):
98    # It is possible to have multiple buildbot steps for the same
99    # instrumenation test package using different annotations.
100    if annotation and len(annotation) == 1:
101      suite_name = annotation[0]
102    else:
103      suite_name = test_package
104    _LogToFile(results, test_type, suite_name)
105
106    if flakiness_server:
107      _LogToFlakinessDashboard(results, test_type, test_package,
108                               flakiness_server)
109