Skip to content

Commit 7aa17df

Browse files
committed
Auto merge of #124695 - erickt:bump-fuchsia, r=tmandry
Fuchsia test runner: fixup script This commit fixes several issues in the fuchsia-test-runner.py script: 1. Migrate from `pm` to `ffx` for package management, as `pm` is now deprecated. Furthermore, the `pm` calls used in this script no longer work at Fuchsia's HEAD. This is the largest change in this commit, and impacts all steps around repository management (creation and registration of the repo, as well as package publishing). 2. Allow for `libtest` to be either statically or dynamically linked. The script assumed it was dynamically linked, but the current Rust behavior at HEAD is to statically link it. 3. Minor cleanup to use `ffx --machine json` rather than string parsing. 4. Minor cleanup to the docs around the script.
2 parents 5ce96b1 + f44d611 commit 7aa17df

File tree

2 files changed

+111
-93
lines changed

2 files changed

+111
-93
lines changed

src/ci/docker/scripts/fuchsia-test-runner.py

+93-87
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@
99

1010
import argparse
1111
from dataclasses import dataclass
12-
import fcntl
1312
import glob
1413
import hashlib
15-
import io
1614
import json
1715
import os
1816
import platform
@@ -143,6 +141,14 @@ def subprocess_output(self):
143141
return sys.stdout
144142
return subprocess.DEVNULL
145143

144+
def check_call(self, args, **kwargs):
145+
self.log_info(f"Running: {' '.join(args)}")
146+
return subprocess.check_call(args, **kwargs)
147+
148+
def check_output(self, args, **kwargs):
149+
self.log_info(f"Running: {' '.join(args)}")
150+
return subprocess.check_output(args, **kwargs)
151+
146152
def ffx_daemon_log_path(self):
147153
return os.path.join(self.tmp_dir(), "ffx_daemon_log")
148154

@@ -178,7 +184,7 @@ def start_ffx_isolation(self):
178184
)
179185

