1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
base / tracing / test / test_data.py [blame]
#!/usr/bin/env vpython3
# Copyright 2024 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
A wrapper script for upload_to_google_storage_first_class.py.
Usage:
# Uploads file and generates .sha256 file
$ ./test_data.py upload data/trace.pftrace
# Generates deps entry for a single file
$ ./test_data.py get_deps data/trace.pftrace
# Generate full deps entry for all files in base/tracing/test/data/
$ ./test_data.py get_all_deps
The upload command uploads the given file to the gs://perfetto bucket and
generates a .sha256 file in the base/tracing/test/data/ directory,
which is rolled to the Perfetto repository.
The .sha256 file is used by Perfetto to download the files with their
own test_data download script (third_party/perfetto/tools/test_data).
The script outputs a GCS entry which should be manually added to the
deps dict in /DEPS. See
https://chromium.googlesource.com/chromium/src/+/HEAD/docs/gcs_dependencies.md.
The files are uploaded as gs://perfetto/test_data/file_name-a1b2c3f4.
"""
import argparse
import os
import subprocess
import sys
import json
import re
SRC_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
TEST_DATA_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data'))
DEPOT_TOOLS_PATH = os.path.abspath(os.path.join(SRC_PATH, 'third_party', 'depot_tools'))
sys.path.append(DEPOT_TOOLS_PATH)
from upload_to_google_storage_first_class import get_sha256sum
from download_from_google_storage import Gsutil, GSUTIL_DEFAULT_PATH
# Write .sha256 file to test/data_sha256 to be rolled into Perfetto.
def write_sha256_file(filepath: str):
sha256sum = get_sha256sum(filepath)
sha256_filepath = os.path.abspath(os.path.join(
os.path.dirname(filepath),
'..',
'data_sha256',
os.path.basename(filepath) + '.sha256'))
with open(sha256_filepath, 'w') as sha_file:
sha_file.write(sha256sum)
return sha256sum
# Run `upload_to_google_storage_first_class.py --bucket perfetto <file>`.
def upload_file(filepath: str, dry_run: bool, force: bool):
sha256sum = write_sha256_file(filepath)
# Perfetto uses 'test_data/file_name-a1b2c3f4' object name format.
object_name = '%s/%s-%s' % ('test_data', os.path.basename(filepath), sha256sum)
tool = 'upload_to_google_storage_first_class.py'
command = [tool, '--bucket', 'perfetto', '--object-name', object_name, filepath]
if dry_run:
command.append('--dry-run')
if force:
command.append('--force')
completed_process = subprocess.run(
command,
check=False,
capture_output=True)
if completed_process.returncode == 0:
print('Manually add the deps entry below to the DEPS file. See '
'https://chromium.googlesource.com/chromium/src/+/HEAD/docs/gcs_dependencies.md '
'for more details. Run `test_data.py get_all_deps` to get the full deps entry.')
sys.stdout.buffer.write(completed_process.stdout)
else:
sys.stderr.buffer.write(completed_process.stderr)
# Generate the deps entry for `filepath`, assuming it has been uploaded already.
def generate_deps_entry(filepath: str):
sha256sum = get_sha256sum(filepath)
object_name = '%s/%s-%s' % ('test_data', os.path.basename(filepath), sha256sum)
# Run `gcloud storage ls -L gs://perfetto/test_data/file_name-a1b2c3f4` to
# get the 'generation' and 'size_bytes' fields for the deps entry
gsutil = Gsutil(GSUTIL_DEFAULT_PATH)
gsutil_args = ['ls', '-L', 'gs://perfetto/%s' % object_name]
code, out, err = gsutil.check_call(*gsutil_args)
if code != 0:
raise Exception(code, err + ' ' + object_name)
generation = int(out.split()[out.split().index('Generation:') + 1])
size = int(out.split()[out.split().index('Content-Length:') + 1])
return {
'object_name': object_name,
'sha256sum': sha256sum,
'size_bytes': size,
'generation': generation,
'output_file': os.path.basename(filepath),
}
# Generate the full deps entry for Perfetto test data
def generate_all_deps():
sha256_path = os.path.join(SRC_PATH, 'base/tracing/test/data_sha256')
data_path = os.path.join(SRC_PATH, 'base/tracing/test/data')
objects = []
for file in os.listdir(sha256_path):
if file.endswith('.sha256'):
filepath = os.path.join(data_path, file)[:-7]
assert os.path.isfile(filepath), 'File does not exist'
object_entry = generate_deps_entry(filepath)
objects.append(object_entry)
return {
'src/base/tracing/test/data': {
'bucket':
'perfetto',
'objects': objects,
'dep_type':
'gcs',
},
}
def main():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='cmd')
upload_parser = subparsers.add_parser('upload', help='Upload a file to gs://perfetto')
upload_parser.add_argument('filepath', help='Path to file you want to upload')
upload_parser.add_argument('--dry-run', action='store_true',
help='Check if file already exists on GCS without '
'uploading it and output DEP blob.')
upload_parser.add_argument('-f',
'--force',
action='store_true',
help='Force upload even if remote file exists.')
get_deps_parser = subparsers.add_parser('get_deps', help='Print deps entry for a single file')
get_deps_parser.add_argument('filepath', help='Path to test data file you want the deps entry for.')
subparsers.add_parser('get_all_deps', help='Print deps entry for all files in `base/tracing/test/data/`')
args = parser.parse_args()
if args.cmd == 'get_all_deps':
print(json.dumps(generate_all_deps(), indent=2).replace('"', "'"))
return
filepath = os.path.abspath(args.filepath)
assert os.path.dirname(filepath) == TEST_DATA_PATH, ('You can only '
'upload files in base/tracing/test/data/')
if args.cmd == 'upload':
upload_file(filepath, args.dry_run, args.force)
elif args.cmd == 'get_deps':
print(json.dumps(generate_deps_entry(filepath), indent=2).replace('"', "'"))
if __name__ == '__main__':
sys.exit(main())