Home | History | Annotate | Download | only in skqp
      1 #! /usr/bin/env python
      2 # Copyright 2019 Google LLC.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import json
      7 import os
      8 import re
      9 import subprocess
     10 import sys
     11 import threading
     12 import urllib
     13 import urllib2
     14 
     15 
     16 assert '/' in [os.sep, os.altsep]
     17 
     18 
     19 skia_directory = os.path.abspath(os.path.dirname(__file__) + '/../..')
     20 
     21 
     22 def get_jobs():
     23     path = skia_directory + '/infra/bots/jobs.json'
     24     reg = re.compile('Test-(?P<os>[A-Za-z0-9_]+)-'
     25                      '(?P<compiler>[A-Za-z0-9_]+)-'
     26                      '(?P<model>[A-Za-z0-9_]+)-GPU-'
     27                      '(?P<cpu_or_gpu_value>[A-Za-z0-9_]+)-'
     28                      '(?P<arch>[A-Za-z0-9_]+)-'
     29                      '(?P<configuration>[A-Za-z0-9_]+)-'
     30                      'All(-(?P<extra_config>[A-Za-z0-9_]+)|)')
     31     keys = ['os', 'compiler', 'model', 'cpu_or_gpu_value', 'arch',
     32             'configuration', 'extra_config']
     33     def fmt(s):
     34         return s.encode('utf-8') if s is not None else ''
     35     with open(path) as f:
     36         jobs = json.load(f)
     37     for job in jobs:
     38         m = reg.match(job)
     39         if m is not None:
     40             yield [(k, fmt(m.group(k))) for k in keys]
     41 
     42 
     43 def gold_export_url(job, config, first_commit, last_commit):
     44     qq = [('source_type', 'gm'), ('config', config)] + job
     45     query = [
     46         ('fbegin', first_commit),
     47         ('fend', last_commit),
     48         ('query', urllib.urlencode(qq)),
     49         ('pos', 'true'),
     50         ('neg', 'false'),
     51         ('unt', 'false'),
     52         ('head', 'true')
     53     ]
     54     return 'https://public-gold.skia.org/json/export?' + urllib.urlencode(query)
     55 
     56 
     57 def get_results_for_commit(commit, jobs):
     58     sys.stderr.write('%s\n' % commit)
     59     sys.stderr.flush()
     60     CONFIGS = ['gles', 'vk']
     61     passing_tests_for_all_jobs = []
     62     def process(url):
     63         testResults = json.load(urllib2.urlopen(url))
     64         sys.stderr.write('.')
     65         sys.stderr.flush()
     66         passing_tests = 0
     67         for t in testResults:
     68             assert t['digests']
     69             passing_tests += 1
     70         passing_tests_for_all_jobs.append(passing_tests)
     71     all_urls = [gold_export_url(job, config, commit, commit)
     72                 for job in jobs for config in CONFIGS]
     73     threads = [threading.Thread(target=process, args=(url,)) for url in all_urls]
     74     for t in threads:
     75         t.start()
     76     for t in threads:
     77         t.join()
     78     result = sum(passing_tests_for_all_jobs)
     79     sys.stderr.write('\n%d\n' % result)
     80     sys.stderr.flush()
     81     return result
     82 
     83 
     84 def find_best_commit(commits):
     85     jobs = [j for j in get_jobs()]
     86     results = []
     87     for commit_name in commits:
     88         commit_hash = subprocess.check_output(['git', 'rev-parse', commit_name]).strip()
     89         results.append((commit_hash, get_results_for_commit(commit_hash, jobs)))
     90 
     91     best_result = max(r for h, r in results)
     92     for h, r in results:
     93         if r == best_result:
     94             return h
     95     return None
     96 
     97 
     98 def generate_commit_list(args):
     99     return subprocess.check_output(['git', 'log', '--format=%H'] + args).splitlines()
    100 
    101 
    102 def main(args):
    103     os.chdir(skia_directory)
    104     subprocess.check_call(['git', 'fetch', 'origin'])
    105     sys.stderr.write('%s\n' % ' '.join(args))
    106     commits = generate_commit_list(args)
    107     sys.stderr.write('%d\n' % len(commits))
    108     best = find_best_commit(commits)
    109     sys.stderr.write('DONE:\n')
    110     sys.stderr.flush()
    111     sys.stdout.write('%s\n' % best)
    112 
    113 
    114 usage = '''Example usage:
    115     python %s origin/master ^origin/skqp/dev < /dev/null > LOG 2>&1 & disown
    116 '''
    117 
    118 if __name__ == '__main__':
    119     if len(sys.argv) < 2:
    120         sys.stderr.write(usage % sys.argv[0])
    121         sys.exit(1)
    122     main(sys.argv[1:])
    123