180186
# Disable analytics
181-
subprocess.check_call(
187+
self.check_call(
182188
[
183189
ffx_path,
184190
"config",
@@ -197,7 +203,7 @@ def start_ffx_isolation(self):
197203
"test.experimental_structured_output": "true",
198204
}
199205
for key, value in configs.items():
200-
subprocess.check_call(
206+
self.check_call(
201207
[
202208
ffx_path,
203209
"config",
@@ -222,7 +228,7 @@ def ffx_cmd_env(self):
222228
}
223229

224230
def stop_ffx_isolation(self):
225-
subprocess.check_call(
231+
self.check_call(
226232
[
227233
self.tool_path("ffx"),
228234
"daemon",
@@ -265,7 +271,7 @@ def start(self):
265271
self.start_ffx_isolation()
266272

267273
# Stop any running emulators (there shouldn't be any)
268-
subprocess.check_call(
274+
self.check_call(
269275
[
270276
ffx_path,
271277
"emu",
@@ -282,11 +288,11 @@ def start(self):
282288
product_name = "minimal." + self.triple_to_arch(self.target)
283289
fuchsia_version = "20.20240412.3.1"
284290

285-
# FIXME: We should be able to replace this with the machine parsable
286-
# `ffx --machine json product lookup ...` once F15 is released.
287-
out = subprocess.check_output(
291+
out = self.check_output(
288292
[
289293
ffx_path,
294+
"--machine",
295+
"json",
290296
"product",
291297
"lookup",
292298
product_name,
@@ -300,16 +306,15 @@ def start(self):
300306

301307
self.log_debug(out)
302308

303-
for line in io.BytesIO(out):
304-
if line.startswith(b"gs://"):
305-
transfer_manifest_url = line.rstrip()
306-
break
307-
else:
308-
raise Exception("Unable to parse transfer manifest")
309+
try:
310+
transfer_manifest_url = json.loads(out)["transfer_manifest_url"]
311+
except Exception as e:
312+
print(e)
313+
raise Exception("Unable to parse transfer manifest") from e
309314

310315
# Download the product bundle.
311316
product_bundle_dir = os.path.join(self.tmp_dir(), 'product-bundle')
312-
subprocess.check_call(
317+
self.check_call(
313318
[
314319
ffx_path,
315320
"product",
@@ -325,7 +330,7 @@ def start(self):
325330

326331
# Start emulator
327332
# FIXME: condition --accel hyper on target arch matching host arch
328-
subprocess.check_call(
333+
self.check_call(
329334
[
330335
ffx_path,
331336
"emu",
@@ -346,42 +351,52 @@ def start(self):
346351

347352
# Create new package repo
348353
self.log_info("Creating package repo...")
349-
subprocess.check_call(
354+
self.check_call(
350355
[
351-
self.tool_path("pm"),
352-
"newrepo",
353-
"-repo",
356+
ffx_path,
357+
"repository",
358+
"create",
354359
self.repo_dir(),
355360
],
361+
env=ffx_env,
356362
stdout=self.subprocess_output(),
357363
stderr=self.subprocess_output(),
358364
)
359365

360-
# Add repo
361-
subprocess.check_call(
366+
self.check_call(
362367
[
363368
ffx_path,
364369
"repository",
365370
"add-from-pm",
366-
self.repo_dir(),
367371
"--repository",
368372
self.TEST_REPO_NAME,
373+
self.repo_dir(),
369374
],
370375
env=ffx_env,
371376
stdout=self.subprocess_output(),
372377
stderr=self.subprocess_output(),
373378
)
374379

380+
# Write to file
381+
self.write_to_file()
382+
375383
# Start repository server
376-
subprocess.check_call(
377-
[ffx_path, "repository", "server", "start", "--address", "[::]:0"],
384+
self.check_call(
385+
[
386+
ffx_path,
387+
"repository",
388+
"server",
389+
"start",
390+
"--address",
391+
"[::]:0",
392+
],
378393
env=ffx_env,
379394
stdout=self.subprocess_output(),
380395
stderr=self.subprocess_output(),
381396
)
382397

383398
# Register with newly-started emulator
384-
subprocess.check_call(
399+
self.check_call(
385400
[
386401
ffx_path,
387402
"target",
@@ -395,12 +410,6 @@ def start(self):
395410
stderr=self.subprocess_output(),
396411
)
397412

398-
# Create lockfiles
399-
open(self.pm_lockfile_path(), "a").close()
400-
401-
# Write to file
402-
self.write_to_file()
403-
404413
self.log_info("Success! Your environment is ready to run tests.")
405414

406415
# FIXME: shardify this
@@ -445,7 +454,6 @@ def start(self):
445454
meta/{package_name}.cm={package_dir}/meta/{package_name}.cm
446455
bin/{exe_name}={bin_path}
447456
lib/{libstd_name}={libstd_path}
448-
lib/{libtest_name}={libtest_path}
449457
lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/dist/lib/ld.so.1
450458
lib/libfdio.so={sdk_dir}/arch/{target_arch}/dist/libfdio.so
451459
"""
@@ -482,9 +490,6 @@ def run(self, args):
482490
if not libstd_paths:
483491
raise Exception(f"Failed to locate libstd (in {self.rustlibs_dir()})")
484492

485-
if not libtest_paths:
486-
raise Exception(f"Failed to locate libtest (in {self.rustlibs_dir()})")
487-
488493
# Build a unique, deterministic name for the test using the name of the
489494
# binary and the last 6 hex digits of the hash of the full path
490495
def path_checksum(path):
@@ -500,6 +505,7 @@ def path_checksum(path):
500505
cml_path = os.path.join(package_dir, "meta", f"{package_name}.cml")
501506
cm_path = os.path.join(package_dir, "meta", f"{package_name}.cm")
502507
manifest_path = os.path.join(package_dir, f"{package_name}.manifest")
508+
manifest_json_path = os.path.join(package_dir, "package_manifest.json")
503509
far_path = os.path.join(package_dir, f"{package_name}-0.far")
504510

505511
shared_libs = args.shared_libs[: args.n]
@@ -523,22 +529,6 @@ def log(msg):
523529

524530
log(f"Bin path: {bin_path}")
525531

526-
log("Setting up package...")
527-
528-
# Set up package
529-
subprocess.check_call(
530-
[
531-
self.tool_path("pm"),
532-
"-o",
533-
package_dir,
534-
"-n",
535-
package_name,
536-
"init",
537-
],
538-
stdout=log_file,
539-
stderr=log_file,
540-
)
541-
542532
log("Writing CML...")
543533

544534
# Write and compile CML
@@ -563,7 +553,7 @@ def log(msg):
563553

564554
log("Compiling CML...")
565555

566-
subprocess.check_call(
556+
self.check_call(
567557
[
568558
self.tool_path("cmc"),
569559
"compile",
@@ -590,64 +580,80 @@ def log(msg):
590580
target=self.target,
591581
sdk_dir=self.sdk_dir,
592582
libstd_name=os.path.basename(libstd_paths[0]),
593-
libtest_name=os.path.basename(libtest_paths[0]),
594583
libstd_path=libstd_paths[0],
595-
libtest_path=libtest_paths[0],
596584
target_arch=self.triple_to_arch(self.target),
597585
)
598586
)
587+
# `libtest`` was historically a shared library, but now seems to be (sometimes?)
588+
# statically linked. If we find it as a shared library, include it in the manifest.
589+
if libtest_paths:
590+
manifest.write(
591+
f"lib/{os.path.basename(libtest_paths[0])}={libtest_paths[0]}\n"
592+
)
599593
for shared_lib in shared_libs:
600594
manifest.write(f"lib/{os.path.basename(shared_lib)}={shared_lib}\n")
601595

596+
log("Determining API level...")
597+
out = self.check_output(
598+
[
599+
self.tool_path("ffx"),
600+
"--machine",
601+
"json",
602+
"version",
603+
],
604+
env=self.ffx_cmd_env(),
605+
stderr=log_file,
606+
)
607+
api_level = json.loads(out)["tool_version"]["api_level"]
608+
602609
log("Compiling and archiving manifest...")
603610

604-
subprocess.check_call(
611+
self.check_call(
605612
[
606-
self.tool_path("pm"),
613+
self.tool_path("ffx"),
614+
"package",
615+
"build",
616+
manifest_path,
607617
"-o",
608618
package_dir,
609-
"-m",
610-
manifest_path,
611-
"build",
619+
"--api-level",
620+
str(api_level),
612621
],
622+
env=self.ffx_cmd_env(),
613623
stdout=log_file,
614624
stderr=log_file,
615625
)
616-
subprocess.check_call(
626+
627+
self.check_call(
617628
[
618-
self.tool_path("pm"),
619-
"-o",
620-
package_dir,
621-
"-m",
622-
manifest_path,
629+
self.tool_path("ffx"),
630+
"package",
623631
"archive",
632+
"create",
633+
"-o",
634+
far_path,
635+
manifest_json_path,
624636
],
637+
env=self.ffx_cmd_env(),
625638
stdout=log_file,
626639
stderr=log_file,
627640
)
628641

629642
log("Publishing package to repo...")
630643

631644
# Publish package to repo
632-
with open(self.pm_lockfile_path(), "w") as pm_lockfile:
633-
fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_EX)
634-
subprocess.check_call(
635-
[
636-
self.tool_path("pm"),
637-
"publish",
638-
"-a",
639-
"-repo",
640-
self.repo_dir(),
641-
"-f",
642-
far_path,
643-
],
644-
stdout=log_file,
645-
stderr=log_file,
646-
)
647-
# This lock should be released automatically when the pm
648-
# lockfile is closed, but we'll be polite and unlock it now
649-
# since the spec leaves some wiggle room.
650-
fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_UN)
645+
self.check_call(
646+
[
647+
self.tool_path("ffx"),
648+
"repository",
649+
"publish",
650+
"--package",
651+
os.path.join(package_dir, "package_manifest.json"),
652+
self.repo_dir(),
653+
],
654+
stdout=log_file,
655+
stderr=log_file,
656+
)
651657

652658
log("Running ffx test...")
653659

@@ -765,7 +771,7 @@ def stop(self):
765771

766772
# Shut down the emulator
767773
self.log_info("Stopping emulator...")
768-
subprocess.check_call(
774+
self.check_call(
769775
[
770776
self.tool_path("ffx"),
771777
"emu",

0 commit comments

Comments
 (0)