blob: 5748d3d4ea03e8015d3c15c38136c6ef8d003c69 [file]
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import asyncio
import json
import subprocess
import tempfile
import fidl_fuchsia_tracing as tracing
import fidl_fuchsia_tracing_controller as tracing_controller
import fuchsia_async_extension
from mobly import asserts, test_runner
from mobly_controller import fuchsia_device
from fidl import AsyncSocket
TRACE2JSON = "tracing_runtime_deps/trace2json"
class FuchsiaControllerTests(fuchsia_async_extension.AsyncBaseTestClass):
async def setup_class(self) -> None:
self.fuchsia_devices: list[
fuchsia_device.FuchsiaDevice
] = await self.register_controller(fuchsia_device)
self.device = self.fuchsia_devices[0]
self.device.set_ctx(self)
async def test_fuchsia_device_get_known_categories(self) -> None:
"""Verifies that kernel:vm is an existing category for tracing on the device."""
if self.device.ctx is None:
raise ValueError(f"Device: {self.device.target} has no context")
ch = self.device.ctx.connect_device_proxy(
"core/trace_manager", tracing_controller.ProvisionerMarker
)
controller = tracing_controller.ProvisionerClient(ch)
try:
response = (await controller.get_known_categories()).unwrap()
except AssertionError as e:
raise AssertionError("Error retrieving known categories") from e
categories = response.categories
found_kernel_category = False
for category in categories:
if category.name == "kernel:vm":
found_kernel_category = True
break
asserts.assert_true(
found_kernel_category,
msg="Was not able to find 'kernel.vm' category in known output",
)
async def test_fuchsia_device_tracing_start_stop(self) -> None:
"""Does a simple start and stop of tracing on a device."""
if self.device.ctx is None:
raise ValueError(f"Device: {self.device.target} has no context")
ch = self.device.ctx.connect_device_proxy(
"core/trace_manager", tracing_controller.ProvisionerMarker
)
provisioner = tracing_controller.ProvisionerClient(ch)
categories = [
"blobfs",
"gfx",
"system_metrics",
]
config = tracing_controller.TraceConfig(
buffer_size_megabytes_hint=4,
categories=categories,
buffering_mode=tracing.BufferingMode.ONESHOT,
)
_client, server = self.device.ctx.socket_create()
client = AsyncSocket(_client)
client_end, server_end = self.device.channel_create()
provisioner.initialize_tracing(
controller=server_end.take(), config=config, output=server.take()
)
controller = tracing_controller.SessionClient(client_end)
await controller.start_tracing()
socket_task = asyncio.create_task(client.read_all())
await asyncio.sleep(10)
try:
stop_tracing_response = (
await controller.stop_tracing(write_results=True)
).unwrap()
except AssertionError as e:
raise AssertionError("Error stopping tracing") from e
assert (
stop_tracing_response.provider_stats is not None
), "Stop result provider stats should not be None."
asserts.assert_true(
len(stop_tracing_response.provider_stats) > 0,
msg="Stop result provider stats should not be empty.",
)
# Closing the channel will terminate tracing
controller.close_cleanly()
raw_trace = await socket_task
asserts.assert_equal(type(raw_trace), bytearray)
asserts.assert_true(
len(raw_trace) > 0, msg="Output bytes should not be empty."
)
with tempfile.NamedTemporaryFile(
mode="wb", suffix=".fxt"
) as trace_fxt, tempfile.NamedTemporaryFile(
mode="w+", suffix=".json", encoding="utf8"
) as trace_json:
trace_fxt.write(raw_trace)
trace_fxt.flush()
subprocess.check_call(
[
TRACE2JSON,
f"--input-file={trace_fxt.name}",
f"--output-file={trace_json.name}",
]
)
js_obj = json.load(trace_json)
asserts.assert_true(
js_obj.get("traceEvents") is not None,
"Expected traceEvents to be present",
)
for trace_event in js_obj["traceEvents"]:
trace_cat = trace_event["cat"]
asserts.assert_true(
trace_cat in categories,
msg=f"Found unexpected category that isn't part of trace: {trace_cat}",
)
if __name__ == "__main__":
test_runner.main()