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

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: 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 subprocess
12 import struct 14 import struct
13 import sys 15 import sys
14 import time 16 import time
15 17
16 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 18 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
17 19
18 20
19 # List of files that are known to be non deterministic. This is a "temporary" 21 # List of files that are known to be non deterministic. This is a "temporary"
20 # workaround to find regression on the deterministic builders. 22 # workaround to find regression on the deterministic builders.
21 # 23 #
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 # else, falls through binary comparison, it must be binary equal too. 490 # else, falls through binary comparison, it must be binary equal too.
489 491
490 file_len = os.stat(first_filepath).st_size 492 file_len = os.stat(first_filepath).st_size
491 if file_len != os.stat(second_filepath).st_size: 493 if file_len != os.stat(second_filepath).st_size:
492 return 'different size: %d != %d' % ( 494 return 'different size: %d != %d' % (
493 file_len, os.stat(second_filepath).st_size) 495 file_len, os.stat(second_filepath).st_size)
494 496
495 return diff_binary(first_filepath, second_filepath, file_len) 497 return diff_binary(first_filepath, second_filepath, file_len)
496 498
497 499
500 def get_deps(build_dir, target):
501 """Returns list of object files needed to build target."""
502 NODE_PATTERN = re.compile(r'label="([a-zA-Z0-9_\\/.-]+)"')
503 CHECK_EXTS = ('.o', '.obj')
504 try:
505 out = subprocess.check_output(['ninja', '-C', build_dir,
M-A Ruel 2016/08/24 18:47:27 There's a problem as the directory was renamed, so
Yoshisato Yanagisawa 2016/08/25 08:47:29 I have never seen absolute object file path names
M-A Ruel 2016/08/25 15:46:26 zforman@ worked on making this work on linux but t
Yoshisato Yanagisawa 2016/08/29 05:44:49 I checked the code seems to work on Win.
506 '-t', 'graph', target])
507 except subprocess.CalledProcessError as e:
508 print >> sys.stderr, 'error to get graph for %s: %s' % (target, e)
509 return []
510 files = []
511 for line in out.splitlines():
512 matched = NODE_PATTERN.search(line)
513 if matched:
514 path = matched.group(1)
515 if not os.path.splitext(path)[1] in CHECK_EXTS:
516 continue
517 files.append(path)
518 return files
519
520
521 def compare_deps(first_dir, second_dir, targets):
522 """Print difference of dependent files."""
523 for target in targets:
524 print 'Checking %s difference:' % target
525 first_deps = get_deps(first_dir, target)
526 second_deps = get_deps(second_dir, target)
527 deps = set(first_deps).union(set(second_deps))
M-A Ruel 2016/08/24 18:47:27 the difference should be empty ?
Yoshisato Yanagisawa 2016/08/25 08:47:29 I am not confident. However, I will simplify the
M-A Ruel 2016/08/25 15:46:26 I guess my question was more to print out the diff
Yoshisato Yanagisawa 2016/08/29 05:44:49 I think current code still help us to find this ki
528 for d in deps:
529 first_file = os.path.join(first_dir, d)
530 second_file = os.path.join(second_dir, d)
531 if not os.path.exists(first_file):
532 print '%s: not found' % first_file
533 continue
534 if not os.path.exists(second_file):
535 print '%s: not found' % second_file
536 continue
537 compare_files(first_file, second_file)
538
539
498 def compare_build_artifacts(first_dir, second_dir, target_platform, 540 def compare_build_artifacts(first_dir, second_dir, target_platform,
499 recursive=False): 541 recursive=False):
500 """Compares the artifacts from two distinct builds.""" 542 """Compares the artifacts from two distinct builds."""
501 if not os.path.isdir(first_dir): 543 if not os.path.isdir(first_dir):
502 print >> sys.stderr, '%s isn\'t a valid directory.' % first_dir 544 print >> sys.stderr, '%s isn\'t a valid directory.' % first_dir
503 return 1 545 return 1
504 if not os.path.isdir(second_dir): 546 if not os.path.isdir(second_dir):
505 print >> sys.stderr, '%s isn\'t a valid directory.' % second_dir 547 print >> sys.stderr, '%s isn\'t a valid directory.' % second_dir
506 return 1 548 return 1
507 549
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 print('Unexpected diffs: %d' % len(unexpected_diffs)) 596 print('Unexpected diffs: %d' % len(unexpected_diffs))
555 if unexpected_diffs: 597 if unexpected_diffs:
556 print('Unexpected files with diffs:\n') 598 print('Unexpected files with diffs:\n')
557 for u in unexpected_diffs: 599 for u in unexpected_diffs:
558 print(' %s' % u) 600 print(' %s' % u)
559 if unexpected_equals: 601 if unexpected_equals:
560 print('Unexpected files with no diffs:\n') 602 print('Unexpected files with no diffs:\n')
561 for u in unexpected_equals: 603 for u in unexpected_equals:
562 print(' %s' % u) 604 print(' %s' % u)
563 605
606 if unexpected_diffs:
607 diffs_to_investigate = set(unexpected_diffs).difference(
608 set(missing_files))
609 compare_deps(first_dir, second_dir, diffs_to_investigate)
610
564 return int(bool(unexpected_diffs)) 611 return int(bool(unexpected_diffs))
565 612
566 613
567 def main(): 614 def main():
568 parser = optparse.OptionParser(usage='%prog [options]') 615 parser = optparse.OptionParser(usage='%prog [options]')
569 parser.add_option( 616 parser.add_option(
570 '-f', '--first-build-dir', help='The first build directory.') 617 '-f', '--first-build-dir', help='The first build directory.')
571 parser.add_option( 618 parser.add_option(
572 '-s', '--second-build-dir', help='The second build directory.') 619 '-s', '--second-build-dir', help='The second build directory.')
573 parser.add_option('-r', '--recursive', action='store_true', default=False, 620 parser.add_option('-r', '--recursive', action='store_true', default=False,
574 help='Indicates if the comparison should be recursive.') 621 help='Indicates if the comparison should be recursive.')
575 target = { 622 target = {
576 'darwin': 'mac', 'linux2': 'linux', 'win32': 'win' 623 'darwin': 'mac', 'linux2': 'linux', 'win32': 'win'
577 }.get(sys.platform, sys.platform) 624 }.get(sys.platform, sys.platform)
578 parser.add_option('-t', '--target-platform', help='The target platform.' 625 parser.add_option('-t', '--target-platform', help='The target platform.',
579 default=target, choices=('android', 'mac', 'linux', 'win')) 626 default=target, choices=('android', 'mac', 'linux', 'win'))
580 options, _ = parser.parse_args() 627 options, _ = parser.parse_args()
581 628
582 if not options.first_build_dir: 629 if not options.first_build_dir:
583 parser.error('--first-build-dir is required') 630 parser.error('--first-build-dir is required')
584 if not options.second_build_dir: 631 if not options.second_build_dir:
585 parser.error('--second-build-dir is required') 632 parser.error('--second-build-dir is required')
586 if not options.target_platform: 633 if not options.target_platform:
587 parser.error('--target-platform is required') 634 parser.error('--target-platform is required')
588 635
589 return compare_build_artifacts(os.path.abspath(options.first_build_dir), 636 return compare_build_artifacts(os.path.abspath(options.first_build_dir),
590 os.path.abspath(options.second_build_dir), 637 os.path.abspath(options.second_build_dir),
591 options.target_platform, 638 options.target_platform,
592 options.recursive) 639 options.recursive)
593 640
594 641
595 if __name__ == '__main__': 642 if __name__ == '__main__':
596 sys.exit(main()) 643 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