mirror of
https://github.com/servo/servo.git
synced 2025-08-29 17:18:23 +01:00
mach: Improve test-speedometer error reporting (#38887)
Currently speedometer results are parsed by parsing the console output from stdout (or a file in the case of ohos). Currently json decode errors just cause mach to crash. Instead print an error message, point to the problematic location and exit. A crash can happen if something else also prints, e.g. on macos, we have the `xx threads are still running` message at shutdown. Hence this PR doesn't really fix the unreliable nature of the current implementation, but at least adds a helpful error message, which would point people in the right direction. Testing: test-speedometer is run in CI --------- Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
parent
0e38538bf2
commit
0a8146143a
1 changed files with 50 additions and 19 deletions
|
@ -113,6 +113,22 @@ def format_with_rustfmt(check_only: bool = True) -> int:
|
|||
)
|
||||
|
||||
|
||||
def pretty_print_json_decode_error(error: json.decoder.JSONDecodeError) -> None:
|
||||
print(f"json decode error: {error}")
|
||||
# Print section around that character that raised the json decode error.
|
||||
snippet_radius = 25
|
||||
start, stop = max(0, error.pos - snippet_radius), error.pos + snippet_radius
|
||||
snippet = error.doc[start:stop]
|
||||
print("```")
|
||||
prefix = "... " if start != 0 else ""
|
||||
suffix = " ..." if stop < len(error.doc) else ""
|
||||
print(prefix, snippet, suffix, sep="")
|
||||
# If the snippet is multiline, this won't work as expected, but it's a best effort.
|
||||
right_justification = snippet_radius + 1 + len(suffix)
|
||||
print("^ Offending character".rjust(right_justification))
|
||||
print("```")
|
||||
|
||||
|
||||
@CommandProvider
|
||||
class MachCommands(CommandBase):
|
||||
DEFAULT_RENDER_MODE = "cpu"
|
||||
|
@ -617,8 +633,7 @@ class MachCommands(CommandBase):
|
|||
json.dump(output, f, indent=4)
|
||||
|
||||
def speedometer_runner(self, binary: str, bmf_output: str | None) -> None:
|
||||
speedometer = json.loads(
|
||||
subprocess.check_output(
|
||||
output = subprocess.check_output(
|
||||
[
|
||||
binary,
|
||||
"https://servospeedometer.netlify.app?headless=1",
|
||||
|
@ -627,9 +642,16 @@ class MachCommands(CommandBase):
|
|||
"--window-size=1100x900",
|
||||
"--headless",
|
||||
],
|
||||
encoding="utf-8",
|
||||
timeout=120,
|
||||
).decode()
|
||||
)
|
||||
try:
|
||||
speedometer = json.loads(output)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
pretty_print_json_decode_error(e)
|
||||
print("Error: Failed to parse speedometer results")
|
||||
print("This can happen if other log messages are printed while running servo...")
|
||||
exit(1)
|
||||
|
||||
print(f"Score: {speedometer['Score']['mean']} ± {speedometer['Score']['delta']}")
|
||||
|
||||
|
@ -646,13 +668,13 @@ class MachCommands(CommandBase):
|
|||
hdc_path = path.join(ohos_sdk_native, "../", "toolchains", "hdc")
|
||||
|
||||
def read_log_file(hdc_path: str) -> str:
|
||||
subprocess.call([hdc_path, "file", "recv", log_path])
|
||||
subprocess.call([hdc_path, "file", "recv", log_path, "servo.log"])
|
||||
file = ""
|
||||
try:
|
||||
file = open("servo.log")
|
||||
with open("servo.log") as file:
|
||||
return file.read()
|
||||
except OSError:
|
||||
return ""
|
||||
return file.read()
|
||||
|
||||
subprocess.call([hdc_path, "shell", "aa", "force-stop", "org.servo.servo"])
|
||||
|
||||
|
@ -681,9 +703,6 @@ class MachCommands(CommandBase):
|
|||
|
||||
# A current (2025-06-23) run took 3m 49s = 229s. We keep a safety margin
|
||||
# but we will exit earlier if we see "{"
|
||||
# Currently ohos has a bug where the event loop gets stuck. We produce a
|
||||
# touch event every minute to prevent this
|
||||
# See https://github.com/servo/servo/issues/37727
|
||||
whole_file: str = ""
|
||||
for i in range(10):
|
||||
sleep(30)
|
||||
|
@ -694,9 +713,21 @@ class MachCommands(CommandBase):
|
|||
sleep(2)
|
||||
whole_file = read_log_file(hdc_path)
|
||||
break
|
||||
else:
|
||||
print("Error failed to find console logs in log file")
|
||||
print(f"log-file contents: `{whole_file}`")
|
||||
exit(1)
|
||||
start_index: int = whole_file.index("[INFO script::dom::console]") + len("[INFO script::dom::console]") + 1
|
||||
json_string = whole_file[start_index:]
|
||||
try:
|
||||
speedometer = json.loads(json_string)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print(f"Error: Failed to convert log output to JSON: {e}")
|
||||
pretty_print_json_decode_error(e)
|
||||
print("Error: Failed to parse speedometer results")
|
||||
print("This can happen if other log messages are printed while running servo...")
|
||||
exit(1)
|
||||
|
||||
print(f"Score: {speedometer['Score']['mean']} ± {speedometer['Score']['delta']}")
|
||||
if bmf_output:
|
||||
self.speedometer_to_bmf(speedometer, bmf_output, profile)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue