Skip to content

Commit b089741

Browse files
mnkhourierickt
authored andcommitted
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.
1 parent 79734f1 commit b089741

File tree

2 files changed

+114
-94
lines changed

2 files changed

+114
-94
lines changed

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

Lines changed: 96 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ def subprocess_output(self):
143143
return sys.stdout
144144
return subprocess.DEVNULL
145145

146+
def check_call(self, args, **kwargs):
147+
self.log_info(f"Running: {' '.join(args)}")
148+
return subprocess.check_call(args, **kwargs)
149+
150+
def check_output(self, args, **kwargs):
151+
self.log_info(f"Running: {' '.join(args)}")
152+
return subprocess.check_output(args, **kwargs)
153+
146154
def ffx_daemon_log_path(self):
147155
return os.path.join(self.tmp_dir(), "ffx_daemon_log")
148156

@@ -178,7 +186,7 @@ def start_ffx_isolation(self):
178186
)
179187

180188
# Disable analytics
181-
subprocess.check_call(
189+
self.check_call(
182190
[
183191
ffx_path,
184192
"config",
@@ -197,7 +205,7 @@ def start_ffx_isolation(self):
197205
"test.experimental_structured_output": "true",
198206
}
199207
for key, value in configs.items():
200-
subprocess.check_call(
208+
self.check_call(
201209
[
202210
ffx_path,
203211
"config",
@@ -222,7 +230,7 @@ def ffx_cmd_env(self):
222230
}
223231

224232
def stop_ffx_isolation(self):
225-
subprocess.check_call(
233+
self.check_call(
226234
[
227235
self.tool_path("ffx"),
228236
"daemon",
@@ -265,7 +273,7 @@ def start(self):
265273
self.start_ffx_isolation()
266274

267275
# Stop any running emulators (there shouldn't be any)
268-
subprocess.check_call(
276+
self.check_call(
269277
[
270278
ffx_path,
271279
"emu",
@@ -282,11 +290,11 @@ def start(self):
282290
product_name = "minimal." + self.triple_to_arch(self.target)
283291
fuchsia_version = "20.20240412.3.1"
284292

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(
293+
out = self.check_output(
288294
[
289295
ffx_path,
296+
"--machine",
297+
"json",
290298
"product",
291299
"lookup",
292300
product_name,
@@ -300,16 +308,15 @@ def start(self):
300308

301309
self.log_debug(out)
302310

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

310317
# Download the product bundle.
311318
product_bundle_dir = os.path.join(self.tmp_dir(), 'product-bundle')
312-
subprocess.check_call(
319+
self.check_call(
313320
[
314321
ffx_path,
315322
"product",
@@ -325,7 +332,7 @@ def start(self):
325332

326333
# Start emulator
327334
# FIXME: condition --accel hyper on target arch matching host arch
328-
subprocess.check_call(
335+
self.check_call(
329336
[
330337
ffx_path,
331338
"emu",
@@ -346,42 +353,52 @@ def start(self):
346353

347354
# Create new package repo
348355
self.log_info("Creating package repo...")
349-
subprocess.check_call(
356+
self.check_call(
350357
[
351-
self.tool_path("pm"),
352-
"newrepo",
353-
"-repo",
358+
ffx_path,
359+
"repository",
360+
"create",
354361
self.repo_dir(),
355362
],
363+
env=ffx_env,
356364
stdout=self.subprocess_output(),
357365
stderr=self.subprocess_output(),
358366
)
359367

360-
# Add repo
361-
subprocess.check_call(
368+
self.check_call(
362369
[
363370
ffx_path,
364371
"repository",
365372
"add-from-pm",
366-
self.repo_dir(),
367373
"--repository",
368374
self.TEST_REPO_NAME,
375+
self.repo_dir(),
369376
],
370377
env=ffx_env,
371378
stdout=self.subprocess_output(),
372379
stderr=self.subprocess_output(),
373380
)
374381

382+
# Write to file
383+
self.write_to_file()
384+
375385
# Start repository server
376-
subprocess.check_call(
377-
[ffx_path, "repository", "server", "start", "--address", "[::]:0"],
386+
self.check_call(
387+
[
388+
ffx_path,
389+
"repository",
390+
"server",
391+
"start",
392+
"--address",
393+
"[::]:0",
394+
],
378395
env=ffx_env,
379396
stdout=self.subprocess_output(),
380397
stderr=self.subprocess_output(),
381398
)
382399

383400
# Register with newly-started emulator
384-
subprocess.check_call(
401+
self.check_call(
385402
[
386403
ffx_path,
387404
"target",
@@ -395,12 +412,6 @@ def start(self):
395412
stderr=self.subprocess_output(),
396413
)
397414

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

406417
# FIXME: shardify this
@@ -445,7 +456,6 @@ def start(self):
445456
meta/{package_name}.cm={package_dir}/meta/{package_name}.cm
446457
bin/{exe_name}={bin_path}
447458
lib/{libstd_name}={libstd_path}
448-
lib/{libtest_name}={libtest_path}
449459
lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/dist/lib/ld.so.1
450460
lib/libfdio.so={sdk_dir}/arch/{target_arch}/dist/libfdio.so
451461
"""
@@ -482,9 +492,6 @@ def run(self, args):
482492
if not libstd_paths:
483493
raise Exception(f"Failed to locate libstd (in {self.rustlibs_dir()})")
484494

485-
if not libtest_paths:
486-
raise Exception(f"Failed to locate libtest (in {self.rustlibs_dir()})")
487-
488495
# Build a unique, deterministic name for the test using the name of the
489496
# binary and the last 6 hex digits of the hash of the full path
490497
def path_checksum(path):
@@ -500,6 +507,7 @@ def path_checksum(path):
500507
cml_path = os.path.join(package_dir, "meta", f"{package_name}.cml")
501508
cm_path = os.path.join(package_dir, "meta", f"{package_name}.cm")
502509
manifest_path = os.path.join(package_dir, f"{package_name}.manifest")
510+
manifest_json_path = os.path.join(package_dir, f"package_manifest.json")
503511
far_path = os.path.join(package_dir, f"{package_name}-0.far")
504512

505513
shared_libs = args.shared_libs[: args.n]
@@ -523,22 +531,6 @@ def log(msg):
523531

524532
log(f"Bin path: {bin_path}")
525533

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-
542534
log("Writing CML...")
543535

544536
# Write and compile CML
@@ -563,7 +555,7 @@ def log(msg):
563555

564556
log("Compiling CML...")
565557

566-
subprocess.check_call(
558+
self.check_call(
567559
[
568560
self.tool_path("cmc"),
569561
"compile",
@@ -580,8 +572,8 @@ def log(msg):
580572
log("Writing manifest...")
581573

582574
# Write, build, and archive manifest
583-
with open(manifest_path, "w", encoding="utf-8") as manifest:
584-
manifest.write(
575+
with open(manifest_path, "w", encoding="utf-8") as build_manifest:
576+
build_manifest.write(
585577
self.MANIFEST_TEMPLATE.format(
586578
bin_path=bin_path,
587579
exe_name=exe_name,
@@ -590,71 +582,87 @@ def log(msg):
590582
target=self.target,
591583
sdk_dir=self.sdk_dir,
592584
libstd_name=os.path.basename(libstd_paths[0]),
593-
libtest_name=os.path.basename(libtest_paths[0]),
594585
libstd_path=libstd_paths[0],
595-
libtest_path=libtest_paths[0],
596586
target_arch=self.triple_to_arch(self.target),
597587
)
598588
)
589+
# `libtest`` was historically a shared library, but now seems to be (sometimes?)
590+
# statically linked. If we find it as a shared library, include it in the manifest.
591+
if libtest_paths:
592+
manifest.write(
593+
f"lib/{os.path.basename(libtest_paths[0])}={libtest_paths[0]}\n"
594+
)
599595
for shared_lib in shared_libs:
600-
manifest.write(f"lib/{os.path.basename(shared_lib)}={shared_lib}\n")
596+
build_manifest.write(f"lib/{os.path.basename(shared_lib)}={shared_lib}\n")
597+
598+
log("Determining API level...")
599+
out = self.check_output(
600+
[
601+
self.tool_path("ffx"),
602+
"--machine",
603+
"json",
604+
"version",
605+
],
606+
env=self.ffx_cmd_env(),
607+
stderr=log_file,
608+
)
609+
api_level = json.loads(out)["tool_version"]["api_level"]
601610

602611
log("Compiling and archiving manifest...")
603612

604-
subprocess.check_call(
613+
self.check_call(
605614
[
606-
self.tool_path("pm"),
615+
self.tool_path("ffx"),
616+
"package",
617+
"build",
618+
manifest_path,
607619
"-o",
608620
package_dir,
609-
"-m",
610-
manifest_path,
611-
"build",
621+
"--api-level",
622+
str(api_level),
612623
],
624+
env=self.ffx_cmd_env(),
613625
stdout=log_file,
614626
stderr=log_file,
615627
)
616-
subprocess.check_call(
628+
629+
self.check_call(
617630
[
618-
self.tool_path("pm"),
619-
"-o",
620-
package_dir,
621-
"-m",
622-
manifest_path,
631+
self.tool_path("ffx"),
632+
"package",
623633
"archive",
634+
"create",
635+
"-o",
636+
far_path,
637+
manifest_json_path,
624638
],
639+
env=self.ffx_cmd_env(),
625640
stdout=log_file,
626641
stderr=log_file,
627642
)
628643

629644
log("Publishing package to repo...")
630645

631646
# 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)
647+
self.check_call(
648+
[
649+
ffx_path,
650+
"repository",
651+
"publish",
652+
"--package",
653+
os.path.join(package_dir, "package_manifest.json"),
654+
self.repo_dir(),
655+
],
656+
stdout=log_file,
657+
stderr=log_file,
658+
)
651659

652660
log("Running ffx test...")
653661

654662
# Run test on emulator
655663
subprocess.run(
656664
[
657-
self.tool_path("ffx"),
665+
ffx_path,
658666
"test",
659667
"run",
660668
f"fuchsia-pkg://{self.TEST_REPO_NAME}/{package_name}#meta/{package_name}.cm",
@@ -765,7 +773,7 @@ def stop(self):
765773

766774
# Shut down the emulator
767775
self.log_info("Stopping emulator...")
768-
subprocess.check_call(
776+
self.check_call(
769777
[
770778
self.tool_path("ffx"),
771779
"emu",

0 commit comments

Comments
 (0)