#!/usr/bin/env vpython3 # Copyright (c) 2026 The WebRTC project authors. All Rights Reserved. # # Use of this source code is governed by a BSD-style license # that can be found in the LICENSE file in the root of the source # tree. An additional intellectual property rights grant can be found # in the file PATENTS. All contributing project authors may # be found in the AUTHORS file in the root of the source tree. """Script to validate test registration using GN metadata.""" import argparse import json import os import subprocess import sys def _find_root_path(): root_dir = os.path.dirname(os.path.abspath(__file__)) while os.path.basename(root_dir) not in ('src', 'chromium'): par_dir = os.path.normpath(os.path.join(root_dir, os.pardir)) if par_dir == root_dir: raise RuntimeError('Could not find the repo root.') root_dir = par_dir return root_dir def _dump_dep_file(depfile_path, stamp_path, build_dir, root_dir): build_files = [] for walk_root, _, files in os.walk(root_dir): if any(d in walk_root for d in ['.git', 'out', 'third_party']): continue if 'BUILD.gn' in files: build_files.append( os.path.relpath(os.path.join(walk_root, 'BUILD.gn'), build_dir)) with open(depfile_path, 'w', encoding='utf-8') as depfile: depfile.write(f"{stamp_path}: {' '.join(build_files)}\n") def _all_rtc_cc_tests(build_dir, root_dir): sys.path.append(os.path.join(root_dir, 'build')) import find_depot_tools gn_path = os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py') desc_out = subprocess.check_output( [ sys.executable, gn_path, '--quiet', 'desc', '.', '*', 'metadata', '--format=json' ], cwd=build_dir, stderr=subprocess.STDOUT).decode('utf-8') json_start = desc_out.find('{') if json_start == -1: all_metadata = {} else: all_metadata = json.loads(desc_out[json_start:]) all_tests = set() for label, data in all_metadata.items(): target_metadata = data.get('metadata', {}) if 'rtc_cc_test' in target_metadata: all_tests.add(label) return all_tests def _rtc_cc_tests_in_test_suites(suite_tests_path): with open(suite_tests_path, 'r', encoding='utf-8') as suite_tests_file: suite_tests_metadata = json.load(suite_tests_file) suite_tests = { item['label'] for item in suite_tests_metadata if 'label' in item } return suite_tests def main(): parser = argparse.ArgumentParser() parser.add_argument('--suite-tests', required=True) parser.add_argument('--stamp', required=True) parser.add_argument('--build-dir', default='.') parser.add_argument( '--depfile', help='Optional depfile to write. Used to track dependencies for ' 'the build system.') args = parser.parse_args() build_dir = os.path.abspath(args.build_dir) root_dir = _find_root_path() if args.depfile: _dump_dep_file(args.depfile, args.stamp, build_dir, root_dir) try: all_tests = _all_rtc_cc_tests(build_dir, root_dir) except (subprocess.CalledProcessError, json.JSONDecodeError) as error: print(f"Error querying GN metadata: {error}") return 1 try: suite_tests = _rtc_cc_tests_in_test_suites(args.suite_tests) except (IOError, json.JSONDecodeError) as error: print(f"Error reading suite tests file: {error}") return 1 orphans = all_tests - suite_tests if orphans: print("\nERROR: The following rtc_cc_test targets are reachable from " "the root build but NOT registered in any rtc_test_suite:") for orphan in sorted(list(orphans)): print(f" {orphan}") print( "\nThey will not run on CQ! Please add them to an rtc_test_suite " "in the root BUILD.gn or a relevant sub-directory.\n") return 1 with open(args.stamp, 'w', encoding='utf-8') as stamp_file: stamp_file.write('success') return 0 if __name__ == '__main__': sys.exit(main())