1#!/usr/bin/env python3 2# 3# Copyright 2023 The Chromium Authors 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7import argparse 8import difflib 9import pathlib 10import os 11import sys 12 13REPOSITORY_ROOT = os.path.abspath( 14 os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)) 15 16sys.path.insert(0, os.path.join(REPOSITORY_ROOT, 'build/android/gyp')) 17from util import build_utils # pylint: disable=wrong-import-position 18 19# Set this environment variable in order to regenerate the golden text 20# files. 21_REBASELINE_CRONET_PROGUARD = os.environ.get('REBASELINE_CRONET_PROGUARD', 22 '0') != '0' 23 24 25def _ReadFile(path): 26 """Reads a file as a string""" 27 return pathlib.Path(path).read_text() 28 29 30def _CompareText(generated_text, golden_text, golden_file_path): 31 """ 32 Compares the generated text with the golden text. 33 34 returns a diff that can be applied with `patch` if exists. 35 """ 36 golden_lines = [line.rstrip() for line in golden_text.splitlines()] 37 generated_lines = [line.rstrip() for line in generated_text.splitlines()] 38 if golden_lines == generated_lines: 39 return None 40 41 expected_path = os.path.relpath( 42 golden_file_path, build_utils.DIR_SOURCE_ROOT) 43 44 diff = difflib.unified_diff( 45 golden_lines, 46 generated_lines, 47 fromfile=os.path.join('before', expected_path), 48 tofile=os.path.join('after', expected_path), 49 n=0, 50 lineterm='', 51 ) 52 53 return '\n'.join(diff) 54 55 56def CompareGeneratedWithGolden(generated_file_path, golden_file_path): 57 golden_text = _ReadFile(golden_file_path) 58 generated_text = _ReadFile(generated_file_path) 59 if _REBASELINE_CRONET_PROGUARD: 60 if golden_text != generated_text: 61 print('Updated', golden_file_path) 62 with open(golden_file_path, 'w') as f: 63 f.write(generated_text) 64 return None 65 66 if golden_text is None: 67 print(f'Golden file does not exist: {golden_file_path}') 68 69 return _CompareText(generated_text, golden_text, golden_file_path) 70 71 72def main(): 73 parser = argparse.ArgumentParser() 74 parser.add_argument('--input_generated_file', 75 type=str, 76 help="Path to the generated file.") 77 parser.add_argument('--input_golden_file', 78 type=str, 79 help='Path to the input golden file.') 80 parser.add_argument('--stamp', type=str, help='Path to touch on success') 81 args = parser.parse_args() 82 text_diff = CompareGeneratedWithGolden(args.input_generated_file, 83 args.input_golden_file) 84 if text_diff: 85 86 print(f""" 87Cronet Proguard golden test failed. To generate it: 88####################################################### 89# # 90# Run the command below to generate the file # 91# # 92####################################################### 93 94########### START ########### 95patch -p1 << 'END_DIFF' 96{text_diff} 97END_DIFF 98############ END ############ 99 100If you wish to build the action locally in generation mode, See the instructions below: 101##################################################################### 102# # 103# Run the command below to re-run the action in generation mode # 104# # 105##################################################################### 106./components/cronet/tools/cr_cronet.py -d out/proguard_config gn && \ 107REBASELINE_CRONET_PROGUARD=1 autoninja -C out/proguard_config \ 108cronet_combined_proguard_flags_golden_test 109 110This will generate a GN output directory with the appropriate GN\ 111flags to run the golden_test in generation mode rather than verification mode. 112""") 113 sys.exit(-1) 114 else: 115 build_utils.Touch(args.stamp) 116 117if __name__ == '__main__': 118 sys.exit(main()) 119