Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Runs delta test on two Predator revisions.""" | 5 """Runs delta test on two Predator revisions.""" |
| 6 | 6 |
| 7 import argparse | 7 import argparse |
| 8 from datetime import date | 8 from datetime import date |
| 9 from datetime import timedelta | 9 from datetime import timedelta |
| 10 import logging | 10 import logging |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 | 21 |
| 22 from crash_queries.delta_test import delta_test | 22 from crash_queries.delta_test import delta_test |
| 23 from crash_queries.delta_test import delta_util | 23 from crash_queries.delta_test import delta_util |
| 24 | 24 |
| 25 _TODAY = date.today().strftime('%Y-%m-%d') | 25 _TODAY = date.today().strftime('%Y-%m-%d') |
| 26 _A_YEAR_AGO = (date.today() - timedelta(days=365)).strftime('%Y-%m-%d') | 26 _A_YEAR_AGO = (date.today() - timedelta(days=365)).strftime('%Y-%m-%d') |
| 27 | 27 |
| 28 # App Engine APIs will fail if batch size is more than 1000. | 28 # App Engine APIs will fail if batch size is more than 1000. |
| 29 _MAX_BATCH_SIZE = 1000 | 29 _MAX_BATCH_SIZE = 1000 |
| 30 _DEFAULT_BATCH_SIZE = _MAX_BATCH_SIZE | 30 _DEFAULT_BATCH_SIZE = _MAX_BATCH_SIZE |
| 31 _DEFAULT_MAX_N = 100 | |
| 31 | 32 |
| 32 DELTA_RESULTS_DIRECTORY = os.path.join(os.path.dirname(__file__), | 33 DELTA_RESULTS_DIRECTORY = os.path.join(os.path.dirname(__file__), |
| 33 'delta_results') | 34 'delta_results') |
| 34 CHROMIUM_REPO = 'https://chromium.googlesource.com/chromium/src' | 35 CHROMIUM_REPO = 'https://chromium.googlesource.com/chromium/src' |
| 35 | 36 |
| 36 | 37 |
| 38 def GenerateDeltaResultPath(directory, git_hash1, git_hash2, | |
| 39 since_date, until_date, max_n): | |
| 40 """Returns the file path of delta result.""" | |
| 41 delta_result_prefix = '%s_%s_%s..%s_max_%d.delta' % ( | |
| 42 git_hash1[:7], git_hash2[:7], since_date, until_date, max_n) | |
| 43 | |
| 44 return os.path.join(directory, delta_result_prefix) | |
| 45 | |
| 46 | |
| 37 def RunDeltaTest(): | 47 def RunDeltaTest(): |
| 38 """Runs delta testing between two different Predator revisions.""" | 48 """Runs delta testing between two different Predator revisions.""" |
| 39 argparser = argparse.ArgumentParser( | 49 argparser = argparse.ArgumentParser( |
| 40 description=('Delta test is a script to report the differences between ' | 50 description=('Delta test is a script to report the differences between ' |
| 41 'analysis results of two local repo revisions. Local git ' | 51 'analysis results of two local repo revisions. Local git ' |
| 42 'checkouts are used instead of Gitile to avoid quota ' | 52 'checkouts are used instead of Gitile to avoid quota ' |
| 43 'issue.\nNOTE, since the delta test needs to switch on ' | 53 'issue.\nNOTE, since the delta test needs to switch on ' |
| 44 'different revisions of local repo, please commit all local ' | 54 'different revisions of local repo, please commit all local ' |
| 45 'changes before running the script, and do not make any ' | 55 'changes before running the script, and do not make any ' |
| 46 'new changes while running it.')) | 56 'new changes while running it.')) |
| 47 | 57 |
| 48 argparser.add_argument( | 58 argparser.add_argument( |
| 49 '--revisions', | 59 '--revisions', |
| 50 '-r', | 60 '-r', |
| 51 nargs='+', | 61 nargs='+', |
| 52 default=['HEAD^', 'HEAD'], | 62 default=['HEAD^', 'HEAD'], |
| 53 help=('The Predator revisions to be compared. It can take ' | 63 help=('The Predator revisions to be compared. It can take ' |
| 54 'one or two revisions seperated by empty spaces.\n' | 64 'one or two revisions seperated by empty spaces. N.B. The revision ' |
| 65 'can be any format that git can recognize, for example, it can be ' | |
| 66 'either "97312dbc1" or "HEAD~5"\n' | |
| 55 '(1) -r rev1 rev2: compare rev1 and rev2\n' | 67 '(1) -r rev1 rev2: compare rev1 and rev2\n' |
| 56 '(2) -r rev: compare rev and current HEAD\n' | 68 '(2) -r rev: compare rev and current HEAD\n' |
| 57 '(3) no revisions provided, default to compare HEAD^ and HEAD')) | 69 '(3) no revisions provided, default to compare HEAD^ and HEAD')) |
| 58 | 70 |
| 59 argparser.add_argument( | 71 argparser.add_argument( |
| 60 '--client', | 72 '--client', |
| 61 '-c', | 73 '-c', |
| 62 default='fracas', | 74 default='fracas', |
| 63 help=('Type of client data the delta test is running on, ' | 75 help=('Type of client data the delta test is running on, ' |
| 64 'possible values are: fracas, cracas, clusterfuzz. ' | 76 'possible values are: fracas, cracas, clusterfuzz. ' |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 94 argparser.add_argument( | 106 argparser.add_argument( |
| 95 '--batch', | 107 '--batch', |
| 96 '-b', | 108 '-b', |
| 97 type=int, | 109 type=int, |
| 98 default=_DEFAULT_BATCH_SIZE, | 110 default=_DEFAULT_BATCH_SIZE, |
| 99 help=('The size of batch that can be processed at one time.\n' | 111 help=('The size of batch that can be processed at one time.\n' |
| 100 'NOTE, the batch size cannot be greater than 1000, or app engine ' | 112 'NOTE, the batch size cannot be greater than 1000, or app engine ' |
| 101 'APIs would fail, defaults to 1000.')) | 113 'APIs would fail, defaults to 1000.')) |
| 102 | 114 |
| 103 argparser.add_argument( | 115 argparser.add_argument( |
| 116 '--max', | |
| 117 '-m', | |
| 118 type=int, | |
| 119 default=_DEFAULT_MAX_N, | |
| 120 help='The maximum number of crashes we want to check, defaults to 100.') | |
| 121 | |
| 122 argparser.add_argument( | |
| 104 '--verbose', | 123 '--verbose', |
| 105 '-v', | 124 '-v', |
| 106 action='store_true', | 125 action='store_true', |
| 107 default=False, | 126 default=False, |
| 108 help='Print Predator results. Defaults to False.') | 127 help='Print Predator results. Defaults to False.') |
| 109 | 128 |
| 110 args = argparser.parse_args() | 129 args = argparser.parse_args() |
| 111 | 130 |
| 112 # If in verbose mode, prints debug information. | 131 # If in verbose mode, prints debug information. |
| 113 if args.verbose: | 132 if args.verbose: |
| 114 logging.basicConfig(level=logging.DEBUG) | 133 logging.basicConfig(level=logging.DEBUG) |
| 115 else: | 134 else: |
| 116 logging.basicConfig(level=logging.INFO) | 135 logging.basicConfig(level=logging.INFO) |
| 117 | 136 |
| 118 if len(args.revisions) > 2: | 137 if len(args.revisions) > 2: |
| 119 logging.error('Only support delta test between 2 revisions.') | 138 logging.error('Only support delta test between 2 revisions.') |
| 120 sys.exit(1) | 139 sys.exit(1) |
| 121 | 140 |
| 122 if args.batch > _MAX_BATCH_SIZE: | 141 if args.batch > _MAX_BATCH_SIZE: |
| 123 logging.error('Batch size cannot be greater than %s, or app engine APIs ' | 142 logging.error('Batch size cannot be greater than %s, or app engine APIs ' |
| 124 'would fail.', _MAX_BATCH_SIZE) | 143 'would fail.', _MAX_BATCH_SIZE) |
| 125 sys.exit(1) | 144 sys.exit(1) |
| 126 | 145 |
| 146 args.batch = args.max if args.max < args.batch else args.batch | |
|
lijeffrey
2017/01/24 02:22:49
how about
args.batch = min(args.max, args.batch)?
Sharu Jiang
2017/01/25 19:17:29
Done.
| |
| 147 | |
| 127 # If only one revision provided, default the rev2 to HEAD. | 148 # If only one revision provided, default the rev2 to HEAD. |
| 128 if len(args.revisions) == 1: | 149 if len(args.revisions) == 1: |
| 129 args.revisions.append('HEAD') | 150 args.revisions.append('HEAD') |
| 130 | 151 |
| 131 git_hash1 = delta_util.ParseGitHash(args.revisions[0]) | 152 git_hash1 = delta_util.ParseGitHash(args.revisions[0]) |
| 132 git_hash2 = delta_util.ParseGitHash(args.revisions[1]) | 153 git_hash2 = delta_util.ParseGitHash(args.revisions[1]) |
| 133 | 154 delta_path = GenerateDeltaResultPath(DELTA_RESULTS_DIRECTORY, |
| 134 delta_result_prefix = '%s_%s_%s..%s.delta' % (git_hash1[:7], git_hash2[:7], | 155 git_hash1, git_hash1, |
| 135 args.since, args.until) | 156 args.since, args.until, args.max) |
| 136 delta_csv_path = os.path.join(DELTA_RESULTS_DIRECTORY, | 157 delta_csv_path = delta_path + '.csv' |
| 137 '%s.csv' % delta_result_prefix) | |
| 138 delta_path = os.path.join(DELTA_RESULTS_DIRECTORY, | |
| 139 delta_result_prefix) | |
| 140 | |
| 141 # Check if delta results already existed. | 158 # Check if delta results already existed. |
| 142 # TODO: this code has race conditions for interacting with the file system. | 159 # TODO: this code has race conditions for interacting with the file system. |
| 143 if os.path.exists(delta_csv_path): | 160 if os.path.exists(delta_csv_path): |
| 144 print 'Delta results existed in\n%s' % delta_csv_path | 161 print 'Delta results existed in\n%s' % delta_csv_path |
| 145 if not os.path.exists(delta_path): | 162 if not os.path.exists(delta_path): |
| 146 print 'Cannot print out delta results, please open %s to see the results.' | 163 print 'Cannot print out delta results, please open %s to see the results.' |
| 147 return | 164 return |
| 148 | 165 |
| 149 with open(delta_path) as f: | 166 with open(delta_path) as f: |
| 150 deltas, crash_num = pickle.load(f) | 167 deltas, crash_num = pickle.load(f) |
| 151 else: | 168 else: |
| 152 print 'Running delta test...' | 169 print 'Running delta test...' |
| 153 print ('WARNING: Please commit any local change before running delta test, ' | 170 print ('WARNING: Please commit any local change before running delta test, ' |
| 154 'and do not make any new changes while running the delta test.') | 171 'and do not make any new changes while running the delta test.') |
| 155 # Get delta of results between git_hash1 and git_hash2. | 172 # Get delta of results between git_hash1 and git_hash2. |
| 156 deltas, crash_num = delta_test.DeltaEvaluator( | 173 deltas, crash_num = delta_test.DeltaEvaluator( |
| 157 git_hash1, git_hash2, args.client, args.app, | 174 git_hash1, git_hash2, args.client, args.app, |
| 158 start_date=args.since, end_date=args.until, | 175 start_date=args.since, end_date=args.until, max_n=args.max, |
| 159 batch_size=args.batch, verbose=args.verbose) | 176 batch_size=args.batch, verbose=args.verbose) |
| 160 delta_util.FlushResult([deltas, crash_num], delta_path) | 177 delta_util.FlushResult([deltas, crash_num], delta_path) |
| 161 delta_util.WriteDeltaToCSV(deltas, crash_num, args.app, | 178 delta_util.WriteDeltaToCSV(deltas, crash_num, args.app, |
| 162 git_hash1, git_hash2, delta_csv_path) | 179 git_hash1, git_hash2, delta_csv_path) |
| 163 | 180 |
| 164 # Print delta results to users. | 181 # Print delta results to users. |
| 165 print '\n========================= Summary =========================' | 182 print '\n========================= Summary =========================' |
| 166 delta_util.PrintDelta(deltas, crash_num, args.app) | 183 delta_util.PrintDelta(deltas, crash_num, args.app) |
| 167 | 184 |
| 168 | 185 |
| 169 if __name__ == '__main__': | 186 if __name__ == '__main__': |
| 170 RunDeltaTest() | 187 RunDeltaTest() |
| OLD | NEW |