blob: 9d4ed6184dea31ec24393cb2b571c555e9e727ac [file] [log] [blame]
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +00001#!/usr/bin/env python
2#-*- coding: utf-8 -*-
3# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
4#
5# Use of this source code is governed by a BSD-style license
6# that can be found in the LICENSE file in the root of the source
7# tree. An additional intellectual property rights grant can be found
8# in the file PATENTS. All contributing project authors may
9# be found in the AUTHORS file in the root of the source tree.
10
11"""This script grabs and reports coverage information.
12
13 It grabs coverage information from the latest Linux 32-bit build and
14 pushes it to the coverage tracker, enabling us to track code coverage
15 over time. This script is intended to run on the 32-bit Linux slave.
16
17 This script requires an access.token file in the current directory, as
18 generated by the request_oauth_permission.py script. It also expects a file
19 customer.secret with a single line containing the customer secret. The
20 customer secret is an OAuth concept and is received when one registers the
21 application with the App Engine running the dashboard.
22
23 The script assumes that all coverage data is stored under
24 /home/<build bot user>/www.
25"""
26
27__author__ = 'phoglund@webrtc.org (Patrik Höglund)'
28
29import os
30import re
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +000031import time
32
33import constants
34import dashboard_connection
35
36
37class FailedToParseCoverageHtml(Exception):
38 pass
39
40
41class CouldNotFindCoverageDirectory(Exception):
42 pass
43
44
45def _find_latest_32bit_debug_build(www_directory_contents, coverage_www_dir):
46 """Finds the latest 32-bit coverage directory in the directory listing.
47
48 Coverage directories have the form Linux32bitDBG_<number>. There may be
49 other directories in the list though, for instance for other build
phoglund@webrtc.org0f1a96a2012-03-01 15:50:30 +000050 configurations. We assume here that build numbers keep rising and never
51 wrap around or anything like that.
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +000052 """
53
phoglund@webrtc.org0f1a96a2012-03-01 15:50:30 +000054 found_build_numbers = []
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +000055 for entry in www_directory_contents:
phoglund@webrtc.org0f1a96a2012-03-01 15:50:30 +000056 match = re.match('Linux32DBG_(\d+)', entry)
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +000057 if match is not None:
phoglund@webrtc.org0f1a96a2012-03-01 15:50:30 +000058 found_build_numbers.append(int(match.group(1)))
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +000059
phoglund@webrtc.org0f1a96a2012-03-01 15:50:30 +000060 if not found_build_numbers:
61 raise CouldNotFindCoverageDirectory('Error: Found no 32-bit '
62 'debug build in directory %s.' %
63 coverage_www_dir)
64
65 most_recent = max(found_build_numbers)
66 return 'Linux32DBG_' + str(most_recent)
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +000067
68
69def _grab_coverage_percentage(label, index_html_contents):
70 """Extracts coverage from a LCOV coverage report.
71
72 Grabs coverage by assuming that the label in the coverage HTML report
73 is close to the actual number and that the number is followed by a space
74 and a percentage sign.
75 """
76 match = re.search('<td[^>]*>' + label + '</td>.*?(\d+\.\d) %',
77 index_html_contents, re.DOTALL)
78 if match is None:
79 raise FailedToParseCoverageHtml('Missing coverage at label "%s".' % label)
80
81 try:
82 return float(match.group(1))
83 except ValueError:
84 raise FailedToParseCoverageHtml('%s is not a float.' % match.group(1))
85
86
87def _report_coverage_to_dashboard(dashboard, now, line_coverage,
88 function_coverage):
89 parameters = {'date': '%d' % now,
90 'line_coverage': '%f' % line_coverage,
91 'function_coverage': '%f' % function_coverage
92 }
93
phoglund@webrtc.org86ce46d2012-02-06 10:55:12 +000094 dashboard.send_post_request(constants.ADD_COVERAGE_DATA_URL, parameters)
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +000095
96
97def _main():
98 dashboard = dashboard_connection.DashboardConnection(constants.CONSUMER_KEY)
99 dashboard.read_required_files(constants.CONSUMER_SECRET_FILE,
100 constants.ACCESS_TOKEN_FILE)
101
phoglund@webrtc.org0f1a96a2012-03-01 15:50:30 +0000102 coverage_www_dir = constants.BUILD_BOT_COVERAGE_WWW_DIRECTORY
103 www_dir_contents = os.listdir(coverage_www_dir)
phoglund@webrtc.orgd4f0a0e2012-02-01 10:59:23 +0000104 latest_build_directory = _find_latest_32bit_debug_build(www_dir_contents,
105 coverage_www_dir)
106
107 index_html_path = os.path.join(coverage_www_dir, latest_build_directory,
108 'index.html')
109 index_html_file = open(index_html_path)
110 whole_file = index_html_file.read()
111
112 line_coverage = _grab_coverage_percentage('Lines:', whole_file)
113 function_coverage = _grab_coverage_percentage('Functions:', whole_file)
114 now = int(time.time())
115
116 _report_coverage_to_dashboard(dashboard, now, line_coverage,
117 function_coverage)
118
119
120if __name__ == '__main__':
121 _main()
122