blob: fba4f6c12c47edd6f94f65c5dcc57b8630632809 [file] [log] [blame]
Hal Canary572d9bb2019-04-18 13:49:52 -04001#! /usr/bin/env python
2# Copyright 2018 Google LLC.
3# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
4
5import json
6import md5
7import multiprocessing
8import os
9import shutil
10import sys
11import tempfile
12import urllib
13import urllib2
14
15from subprocess import check_call, check_output
16
17assert '/' in [os.sep, os.altsep] and os.pardir == '..'
18
19ASSETS = 'platform_tools/android/apps/skqp/src/main/assets'
20BUCKET = 'skia-skqp-assets'
21
22def make_skqp_model(arg):
23 name, urls, exe = arg
24 tmp = tempfile.mkdtemp()
25 for url in urls:
26 urllib.urlretrieve(url, tmp + '/' + url[url.rindex('/') + 1:])
27 check_call([exe, tmp, ASSETS + '/gmkb/' + name])
28 shutil.rmtree(tmp)
29 sys.stdout.write(name + ' ')
30 sys.stdout.flush()
31
32def goldgetter(meta, exe):
33 assert os.path.exists(exe)
34 jobs = []
35 for rec in meta:
36 urls = [d['URL'] for d in rec['digests']
37 if d['status'] == 'positive' and
38 (set(d['paramset']['config']) & set(['vk', 'gles']))]
39 if urls:
40 jobs.append((rec['testName'], urls, exe))
41 pool = multiprocessing.Pool(processes=20)
42 pool.map(make_skqp_model, jobs)
43 sys.stdout.write('\n')
44 return set((n for n, _, _ in jobs))
45
46def gold(first_commit, last_commit):
47 c1, c2 = (check_output(['git', 'rev-parse', c]).strip()
48 for c in (first_commit, last_commit))
49 f = urllib2.urlopen('https://public-gold.skia.org/json/export?' + urllib.urlencode([
50 ('fbegin', c1),
51 ('fend', c2),
52 ('query', 'config=gles&config=vk&source_type=gm'),
53 ('pos', 'true'),
54 ('neg', 'false'),
55 ('unt', 'false')
56 ]))
57 j = json.load(f)
58 f.close()
59 return j
60
61def gset(path):
62 s = set()
63 if os.path.isfile(path):
64 with open(path, 'r') as f:
65 for line in f:
66 s.add(line.strip())
67 return s
68
69def make_rendertest_list(models, good, bad):
70 assert good.isdisjoint(bad)
71 do_score = good & models
72 no_score = bad | (good - models)
73 to_delete = models & bad
74 for d in to_delete:
75 path = ASSETS + '/gmkb/' + d
76 if os.path.isdir(path):
77 shutil.rmtree(path)
78 results = dict()
79 for n in do_score:
80 results[n] = 0
81 for n in no_score:
82 results[n] = -1
83 return ''.join('%s,%d\n' % (n, results[n]) for n in sorted(results))
84
85def get_digest(path):
86 m = md5.new()
87 with open(path, 'r') as f:
88 m.update(f.read())
89 return m.hexdigest()
90
91def upload_cmd(path, digest):
92 return ['gsutil', 'cp', path, 'gs://%s/%s' % (BUCKET, digest)]
93
94def upload_model():
95 bucket_url = 'gs://%s/' % BUCKET
96 extant = set((u.replace(bucket_url, '', 1)
97 for u in check_output(['gsutil', 'ls', bucket_url]).splitlines() if u))
98 cmds = []
99 filelist = []
100 for dirpath, _, filenames in os.walk(ASSETS + '/gmkb'):
101 for filename in filenames:
102 path = os.path.join(dirpath, filename)
103 digest = get_digest(path)
104 if digest not in extant:
105 cmds.append(upload_cmd(path, digest))
106 filelist.append('%s;%s\n' % (digest, os.path.relpath(path, ASSETS)))
107 tmp = tempfile.mkdtemp()
108 filelist_path = tmp + '/x'
109 with open(filelist_path, 'w') as o:
110 for l in filelist:
111 o.write(l)
112 filelist_digest = get_digest(filelist_path)
113 if filelist_digest not in extant:
114 cmds.append(upload_cmd(filelist_path, filelist_digest))
115
116 pool = multiprocessing.Pool(processes=20)
117 pool.map(check_call, cmds)
118 shutil.rmtree(tmp)
119 return filelist_digest
120
121def remove(x):
122 if os.path.isdir(x) and not os.path.islink(x):
123 shutil.rmtree(x)
124 if os.path.exists(x):
125 os.remove(x)
126
127def main(first_commit, last_commit):
128 check_call(upload_cmd('/dev/null', get_digest('/dev/null')))
129
130 os.chdir(os.path.dirname(__file__) + '/../..')
131 remove(ASSETS + '/files.checksum')
132 for d in [ASSETS + '/gmkb', ASSETS + '/skqp', ]:
133 remove(d)
134 os.mkdir(d)
135
136 check_call([sys.executable, 'tools/git-sync-deps'],
137 env=dict(os.environ, GIT_SYNC_DEPS_QUIET='T'))
138 build = 'out/ndebug'
139 check_call(['bin/gn', 'gen', build,
140 '--args=cc="clang" cxx="clang++" is_debug=false'])
141 check_call(['ninja', '-C', build,
142 'jitter_gms', 'list_gpu_unit_tests', 'make_skqp_model'])
143
144 models = goldgetter(gold(first_commit, last_commit), build + '/make_skqp_model')
145
146 check_call([build + '/jitter_gms', 'tools/skqp/bad_gms.txt'])
147
148 with open(ASSETS + '/skqp/rendertests.txt', 'w') as o:
149 o.write(make_rendertest_list(models, gset('good.txt'), gset('bad.txt')))
150
151 remove('good.txt')
152 remove('bad.txt')
153
154 with open(ASSETS + '/skqp/unittests.txt', 'w') as o:
155 o.write(check_output([build + '/list_gpu_unit_tests']))
156
157 with open(ASSETS + '/files.checksum', 'w') as o:
158 o.write(upload_model() + '\n')
159
160 sys.stdout.write(ASSETS + '/files.checksum\n')
161 sys.stdout.write(ASSETS + '/skqp/rendertests.txt\n')
162 sys.stdout.write(ASSETS + '/skqp/unittests.txt\n')
163
164if __name__ == '__main__':
165 if len(sys.argv) != 3:
166 sys.stderr.write('Usage:\n %s C1 C2\n\n' % sys.argv[0])
167 sys.exit(1)
168 main(sys.argv[1], sys.argv[2])