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