1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
#!/usr/bin/env vpython3
# Copyright 2017 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Runs traffic_annotation_auditor on the given change list or all files to make
sure network traffic annoations are syntactically and semantically correct and
all required functions are annotated.
"""
from __future__ import print_function
import os
import argparse
import sys
from annotation_tools import NetworkTrafficAnnotationTools
# If this test starts failing, please set TEST_IS_ENABLED to "False" and file a
# bug to get this reenabled, and cc the people listed in
# //tools/traffic_annotation/OWNERS.
TEST_IS_ENABLED = True
# If this test starts failing due to a critical bug in auditor.py, please set
# USE_PYTHON_AUDITOR to "False" and file a bug (see comment above).
USE_PYTHON_AUDITOR = True
# Threshold for the change list size to trigger full test.
CHANGELIST_SIZE_TO_TRIGGER_FULL_TEST = 100
class NetworkTrafficAnnotationChecker():
EXTENSIONS = ['.cc', '.mm', '.java']
IMPORTANT_FILES = {'annotations.xml', 'grouping.xml', 'safe_list.txt'}
def __init__(self, build_path=None):
"""Initializes a NetworkTrafficAnnotationChecker object.
Args:
build_path: str Absolute or relative path to a fully compiled build
directory. If not specified, the script tries to find it based on
relative position of this file (src/tools/traffic_annotation).
"""
self.tools = NetworkTrafficAnnotationTools(build_path)
def IsImportantFile(self, file_path):
"""Returns true if the given file is an important file.
Importrant files trigger a run on the full Chromium codebase, instead of
only analyzing modified source files."""
return os.path.basename(file_path) in self.IMPORTANT_FILES
def ShouldCheckFile(self, file_path):
"""Returns true if the input file has an extension relevant to network
traffic annotations."""
return os.path.splitext(file_path)[1] in self.EXTENSIONS
def GetFilePaths(self, complete_run, limit):
if complete_run:
return []
# Get list of modified files. If failed, silently ignore as the test is
# run in error resilient mode.
file_paths = self.tools.GetModifiedFiles() or []
important_file_changed = any(
self.IsImportantFile(file_path) for file_path in file_paths)
# If the annotations file has changed, trigger a full test to avoid
# missing a case where the annotations file has changed, but not the
# corresponding file, causing a mismatch that is not detected by just
# checking the changed .cc and .mm files.
if important_file_changed:
return []
file_paths = [
file_path for file_path in file_paths if self.ShouldCheckFile(
file_path)]
if not file_paths:
return None
# If the number of changed files in the CL exceeds a threshold, trigger
# full test to avoid sending very long list of arguments and possible
# failure in argument buffers.
if len(file_paths) > CHANGELIST_SIZE_TO_TRIGGER_FULL_TEST:
file_paths = []
return file_paths
def CheckFiles(self, complete_run, limit, errors_file, use_python_auditor):
"""Passes all given files to traffic_annotation_auditor to be checked for
possible violations of network traffic annotation rules.
Args:
complete_run: bool Flag requesting to run test on all relevant files.
limit: int The upper threshold for number of errors and warnings. Use 0
for unlimited.
errors_file: str Path to a file to write errors to.
use_python_auditor: bool If True, test auditor.py instead of
t_a_auditor.exe.
Returns:
int Exit code of the network traffic annotation auditor.
"""
if not self.tools.CanRunAuditor(use_python_auditor):
print("Network traffic annotation presubmit check was not performed. A "
"compiled build directory and traffic_annotation_auditor binary "
"are required to do it.")
return 0
file_paths = self.GetFilePaths(complete_run, limit)
if file_paths is None:
return 0
args = ["--test-only", "--limit=%i" % limit, "--error-resilient"]
if errors_file:
args += ["--errors-file", errors_file]
args += file_paths
stdout_text, stderr_text, return_code = self.tools.RunAuditor(
args, use_python_auditor)
if stdout_text:
print(stdout_text)
if stderr_text:
print("\n[Runtime Messages]:\n%s" % stderr_text)
return return_code
def main():
if not TEST_IS_ENABLED:
return 0
parser = argparse.ArgumentParser(
description="Network Traffic Annotation Presubmit checker.")
parser.add_argument(
'--build-path',
help='Specifies a compiled build directory, e.g. out/Debug. If not '
'specified, the script tries to guess it. Will not proceed if not '
'found.')
parser.add_argument(
'--limit',
default=5,
type=int,
help='Limit for the maximum number of returned errors and warnings. '
'Default value is 5, use 0 for unlimited.')
parser.add_argument(
'--complete', action='store_true',
help='Run the test on the complete repository. Otherwise only the '
'modified files are tested.')
parser.add_argument('--errors-file',
type=str,
help='Optional path to a JSON output file with errors.')
args = parser.parse_args()
checker = NetworkTrafficAnnotationChecker(args.build_path)
exit_code = checker.CheckFiles(args.complete,
args.limit,
args.errors_file,
use_python_auditor=USE_PYTHON_AUDITOR)
return exit_code
if '__main__' == __name__:
sys.exit(main())
|