Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: tools/determinism/compare_build_artifacts.py

Issue 2278493002: Show detailed difference on unexpected difference. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rename before ninja, do not expect deps are different. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Compare the artifacts from two builds.""" 6 """Compare the artifacts from two builds."""
7 7
8 import difflib 8 import difflib
9 import json 9 import json
10 import optparse 10 import optparse
11 import os 11 import os
12 import re
13 import shutil
12 import struct 14 import struct
15 import subprocess
13 import sys 16 import sys
14 import time 17 import time
15 18
16 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 19 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
17 20
18 21
19 # List of files that are known to be non deterministic. This is a "temporary" 22 # List of files that are known to be non deterministic. This is a "temporary"
20 # workaround to find regression on the deterministic builders. 23 # workaround to find regression on the deterministic builders.
21 # 24 #
22 # PNaCl general bug: https://crbug.com/429358 25 # PNaCl general bug: https://crbug.com/429358
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 # else, falls through binary comparison, it must be binary equal too. 491 # else, falls through binary comparison, it must be binary equal too.
489 492
490 file_len = os.stat(first_filepath).st_size 493 file_len = os.stat(first_filepath).st_size
491 if file_len != os.stat(second_filepath).st_size: 494 if file_len != os.stat(second_filepath).st_size:
492 return 'different size: %d != %d' % ( 495 return 'different size: %d != %d' % (
493 file_len, os.stat(second_filepath).st_size) 496 file_len, os.stat(second_filepath).st_size)
494 497
495 return diff_binary(first_filepath, second_filepath, file_len) 498 return diff_binary(first_filepath, second_filepath, file_len)
496 499
497 500
501 def get_deps(build_dir, target):
502 """Returns list of object files needed to build target."""
503 NODE_PATTERN = re.compile(r'label="([a-zA-Z0-9_\\/.-]+)"')
504 CHECK_EXTS = ('.o', '.obj')
505
506 # Rename to possibly original directory name if possible.
507 fixed_build_dir = build_dir
508 if build_dir.endswith('.1') or build_dir.endswith('.2'):
509 fixed_build_dir = build_dir[:-2]
510 if os.path.exists(fixed_build_dir):
511 print >> sys.stderr, ('fixed_build_dir %s exists.'
512 ' will try to use orig dir.' % fixed_build_dir)
513 fixed_build_dir = build_dir
514 else:
515 shutil.move(build_dir, fixed_build_dir)
516
517 try:
518 out = subprocess.check_output(['ninja', '-C', fixed_build_dir,
519 '-t', 'graph', target])
520 except subprocess.CalledProcessError as e:
521 print >> sys.stderr, 'error to get graph for %s: %s' % (target, e)
522 return []
523
524 finally:
525 # Rename again if we renamed before.
526 if fixed_build_dir != build_dir:
527 shutil.move(fixed_build_dir, build_dir)
528
529 files = []
530 for line in out.splitlines():
531 matched = NODE_PATTERN.search(line)
532 if matched:
533 path = matched.group(1)
534 if not os.path.splitext(path)[1] in CHECK_EXTS:
535 continue
536 if os.path.isabs(path):
537 print >> sys.stderr, ('not support abs path %s used for target %s'
538 % (path, target))
539 continue
540 files.append(path)
541 return files
542
543
544 def compare_deps(first_dir, second_dir, targets):
545 """Print difference of dependent files."""
546 for target in targets:
547 print 'Checking %s difference:' % target
548 first_deps = get_deps(first_dir, target)
549 second_deps =get_deps(second_dir, target)
550 if set(first_deps) != set(second_deps):
551 # Since we do not thiks this case occur, we do not do anything special
552 # for this case.
553 print 'deps on %s are different: %s' % (
554 target, set(first_deps).symmetric_difference(set(second_deps)))
555 continue
556 for d in first_deps:
557 first_file = os.path.join(first_dir, d)
558 second_file = os.path.join(second_dir, d)
559 compare_files(first_file, second_file)
560
561
498 def compare_build_artifacts(first_dir, second_dir, target_platform, 562 def compare_build_artifacts(first_dir, second_dir, target_platform,
499 recursive=False): 563 recursive=False):
500 """Compares the artifacts from two distinct builds.""" 564 """Compares the artifacts from two distinct builds."""
501 if not os.path.isdir(first_dir): 565 if not os.path.isdir(first_dir):
502 print >> sys.stderr, '%s isn\'t a valid directory.' % first_dir 566 print >> sys.stderr, '%s isn\'t a valid directory.' % first_dir
503 return 1 567 return 1
504 if not os.path.isdir(second_dir): 568 if not os.path.isdir(second_dir):
505 print >> sys.stderr, '%s isn\'t a valid directory.' % second_dir 569 print >> sys.stderr, '%s isn\'t a valid directory.' % second_dir
506 return 1 570 return 1
507 571
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 print('Unexpected diffs: %d' % len(unexpected_diffs)) 618 print('Unexpected diffs: %d' % len(unexpected_diffs))
555 if unexpected_diffs: 619 if unexpected_diffs:
556 print('Unexpected files with diffs:\n') 620 print('Unexpected files with diffs:\n')
557 for u in unexpected_diffs: 621 for u in unexpected_diffs:
558 print(' %s' % u) 622 print(' %s' % u)
559 if unexpected_equals: 623 if unexpected_equals:
560 print('Unexpected files with no diffs:\n') 624 print('Unexpected files with no diffs:\n')
561 for u in unexpected_equals: 625 for u in unexpected_equals:
562 print(' %s' % u) 626 print(' %s' % u)
563 627
628 if unexpected_diffs:
629 diffs_to_investigate = set(unexpected_diffs).difference(
630 set(missing_files))
631 compare_deps(first_dir, second_dir, diffs_to_investigate)
632
564 return int(bool(unexpected_diffs)) 633 return int(bool(unexpected_diffs))
565 634
566 635
567 def main(): 636 def main():
568 parser = optparse.OptionParser(usage='%prog [options]') 637 parser = optparse.OptionParser(usage='%prog [options]')
569 parser.add_option( 638 parser.add_option(
570 '-f', '--first-build-dir', help='The first build directory.') 639 '-f', '--first-build-dir', help='The first build directory.')
571 parser.add_option( 640 parser.add_option(
572 '-s', '--second-build-dir', help='The second build directory.') 641 '-s', '--second-build-dir', help='The second build directory.')
573 parser.add_option('-r', '--recursive', action='store_true', default=False, 642 parser.add_option('-r', '--recursive', action='store_true', default=False,
(...skipping 13 matching lines...) Expand all
587 parser.error('--target-platform is required') 656 parser.error('--target-platform is required')
588 657
589 return compare_build_artifacts(os.path.abspath(options.first_build_dir), 658 return compare_build_artifacts(os.path.abspath(options.first_build_dir),
590 os.path.abspath(options.second_build_dir), 659 os.path.abspath(options.second_build_dir),
591 options.target_platform, 660 options.target_platform,
592 options.recursive) 661 options.recursive)
593 662
594 663
595 if __name__ == '__main__': 664 if __name__ == '__main__':
596 sys.exit(main()) 665 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698