12 from pathlib
import Path
14 from urllib
import parse
16 import dump_trace_images
18 TRACES_DB_PATH
= os
.getcwd() + "/traces-db/"
19 RESULTS_PATH
= os
.getcwd() + "/results/"
21 def replay(trace_path
, device_name
):
22 success
= dump_trace_images
.dump_from_trace(trace_path
, [], device_name
)
25 print("[check_image] Trace %s couldn't be replayed. See above logs for more information." % (str(trace_path
)))
26 return None, None, None
28 base_path
= trace_path
.parent
29 file_name
= trace_path
.name
30 files
= glob
.glob(str(base_path
/ "test" / device_name
/ (file_name
+ "-*" + ".png")))
33 files
= glob
.glob(str(base_path
/ "test" / device_name
/ (file_name
+ ".log")))
36 return hashlib
.md5(Image
.open(image_file
).tobytes()).hexdigest(), image_file
, log_file
38 def download_metadata(repo_url
, repo_commit
, trace_path
):
39 # The GitLab API doesn't want the .git postfix
41 if url
.endswith(".git"):
43 url
= parse
.urlparse(url
)
46 if url_path
.startswith("/"):
47 url_path
= url_path
[1:]
49 gitlab_api_url
= url
.scheme
+ "://" + url
.netloc
+ "/api/v4/projects/" + parse
.quote_plus(url_path
)
51 r
= requests
.get(gitlab_api_url
+ "/repository/files/%s/raw?ref=%s" % (parse
.quote_plus(trace_path
), repo_commit
))
52 metadata_raw
= r
.text
.strip().split('\n')
53 metadata
= dict(line
.split(' ', 1) for line
in metadata_raw
[1:])
54 oid
= metadata
["oid"][7:] if metadata
["oid"].startswith('sha256:') else metadata
["oid"]
55 size
= int(metadata
['size'])
59 def download_trace(repo_url
, repo_commit
, trace_path
, oid
, size
):
61 "Accept": "application/vnd.git-lfs+json",
62 "Content-Type": "application/vnd.git-lfs+json"
65 "operation": "download",
66 "transfers": [ "basic" ],
67 "ref": { "name": "refs/heads/%s" % repo_commit
},
76 # The LFS API really wants the .git postfix...
77 if not repo_url
.endswith(".git"):
80 r
= requests
.post(repo_url
+ "/info/lfs/objects/batch", headers
=headers
, json
=json
)
81 url
= r
.json()["objects"][0]["actions"]["download"]["href"]
82 open(TRACES_DB_PATH
+ trace_path
, "wb").write(requests
.get(url
).content
)
84 def checksum(filename
, hash_factory
=hashlib
.sha256
, chunk_num_blocks
=128):
86 with
open(filename
,'rb') as f
:
87 for chunk
in iter(lambda: f
.read(chunk_num_blocks
*h
.block_size
), b
''):
91 def ensure_trace(repo_url
, repo_commit
, trace
):
92 trace_path
= TRACES_DB_PATH
+ trace
['path']
94 assert(repo_commit
is None)
95 assert(os
.path
.exists(trace_path
))
98 os
.makedirs(os
.path
.dirname(trace_path
), exist_ok
=True)
100 if os
.path
.exists(trace_path
):
101 local_oid
= checksum(trace_path
)
103 remote_oid
, size
= download_metadata(repo_url
, repo_commit
, trace
['path'])
105 if not os
.path
.exists(trace_path
) or local_oid
!= remote_oid
:
106 print("[check_image] Downloading trace %s" % (trace
['path']), end
=" ", flush
=True)
107 download_time
= time
.time()
108 download_trace(repo_url
, repo_commit
, trace
['path'], remote_oid
, size
)
109 print("took %ds." % (time
.time() - download_time
), flush
=True)
111 def check_trace(repo_url
, repo_commit
, device_name
, trace
, expectation
):
112 ensure_trace(repo_url
, repo_commit
, trace
)
114 trace_path
= Path(TRACES_DB_PATH
+ trace
['path'])
115 checksum
, image_file
, log_file
= replay(trace_path
, device_name
)
118 elif checksum
== expectation
['checksum']:
119 print("[check_image] Images match for %s" % (trace
['path']))
122 print("[check_image] Images differ for %s (expected: %s, actual: %s)" %
123 (trace
['path'], expectation
['checksum'], checksum
))
124 print("[check_image] For more information see "
125 "https://gitlab.freedesktop.org/mesa/mesa/blob/master/.gitlab-ci/tracie/README.md")
128 trace_dir
= os
.path
.split(trace
['path'])[0]
129 results_path
= os
.path
.join(RESULTS_PATH
, trace_dir
, "test", device_name
)
130 os
.makedirs(results_path
, exist_ok
=True)
131 os
.rename(log_file
, os
.path
.join(results_path
, os
.path
.split(log_file
)[1]))
132 if not ok
or os
.environ
.get('TRACIE_STORE_IMAGES', '0') == '1':
133 os
.rename(image_file
, os
.path
.join(results_path
, os
.path
.split(image_file
)[1]))
138 parser
= argparse
.ArgumentParser()
139 parser
.add_argument('--file', required
=True,
140 help='the name of the traces.yml file listing traces and their checksums for each device')
141 parser
.add_argument('--device-name', required
=True,
142 help="the name of the graphics device used to replay traces")
144 args
= parser
.parse_args()
146 with
open(args
.file, 'r') as f
:
147 y
= yaml
.safe_load(f
)
150 repo
= y
["traces-db"]["repo"]
151 commit_id
= y
["traces-db"]["commit"]
159 for expectation
in trace
['expectations']:
160 if expectation
['device'] == args
.device_name
:
161 ok
= check_trace(repo
, commit_id
, args
.device_name
, trace
, expectation
)
162 all_ok
= all_ok
and ok
164 sys
.exit(0 if all_ok
else 1)
166 if __name__
== "__main__":