xref: /aosp_15_r20/external/cronet/testing/variations/presubmit/find_features.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker# Copyright 2023 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker"""Python module to find feature names in source code.
5*6777b538SAndroid Build Coastguard Worker
6*6777b538SAndroid Build Coastguard WorkerThese functions are declared in a separate module to allow multiprocessing to
7*6777b538SAndroid Build Coastguard Workercorrectly unpickle the called functions again.
8*6777b538SAndroid Build Coastguard Worker"""
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Workerimport glob
11*6777b538SAndroid Build Coastguard Workerimport itertools
12*6777b538SAndroid Build Coastguard Workerimport multiprocessing
13*6777b538SAndroid Build Coastguard Workerimport pathlib
14*6777b538SAndroid Build Coastguard Workerimport re
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard WorkerBASE_FEATURE_PATTERN = br"BASE_FEATURE\((.*?),(.*?),(.*?)\);"
17*6777b538SAndroid Build Coastguard WorkerBASE_FEATURE_RE = re.compile(BASE_FEATURE_PATTERN, flags=re.MULTILINE+re.DOTALL)
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker# Only search these directories for flags. If your flag is outside these root
20*6777b538SAndroid Build Coastguard Worker# directories, then add the directory here.
21*6777b538SAndroid Build Coastguard WorkerDIRECTORIES_TO_SEARCH = [
22*6777b538SAndroid Build Coastguard Worker    "android_webview",
23*6777b538SAndroid Build Coastguard Worker    "apps",
24*6777b538SAndroid Build Coastguard Worker    "ash",
25*6777b538SAndroid Build Coastguard Worker    "base",
26*6777b538SAndroid Build Coastguard Worker    "cc",
27*6777b538SAndroid Build Coastguard Worker    "chrome",
28*6777b538SAndroid Build Coastguard Worker    "chromecast",
29*6777b538SAndroid Build Coastguard Worker    "chromeos",
30*6777b538SAndroid Build Coastguard Worker    "clank",
31*6777b538SAndroid Build Coastguard Worker    "components",
32*6777b538SAndroid Build Coastguard Worker    "content",
33*6777b538SAndroid Build Coastguard Worker    "courgette",
34*6777b538SAndroid Build Coastguard Worker    "crypto",
35*6777b538SAndroid Build Coastguard Worker    "dbus",
36*6777b538SAndroid Build Coastguard Worker    "device",
37*6777b538SAndroid Build Coastguard Worker    "extensions",
38*6777b538SAndroid Build Coastguard Worker    "fuchsia_web",
39*6777b538SAndroid Build Coastguard Worker    "gin",
40*6777b538SAndroid Build Coastguard Worker    "google_apis",
41*6777b538SAndroid Build Coastguard Worker    "google_update",
42*6777b538SAndroid Build Coastguard Worker    "gpu",
43*6777b538SAndroid Build Coastguard Worker    "headless",
44*6777b538SAndroid Build Coastguard Worker    "infra",
45*6777b538SAndroid Build Coastguard Worker    "internal",
46*6777b538SAndroid Build Coastguard Worker    "ios",
47*6777b538SAndroid Build Coastguard Worker    "ipc",
48*6777b538SAndroid Build Coastguard Worker    "media",
49*6777b538SAndroid Build Coastguard Worker    "mojo",
50*6777b538SAndroid Build Coastguard Worker    "native_client",
51*6777b538SAndroid Build Coastguard Worker    "native_client_sdk",
52*6777b538SAndroid Build Coastguard Worker    "net",
53*6777b538SAndroid Build Coastguard Worker    "pdf",
54*6777b538SAndroid Build Coastguard Worker    "ppapi",
55*6777b538SAndroid Build Coastguard Worker    "printing",
56*6777b538SAndroid Build Coastguard Worker    "remoting",
57*6777b538SAndroid Build Coastguard Worker    "rlz",
58*6777b538SAndroid Build Coastguard Worker    "sandbox",
59*6777b538SAndroid Build Coastguard Worker    "services",
60*6777b538SAndroid Build Coastguard Worker    "skia",
61*6777b538SAndroid Build Coastguard Worker    "sql",
62*6777b538SAndroid Build Coastguard Worker    "storage",
63*6777b538SAndroid Build Coastguard Worker    # third_party/blink handled separately in FindDeclaredFeatures
64*6777b538SAndroid Build Coastguard Worker    "ui",
65*6777b538SAndroid Build Coastguard Worker    "url",
66*6777b538SAndroid Build Coastguard Worker    "v8",
67*6777b538SAndroid Build Coastguard Worker    "webkit",
68*6777b538SAndroid Build Coastguard Worker    "weblayer",
69*6777b538SAndroid Build Coastguard Worker]
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Workerdef _FindFeaturesInFile(filepath):
72*6777b538SAndroid Build Coastguard Worker  # Work on bytes to avoid utf-8 decode errors outside feature declarations
73*6777b538SAndroid Build Coastguard Worker  file_contents = pathlib.Path(filepath).read_bytes()
74*6777b538SAndroid Build Coastguard Worker  matches = BASE_FEATURE_RE.finditer(file_contents)
75*6777b538SAndroid Build Coastguard Worker  # Remove whitespace and surrounding " from the second argument
76*6777b538SAndroid Build Coastguard Worker  # which is the feature name.
77*6777b538SAndroid Build Coastguard Worker  return [m.group(2).strip().strip(b'"').decode("utf-8") for m in matches]
78*6777b538SAndroid Build Coastguard Worker
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Workerdef FindDeclaredFeatures(input_api):
81*6777b538SAndroid Build Coastguard Worker  """Finds all declared feature names in the source code.
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker  This function will scan all *.cc and *.mm files and look for features
84*6777b538SAndroid Build Coastguard Worker  defined with the BASE_FEATURE macro. It will extract the feature names.
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker  Args:
87*6777b538SAndroid Build Coastguard Worker    input_api: InputApi instance for opening files
88*6777b538SAndroid Build Coastguard Worker  Returns:
89*6777b538SAndroid Build Coastguard Worker    Set of defined feature names in the source tree.
90*6777b538SAndroid Build Coastguard Worker  """
91*6777b538SAndroid Build Coastguard Worker  # Features are supposed to be defined in .cc files.
92*6777b538SAndroid Build Coastguard Worker  # Iterate over the search folders in the root.
93*6777b538SAndroid Build Coastguard Worker  root = pathlib.Path(input_api.change.RepositoryRoot())
94*6777b538SAndroid Build Coastguard Worker  glob_patterns = [str(p / pathlib.Path("**/*.cc")) for p in root.iterdir() if
95*6777b538SAndroid Build Coastguard Worker        p.is_dir() and p.name in DIRECTORIES_TO_SEARCH]
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker  # blink is the only directory in third_party that should be searched.
98*6777b538SAndroid Build Coastguard Worker  blink_glob = str(root / pathlib.Path("third_party/blink/**/*.cc"))
99*6777b538SAndroid Build Coastguard Worker  glob_patterns.append(blink_glob)
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker  # Additional features for iOS can be found in mm files in the ios directory.
102*6777b538SAndroid Build Coastguard Worker  mm_glob = str(root / pathlib.Path("ios/**/*.mm"))
103*6777b538SAndroid Build Coastguard Worker  glob_patterns.append(mm_glob)
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker  # Create glob iterators that lazily go over the files to search
106*6777b538SAndroid Build Coastguard Worker  glob_iterators = [glob.iglob(pattern, recursive=True) for pattern in
107*6777b538SAndroid Build Coastguard Worker        glob_patterns]
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker  # Limit to 4 processes - the disk accesses becomes a bottleneck with just a
110*6777b538SAndroid Build Coastguard Worker  # few processes, but splitting the searching across multiple CPUs does yield
111*6777b538SAndroid Build Coastguard Worker  # a benefit of a few seconds.
112*6777b538SAndroid Build Coastguard Worker  # The exact batch size does not seem to matter much, as long as it is >> 1.
113*6777b538SAndroid Build Coastguard Worker  pool = multiprocessing.Pool(4)
114*6777b538SAndroid Build Coastguard Worker  found_features = pool.imap_unordered(_FindFeaturesInFile,
115*6777b538SAndroid Build Coastguard Worker                       itertools.chain(*glob_iterators), 1000)
116*6777b538SAndroid Build Coastguard Worker  pool.close()
117*6777b538SAndroid Build Coastguard Worker  pool.join()
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Worker  feature_names = set()
120*6777b538SAndroid Build Coastguard Worker  for feature_list in found_features:
121*6777b538SAndroid Build Coastguard Worker    feature_names.update(feature_list)
122*6777b538SAndroid Build Coastguard Worker  return feature_names
123