// Copyright 2019 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.

#include "multiple_device_test.h"

#include <zircon/errors.h>

#include <string>

#include "component_lifecycle.h"
#include "src/devices/lib/log/log.h"
TEST_F(MultipleDeviceTestCase, UnbindThenSuspend) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURES(
      AddDevice(platform_bus(), "parent-device", 0 /* protocol id */, "", &parent_index));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(device(parent_index)->device, "child-device",
                                     0 /* protocol id */, "", &child_index));

  ASSERT_NO_FATAL_FAILURES(coordinator_.ScheduleRemove(device(parent_index)->device));
  coordinator_loop()->RunUntilIdle();

  zx_txid_t txid;
  // The child should be unbound first.
  ASSERT_NO_FATAL_FAILURES(CheckUnbindReceived(device(child_index)->controller_remote, &txid));
  coordinator_loop()->RunUntilIdle();

  const uint32_t flags = DEVICE_SUSPEND_FLAG_POWEROFF;
  ASSERT_NO_FATAL_FAILURES(DoSuspend(flags));

  ASSERT_NO_FATAL_FAILURES(SendUnbindReply(device(child_index)->controller_remote, txid));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(child_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(parent_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();

  // The suspend task should complete but not send a suspend message.
  ASSERT_FALSE(DeviceHasPendingMessages(device(parent_index)->controller_remote));
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceivedAndReply(platform_bus_controller_remote(), flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();
}

TEST_F(MultipleDeviceTestCase, SuspendThenUnbind) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURES(
      AddDevice(platform_bus(), "parent-device", 0 /* protocol id */, "", &parent_index));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(device(parent_index)->device, "child-device",
                                     0 /* protocol id */, "", &child_index));

  const uint32_t flags = DEVICE_SUSPEND_FLAG_POWEROFF;
  ASSERT_NO_FATAL_FAILURES(DoSuspend(flags));

  zx_txid_t txid;

  // Don't reply to the suspend yet.
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceived(device(child_index)->controller_remote, flags, &txid));
  ASSERT_NO_FATAL_FAILURES(coordinator_.ScheduleRemove(device(parent_index)->device));
  coordinator_loop()->RunUntilIdle();

  // Check that the child device has not yet started unbinding.
  ASSERT_FALSE(DeviceHasPendingMessages(device(child_index)->controller_remote));

  ASSERT_NO_FATAL_FAILURES(SendSuspendReply(device(child_index)->controller_remote, ZX_OK, txid));
  coordinator_loop()->RunUntilIdle();

  // The parent should not have received a suspend. It is in process of removal.
  ASSERT_FALSE(DeviceHasPendingMessages(device(parent_index)->controller_remote));

  // Finish unbinding the child.
  ASSERT_NO_FATAL_FAILURES(CheckUnbindReceivedAndReply(device(child_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(child_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceivedAndReply(platform_bus_controller_remote(), flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();

  // The parent should now be removed.
  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(parent_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();
}

TEST_F(MultipleDeviceTestCase, ConcurrentSuspend) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURES(
      AddDevice(platform_bus(), "parent-device", 0 /* protocol id */, "", &parent_index));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(device(parent_index)->device, "child-device",
                                     0 /* protocol id */, "", &child_index));

  const uint32_t flags = DEVICE_SUSPEND_FLAG_POWEROFF;
  zx_status_t first_suspend_status = ZX_ERR_INTERNAL;
  ASSERT_NO_FATAL_FAILURES(
      DoSuspendWithCallback(flags, [&first_suspend_status](zx_status_t completion_status) {
        first_suspend_status = completion_status;
      }));

  zx_txid_t txid;

  // Don't reply to the suspend yet.
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceived(device(child_index)->controller_remote, flags, &txid));

  zx_status_t second_suspend_status = ZX_OK;
  ASSERT_NO_FATAL_FAILURES(
      DoSuspendWithCallback(flags, [&second_suspend_status](zx_status_t completion_status) {
        second_suspend_status = completion_status;
      }));
  ASSERT_EQ(second_suspend_status, ZX_ERR_ALREADY_EXISTS);
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(SendSuspendReply(device(child_index)->controller_remote, ZX_OK, txid));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceivedAndReply(device(parent_index)->controller_remote, flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceivedAndReply(platform_bus_controller_remote(), flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceivedAndReply(sys_proxy_controller_remote_, flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_EQ(first_suspend_status, ZX_OK);
}

TEST_F(MultipleDeviceTestCase, SuspendFidlMexec) {
  ASSERT_OK(coordinator_loop()->StartThread("DevCoordLoop"));
  set_coordinator_loop_thread_running(true);

  async::Loop driver_host_loop{&kAsyncLoopConfigNoAttachToCurrentThread};
  ASSERT_OK(driver_host_loop.StartThread("DriverHostLoop"));

  async::Wait suspend_task_pbus(
      platform_bus_controller_remote().get(), ZX_CHANNEL_READABLE, 0,
      [this](async_dispatcher_t*, async::Wait*, zx_status_t, const zx_packet_signal_t*) {
        CheckSuspendReceivedAndReply(platform_bus_controller_remote(), DEVICE_SUSPEND_FLAG_MEXEC,
                                     ZX_OK);
      });
  ASSERT_OK(suspend_task_pbus.Begin(driver_host_loop.dispatcher()));

  async::Wait suspend_task_sys(
      sys_proxy_controller_remote_.get(), ZX_CHANNEL_READABLE, 0,
      [this](async_dispatcher_t*, async::Wait*, zx_status_t, const zx_packet_signal_t*) {
        CheckSuspendReceivedAndReply(sys_proxy_controller_remote_, DEVICE_SUSPEND_FLAG_MEXEC,
                                     ZX_OK);
      });
  ASSERT_OK(suspend_task_sys.Begin(driver_host_loop.dispatcher()));

  zx::channel services, services_remote;
  ASSERT_OK(zx::channel::create(0, &services, &services_remote));

  svc::Outgoing outgoing{coordinator_loop()->dispatcher()};
  ASSERT_OK(coordinator()->InitOutgoingServices(outgoing.svc_dir()));
  ASSERT_OK(outgoing.Serve(std::move(services_remote)));

  zx::channel channel, channel_remote;
  ASSERT_OK(zx::channel::create(0, &channel, &channel_remote));
  std::string svc_dir = "/svc/";
  std::string service = svc_dir + llcpp::fuchsia::hardware::power::statecontrol::Admin::Name;
  ASSERT_OK(fdio_service_connect_at(services.get(), service.c_str(), channel_remote.release()));

  bool callback_executed = false;
  DoSuspend(DEVICE_SUSPEND_FLAG_MEXEC, [&](uint32_t flags) {
    auto response = llcpp::fuchsia::hardware::power::statecontrol::Admin::Call::Suspend(
        zx::unowned_channel(channel.get()),
        llcpp::fuchsia::hardware::power::statecontrol::SystemPowerState::MEXEC);
    ASSERT_OK(response.status());
    zx_status_t call_status = ZX_OK;
    if (response->result.is_err()) {
      call_status = response->result.err();
    }
    ASSERT_OK(call_status);
    callback_executed = true;
  });

  ASSERT_TRUE(callback_executed);
  ASSERT_FALSE(suspend_task_pbus.is_pending());
  ASSERT_FALSE(suspend_task_sys.is_pending());
}

TEST_F(MultipleDeviceTestCase, SuspendFidlMexecFail) {
  ASSERT_OK(coordinator_loop()->StartThread("DevCoordLoop"));
  set_coordinator_loop_thread_running(true);

  async::Loop driver_host_loop{&kAsyncLoopConfigNoAttachToCurrentThread};
  ASSERT_OK(driver_host_loop.StartThread("DriverHostLoop"));

  async::Wait suspend_task_pbus(
      platform_bus_controller_remote().get(), ZX_CHANNEL_READABLE, 0,
      [this](async_dispatcher_t*, async::Wait*, zx_status_t, const zx_packet_signal_t*) {
        zx_txid_t txid;
        CheckSuspendReceived(platform_bus_controller_remote(), DEVICE_SUSPEND_FLAG_MEXEC, &txid);
      });
  ASSERT_OK(suspend_task_pbus.Begin(driver_host_loop.dispatcher()));

  async::Wait suspend_task_sys(
      sys_proxy_controller_remote_.get(), ZX_CHANNEL_READABLE, 0,
      [this](async_dispatcher_t*, async::Wait*, zx_status_t, const zx_packet_signal_t*) {
        CheckSuspendReceived(sys_proxy_controller_remote_, DEVICE_SUSPEND_FLAG_MEXEC, ZX_OK);
      });
  ASSERT_OK(suspend_task_sys.Begin(driver_host_loop.dispatcher()));

  zx::channel services, services_remote;
  ASSERT_OK(zx::channel::create(0, &services, &services_remote));

  svc::Outgoing outgoing{coordinator_loop()->dispatcher()};
  ASSERT_OK(coordinator()->InitOutgoingServices(outgoing.svc_dir()));
  ASSERT_OK(outgoing.Serve(std::move(services_remote)));

  zx::channel channel, channel_remote;
  ASSERT_OK(zx::channel::create(0, &channel, &channel_remote));

  std::string svc_dir = "/svc/";
  std::string service = svc_dir + llcpp::fuchsia::hardware::power::statecontrol::Admin::Name;
  ASSERT_OK(fdio_service_connect_at(services.get(), service.c_str(), channel_remote.release()));

  bool callback_executed = false;
  DoSuspend(DEVICE_SUSPEND_FLAG_MEXEC, [&](uint32_t flags) {
    auto response = llcpp::fuchsia::hardware::power::statecontrol::Admin::Call::Suspend(
        zx::unowned(channel),
        llcpp::fuchsia::hardware::power::statecontrol::SystemPowerState::MEXEC);
    ASSERT_OK(response.status());
    zx_status_t call_status = ZX_OK;
    if (response->result.is_err()) {
      call_status = response->result.err();
    }
    ASSERT_EQ(call_status, ZX_ERR_TIMED_OUT);
    callback_executed = true;
  });

  ASSERT_TRUE(callback_executed);
  ASSERT_FALSE(suspend_task_pbus.is_pending());
  ASSERT_TRUE(suspend_task_sys.is_pending());
}

TEST_F(MultipleDeviceTestCase, UnbindThenResume) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURES(
      AddDevice(platform_bus(), "parent-device", 0 /* protocol id */, "", &parent_index));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(device(parent_index)->device, "child-device",
                                     0 /* protocol id */, "", &child_index));

  coordinator_.sys_device()->set_state(Device::State::kSuspended);
  coordinator_.sys_device()->proxy()->set_state(Device::State::kSuspended);
  platform_bus()->set_state(Device::State::kSuspended);
  device(parent_index)->device->set_state(Device::State::kSuspended);
  device(child_index)->device->set_state(Device::State::kSuspended);

  ASSERT_NO_FATAL_FAILURES(coordinator_.ScheduleRemove(device(parent_index)->device));
  coordinator_loop()->RunUntilIdle();
  // The child should be unbound first.
  zx_txid_t txid;
  ASSERT_NO_FATAL_FAILURES(CheckUnbindReceived(device(child_index)->controller_remote, &txid));

  ASSERT_NO_FATAL_FAILURES(DoResume(SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON));

  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(
      sys_proxy_controller_remote_, SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(
      platform_bus_controller_remote(), SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(device(parent_index)->controller_remote,
                                               SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON,
                                               ZX_OK));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(SendUnbindReply(device(child_index)->controller_remote, txid));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(child_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(parent_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();

  // The resume task should complete but not send a resume message.
  ASSERT_FALSE(DeviceHasPendingMessages(device(parent_index)->controller_remote));
  ASSERT_FALSE(DeviceHasPendingMessages(device(child_index)->controller_remote));
}

TEST_F(MultipleDeviceTestCase, ResumeThenUnbind) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURES(
      AddDevice(platform_bus(), "parent-device", 0 /* protocol id */, "", &parent_index));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(device(parent_index)->device, "child-device",
                                     0 /* protocol id */, "", &child_index));

  coordinator_.sys_device()->set_state(Device::State::kSuspended);
  coordinator_.sys_device()->proxy()->set_state(Device::State::kSuspended);
  platform_bus()->set_state(Device::State::kSuspended);
  device(parent_index)->device->set_state(Device::State::kSuspended);
  device(child_index)->device->set_state(Device::State::kSuspended);

  ASSERT_NO_FATAL_FAILURES(DoResume(SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON));

  zx_txid_t txid;
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(
      sys_proxy_controller_remote_, SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(
      platform_bus_controller_remote(), SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  // Don't reply to the resume yet.
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(device(parent_index)->controller_remote,
                                               SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON,
                                               &txid));
  ASSERT_NO_FATAL_FAILURES(coordinator_.ScheduleRemove(device(parent_index)->device));
  coordinator_loop()->RunUntilIdle();

  // Check that the child device has not yet started unbinding.
  ASSERT_FALSE(DeviceHasPendingMessages(device(child_index)->controller_remote));

  ASSERT_NO_FATAL_FAILURES(SendResumeReply(device(parent_index)->controller_remote, ZX_OK, txid));
  coordinator_loop()->RunUntilIdle();

  // The Child should have started resuming now. Complete resume of child.
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(device(child_index)->controller_remote,
                                               SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON,
                                               ZX_OK));
  coordinator_loop()->RunUntilIdle();
  // Since the resume is complete, unbinding the child should start now.
  ASSERT_NO_FATAL_FAILURES(CheckUnbindReceivedAndReply(device(child_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(child_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();

  // The parent should now be removed.
  ASSERT_NO_FATAL_FAILURES(CheckRemoveReceivedAndReply(device(parent_index)->controller_remote));
  coordinator_loop()->RunUntilIdle();
}

TEST_F(MultipleDeviceTestCase, SuspendThenResume) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURES(
      AddDevice(platform_bus(), "parent-device", 0 /* protocol id */, "", &parent_index));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(device(parent_index)->device, "child-device",
                                     0 /* protocol id */, "", &child_index));

  const uint32_t flags = DEVICE_SUSPEND_FLAG_POWEROFF;
  ASSERT_NO_FATAL_FAILURES(DoSuspend(flags));

  zx_txid_t txid;
  // Don't reply to the suspend yet.
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceived(device(child_index)->controller_remote, flags, &txid));

  // This should return without scheduling resume tasks since suspend is in
  // progress.
  ASSERT_NO_FATAL_FAILURES(DoResume(SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(SendSuspendReply(device(child_index)->controller_remote, ZX_OK, txid));
  coordinator_loop()->RunUntilIdle();

  // The parent should have started suspending.
  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceivedAndReply(device(parent_index)->controller_remote, flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(
      CheckSuspendReceivedAndReply(platform_bus_controller_remote(), flags, ZX_OK));
  ASSERT_FALSE(DeviceHasPendingMessages(device(parent_index)->controller_remote));
  ASSERT_FALSE(DeviceHasPendingMessages(device(child_index)->controller_remote));
  ASSERT_EQ(device(parent_index)->device->state(), Device::State::kSuspended);
  ASSERT_EQ(device(child_index)->device->state(), Device::State::kSuspended);
}

TEST_F(MultipleDeviceTestCase, ResumeThenSuspend) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURES(
      AddDevice(platform_bus(), "parent-device", 0 /* protocol id */, "", &parent_index));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(device(parent_index)->device, "child-device",
                                     0 /* protocol id */, "", &child_index));

  coordinator_.sys_device()->set_state(Device::State::kSuspended);
  coordinator_.sys_device()->proxy()->set_state(Device::State::kSuspended);
  platform_bus()->set_state(Device::State::kSuspended);
  device(parent_index)->device->set_state(Device::State::kSuspended);
  device(child_index)->device->set_state(Device::State::kSuspended);

  ASSERT_NO_FATAL_FAILURES(DoResume(SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(
      sys_proxy_controller_remote_, SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(
      platform_bus_controller_remote(), SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  // Dont reply yet for the resume
  zx_txid_t txid;
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(device(parent_index)->controller_remote,
                                               SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON,
                                               &txid));
  coordinator_loop()->RunUntilIdle();

  const uint32_t flags = DEVICE_SUSPEND_FLAG_SUSPEND_RAM;
  // Should be a no-op because resume is in progress.
  ASSERT_NO_FATAL_FAILURES(DoSuspend(flags));

  ASSERT_NO_FATAL_FAILURES(SendResumeReply(device(parent_index)->controller_remote, ZX_OK, txid));
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(device(child_index)->controller_remote,
                                               SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON,
                                               ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_FALSE(DeviceHasPendingMessages(device(parent_index)->controller_remote));
  ASSERT_FALSE(DeviceHasPendingMessages(device(child_index)->controller_remote));
  ASSERT_EQ(device(parent_index)->device->state(), Device::State::kActive);
  ASSERT_EQ(device(child_index)->device->state(), Device::State::kActive);
}

TEST_F(MultipleDeviceTestCase, ResumeTimeout) {
  ASSERT_OK(coordinator_loop()->StartThread("DevCoordLoop"));
  set_coordinator_loop_thread_running(true);

  async::Loop driver_host_loop{&kAsyncLoopConfigNoAttachToCurrentThread};
  ASSERT_OK(driver_host_loop.StartThread("DriverHostLoop"));

  coordinator_.sys_device()->set_state(Device::State::kSuspended);
  coordinator_.sys_device()->proxy()->set_state(Device::State::kSuspended);
  platform_bus()->set_state(Device::State::kSuspended);

  bool resume_callback_executed = false;
  zx::event resume_received_event;
  zx::event::create(0, &resume_received_event);

  ResumeCallback callback = [&resume_callback_executed,
                             &resume_received_event](zx_status_t status) {
    ASSERT_EQ(status, ZX_ERR_TIMED_OUT);
    resume_callback_executed = true;
    resume_received_event.signal(0, ZX_USER_SIGNAL_0);
  };

  ASSERT_NO_FATAL_FAILURES(
      DoResume(SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, std::move(callback)));

  // Dont reply for sys proxy resume. we should timeout
  async::Wait resume_task_sys_proxy(
      sys_proxy_controller_remote_.get(), ZX_CHANNEL_READABLE, 0,
      [this](async_dispatcher_t*, async::Wait*, zx_status_t, const zx_packet_signal_t*) {
        zx_txid_t txid;
        ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(
            sys_proxy_controller_remote_, SystemPowerState::SYSTEM_POWER_STATE_FULLY_ON, &txid));
      });
  ASSERT_OK(resume_task_sys_proxy.Begin(driver_host_loop.dispatcher()));

  // Wait for the event that the callback sets, otherwise the test will quit.
  resume_received_event.wait_one(ZX_USER_SIGNAL_0, zx::time(ZX_TIME_INFINITE), nullptr);
  ASSERT_TRUE(resume_callback_executed);
}

// Test devices are suspended when component lifecycle stop event is received.
TEST_F(MultipleDeviceTestCase, ComponentLifecycleStop) {
  ASSERT_OK(coordinator_loop()->StartThread("DevCoordLoop"));
  set_coordinator_loop_thread_running(true);

  async::Loop devhost_loop{&kAsyncLoopConfigNoAttachToCurrentThread};
  ASSERT_OK(devhost_loop.StartThread("DevHostLoop"));

  async::Wait suspend_task_pbus(
      platform_bus_controller_remote().get(), ZX_CHANNEL_READABLE, 0,
      [this](async_dispatcher_t*, async::Wait*, zx_status_t, const zx_packet_signal_t*) {
        CheckSuspendReceivedAndReply(platform_bus_controller_remote(), DEVICE_SUSPEND_FLAG_MEXEC,
                                     ZX_OK);
      });
  ASSERT_OK(suspend_task_pbus.Begin(devhost_loop.dispatcher()));

  async::Wait suspend_task_sys(
      sys_proxy_controller_remote_.get(), ZX_CHANNEL_READABLE, 0,
      [this](async_dispatcher_t*, async::Wait*, zx_status_t, const zx_packet_signal_t*) {
        CheckSuspendReceivedAndReply(sys_proxy_controller_remote_, DEVICE_SUSPEND_FLAG_MEXEC,
                                     ZX_OK);
      });
  ASSERT_OK(suspend_task_sys.Begin(devhost_loop.dispatcher()));

  zx::channel component_lifecycle_client, component_lifecycle_server;
  ASSERT_OK(zx::channel::create(0, &component_lifecycle_client, &component_lifecycle_server));
  ASSERT_OK(devmgr::ComponentLifecycleServer::Create(
      coordinator_loop()->dispatcher(), coordinator(), std::move(component_lifecycle_server)));
  llcpp::fuchsia::process::lifecycle::Lifecycle::SyncClient client(
      std::move(component_lifecycle_client));
  auto result = client.Stop();
  ASSERT_OK(result.status());
  // the lifecycle channel should be closed now
  zx_signals_t pending;
  EXPECT_OK(client.channel().wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time::infinite(), &pending));
  EXPECT_TRUE(pending & ZX_CHANNEL_PEER_CLOSED);
  ASSERT_FALSE(suspend_task_pbus.is_pending());
  ASSERT_FALSE(suspend_task_sys.is_pending());
}
