• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[
2  {
3    "cmd": [
4      "vpython",
5      "-u",
6      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
7      "--json-output",
8      "/path/to/tmp/json",
9      "ensure-directory",
10      "--mode",
11      "0777",
12      "[START_DIR]/tmp"
13    ],
14    "infra_step": true,
15    "name": "makedirs tmp_dir"
16  },
17  {
18    "cmd": [
19      "python",
20      "-u",
21      "import os\nprint(os.environ.get('SWARMING_BOT_ID', ''))\n"
22    ],
23    "name": "get swarming bot id",
24    "~followup_annotations": [
25      "@@@STEP_LOG_LINE@python.inline@import os@@@",
26      "@@@STEP_LOG_LINE@python.inline@print(os.environ.get('SWARMING_BOT_ID', ''))@@@",
27      "@@@STEP_LOG_END@python.inline@@@"
28    ]
29  },
30  {
31    "cmd": [
32      "/opt/infra-android/tools/adb",
33      "shell",
34      "mkdir",
35      "-p",
36      "/sdcard/revenge_of_the_skiabot/resources"
37    ],
38    "cwd": "[START_DIR]/skia",
39    "env": {
40      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
41      "CHROME_HEADLESS": "1",
42      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
43    },
44    "infra_step": true,
45    "name": "mkdir /sdcard/revenge_of_the_skiabot/resources"
46  },
47  {
48    "cmd": [
49      "python",
50      "-u",
51      "\nimport os\nimport subprocess\nimport sys\nimport time\nADB = sys.argv[1]\ncpu = int(sys.argv[2])\ngov = sys.argv[3]\n\nlog = subprocess.check_output([ADB, 'root'])\n# check for message like 'adbd cannot run as root in production builds'\nprint(log)\nif 'cannot' in log:\n  raise Exception('adb root failed')\n\nsubprocess.check_output([ADB, 'shell', 'echo \"%s\" > '\n    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % (gov, cpu)])\nactual_gov = subprocess.check_output([ADB, 'shell', 'cat '\n    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % cpu]).strip()\nif actual_gov != gov:\n  raise Exception('(actual, expected) (%s, %s)'\n                  % (actual_gov, gov))\n",
52      "/opt/infra-android/tools/adb",
53      "0",
54      "hotplug"
55    ],
56    "env": {
57      "CHROME_HEADLESS": "1",
58      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
59    },
60    "infra_step": true,
61    "name": "Set CPU 0's governor to hotplug",
62    "timeout": 30,
63    "~followup_annotations": [
64      "@@@STEP_LOG_LINE@python.inline@@@@",
65      "@@@STEP_LOG_LINE@python.inline@import os@@@",
66      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
67      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
68      "@@@STEP_LOG_LINE@python.inline@import time@@@",
69      "@@@STEP_LOG_LINE@python.inline@ADB = sys.argv[1]@@@",
70      "@@@STEP_LOG_LINE@python.inline@cpu = int(sys.argv[2])@@@",
71      "@@@STEP_LOG_LINE@python.inline@gov = sys.argv[3]@@@",
72      "@@@STEP_LOG_LINE@python.inline@@@@",
73      "@@@STEP_LOG_LINE@python.inline@log = subprocess.check_output([ADB, 'root'])@@@",
74      "@@@STEP_LOG_LINE@python.inline@# check for message like 'adbd cannot run as root in production builds'@@@",
75      "@@@STEP_LOG_LINE@python.inline@print(log)@@@",
76      "@@@STEP_LOG_LINE@python.inline@if 'cannot' in log:@@@",
77      "@@@STEP_LOG_LINE@python.inline@  raise Exception('adb root failed')@@@",
78      "@@@STEP_LOG_LINE@python.inline@@@@",
79      "@@@STEP_LOG_LINE@python.inline@subprocess.check_output([ADB, 'shell', 'echo \"%s\" > '@@@",
80      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % (gov, cpu)])@@@",
81      "@@@STEP_LOG_LINE@python.inline@actual_gov = subprocess.check_output([ADB, 'shell', 'cat '@@@",
82      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % cpu]).strip()@@@",
83      "@@@STEP_LOG_LINE@python.inline@if actual_gov != gov:@@@",
84      "@@@STEP_LOG_LINE@python.inline@  raise Exception('(actual, expected) (%s, %s)'@@@",
85      "@@@STEP_LOG_LINE@python.inline@                  % (actual_gov, gov))@@@",
86      "@@@STEP_LOG_END@python.inline@@@"
87    ]
88  },
89  {
90    "cmd": [
91      "/opt/infra-android/tools/adb",
92      "push",
93      "[START_DIR]/build/dm",
94      "/data/local/tmp/"
95    ],
96    "cwd": "[START_DIR]/skia",
97    "env": {
98      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
99      "CHROME_HEADLESS": "1",
100      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
101    },
102    "infra_step": true,
103    "name": "push dm"
104  },
105  {
106    "cmd": [
107      "vpython",
108      "-u",
109      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
110      "--json-output",
111      "/path/to/tmp/json",
112      "glob",
113      "[START_DIR]/skia/resources",
114      "*"
115    ],
116    "infra_step": true,
117    "name": "ls [START_DIR]/skia/resources/*",
118    "~followup_annotations": [
119      "@@@STEP_LOG_LINE@glob@[START_DIR]/skia/resources/bar.jpg@@@",
120      "@@@STEP_LOG_LINE@glob@[START_DIR]/skia/resources/foo.png@@@",
121      "@@@STEP_LOG_END@glob@@@"
122    ]
123  },
124  {
125    "cmd": [
126      "/opt/infra-android/tools/adb",
127      "push",
128      "[START_DIR]/skia/resources/bar.jpg",
129      "[START_DIR]/skia/resources/foo.png",
130      "/sdcard/revenge_of_the_skiabot/resources"
131    ],
132    "cwd": "[START_DIR]/skia",
133    "env": {
134      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
135      "CHROME_HEADLESS": "1",
136      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
137    },
138    "infra_step": true,
139    "name": "push [START_DIR]/skia/resources/* /sdcard/revenge_of_the_skiabot/resources"
140  },
141  {
142    "cmd": [
143      "vpython",
144      "-u",
145      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
146      "--json-output",
147      "/path/to/tmp/json",
148      "copy",
149      "[START_DIR]/skia/infra/bots/assets/lottie-samples/VERSION",
150      "/path/to/tmp/"
151    ],
152    "infra_step": true,
153    "name": "Get lottie-samples VERSION",
154    "~followup_annotations": [
155      "@@@STEP_LOG_LINE@VERSION@42@@@",
156      "@@@STEP_LOG_END@VERSION@@@"
157    ]
158  },
159  {
160    "cmd": [
161      "vpython",
162      "-u",
163      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
164      "--json-output",
165      "/path/to/tmp/json",
166      "copy",
167      "42",
168      "[START_DIR]/tmp/LOTTIE_VERSION"
169    ],
170    "infra_step": true,
171    "name": "write LOTTIE_VERSION",
172    "~followup_annotations": [
173      "@@@STEP_LOG_LINE@LOTTIE_VERSION@42@@@",
174      "@@@STEP_LOG_END@LOTTIE_VERSION@@@"
175    ]
176  },
177  {
178    "cmd": [
179      "/opt/infra-android/tools/adb",
180      "shell",
181      "cat",
182      "/sdcard/revenge_of_the_skiabot/LOTTIE_VERSION"
183    ],
184    "cwd": "[START_DIR]/skia",
185    "env": {
186      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
187      "CHROME_HEADLESS": "1",
188      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
189    },
190    "infra_step": true,
191    "name": "read /sdcard/revenge_of_the_skiabot/LOTTIE_VERSION"
192  },
193  {
194    "cmd": [
195      "python",
196      "-u",
197      "\nimport subprocess\nimport sys\n\n# Remove the path.\nadb = sys.argv[1]\npath = sys.argv[2]\nprint('Removing %s' % path)\ncmd = [adb, 'shell', 'rm', '-rf', path]\nprint(' '.join(cmd))\nsubprocess.check_call(cmd)\n\n# Verify that the path was deleted.\nprint('Checking for existence of %s' % path)\ncmd = [adb, 'shell', 'ls', path]\nprint(' '.join(cmd))\ntry:\n  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)\nexcept subprocess.CalledProcessError as e:\n  output = e.output\nprint('Output was:')\nprint('======')\nprint(output)\nprint('======')\nif 'No such file or directory' not in output:\n  raise Exception('%s exists despite being deleted' % path)\n",
198      "/opt/infra-android/tools/adb",
199      "/sdcard/revenge_of_the_skiabot/LOTTIE_VERSION"
200    ],
201    "env": {
202      "CHROME_HEADLESS": "1",
203      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
204    },
205    "infra_step": true,
206    "name": "rm /sdcard/revenge_of_the_skiabot/LOTTIE_VERSION",
207    "~followup_annotations": [
208      "@@@STEP_LOG_LINE@python.inline@@@@",
209      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
210      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
211      "@@@STEP_LOG_LINE@python.inline@@@@",
212      "@@@STEP_LOG_LINE@python.inline@# Remove the path.@@@",
213      "@@@STEP_LOG_LINE@python.inline@adb = sys.argv[1]@@@",
214      "@@@STEP_LOG_LINE@python.inline@path = sys.argv[2]@@@",
215      "@@@STEP_LOG_LINE@python.inline@print('Removing %s' % path)@@@",
216      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'rm', '-rf', path]@@@",
217      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
218      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(cmd)@@@",
219      "@@@STEP_LOG_LINE@python.inline@@@@",
220      "@@@STEP_LOG_LINE@python.inline@# Verify that the path was deleted.@@@",
221      "@@@STEP_LOG_LINE@python.inline@print('Checking for existence of %s' % path)@@@",
222      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'ls', path]@@@",
223      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
224      "@@@STEP_LOG_LINE@python.inline@try:@@@",
225      "@@@STEP_LOG_LINE@python.inline@  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)@@@",
226      "@@@STEP_LOG_LINE@python.inline@except subprocess.CalledProcessError as e:@@@",
227      "@@@STEP_LOG_LINE@python.inline@  output = e.output@@@",
228      "@@@STEP_LOG_LINE@python.inline@print('Output was:')@@@",
229      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
230      "@@@STEP_LOG_LINE@python.inline@print(output)@@@",
231      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
232      "@@@STEP_LOG_LINE@python.inline@if 'No such file or directory' not in output:@@@",
233      "@@@STEP_LOG_LINE@python.inline@  raise Exception('%s exists despite being deleted' % path)@@@",
234      "@@@STEP_LOG_END@python.inline@@@"
235    ]
236  },
237  {
238    "cmd": [
239      "python",
240      "-u",
241      "\nimport subprocess\nimport sys\n\n# Remove the path.\nadb = sys.argv[1]\npath = sys.argv[2]\nprint('Removing %s' % path)\ncmd = [adb, 'shell', 'rm', '-rf', path]\nprint(' '.join(cmd))\nsubprocess.check_call(cmd)\n\n# Verify that the path was deleted.\nprint('Checking for existence of %s' % path)\ncmd = [adb, 'shell', 'ls', path]\nprint(' '.join(cmd))\ntry:\n  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)\nexcept subprocess.CalledProcessError as e:\n  output = e.output\nprint('Output was:')\nprint('======')\nprint(output)\nprint('======')\nif 'No such file or directory' not in output:\n  raise Exception('%s exists despite being deleted' % path)\n",
242      "/opt/infra-android/tools/adb",
243      "/sdcard/revenge_of_the_skiabot/lotties"
244    ],
245    "env": {
246      "CHROME_HEADLESS": "1",
247      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
248    },
249    "infra_step": true,
250    "name": "rm /sdcard/revenge_of_the_skiabot/lotties",
251    "~followup_annotations": [
252      "@@@STEP_LOG_LINE@python.inline@@@@",
253      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
254      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
255      "@@@STEP_LOG_LINE@python.inline@@@@",
256      "@@@STEP_LOG_LINE@python.inline@# Remove the path.@@@",
257      "@@@STEP_LOG_LINE@python.inline@adb = sys.argv[1]@@@",
258      "@@@STEP_LOG_LINE@python.inline@path = sys.argv[2]@@@",
259      "@@@STEP_LOG_LINE@python.inline@print('Removing %s' % path)@@@",
260      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'rm', '-rf', path]@@@",
261      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
262      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(cmd)@@@",
263      "@@@STEP_LOG_LINE@python.inline@@@@",
264      "@@@STEP_LOG_LINE@python.inline@# Verify that the path was deleted.@@@",
265      "@@@STEP_LOG_LINE@python.inline@print('Checking for existence of %s' % path)@@@",
266      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'ls', path]@@@",
267      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
268      "@@@STEP_LOG_LINE@python.inline@try:@@@",
269      "@@@STEP_LOG_LINE@python.inline@  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)@@@",
270      "@@@STEP_LOG_LINE@python.inline@except subprocess.CalledProcessError as e:@@@",
271      "@@@STEP_LOG_LINE@python.inline@  output = e.output@@@",
272      "@@@STEP_LOG_LINE@python.inline@print('Output was:')@@@",
273      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
274      "@@@STEP_LOG_LINE@python.inline@print(output)@@@",
275      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
276      "@@@STEP_LOG_LINE@python.inline@if 'No such file or directory' not in output:@@@",
277      "@@@STEP_LOG_LINE@python.inline@  raise Exception('%s exists despite being deleted' % path)@@@",
278      "@@@STEP_LOG_END@python.inline@@@"
279    ]
280  },
281  {
282    "cmd": [
283      "/opt/infra-android/tools/adb",
284      "shell",
285      "mkdir",
286      "-p",
287      "/sdcard/revenge_of_the_skiabot/lotties"
288    ],
289    "cwd": "[START_DIR]/skia",
290    "env": {
291      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
292      "CHROME_HEADLESS": "1",
293      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
294    },
295    "infra_step": true,
296    "name": "mkdir /sdcard/revenge_of_the_skiabot/lotties"
297  },
298  {
299    "cmd": [
300      "vpython",
301      "-u",
302      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
303      "--json-output",
304      "/path/to/tmp/json",
305      "glob",
306      "[START_DIR]/lottie-samples",
307      "*"
308    ],
309    "infra_step": true,
310    "name": "ls [START_DIR]/lottie-samples/*",
311    "~followup_annotations": [
312      "@@@STEP_LOG_LINE@glob@[START_DIR]/lottie-samples/bar.jpg@@@",
313      "@@@STEP_LOG_LINE@glob@[START_DIR]/lottie-samples/foo.png@@@",
314      "@@@STEP_LOG_END@glob@@@"
315    ]
316  },
317  {
318    "cmd": [
319      "/opt/infra-android/tools/adb",
320      "push",
321      "[START_DIR]/lottie-samples/bar.jpg",
322      "[START_DIR]/lottie-samples/foo.png",
323      "/sdcard/revenge_of_the_skiabot/lotties"
324    ],
325    "cwd": "[START_DIR]/skia",
326    "env": {
327      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
328      "CHROME_HEADLESS": "1",
329      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
330    },
331    "infra_step": true,
332    "name": "push [START_DIR]/lottie-samples/* /sdcard/revenge_of_the_skiabot/lotties"
333  },
334  {
335    "cmd": [
336      "/opt/infra-android/tools/adb",
337      "push",
338      "[START_DIR]/tmp/LOTTIE_VERSION",
339      "/sdcard/revenge_of_the_skiabot/LOTTIE_VERSION"
340    ],
341    "cwd": "[START_DIR]/skia",
342    "env": {
343      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
344      "CHROME_HEADLESS": "1",
345      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
346    },
347    "infra_step": true,
348    "name": "push [START_DIR]/tmp/LOTTIE_VERSION /sdcard/revenge_of_the_skiabot/LOTTIE_VERSION"
349  },
350  {
351    "cmd": [
352      "python",
353      "-u",
354      "\nimport subprocess\nimport sys\n\n# Remove the path.\nadb = sys.argv[1]\npath = sys.argv[2]\nprint('Removing %s' % path)\ncmd = [adb, 'shell', 'rm', '-rf', path]\nprint(' '.join(cmd))\nsubprocess.check_call(cmd)\n\n# Verify that the path was deleted.\nprint('Checking for existence of %s' % path)\ncmd = [adb, 'shell', 'ls', path]\nprint(' '.join(cmd))\ntry:\n  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)\nexcept subprocess.CalledProcessError as e:\n  output = e.output\nprint('Output was:')\nprint('======')\nprint(output)\nprint('======')\nif 'No such file or directory' not in output:\n  raise Exception('%s exists despite being deleted' % path)\n",
355      "/opt/infra-android/tools/adb",
356      "/sdcard/revenge_of_the_skiabot/dm_out"
357    ],
358    "env": {
359      "CHROME_HEADLESS": "1",
360      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
361    },
362    "infra_step": true,
363    "name": "rm /sdcard/revenge_of_the_skiabot/dm_out",
364    "~followup_annotations": [
365      "@@@STEP_LOG_LINE@python.inline@@@@",
366      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
367      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
368      "@@@STEP_LOG_LINE@python.inline@@@@",
369      "@@@STEP_LOG_LINE@python.inline@# Remove the path.@@@",
370      "@@@STEP_LOG_LINE@python.inline@adb = sys.argv[1]@@@",
371      "@@@STEP_LOG_LINE@python.inline@path = sys.argv[2]@@@",
372      "@@@STEP_LOG_LINE@python.inline@print('Removing %s' % path)@@@",
373      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'rm', '-rf', path]@@@",
374      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
375      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(cmd)@@@",
376      "@@@STEP_LOG_LINE@python.inline@@@@",
377      "@@@STEP_LOG_LINE@python.inline@# Verify that the path was deleted.@@@",
378      "@@@STEP_LOG_LINE@python.inline@print('Checking for existence of %s' % path)@@@",
379      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'ls', path]@@@",
380      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
381      "@@@STEP_LOG_LINE@python.inline@try:@@@",
382      "@@@STEP_LOG_LINE@python.inline@  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)@@@",
383      "@@@STEP_LOG_LINE@python.inline@except subprocess.CalledProcessError as e:@@@",
384      "@@@STEP_LOG_LINE@python.inline@  output = e.output@@@",
385      "@@@STEP_LOG_LINE@python.inline@print('Output was:')@@@",
386      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
387      "@@@STEP_LOG_LINE@python.inline@print(output)@@@",
388      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
389      "@@@STEP_LOG_LINE@python.inline@if 'No such file or directory' not in output:@@@",
390      "@@@STEP_LOG_LINE@python.inline@  raise Exception('%s exists despite being deleted' % path)@@@",
391      "@@@STEP_LOG_END@python.inline@@@"
392    ]
393  },
394  {
395    "cmd": [
396      "/opt/infra-android/tools/adb",
397      "shell",
398      "mkdir",
399      "-p",
400      "/sdcard/revenge_of_the_skiabot/dm_out"
401    ],
402    "cwd": "[START_DIR]/skia",
403    "env": {
404      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
405      "CHROME_HEADLESS": "1",
406      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
407    },
408    "infra_step": true,
409    "name": "mkdir /sdcard/revenge_of_the_skiabot/dm_out"
410  },
411  {
412    "cmd": [
413      "vpython",
414      "-u",
415      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
416      "--json-output",
417      "/path/to/tmp/json",
418      "listdir",
419      "[START_DIR]/lottie-samples"
420    ],
421    "infra_step": true,
422    "name": "list lottie files",
423    "~followup_annotations": [
424      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/LICENSE@@@",
425      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie 3!.json@@@",
426      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie(test)'!2.json@@@",
427      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie1.json@@@",
428      "@@@STEP_LOG_END@listdir@@@"
429    ]
430  },
431  {
432    "cmd": [
433      "vpython",
434      "-u",
435      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
436      "--json-output",
437      "/path/to/tmp/json",
438      "copy",
439      "set -x; LD_LIBRARY_PATH=/data/local/tmp/ /data/local/tmp/dm --resourcePath /sdcard/revenge_of_the_skiabot/resources --lotties /sdcard/revenge_of_the_skiabot/lotties --src lottie --nonativeFonts --verbose --traceMatch skottie --trace /sdcard/revenge_of_the_skiabot/dm_out/2.json --match \"^lottie 3!.json$\" --config gles --nocpu; echo $? >/data/local/tmp/rc",
440      "[START_DIR]/tmp/dm.sh"
441    ],
442    "env": {
443      "CHROME_HEADLESS": "1",
444      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
445    },
446    "infra_step": true,
447    "name": "write dm.sh",
448    "~followup_annotations": [
449      "@@@STEP_LOG_LINE@dm.sh@set -x; LD_LIBRARY_PATH=/data/local/tmp/ /data/local/tmp/dm --resourcePath /sdcard/revenge_of_the_skiabot/resources --lotties /sdcard/revenge_of_the_skiabot/lotties --src lottie --nonativeFonts --verbose --traceMatch skottie --trace /sdcard/revenge_of_the_skiabot/dm_out/2.json --match \"^lottie 3!.json$\" --config gles --nocpu; echo $? >/data/local/tmp/rc@@@",
450      "@@@STEP_LOG_END@dm.sh@@@"
451    ]
452  },
453  {
454    "cmd": [
455      "/opt/infra-android/tools/adb",
456      "push",
457      "[START_DIR]/tmp/dm.sh",
458      "/data/local/tmp/"
459    ],
460    "cwd": "[START_DIR]/skia",
461    "env": {
462      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
463      "CHROME_HEADLESS": "1",
464      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
465    },
466    "infra_step": true,
467    "name": "push dm.sh"
468  },
469  {
470    "cmd": [
471      "/opt/infra-android/tools/adb",
472      "logcat",
473      "-c"
474    ],
475    "cwd": "[START_DIR]/skia",
476    "env": {
477      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
478      "CHROME_HEADLESS": "1",
479      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
480    },
481    "infra_step": true,
482    "name": "clear log"
483  },
484  {
485    "cmd": [
486      "python",
487      "-u",
488      "\nimport subprocess\nimport sys\nbin_dir = sys.argv[1]\nsh      = sys.argv[2]\nsubprocess.check_call(['/opt/infra-android/tools/adb', 'shell', 'sh', bin_dir + sh])\ntry:\n  sys.exit(int(subprocess.check_output(['/opt/infra-android/tools/adb', 'shell', 'cat',\n                                        bin_dir + 'rc'])))\nexcept ValueError:\n  print(\"Couldn't read the return code.  Probably killed for OOM.\")\n  sys.exit(1)\n",
489      "/data/local/tmp/",
490      "dm.sh"
491    ],
492    "env": {
493      "CHROME_HEADLESS": "1",
494      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
495    },
496    "name": "dm",
497    "~followup_annotations": [
498      "@@@STEP_LOG_LINE@python.inline@@@@",
499      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
500      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
501      "@@@STEP_LOG_LINE@python.inline@bin_dir = sys.argv[1]@@@",
502      "@@@STEP_LOG_LINE@python.inline@sh      = sys.argv[2]@@@",
503      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(['/opt/infra-android/tools/adb', 'shell', 'sh', bin_dir + sh])@@@",
504      "@@@STEP_LOG_LINE@python.inline@try:@@@",
505      "@@@STEP_LOG_LINE@python.inline@  sys.exit(int(subprocess.check_output(['/opt/infra-android/tools/adb', 'shell', 'cat',@@@",
506      "@@@STEP_LOG_LINE@python.inline@                                        bin_dir + 'rc'])))@@@",
507      "@@@STEP_LOG_LINE@python.inline@except ValueError:@@@",
508      "@@@STEP_LOG_LINE@python.inline@  print(\"Couldn't read the return code.  Probably killed for OOM.\")@@@",
509      "@@@STEP_LOG_LINE@python.inline@  sys.exit(1)@@@",
510      "@@@STEP_LOG_END@python.inline@@@"
511    ]
512  },
513  {
514    "cmd": [
515      "/opt/infra-android/tools/adb",
516      "shell",
517      "cat",
518      "/sdcard/revenge_of_the_skiabot/dm_out/2.json"
519    ],
520    "cwd": "[START_DIR]/skia",
521    "env": {
522      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
523      "CHROME_HEADLESS": "1",
524      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
525    },
526    "infra_step": true,
527    "name": "read /sdcard/revenge_of_the_skiabot/dm_out/2.json"
528  },
529  {
530    "cmd": [
531      "python",
532      "-u",
533      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\ntrace_json = json.loads(trace_output)\nlottie_filename = sys.argv[2]\noutput_json_file = sys.argv[3]\n\nperf_results = {}\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_start = False\nfor trace in trace_json:\n  if 'skottie::Animation::seek' in trace['name']:\n    if frame_start:\n      raise Exception('We got consecutive Animation::seek without a ' +\n                      'render. Something is wrong.')\n    frame_start = True\n    current_frame_duration = trace['dur']\n  elif 'skottie::Animation::render' in trace['name']:\n    if not frame_start:\n      raise Exception('We got an Animation::render without a seek first. ' +\n                      'Something is wrong.')\n\n    current_frame_duration += trace['dur']\n    frame_start = False\n    total_frames += 1\n    frame_max = max(frame_max, current_frame_duration)\n    frame_min = (min(frame_min, current_frame_duration)\n                 if frame_min else current_frame_duration)\n    frame_cumulative += current_frame_duration\n\nexpected_dm_frames = 25\nif total_frames != expected_dm_frames:\n  raise Exception(\n      'Got ' + str(total_frames) + ' frames instead of ' +\n      str(expected_dm_frames))\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/total_frames\n\n# Write perf_results to the output json.\nwith open(output_json_file, 'w') as f:\n  f.write(json.dumps(perf_results))\n",
534      "\n[{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":452,\"dur\":2.57,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPaint(const SkPaint &)\",\"ts\":473,\"dur\":2.67e+03,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.15e+03,\"dur\":2.25,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.15e+03,\"dur\":216,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPath(const SkPath &, const SkPaint &)\",\"ts\":3.35e+03,\"dur\":15.1,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.37e+03,\"dur\":1.17,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.37e+03,\"dur\":140,\"tid\":1,\"pid\":0}]\n",
535      "lottie 3!.json",
536      "/path/to/tmp/json"
537    ],
538    "env": {
539      "CHROME_HEADLESS": "1",
540      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
541    },
542    "name": "parse lottie 3!.json trace",
543    "~followup_annotations": [
544      "@@@STEP_LOG_LINE@json.output@{@@@",
545      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
546      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
547      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
548      "@@@STEP_LOG_LINE@json.output@}@@@",
549      "@@@STEP_LOG_END@json.output@@@",
550      "@@@STEP_LOG_LINE@python.inline@@@@",
551      "@@@STEP_LOG_LINE@python.inline@import json@@@",
552      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
553      "@@@STEP_LOG_LINE@python.inline@@@@",
554      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
555      "@@@STEP_LOG_LINE@python.inline@trace_json = json.loads(trace_output)@@@",
556      "@@@STEP_LOG_LINE@python.inline@lottie_filename = sys.argv[2]@@@",
557      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[3]@@@",
558      "@@@STEP_LOG_LINE@python.inline@@@@",
559      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
560      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
561      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
562      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
563      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
564      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
565      "@@@STEP_LOG_LINE@python.inline@frame_start = False@@@",
566      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json:@@@",
567      "@@@STEP_LOG_LINE@python.inline@  if 'skottie::Animation::seek' in trace['name']:@@@",
568      "@@@STEP_LOG_LINE@python.inline@    if frame_start:@@@",
569      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got consecutive Animation::seek without a ' +@@@",
570      "@@@STEP_LOG_LINE@python.inline@                      'render. Something is wrong.')@@@",
571      "@@@STEP_LOG_LINE@python.inline@    frame_start = True@@@",
572      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration = trace['dur']@@@",
573      "@@@STEP_LOG_LINE@python.inline@  elif 'skottie::Animation::render' in trace['name']:@@@",
574      "@@@STEP_LOG_LINE@python.inline@    if not frame_start:@@@",
575      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got an Animation::render without a seek first. ' +@@@",
576      "@@@STEP_LOG_LINE@python.inline@                      'Something is wrong.')@@@",
577      "@@@STEP_LOG_LINE@python.inline@@@@",
578      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration += trace['dur']@@@",
579      "@@@STEP_LOG_LINE@python.inline@    frame_start = False@@@",
580      "@@@STEP_LOG_LINE@python.inline@    total_frames += 1@@@",
581      "@@@STEP_LOG_LINE@python.inline@    frame_max = max(frame_max, current_frame_duration)@@@",
582      "@@@STEP_LOG_LINE@python.inline@    frame_min = (min(frame_min, current_frame_duration)@@@",
583      "@@@STEP_LOG_LINE@python.inline@                 if frame_min else current_frame_duration)@@@",
584      "@@@STEP_LOG_LINE@python.inline@    frame_cumulative += current_frame_duration@@@",
585      "@@@STEP_LOG_LINE@python.inline@@@@",
586      "@@@STEP_LOG_LINE@python.inline@expected_dm_frames = 25@@@",
587      "@@@STEP_LOG_LINE@python.inline@if total_frames != expected_dm_frames:@@@",
588      "@@@STEP_LOG_LINE@python.inline@  raise Exception(@@@",
589      "@@@STEP_LOG_LINE@python.inline@      'Got ' + str(total_frames) + ' frames instead of ' +@@@",
590      "@@@STEP_LOG_LINE@python.inline@      str(expected_dm_frames))@@@",
591      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
592      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
593      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/total_frames@@@",
594      "@@@STEP_LOG_LINE@python.inline@@@@",
595      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
596      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
597      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
598      "@@@STEP_LOG_END@python.inline@@@"
599    ]
600  },
601  {
602    "cmd": [
603      "python",
604      "-u",
605      "\nimport subprocess\nimport sys\n\n# Remove the path.\nadb = sys.argv[1]\npath = sys.argv[2]\nprint('Removing %s' % path)\ncmd = [adb, 'shell', 'rm', '-rf', path]\nprint(' '.join(cmd))\nsubprocess.check_call(cmd)\n\n# Verify that the path was deleted.\nprint('Checking for existence of %s' % path)\ncmd = [adb, 'shell', 'ls', path]\nprint(' '.join(cmd))\ntry:\n  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)\nexcept subprocess.CalledProcessError as e:\n  output = e.output\nprint('Output was:')\nprint('======')\nprint(output)\nprint('======')\nif 'No such file or directory' not in output:\n  raise Exception('%s exists despite being deleted' % path)\n",
606      "/opt/infra-android/tools/adb",
607      "/sdcard/revenge_of_the_skiabot/dm_out/2.json"
608    ],
609    "env": {
610      "CHROME_HEADLESS": "1",
611      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
612    },
613    "infra_step": true,
614    "name": "rm /sdcard/revenge_of_the_skiabot/dm_out/2.json",
615    "~followup_annotations": [
616      "@@@STEP_LOG_LINE@python.inline@@@@",
617      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
618      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
619      "@@@STEP_LOG_LINE@python.inline@@@@",
620      "@@@STEP_LOG_LINE@python.inline@# Remove the path.@@@",
621      "@@@STEP_LOG_LINE@python.inline@adb = sys.argv[1]@@@",
622      "@@@STEP_LOG_LINE@python.inline@path = sys.argv[2]@@@",
623      "@@@STEP_LOG_LINE@python.inline@print('Removing %s' % path)@@@",
624      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'rm', '-rf', path]@@@",
625      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
626      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(cmd)@@@",
627      "@@@STEP_LOG_LINE@python.inline@@@@",
628      "@@@STEP_LOG_LINE@python.inline@# Verify that the path was deleted.@@@",
629      "@@@STEP_LOG_LINE@python.inline@print('Checking for existence of %s' % path)@@@",
630      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'ls', path]@@@",
631      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
632      "@@@STEP_LOG_LINE@python.inline@try:@@@",
633      "@@@STEP_LOG_LINE@python.inline@  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)@@@",
634      "@@@STEP_LOG_LINE@python.inline@except subprocess.CalledProcessError as e:@@@",
635      "@@@STEP_LOG_LINE@python.inline@  output = e.output@@@",
636      "@@@STEP_LOG_LINE@python.inline@print('Output was:')@@@",
637      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
638      "@@@STEP_LOG_LINE@python.inline@print(output)@@@",
639      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
640      "@@@STEP_LOG_LINE@python.inline@if 'No such file or directory' not in output:@@@",
641      "@@@STEP_LOG_LINE@python.inline@  raise Exception('%s exists despite being deleted' % path)@@@",
642      "@@@STEP_LOG_END@python.inline@@@"
643    ]
644  },
645  {
646    "cmd": [
647      "vpython",
648      "-u",
649      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
650      "--json-output",
651      "/path/to/tmp/json",
652      "copy",
653      "set -x; LD_LIBRARY_PATH=/data/local/tmp/ /data/local/tmp/dm --resourcePath /sdcard/revenge_of_the_skiabot/resources --lotties /sdcard/revenge_of_the_skiabot/lotties --src lottie --nonativeFonts --verbose --traceMatch skottie --trace /sdcard/revenge_of_the_skiabot/dm_out/3.json --match \\^lottie\\(test\\)\\'\\!2\\.json\\$ --config gles --nocpu; echo $? >/data/local/tmp/rc",
654      "[START_DIR]/tmp/dm.sh"
655    ],
656    "env": {
657      "CHROME_HEADLESS": "1",
658      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
659    },
660    "infra_step": true,
661    "name": "write dm.sh (2)",
662    "~followup_annotations": [
663      "@@@STEP_LOG_LINE@dm.sh@set -x; LD_LIBRARY_PATH=/data/local/tmp/ /data/local/tmp/dm --resourcePath /sdcard/revenge_of_the_skiabot/resources --lotties /sdcard/revenge_of_the_skiabot/lotties --src lottie --nonativeFonts --verbose --traceMatch skottie --trace /sdcard/revenge_of_the_skiabot/dm_out/3.json --match \\^lottie\\(test\\)\\'\\!2\\.json\\$ --config gles --nocpu; echo $? >/data/local/tmp/rc@@@",
664      "@@@STEP_LOG_END@dm.sh@@@"
665    ]
666  },
667  {
668    "cmd": [
669      "/opt/infra-android/tools/adb",
670      "push",
671      "[START_DIR]/tmp/dm.sh",
672      "/data/local/tmp/"
673    ],
674    "cwd": "[START_DIR]/skia",
675    "env": {
676      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
677      "CHROME_HEADLESS": "1",
678      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
679    },
680    "infra_step": true,
681    "name": "push dm.sh (2)"
682  },
683  {
684    "cmd": [
685      "/opt/infra-android/tools/adb",
686      "logcat",
687      "-c"
688    ],
689    "cwd": "[START_DIR]/skia",
690    "env": {
691      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
692      "CHROME_HEADLESS": "1",
693      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
694    },
695    "infra_step": true,
696    "name": "clear log (2)"
697  },
698  {
699    "cmd": [
700      "python",
701      "-u",
702      "\nimport subprocess\nimport sys\nbin_dir = sys.argv[1]\nsh      = sys.argv[2]\nsubprocess.check_call(['/opt/infra-android/tools/adb', 'shell', 'sh', bin_dir + sh])\ntry:\n  sys.exit(int(subprocess.check_output(['/opt/infra-android/tools/adb', 'shell', 'cat',\n                                        bin_dir + 'rc'])))\nexcept ValueError:\n  print(\"Couldn't read the return code.  Probably killed for OOM.\")\n  sys.exit(1)\n",
703      "/data/local/tmp/",
704      "dm.sh"
705    ],
706    "env": {
707      "CHROME_HEADLESS": "1",
708      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
709    },
710    "name": "dm (2)",
711    "~followup_annotations": [
712      "@@@STEP_LOG_LINE@python.inline@@@@",
713      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
714      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
715      "@@@STEP_LOG_LINE@python.inline@bin_dir = sys.argv[1]@@@",
716      "@@@STEP_LOG_LINE@python.inline@sh      = sys.argv[2]@@@",
717      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(['/opt/infra-android/tools/adb', 'shell', 'sh', bin_dir + sh])@@@",
718      "@@@STEP_LOG_LINE@python.inline@try:@@@",
719      "@@@STEP_LOG_LINE@python.inline@  sys.exit(int(subprocess.check_output(['/opt/infra-android/tools/adb', 'shell', 'cat',@@@",
720      "@@@STEP_LOG_LINE@python.inline@                                        bin_dir + 'rc'])))@@@",
721      "@@@STEP_LOG_LINE@python.inline@except ValueError:@@@",
722      "@@@STEP_LOG_LINE@python.inline@  print(\"Couldn't read the return code.  Probably killed for OOM.\")@@@",
723      "@@@STEP_LOG_LINE@python.inline@  sys.exit(1)@@@",
724      "@@@STEP_LOG_END@python.inline@@@"
725    ]
726  },
727  {
728    "cmd": [
729      "/opt/infra-android/tools/adb",
730      "shell",
731      "cat",
732      "/sdcard/revenge_of_the_skiabot/dm_out/3.json"
733    ],
734    "cwd": "[START_DIR]/skia",
735    "env": {
736      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
737      "CHROME_HEADLESS": "1",
738      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
739    },
740    "infra_step": true,
741    "name": "read /sdcard/revenge_of_the_skiabot/dm_out/3.json"
742  },
743  {
744    "cmd": [
745      "python",
746      "-u",
747      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\ntrace_json = json.loads(trace_output)\nlottie_filename = sys.argv[2]\noutput_json_file = sys.argv[3]\n\nperf_results = {}\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_start = False\nfor trace in trace_json:\n  if 'skottie::Animation::seek' in trace['name']:\n    if frame_start:\n      raise Exception('We got consecutive Animation::seek without a ' +\n                      'render. Something is wrong.')\n    frame_start = True\n    current_frame_duration = trace['dur']\n  elif 'skottie::Animation::render' in trace['name']:\n    if not frame_start:\n      raise Exception('We got an Animation::render without a seek first. ' +\n                      'Something is wrong.')\n\n    current_frame_duration += trace['dur']\n    frame_start = False\n    total_frames += 1\n    frame_max = max(frame_max, current_frame_duration)\n    frame_min = (min(frame_min, current_frame_duration)\n                 if frame_min else current_frame_duration)\n    frame_cumulative += current_frame_duration\n\nexpected_dm_frames = 25\nif total_frames != expected_dm_frames:\n  raise Exception(\n      'Got ' + str(total_frames) + ' frames instead of ' +\n      str(expected_dm_frames))\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/total_frames\n\n# Write perf_results to the output json.\nwith open(output_json_file, 'w') as f:\n  f.write(json.dumps(perf_results))\n",
748      "\n[{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":452,\"dur\":2.57,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPaint(const SkPaint &)\",\"ts\":473,\"dur\":2.67e+03,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.15e+03,\"dur\":2.25,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.15e+03,\"dur\":216,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPath(const SkPath &, const SkPaint &)\",\"ts\":3.35e+03,\"dur\":15.1,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.37e+03,\"dur\":1.17,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.37e+03,\"dur\":140,\"tid\":1,\"pid\":0}]\n",
749      "lottie(test)'!2.json",
750      "/path/to/tmp/json"
751    ],
752    "env": {
753      "CHROME_HEADLESS": "1",
754      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
755    },
756    "name": "parse lottie(test)'!2.json trace",
757    "~followup_annotations": [
758      "@@@STEP_LOG_LINE@json.output@{@@@",
759      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
760      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
761      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
762      "@@@STEP_LOG_LINE@json.output@}@@@",
763      "@@@STEP_LOG_END@json.output@@@",
764      "@@@STEP_LOG_LINE@python.inline@@@@",
765      "@@@STEP_LOG_LINE@python.inline@import json@@@",
766      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
767      "@@@STEP_LOG_LINE@python.inline@@@@",
768      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
769      "@@@STEP_LOG_LINE@python.inline@trace_json = json.loads(trace_output)@@@",
770      "@@@STEP_LOG_LINE@python.inline@lottie_filename = sys.argv[2]@@@",
771      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[3]@@@",
772      "@@@STEP_LOG_LINE@python.inline@@@@",
773      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
774      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
775      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
776      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
777      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
778      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
779      "@@@STEP_LOG_LINE@python.inline@frame_start = False@@@",
780      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json:@@@",
781      "@@@STEP_LOG_LINE@python.inline@  if 'skottie::Animation::seek' in trace['name']:@@@",
782      "@@@STEP_LOG_LINE@python.inline@    if frame_start:@@@",
783      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got consecutive Animation::seek without a ' +@@@",
784      "@@@STEP_LOG_LINE@python.inline@                      'render. Something is wrong.')@@@",
785      "@@@STEP_LOG_LINE@python.inline@    frame_start = True@@@",
786      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration = trace['dur']@@@",
787      "@@@STEP_LOG_LINE@python.inline@  elif 'skottie::Animation::render' in trace['name']:@@@",
788      "@@@STEP_LOG_LINE@python.inline@    if not frame_start:@@@",
789      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got an Animation::render without a seek first. ' +@@@",
790      "@@@STEP_LOG_LINE@python.inline@                      'Something is wrong.')@@@",
791      "@@@STEP_LOG_LINE@python.inline@@@@",
792      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration += trace['dur']@@@",
793      "@@@STEP_LOG_LINE@python.inline@    frame_start = False@@@",
794      "@@@STEP_LOG_LINE@python.inline@    total_frames += 1@@@",
795      "@@@STEP_LOG_LINE@python.inline@    frame_max = max(frame_max, current_frame_duration)@@@",
796      "@@@STEP_LOG_LINE@python.inline@    frame_min = (min(frame_min, current_frame_duration)@@@",
797      "@@@STEP_LOG_LINE@python.inline@                 if frame_min else current_frame_duration)@@@",
798      "@@@STEP_LOG_LINE@python.inline@    frame_cumulative += current_frame_duration@@@",
799      "@@@STEP_LOG_LINE@python.inline@@@@",
800      "@@@STEP_LOG_LINE@python.inline@expected_dm_frames = 25@@@",
801      "@@@STEP_LOG_LINE@python.inline@if total_frames != expected_dm_frames:@@@",
802      "@@@STEP_LOG_LINE@python.inline@  raise Exception(@@@",
803      "@@@STEP_LOG_LINE@python.inline@      'Got ' + str(total_frames) + ' frames instead of ' +@@@",
804      "@@@STEP_LOG_LINE@python.inline@      str(expected_dm_frames))@@@",
805      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
806      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
807      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/total_frames@@@",
808      "@@@STEP_LOG_LINE@python.inline@@@@",
809      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
810      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
811      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
812      "@@@STEP_LOG_END@python.inline@@@"
813    ]
814  },
815  {
816    "cmd": [
817      "python",
818      "-u",
819      "\nimport subprocess\nimport sys\n\n# Remove the path.\nadb = sys.argv[1]\npath = sys.argv[2]\nprint('Removing %s' % path)\ncmd = [adb, 'shell', 'rm', '-rf', path]\nprint(' '.join(cmd))\nsubprocess.check_call(cmd)\n\n# Verify that the path was deleted.\nprint('Checking for existence of %s' % path)\ncmd = [adb, 'shell', 'ls', path]\nprint(' '.join(cmd))\ntry:\n  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)\nexcept subprocess.CalledProcessError as e:\n  output = e.output\nprint('Output was:')\nprint('======')\nprint(output)\nprint('======')\nif 'No such file or directory' not in output:\n  raise Exception('%s exists despite being deleted' % path)\n",
820      "/opt/infra-android/tools/adb",
821      "/sdcard/revenge_of_the_skiabot/dm_out/3.json"
822    ],
823    "env": {
824      "CHROME_HEADLESS": "1",
825      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
826    },
827    "infra_step": true,
828    "name": "rm /sdcard/revenge_of_the_skiabot/dm_out/3.json",
829    "~followup_annotations": [
830      "@@@STEP_LOG_LINE@python.inline@@@@",
831      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
832      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
833      "@@@STEP_LOG_LINE@python.inline@@@@",
834      "@@@STEP_LOG_LINE@python.inline@# Remove the path.@@@",
835      "@@@STEP_LOG_LINE@python.inline@adb = sys.argv[1]@@@",
836      "@@@STEP_LOG_LINE@python.inline@path = sys.argv[2]@@@",
837      "@@@STEP_LOG_LINE@python.inline@print('Removing %s' % path)@@@",
838      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'rm', '-rf', path]@@@",
839      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
840      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(cmd)@@@",
841      "@@@STEP_LOG_LINE@python.inline@@@@",
842      "@@@STEP_LOG_LINE@python.inline@# Verify that the path was deleted.@@@",
843      "@@@STEP_LOG_LINE@python.inline@print('Checking for existence of %s' % path)@@@",
844      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'ls', path]@@@",
845      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
846      "@@@STEP_LOG_LINE@python.inline@try:@@@",
847      "@@@STEP_LOG_LINE@python.inline@  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)@@@",
848      "@@@STEP_LOG_LINE@python.inline@except subprocess.CalledProcessError as e:@@@",
849      "@@@STEP_LOG_LINE@python.inline@  output = e.output@@@",
850      "@@@STEP_LOG_LINE@python.inline@print('Output was:')@@@",
851      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
852      "@@@STEP_LOG_LINE@python.inline@print(output)@@@",
853      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
854      "@@@STEP_LOG_LINE@python.inline@if 'No such file or directory' not in output:@@@",
855      "@@@STEP_LOG_LINE@python.inline@  raise Exception('%s exists despite being deleted' % path)@@@",
856      "@@@STEP_LOG_END@python.inline@@@"
857    ]
858  },
859  {
860    "cmd": [
861      "vpython",
862      "-u",
863      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
864      "--json-output",
865      "/path/to/tmp/json",
866      "copy",
867      "set -x; LD_LIBRARY_PATH=/data/local/tmp/ /data/local/tmp/dm --resourcePath /sdcard/revenge_of_the_skiabot/resources --lotties /sdcard/revenge_of_the_skiabot/lotties --src lottie --nonativeFonts --verbose --traceMatch skottie --trace /sdcard/revenge_of_the_skiabot/dm_out/4.json --match \\^lottie1\\.json\\$ --config gles --nocpu; echo $? >/data/local/tmp/rc",
868      "[START_DIR]/tmp/dm.sh"
869    ],
870    "env": {
871      "CHROME_HEADLESS": "1",
872      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
873    },
874    "infra_step": true,
875    "name": "write dm.sh (3)",
876    "~followup_annotations": [
877      "@@@STEP_LOG_LINE@dm.sh@set -x; LD_LIBRARY_PATH=/data/local/tmp/ /data/local/tmp/dm --resourcePath /sdcard/revenge_of_the_skiabot/resources --lotties /sdcard/revenge_of_the_skiabot/lotties --src lottie --nonativeFonts --verbose --traceMatch skottie --trace /sdcard/revenge_of_the_skiabot/dm_out/4.json --match \\^lottie1\\.json\\$ --config gles --nocpu; echo $? >/data/local/tmp/rc@@@",
878      "@@@STEP_LOG_END@dm.sh@@@"
879    ]
880  },
881  {
882    "cmd": [
883      "/opt/infra-android/tools/adb",
884      "push",
885      "[START_DIR]/tmp/dm.sh",
886      "/data/local/tmp/"
887    ],
888    "cwd": "[START_DIR]/skia",
889    "env": {
890      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
891      "CHROME_HEADLESS": "1",
892      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
893    },
894    "infra_step": true,
895    "name": "push dm.sh (3)"
896  },
897  {
898    "cmd": [
899      "/opt/infra-android/tools/adb",
900      "logcat",
901      "-c"
902    ],
903    "cwd": "[START_DIR]/skia",
904    "env": {
905      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
906      "CHROME_HEADLESS": "1",
907      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
908    },
909    "infra_step": true,
910    "name": "clear log (3)"
911  },
912  {
913    "cmd": [
914      "python",
915      "-u",
916      "\nimport subprocess\nimport sys\nbin_dir = sys.argv[1]\nsh      = sys.argv[2]\nsubprocess.check_call(['/opt/infra-android/tools/adb', 'shell', 'sh', bin_dir + sh])\ntry:\n  sys.exit(int(subprocess.check_output(['/opt/infra-android/tools/adb', 'shell', 'cat',\n                                        bin_dir + 'rc'])))\nexcept ValueError:\n  print(\"Couldn't read the return code.  Probably killed for OOM.\")\n  sys.exit(1)\n",
917      "/data/local/tmp/",
918      "dm.sh"
919    ],
920    "env": {
921      "CHROME_HEADLESS": "1",
922      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
923    },
924    "name": "dm (3)",
925    "~followup_annotations": [
926      "@@@STEP_LOG_LINE@python.inline@@@@",
927      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
928      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
929      "@@@STEP_LOG_LINE@python.inline@bin_dir = sys.argv[1]@@@",
930      "@@@STEP_LOG_LINE@python.inline@sh      = sys.argv[2]@@@",
931      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(['/opt/infra-android/tools/adb', 'shell', 'sh', bin_dir + sh])@@@",
932      "@@@STEP_LOG_LINE@python.inline@try:@@@",
933      "@@@STEP_LOG_LINE@python.inline@  sys.exit(int(subprocess.check_output(['/opt/infra-android/tools/adb', 'shell', 'cat',@@@",
934      "@@@STEP_LOG_LINE@python.inline@                                        bin_dir + 'rc'])))@@@",
935      "@@@STEP_LOG_LINE@python.inline@except ValueError:@@@",
936      "@@@STEP_LOG_LINE@python.inline@  print(\"Couldn't read the return code.  Probably killed for OOM.\")@@@",
937      "@@@STEP_LOG_LINE@python.inline@  sys.exit(1)@@@",
938      "@@@STEP_LOG_END@python.inline@@@"
939    ]
940  },
941  {
942    "cmd": [
943      "/opt/infra-android/tools/adb",
944      "shell",
945      "cat",
946      "/sdcard/revenge_of_the_skiabot/dm_out/4.json"
947    ],
948    "cwd": "[START_DIR]/skia",
949    "env": {
950      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
951      "CHROME_HEADLESS": "1",
952      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
953    },
954    "infra_step": true,
955    "name": "read /sdcard/revenge_of_the_skiabot/dm_out/4.json"
956  },
957  {
958    "cmd": [
959      "python",
960      "-u",
961      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\ntrace_json = json.loads(trace_output)\nlottie_filename = sys.argv[2]\noutput_json_file = sys.argv[3]\n\nperf_results = {}\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_start = False\nfor trace in trace_json:\n  if 'skottie::Animation::seek' in trace['name']:\n    if frame_start:\n      raise Exception('We got consecutive Animation::seek without a ' +\n                      'render. Something is wrong.')\n    frame_start = True\n    current_frame_duration = trace['dur']\n  elif 'skottie::Animation::render' in trace['name']:\n    if not frame_start:\n      raise Exception('We got an Animation::render without a seek first. ' +\n                      'Something is wrong.')\n\n    current_frame_duration += trace['dur']\n    frame_start = False\n    total_frames += 1\n    frame_max = max(frame_max, current_frame_duration)\n    frame_min = (min(frame_min, current_frame_duration)\n                 if frame_min else current_frame_duration)\n    frame_cumulative += current_frame_duration\n\nexpected_dm_frames = 25\nif total_frames != expected_dm_frames:\n  raise Exception(\n      'Got ' + str(total_frames) + ' frames instead of ' +\n      str(expected_dm_frames))\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/total_frames\n\n# Write perf_results to the output json.\nwith open(output_json_file, 'w') as f:\n  f.write(json.dumps(perf_results))\n",
962      "\n[{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":452,\"dur\":2.57,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPaint(const SkPaint &)\",\"ts\":473,\"dur\":2.67e+03,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.15e+03,\"dur\":2.25,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.15e+03,\"dur\":216,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPath(const SkPath &, const SkPaint &)\",\"ts\":3.35e+03,\"dur\":15.1,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.37e+03,\"dur\":1.17,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.37e+03,\"dur\":140,\"tid\":1,\"pid\":0}]\n",
963      "lottie1.json",
964      "/path/to/tmp/json"
965    ],
966    "env": {
967      "CHROME_HEADLESS": "1",
968      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
969    },
970    "name": "parse lottie1.json trace",
971    "~followup_annotations": [
972      "@@@STEP_LOG_LINE@json.output@{@@@",
973      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
974      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
975      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
976      "@@@STEP_LOG_LINE@json.output@}@@@",
977      "@@@STEP_LOG_END@json.output@@@",
978      "@@@STEP_LOG_LINE@python.inline@@@@",
979      "@@@STEP_LOG_LINE@python.inline@import json@@@",
980      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
981      "@@@STEP_LOG_LINE@python.inline@@@@",
982      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
983      "@@@STEP_LOG_LINE@python.inline@trace_json = json.loads(trace_output)@@@",
984      "@@@STEP_LOG_LINE@python.inline@lottie_filename = sys.argv[2]@@@",
985      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[3]@@@",
986      "@@@STEP_LOG_LINE@python.inline@@@@",
987      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
988      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
989      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
990      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
991      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
992      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
993      "@@@STEP_LOG_LINE@python.inline@frame_start = False@@@",
994      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json:@@@",
995      "@@@STEP_LOG_LINE@python.inline@  if 'skottie::Animation::seek' in trace['name']:@@@",
996      "@@@STEP_LOG_LINE@python.inline@    if frame_start:@@@",
997      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got consecutive Animation::seek without a ' +@@@",
998      "@@@STEP_LOG_LINE@python.inline@                      'render. Something is wrong.')@@@",
999      "@@@STEP_LOG_LINE@python.inline@    frame_start = True@@@",
1000      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration = trace['dur']@@@",
1001      "@@@STEP_LOG_LINE@python.inline@  elif 'skottie::Animation::render' in trace['name']:@@@",
1002      "@@@STEP_LOG_LINE@python.inline@    if not frame_start:@@@",
1003      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got an Animation::render without a seek first. ' +@@@",
1004      "@@@STEP_LOG_LINE@python.inline@                      'Something is wrong.')@@@",
1005      "@@@STEP_LOG_LINE@python.inline@@@@",
1006      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration += trace['dur']@@@",
1007      "@@@STEP_LOG_LINE@python.inline@    frame_start = False@@@",
1008      "@@@STEP_LOG_LINE@python.inline@    total_frames += 1@@@",
1009      "@@@STEP_LOG_LINE@python.inline@    frame_max = max(frame_max, current_frame_duration)@@@",
1010      "@@@STEP_LOG_LINE@python.inline@    frame_min = (min(frame_min, current_frame_duration)@@@",
1011      "@@@STEP_LOG_LINE@python.inline@                 if frame_min else current_frame_duration)@@@",
1012      "@@@STEP_LOG_LINE@python.inline@    frame_cumulative += current_frame_duration@@@",
1013      "@@@STEP_LOG_LINE@python.inline@@@@",
1014      "@@@STEP_LOG_LINE@python.inline@expected_dm_frames = 25@@@",
1015      "@@@STEP_LOG_LINE@python.inline@if total_frames != expected_dm_frames:@@@",
1016      "@@@STEP_LOG_LINE@python.inline@  raise Exception(@@@",
1017      "@@@STEP_LOG_LINE@python.inline@      'Got ' + str(total_frames) + ' frames instead of ' +@@@",
1018      "@@@STEP_LOG_LINE@python.inline@      str(expected_dm_frames))@@@",
1019      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
1020      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
1021      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/total_frames@@@",
1022      "@@@STEP_LOG_LINE@python.inline@@@@",
1023      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
1024      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
1025      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
1026      "@@@STEP_LOG_END@python.inline@@@"
1027    ]
1028  },
1029  {
1030    "cmd": [
1031      "python",
1032      "-u",
1033      "\nimport subprocess\nimport sys\n\n# Remove the path.\nadb = sys.argv[1]\npath = sys.argv[2]\nprint('Removing %s' % path)\ncmd = [adb, 'shell', 'rm', '-rf', path]\nprint(' '.join(cmd))\nsubprocess.check_call(cmd)\n\n# Verify that the path was deleted.\nprint('Checking for existence of %s' % path)\ncmd = [adb, 'shell', 'ls', path]\nprint(' '.join(cmd))\ntry:\n  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)\nexcept subprocess.CalledProcessError as e:\n  output = e.output\nprint('Output was:')\nprint('======')\nprint(output)\nprint('======')\nif 'No such file or directory' not in output:\n  raise Exception('%s exists despite being deleted' % path)\n",
1034      "/opt/infra-android/tools/adb",
1035      "/sdcard/revenge_of_the_skiabot/dm_out/4.json"
1036    ],
1037    "env": {
1038      "CHROME_HEADLESS": "1",
1039      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
1040    },
1041    "infra_step": true,
1042    "name": "rm /sdcard/revenge_of_the_skiabot/dm_out/4.json",
1043    "~followup_annotations": [
1044      "@@@STEP_LOG_LINE@python.inline@@@@",
1045      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
1046      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
1047      "@@@STEP_LOG_LINE@python.inline@@@@",
1048      "@@@STEP_LOG_LINE@python.inline@# Remove the path.@@@",
1049      "@@@STEP_LOG_LINE@python.inline@adb = sys.argv[1]@@@",
1050      "@@@STEP_LOG_LINE@python.inline@path = sys.argv[2]@@@",
1051      "@@@STEP_LOG_LINE@python.inline@print('Removing %s' % path)@@@",
1052      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'rm', '-rf', path]@@@",
1053      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
1054      "@@@STEP_LOG_LINE@python.inline@subprocess.check_call(cmd)@@@",
1055      "@@@STEP_LOG_LINE@python.inline@@@@",
1056      "@@@STEP_LOG_LINE@python.inline@# Verify that the path was deleted.@@@",
1057      "@@@STEP_LOG_LINE@python.inline@print('Checking for existence of %s' % path)@@@",
1058      "@@@STEP_LOG_LINE@python.inline@cmd = [adb, 'shell', 'ls', path]@@@",
1059      "@@@STEP_LOG_LINE@python.inline@print(' '.join(cmd))@@@",
1060      "@@@STEP_LOG_LINE@python.inline@try:@@@",
1061      "@@@STEP_LOG_LINE@python.inline@  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)@@@",
1062      "@@@STEP_LOG_LINE@python.inline@except subprocess.CalledProcessError as e:@@@",
1063      "@@@STEP_LOG_LINE@python.inline@  output = e.output@@@",
1064      "@@@STEP_LOG_LINE@python.inline@print('Output was:')@@@",
1065      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
1066      "@@@STEP_LOG_LINE@python.inline@print(output)@@@",
1067      "@@@STEP_LOG_LINE@python.inline@print('======')@@@",
1068      "@@@STEP_LOG_LINE@python.inline@if 'No such file or directory' not in output:@@@",
1069      "@@@STEP_LOG_LINE@python.inline@  raise Exception('%s exists despite being deleted' % path)@@@",
1070      "@@@STEP_LOG_END@python.inline@@@"
1071    ]
1072  },
1073  {
1074    "cmd": [
1075      "python",
1076      "-u",
1077      "import os\nprint(os.environ.get('SWARMING_BOT_ID', ''))\n"
1078    ],
1079    "name": "get swarming bot id (2)",
1080    "~followup_annotations": [
1081      "@@@STEP_LOG_LINE@python.inline@import os@@@",
1082      "@@@STEP_LOG_LINE@python.inline@print(os.environ.get('SWARMING_BOT_ID', ''))@@@",
1083      "@@@STEP_LOG_END@python.inline@@@"
1084    ]
1085  },
1086  {
1087    "cmd": [
1088      "python",
1089      "-u",
1090      "import os\nprint(os.environ.get('SWARMING_TASK_ID', ''))\n"
1091    ],
1092    "name": "get swarming task id",
1093    "~followup_annotations": [
1094      "@@@STEP_LOG_LINE@python.inline@import os@@@",
1095      "@@@STEP_LOG_LINE@python.inline@print(os.environ.get('SWARMING_TASK_ID', ''))@@@",
1096      "@@@STEP_LOG_END@python.inline@@@"
1097    ]
1098  },
1099  {
1100    "cmd": [
1101      "vpython",
1102      "-u",
1103      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
1104      "--json-output",
1105      "/path/to/tmp/json",
1106      "ensure-directory",
1107      "--mode",
1108      "0777",
1109      "[START_DIR]/[SWARM_OUT_DIR]"
1110    ],
1111    "infra_step": true,
1112    "name": "makedirs perf_dir"
1113  },
1114  {
1115    "cmd": [
1116      "vpython",
1117      "-u",
1118      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
1119      "--json-output",
1120      "/path/to/tmp/json",
1121      "copy",
1122      "{\n    \"gitHash\": \"abc123\",\n    \"key\": {\n        \"arch\": \"arm\",\n        \"bench_type\": \"tracing\",\n        \"compiler\": \"Clang\",\n        \"configuration\": \"Release\",\n        \"cpu_or_gpu\": \"GPU\",\n        \"cpu_or_gpu_value\": \"Mali400MP2\",\n        \"extra_config\": \"Android_SkottieTracing\",\n        \"model\": \"AndroidOne\",\n        \"os\": \"Android\",\n        \"source_type\": \"skottie\"\n    },\n    \"renderer\": \"skottie\",\n    \"results\": {\n        \"lottie 3!.json\": {\n            \"gles\": {\n                \"frame_avg_us\": 179.71,\n                \"frame_max_us\": 218.25,\n                \"frame_min_us\": 141.17\n            }\n        },\n        \"lottie(test)'!2.json\": {\n            \"gles\": {\n                \"frame_avg_us\": 179.71,\n                \"frame_max_us\": 218.25,\n                \"frame_min_us\": 141.17\n            }\n        },\n        \"lottie1.json\": {\n            \"gles\": {\n                \"frame_avg_us\": 179.71,\n                \"frame_max_us\": 218.25,\n                \"frame_min_us\": 141.17\n            }\n        }\n    },\n    \"swarming_bot_id\": \"\",\n    \"swarming_task_id\": \"\"\n}",
1123      "[START_DIR]/[SWARM_OUT_DIR]/perf_abc123_1337000001.json"
1124    ],
1125    "infra_step": true,
1126    "name": "write output JSON",
1127    "~followup_annotations": [
1128      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@{@@@",
1129      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"gitHash\": \"abc123\",@@@",
1130      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"key\": {@@@",
1131      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"arch\": \"arm\",@@@",
1132      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"bench_type\": \"tracing\",@@@",
1133      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"compiler\": \"Clang\",@@@",
1134      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"configuration\": \"Release\",@@@",
1135      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"cpu_or_gpu\": \"GPU\",@@@",
1136      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"cpu_or_gpu_value\": \"Mali400MP2\",@@@",
1137      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"extra_config\": \"Android_SkottieTracing\",@@@",
1138      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"model\": \"AndroidOne\",@@@",
1139      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"os\": \"Android\",@@@",
1140      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"source_type\": \"skottie\"@@@",
1141      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    },@@@",
1142      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"renderer\": \"skottie\",@@@",
1143      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"results\": {@@@",
1144      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"lottie 3!.json\": {@@@",
1145      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            \"gles\": {@@@",
1146      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_avg_us\": 179.71,@@@",
1147      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_max_us\": 218.25,@@@",
1148      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_min_us\": 141.17@@@",
1149      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            }@@@",
1150      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        },@@@",
1151      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"lottie(test)'!2.json\": {@@@",
1152      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            \"gles\": {@@@",
1153      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_avg_us\": 179.71,@@@",
1154      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_max_us\": 218.25,@@@",
1155      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_min_us\": 141.17@@@",
1156      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            }@@@",
1157      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        },@@@",
1158      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"lottie1.json\": {@@@",
1159      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            \"gles\": {@@@",
1160      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_avg_us\": 179.71,@@@",
1161      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_max_us\": 218.25,@@@",
1162      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_min_us\": 141.17@@@",
1163      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            }@@@",
1164      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        }@@@",
1165      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    },@@@",
1166      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"swarming_bot_id\": \"\",@@@",
1167      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"swarming_task_id\": \"\"@@@",
1168      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@}@@@",
1169      "@@@STEP_LOG_END@perf_abc123_1337000001.json@@@"
1170    ]
1171  },
1172  {
1173    "cmd": [
1174      "python",
1175      "-u",
1176      "\nimport os\nimport subprocess\nimport sys\nout = sys.argv[1]\nlog = subprocess.check_output(['/opt/infra-android/tools/adb', 'logcat', '-d'])\nfor line in log.split('\\n'):\n  tokens = line.split()\n  if len(tokens) == 11 and tokens[-7] == 'F' and tokens[-3] == 'pc':\n    addr, path = tokens[-2:]\n    local = os.path.join(out, os.path.basename(path))\n    if os.path.exists(local):\n      try:\n        sym = subprocess.check_output(['addr2line', '-Cfpe', local, addr])\n        line = line.replace(addr, addr + ' ' + sym.strip())\n      except subprocess.CalledProcessError:\n        pass\n  print(line)\n",
1177      "[START_DIR]/build"
1178    ],
1179    "env": {
1180      "CHROME_HEADLESS": "1",
1181      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
1182    },
1183    "infra_step": true,
1184    "name": "dump log",
1185    "timeout": 300,
1186    "~followup_annotations": [
1187      "@@@STEP_LOG_LINE@python.inline@@@@",
1188      "@@@STEP_LOG_LINE@python.inline@import os@@@",
1189      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
1190      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
1191      "@@@STEP_LOG_LINE@python.inline@out = sys.argv[1]@@@",
1192      "@@@STEP_LOG_LINE@python.inline@log = subprocess.check_output(['/opt/infra-android/tools/adb', 'logcat', '-d'])@@@",
1193      "@@@STEP_LOG_LINE@python.inline@for line in log.split('\\n'):@@@",
1194      "@@@STEP_LOG_LINE@python.inline@  tokens = line.split()@@@",
1195      "@@@STEP_LOG_LINE@python.inline@  if len(tokens) == 11 and tokens[-7] == 'F' and tokens[-3] == 'pc':@@@",
1196      "@@@STEP_LOG_LINE@python.inline@    addr, path = tokens[-2:]@@@",
1197      "@@@STEP_LOG_LINE@python.inline@    local = os.path.join(out, os.path.basename(path))@@@",
1198      "@@@STEP_LOG_LINE@python.inline@    if os.path.exists(local):@@@",
1199      "@@@STEP_LOG_LINE@python.inline@      try:@@@",
1200      "@@@STEP_LOG_LINE@python.inline@        sym = subprocess.check_output(['addr2line', '-Cfpe', local, addr])@@@",
1201      "@@@STEP_LOG_LINE@python.inline@        line = line.replace(addr, addr + ' ' + sym.strip())@@@",
1202      "@@@STEP_LOG_LINE@python.inline@      except subprocess.CalledProcessError:@@@",
1203      "@@@STEP_LOG_LINE@python.inline@        pass@@@",
1204      "@@@STEP_LOG_LINE@python.inline@  print(line)@@@",
1205      "@@@STEP_LOG_END@python.inline@@@"
1206    ]
1207  },
1208  {
1209    "cmd": [
1210      "/opt/infra-android/tools/adb",
1211      "kill-server"
1212    ],
1213    "cwd": "[START_DIR]/skia",
1214    "env": {
1215      "ADB_VENDOR_KEYS": "/home/chrome-bot/.android/chrome_infrastructure_adbkey",
1216      "CHROME_HEADLESS": "1",
1217      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
1218    },
1219    "infra_step": true,
1220    "name": "kill adb server"
1221  },
1222  {
1223    "name": "$result"
1224  }
1225]