[M120 Migration] Implement ewk_view_is_video_playing api
[platform/framework/web/chromium-efl.git] / build / fuchsia / binary_size_differ.py
1 #!/usr/bin/env vpython3
2 #
3 # Copyright 2021 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 '''Implements Chrome-Fuchsia package binary size differ.'''
7
8 import argparse
9 import json
10 import os
11 import sys
12 import traceback
13
14 from binary_sizes import ReadPackageSizesJson
15 from binary_sizes import PACKAGES_SIZES_FILE
16
17 # Eng is not responsible for changes that cause "reasonable growth" if the
18 # uncompressed binary size does not grow.
19 # First-warning will fail the test if the uncompressed and compressed size
20 # grow, while always-fail will fail the test regardless of uncompressed growth
21 # (solely based on compressed growth).
22 _FIRST_WARNING_DELTA_BYTES = 12 * 1024  # 12 KiB
23 _ALWAYS_FAIL_DELTA_BYTES = 100 * 1024  # 100 KiB
24 _TRYBOT_DOC = 'https://chromium.googlesource.com/chromium/src/+/main/docs/speed/binary_size/fuchsia_binary_size_trybot.md'
25
26 SIZE_FAILURE = 1
27 ROLLER_SIZE_WARNING = 2
28 SUCCESS = 0
29
30
31 def ComputePackageDiffs(before_sizes_file, after_sizes_file, author=None):
32   '''Computes difference between after and before diff, for each package.'''
33   before_sizes = ReadPackageSizesJson(before_sizes_file)
34   after_sizes = ReadPackageSizesJson(after_sizes_file)
35
36   assert before_sizes.keys() == after_sizes.keys(), (
37       'Package files cannot'
38       ' be compared with different packages: '
39       '{} vs {}'.format(before_sizes.keys(), after_sizes.keys()))
40
41   growth = {'compressed': {}, 'uncompressed': {}}
42   status_code = SUCCESS
43   summary = ''
44   for package_name in before_sizes:
45     growth['compressed'][package_name] = (after_sizes[package_name].compressed -
46                                           before_sizes[package_name].compressed)
47     growth['uncompressed'][package_name] = (
48         after_sizes[package_name].uncompressed -
49         before_sizes[package_name].uncompressed)
50     # Developers are only responsible if uncompressed increases.
51     if ((growth['compressed'][package_name] >= _FIRST_WARNING_DELTA_BYTES
52          and growth['uncompressed'][package_name] > 0)
53         # However, if compressed growth is unusually large, fail always.
54         or growth['compressed'][package_name] >= _ALWAYS_FAIL_DELTA_BYTES):
55       if not summary:
56         summary = ('Size check failed! The following package(s) are affected:'
57                    '<br>')
58       status_code = SIZE_FAILURE
59       summary += (('- {} (compressed) grew by {} bytes (uncompressed growth:'
60                    ' {} bytes).<br>').format(
61                        package_name, growth['compressed'][package_name],
62                        growth['uncompressed'][package_name]))
63       summary += ('Note that this bot compares growth against trunk, and is '
64                   'not aware of CL chaining.<br>')
65
66   # Allow rollers to pass even with size increases. See crbug.com/1355914.
67   if author and '-autoroll' in author and status_code == SIZE_FAILURE:
68     summary = summary.replace('Size check failed! ', '')
69     summary = (
70         'The following growth by an autoroller will be ignored:<br><br>' +
71         summary)
72     status_code = ROLLER_SIZE_WARNING
73   growth['status_code'] = status_code
74   summary += ('<br>See the following document for more information about'
75               ' this trybot:<br>{}'.format(_TRYBOT_DOC))
76   growth['summary'] = summary
77
78   # TODO(crbug.com/1266085): Investigate using these fields.
79   growth['archive_filenames'] = []
80   growth['links'] = []
81   return growth
82
83
84 def main():
85   parser = argparse.ArgumentParser()
86   parser.add_argument(
87       '--before-dir',
88       type=os.path.realpath,
89       required=True,
90       help='Location of the build without the patch',
91   )
92   parser.add_argument(
93       '--after-dir',
94       type=os.path.realpath,
95       required=True,
96       help='Location of the build with the patch',
97   )
98   parser.add_argument('--author', help='Author of change')
99   parser.add_argument(
100       '--results-path',
101       type=os.path.realpath,
102       required=True,
103       help='Output path for the trybot result .json file',
104   )
105   parser.add_argument('--verbose',
106                       '-v',
107                       action='store_true',
108                       help='Enable verbose output')
109   args = parser.parse_args()
110
111   if args.verbose:
112     print('Fuchsia binary sizes')
113     print('Working directory', os.getcwd())
114     print('Args:')
115     for var in vars(args):
116       print('  {}: {}'.format(var, getattr(args, var) or ''))
117
118   if not os.path.isdir(args.before_dir) or not os.path.isdir(args.after_dir):
119     raise Exception(
120         'Could not find build output directory "{}" or "{}".'.format(
121             args.before_dir, args.after_dir))
122
123   test_name = 'sizes'
124   before_sizes_file = os.path.join(args.before_dir, test_name,
125                                    PACKAGES_SIZES_FILE)
126   after_sizes_file = os.path.join(args.after_dir, test_name,
127                                   PACKAGES_SIZES_FILE)
128   if not os.path.isfile(before_sizes_file):
129     raise Exception(
130         'Could not find before sizes file: "{}"'.format(before_sizes_file))
131
132   if not os.path.isfile(after_sizes_file):
133     raise Exception(
134         'Could not find after sizes file: "{}"'.format(after_sizes_file))
135
136   test_completed = False
137   try:
138     growth = ComputePackageDiffs(before_sizes_file,
139                                  after_sizes_file,
140                                  author=args.author)
141     test_completed = True
142     with open(args.results_path, 'wt') as results_file:
143       json.dump(growth, results_file)
144   except:
145     _, value, trace = sys.exc_info()
146     traceback.print_tb(trace)
147     print(str(value))
148   finally:
149     return 0 if test_completed else 1
150
151
152 if __name__ == '__main__':
153   sys.exit(main())