13 from pathlib
import Path
15 from urllib
import parse
17 import dump_trace_images
19 TRACES_DB_PATH
= os
.getcwd() + "/traces-db/"
20 RESULTS_PATH
= os
.getcwd() + "/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']] = {}
110 trace_path
= Path(TRACES_DB_PATH
+ trace
['path'])
111 checksum
, image_file
, log_file
= replay(trace_path
, device_name
)
114 elif checksum
== expectation
['checksum']:
115 print("[check_image] Images match for %s" % (trace
['path']))
118 print("[check_image] Images differ for %s (expected: %s, actual: %s)" %
119 (trace
['path'], expectation
['checksum'], checksum
))
120 print("[check_image] For more information see "
121 "https://gitlab.freedesktop.org/mesa/mesa/blob/master/.gitlab-ci/tracie/README.md")
124 trace_dir
= os
.path
.split(trace
['path'])[0]
125 dir_in_results
= os
.path
.join(trace_dir
, "test", device_name
)
126 results_path
= os
.path
.join(RESULTS_PATH
, dir_in_results
)
127 os
.makedirs(results_path
, exist_ok
=True)
128 shutil
.move(log_file
, os
.path
.join(results_path
, os
.path
.split(log_file
)[1]))
129 if not ok
or os
.environ
.get('TRACIE_STORE_IMAGES', '0') == '1':
130 image_name
= os
.path
.split(image_file
)[1]
131 shutil
.move(image_file
, os
.path
.join(results_path
, image_name
))
132 result
[trace
['path']]['image'] = os
.path
.join(dir_in_results
, image_name
)
134 result
[trace
['path']]['expected'] = expectation
['checksum']
135 result
[trace
['path']]['actual'] = checksum
140 parser
= argparse
.ArgumentParser()
141 parser
.add_argument('--file', required
=True,
142 help='the name of the traces.yml file listing traces and their checksums for each device')
143 parser
.add_argument('--device-name', required
=True,
144 help="the name of the graphics device used to replay traces")
146 args
= parser
.parse_args()
148 with
open(args
.file, 'r') as f
:
149 y
= yaml
.safe_load(f
)
152 project_url
= y
["traces-db"]["gitlab-project-url"]
153 commit_id
= y
["traces-db"]["commit"]
162 for expectation
in trace
['expectations']:
163 if expectation
['device'] == args
.device_name
:
164 ok
, result
= gitlab_check_trace(project_url
, commit_id
, args
.device_name
, trace
, expectation
)
165 all_ok
= all_ok
and ok
166 results
.update(result
)
168 with
open(os
.path
.join(RESULTS_PATH
, 'results.yml'), 'w') as f
:
169 yaml
.safe_dump(results
, f
, default_flow_style
=False)
172 sys
.exit(0 if all_ok
else 1)
174 if __name__
== "__main__":