13 from pathlib
import Path
15 from urllib
import parse
17 import dump_trace_images
19 TRACES_DB_PATH
= "./traces-db/"
20 RESULTS_PATH
= "./results/"
22 def replay(trace_path
, device_name
):
23 success
= dump_trace_images
.dump_from_trace(trace_path
, [], device_name
)
26 print("[check_image] Trace %s couldn't be replayed. See above logs for more information." % (str(trace_path
)))
27 return None, None, None
29 base_path
= trace_path
.parent
30 file_name
= trace_path
.name
31 files
= glob
.glob(str(base_path
/ "test" / device_name
/ (file_name
+ "-*" + ".png")))
34 files
= glob
.glob(str(base_path
/ "test" / device_name
/ (file_name
+ ".log")))
37 return hashlib
.md5(Image
.open(image_file
).tobytes()).hexdigest(), image_file
, log_file
39 def gitlab_download_metadata(project_url
, repo_commit
, trace_path
):
40 url
= parse
.urlparse(project_url
)
43 if url_path
.startswith("/"):
44 url_path
= url_path
[1:]
46 gitlab_api_url
= url
.scheme
+ "://" + url
.netloc
+ "/api/v4/projects/" + parse
.quote_plus(url_path
)
48 r
= requests
.get(gitlab_api_url
+ "/repository/files/%s/raw?ref=%s" % (parse
.quote_plus(trace_path
), repo_commit
))
49 metadata_raw
= r
.text
.strip().split('\n')
50 metadata
= dict(line
.split(' ', 1) for line
in metadata_raw
[1:])
51 oid
= metadata
["oid"][7:] if metadata
["oid"].startswith('sha256:') else metadata
["oid"]
52 size
= int(metadata
['size'])
56 def gitlfs_download_trace(repo_url
, repo_commit
, trace_path
, oid
, size
):
58 "Accept": "application/vnd.git-lfs+json",
59 "Content-Type": "application/vnd.git-lfs+json"
62 "operation": "download",
63 "transfers": [ "basic" ],
64 "ref": { "name": "refs/heads/%s" % repo_commit
},
73 r
= requests
.post(repo_url
+ "/info/lfs/objects/batch", headers
=headers
, json
=json
)
74 url
= r
.json()["objects"][0]["actions"]["download"]["href"]
75 open(TRACES_DB_PATH
+ trace_path
, "wb").write(requests
.get(url
).content
)
77 def checksum(filename
, hash_factory
=hashlib
.sha256
, chunk_num_blocks
=128):
79 with
open(filename
,'rb') as f
:
80 for chunk
in iter(lambda: f
.read(chunk_num_blocks
*h
.block_size
), b
''):
84 def gitlab_ensure_trace(project_url
, repo_commit
, trace
):
85 trace_path
= TRACES_DB_PATH
+ trace
['path']
86 if project_url
is None:
87 assert(repo_commit
is None)
88 assert(os
.path
.exists(trace_path
))
91 os
.makedirs(os
.path
.dirname(trace_path
), exist_ok
=True)
93 if os
.path
.exists(trace_path
):
94 local_oid
= checksum(trace_path
)
96 remote_oid
, size
= gitlab_download_metadata(project_url
, repo_commit
, trace
['path'])
98 if not os
.path
.exists(trace_path
) or local_oid
!= remote_oid
:
99 print("[check_image] Downloading trace %s" % (trace
['path']), end
=" ", flush
=True)
100 download_time
= time
.time()
101 gitlfs_download_trace(project_url
+ ".git", repo_commit
, trace
['path'], remote_oid
, size
)
102 print("took %ds." % (time
.time() - download_time
), flush
=True)
104 def gitlab_check_trace(project_url
, repo_commit
, device_name
, trace
, expectation
):
105 gitlab_ensure_trace(project_url
, repo_commit
, trace
)
108 result
[trace
['path']] = {}
109 result
[trace
['path']]['expected'] = expectation
['checksum']
111 trace_path
= Path(TRACES_DB_PATH
+ trace
['path'])
112 checksum
, image_file
, log_file
= replay(trace_path
, device_name
)
114 result
[trace
['path']]['actual'] = 'error'
116 elif checksum
== expectation
['checksum']:
117 print("[check_image] Images match for %s" % (trace
['path']))
120 print("[check_image] Images differ for %s (expected: %s, actual: %s)" %
121 (trace
['path'], expectation
['checksum'], checksum
))
122 print("[check_image] For more information see "
123 "https://gitlab.freedesktop.org/mesa/mesa/blob/master/.gitlab-ci/tracie/README.md")
126 trace_dir
= os
.path
.split(trace
['path'])[0]
127 dir_in_results
= os
.path
.join(trace_dir
, "test", device_name
)
128 results_path
= os
.path
.join(RESULTS_PATH
, dir_in_results
)
129 os
.makedirs(results_path
, exist_ok
=True)
130 shutil
.move(log_file
, os
.path
.join(results_path
, os
.path
.split(log_file
)[1]))
131 if not ok
or os
.environ
.get('TRACIE_STORE_IMAGES', '0') == '1':
132 image_name
= os
.path
.split(image_file
)[1]
133 shutil
.move(image_file
, os
.path
.join(results_path
, image_name
))
134 result
[trace
['path']]['image'] = os
.path
.join(dir_in_results
, image_name
)
136 result
[trace
['path']]['actual'] = checksum
140 def run(filename
, device_name
):
142 with
open(filename
, 'r') as f
:
143 y
= yaml
.safe_load(f
)
146 project_url
= y
["traces-db"]["gitlab-project-url"]
147 commit_id
= y
["traces-db"]["commit"]
152 traces
= y
['traces'] or []
156 for expectation
in trace
['expectations']:
157 if expectation
['device'] == device_name
:
158 ok
, result
= gitlab_check_trace(project_url
, commit_id
,
161 all_ok
= all_ok
and ok
162 results
.update(result
)
164 os
.makedirs(RESULTS_PATH
, exist_ok
=True)
165 with
open(os
.path
.join(RESULTS_PATH
, 'results.yml'), 'w') as f
:
166 yaml
.safe_dump(results
, f
, default_flow_style
=False)
171 parser
= argparse
.ArgumentParser()
172 parser
.add_argument('--file', required
=True,
173 help='the name of the traces.yml file listing traces and their checksums for each device')
174 parser
.add_argument('--device-name', required
=True,
175 help="the name of the graphics device used to replay traces")
177 args
= parser
.parse_args(args
)
178 return run(args
.file, args
.device_name
)
180 if __name__
== "__main__":
181 all_ok
= main(sys
.argv
[1:])
182 sys
.exit(0 if all_ok
else 1)