File: check_annotations.py

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (167 lines) | stat: -rwxr-xr-x 5,839 bytes parent folder | download | duplicates (6)
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())