Home | History | Annotate | Download | only in Scripts
      1 #!/usr/bin/python
      2 import json
      3 import optparse
      4 import os
      5 import sys
      6 
      7 from webkitpy.common.host import Host
      8 from webkitpy.layout_tests.port import platform_options, configuration_options
      9 
     10 
     11 def main(argv):
     12     parser = optparse.OptionParser(usage='%prog [path-to-results.json]')
     13     parser.add_option('--failures', action='store_true',
     14                       help='show failing tests')
     15     parser.add_option('--flakes', action='store_true',
     16                       help='show flaky tests')
     17     parser.add_option('--expected', action='store_true',
     18                       help='include expected results along with unexpected')
     19     parser.add_option('--passes', action='store_true',
     20                       help='show passing tests')
     21     parser.add_option('--ignored-failures-path', action='store',
     22                       help='ignore failures seen in a previous run')
     23     parser.add_options(platform_options())
     24     parser.add_options(configuration_options())
     25     options, args = parser.parse_args(argv)
     26 
     27     host = Host()
     28     if args:
     29         if args[0] == '-':
     30             txt = sys.stdin.read()
     31         elif os.path.exists(args[0]):
     32             with open(args[0], 'r') as fp:
     33                 txt = fp.read()
     34         else:
     35             print >> sys.stderr, "file not found: %s" % args[0]
     36             sys.exit(1)
     37     else:
     38         txt = host.filesystem.read_text_file(host.filesystem.join(host.port_factory.get(options=options).results_directory(), 'full_results.json'))
     39 
     40     if txt.startswith('ADD_RESULTS(') and txt.endswith(');'):
     41         txt = txt[12:-2]  # ignore optional JSONP wrapper
     42     results = json.loads(txt)
     43 
     44     passes, failures, flakes = decode_results(results, options.expected)
     45 
     46     tests_to_print = []
     47     if options.passes:
     48         tests_to_print += passes.keys()
     49     if options.failures:
     50         tests_to_print += failures.keys()
     51     if options.flakes:
     52         tests_to_print += flakes.keys()
     53     print "\n".join(sorted(tests_to_print))
     54 
     55     if options.ignored_failures_path:
     56         with open(options.ignored_failures_path, 'r') as fp:
     57             txt = fp.read()
     58         if txt.startswith('ADD_RESULTS(') and txt.endswith(');'):
     59             txt = txt[12:-2]  # ignore optional JSONP wrapper
     60         results = json.loads(txt)
     61         _, ignored_failures, _ = decode_results(results, options.expected)
     62         new_failures = set(failures.keys()) - set(ignored_failures.keys())
     63         if new_failures:
     64             print "New failures:"
     65             print "\n".join(sorted(new_failures))
     66             print
     67         if ignored_failures:
     68             print "Ignored failures:"
     69             print "\n".join(sorted(ignored_failures.keys()))
     70         if new_failures:
     71             return 1
     72         return 0
     73 
     74 
     75 def decode_results(results, include_expected=False):
     76     tests = convert_trie_to_flat_paths(results['tests'])
     77     failures = {}
     78     flakes = {}
     79     passes = {}
     80     for (test, result) in tests.iteritems():
     81         if include_expected or result.get('is_unexpected'):
     82             actual_result = result['actual']
     83             if ' PASS' in actual_result:
     84                 flakes[test] = actual_result
     85             elif actual_result == 'PASS':
     86                 passes[test] = result
     87             else:
     88                 failures[test] = actual_result
     89 
     90     return (passes, failures, flakes)
     91 
     92 
     93 def convert_trie_to_flat_paths(trie, prefix=None):
     94     # Cloned from webkitpy.layout_tests.layout_package.json_results_generator
     95     # so that this code can stand alone.
     96     result = {}
     97     for name, data in trie.iteritems():
     98         if prefix:
     99             name = prefix + "/" + name
    100 
    101         if len(data) and not "actual" in data and not "expected" in data:
    102             result.update(convert_trie_to_flat_paths(data, name))
    103         else:
    104             result[name] = data
    105 
    106     return result
    107 
    108 
    109 if __name__ ==  '__main__':
    110     sys.exit(main(sys.argv[1:]))
    111