phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 1 | #!/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 | |
| 29 | import os |
| 30 | import re |
phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 31 | import time |
| 32 | |
| 33 | import constants |
| 34 | import dashboard_connection |
| 35 | |
| 36 | |
| 37 | class FailedToParseCoverageHtml(Exception): |
| 38 | pass |
| 39 | |
| 40 | |
| 41 | class CouldNotFindCoverageDirectory(Exception): |
| 42 | pass |
| 43 | |
| 44 | |
| 45 | def _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.org | 0f1a96a | 2012-03-01 15:50:30 +0000 | [diff] [blame] | 50 | configurations. We assume here that build numbers keep rising and never |
| 51 | wrap around or anything like that. |
phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 52 | """ |
| 53 | |
phoglund@webrtc.org | 0f1a96a | 2012-03-01 15:50:30 +0000 | [diff] [blame] | 54 | found_build_numbers = [] |
phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 55 | for entry in www_directory_contents: |
phoglund@webrtc.org | 0f1a96a | 2012-03-01 15:50:30 +0000 | [diff] [blame] | 56 | match = re.match('Linux32DBG_(\d+)', entry) |
phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 57 | if match is not None: |
phoglund@webrtc.org | 0f1a96a | 2012-03-01 15:50:30 +0000 | [diff] [blame] | 58 | found_build_numbers.append(int(match.group(1))) |
phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 59 | |
phoglund@webrtc.org | 0f1a96a | 2012-03-01 15:50:30 +0000 | [diff] [blame] | 60 | 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.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 67 | |
| 68 | |
| 69 | def _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 | |
| 87 | def _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.org | 86ce46d | 2012-02-06 10:55:12 +0000 | [diff] [blame] | 94 | dashboard.send_post_request(constants.ADD_COVERAGE_DATA_URL, parameters) |
phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 95 | |
| 96 | |
| 97 | def _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.org | 0f1a96a | 2012-03-01 15:50:30 +0000 | [diff] [blame] | 102 | coverage_www_dir = constants.BUILD_BOT_COVERAGE_WWW_DIRECTORY |
| 103 | www_dir_contents = os.listdir(coverage_www_dir) |
phoglund@webrtc.org | d4f0a0e | 2012-02-01 10:59:23 +0000 | [diff] [blame] | 104 | 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 | |
| 120 | if __name__ == '__main__': |
| 121 | _main() |
| 122 | |