src/devices/bin/driver_manager/resume_tests.cc
// Verify the resume order is correct
Verify the resume order is correct
Verify the resume order is correct
void ResumeTestCase::ResumeTest(SystemPowerState target_state) {
  struct DeviceDesc {
    const size_t parent_desc_index;
    const char* const name;
    size_t index = 0;
    bool suspended = false;
    bool resumed = false;
  };
  DeviceDesc devices[] = {
      {UINT32_MAX, "root_child1"}, {UINT32_MAX, "root_child2"}, {0, "root_child1_1"},
      {0, "root_child1_2"},        {2, "root_child1_1_1"},      {1, "root_child2_1"},
  };
  for (auto& desc : devices) {
    fbl::RefPtr<Device> parent;
    if (desc.parent_desc_index == UINT32_MAX) {
      parent = platform_bus();
    } else {
      size_t index = devices[desc.parent_desc_index].index;
      parent = device(index)->device;
    }
    ASSERT_NO_FATAL_FAILURES(AddDevice(parent, desc.name, 0 , "", &desc.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);
  for (auto& desc : devices) {
    fbl::RefPtr<Device> dev;
    size_t index = desc.index;
    if (index == UINT32_MAX) {
      continue;
    }
    dev = device(index)->device;
    if (dev->state() != Device::State::kSuspended) {
      dev->set_state(Device::State::kSuspended);
    }
  }
  ASSERT_NO_FATAL_FAILURES(DoResume(target_state));
  coordinator_loop()->RunUntilIdle();
  ASSERT_TRUE(DeviceHasPendingMessages(sys_proxy_controller_remote_));
  ASSERT_NO_FATAL_FAILURES(CheckResumeReceived(sys_proxy_controller_remote_, target_state, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_EQ(coordinator_.sys_device()->state(), Device::State::kActive);
  ASSERT_TRUE(DeviceHasPendingMessages(platform_bus_controller_remote()));
  ASSERT_NO_FATAL_FAILURES(
      CheckResumeReceived(platform_bus_controller_remote(), target_state, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_EQ(platform_bus()->state(), Device::State::kActive);
  size_t num_to_resume = std::size(devices);
  while (num_to_resume > 0) {
    bool made_progress = false;
    for (size_t i = 0; i < std::size(devices); ++i) {
      auto& desc = devices[i];
      if (desc.resumed) {
        continue;
      }
      if (!DeviceHasPendingMessages(desc.index)) {
        continue;
      }
      ASSERT_NO_FATAL_FAILURES(
          CheckResumeReceived(device(desc.index)->controller_remote, target_state, ZX_OK));
      coordinator_loop()->RunUntilIdle();
      size_t parent_index = devices[i].parent_desc_index;
      for (auto& other_desc : devices) {
        if (parent_index == UINT32_MAX) {
          ASSERT_EQ(platform_bus()->state(), Device::State::kActive);
        } else if (other_desc.index == parent_index) {
          ASSERT_EQ(device(desc.index)->device->state(), Device::State::kActive);
          ASSERT_TRUE(other_desc.resumed);
        } else if (other_desc.parent_desc_index == i) {
          ASSERT_NE(device(other_desc.index)->device->state(), Device::State::kActive);
          ASSERT_FALSE(other_desc.resumed);
        }
      }
      desc.resumed = true;
      --num_to_resume;
      made_progress = true;
    }
    ASSERT_TRUE(made_progress);
    coordinator_loop()->RunUntilIdle();
  }
}
void ResumeTestCase :: ResumeTest ( SystemPowerState target_state ) { struct DeviceDesc { const size_t parent_desc_index ; const char * const name ; size_t index = 0 ; bool suspended = false ; bool resumed = false ; } ; DeviceDesc devices [ ] = { { UINT32_MAX , " " } , { UINT32_MAX , " " } , { 0 , " " } , { 0 , " " } , { 2 , " " } , { 1 , " " } , } ; for ( auto & desc : devices ) { fbl :: RefPtr < Device > parent ; if ( desc . parent_desc_index == UINT32_MAX ) { parent = platform_bus ( ) ; } else { size_t index = devices [ desc . parent_desc_index ] . index ; parent = device ( index ) -> device ; } ASSERT_NO_FATAL_FAILURES ( AddDevice ( parent , desc . name , 0 , " " , & desc . 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 ) ; for ( auto & desc : devices ) { fbl :: RefPtr < Device > dev ; size_t index = desc . index ; if ( index == UINT32_MAX ) { continue ; } dev = device ( index ) -> device ; if ( dev -> state ( ) != Device :: State :: kSuspended ) { dev -> set_state ( Device :: State :: kSuspended ) ; } } ASSERT_NO_FATAL_FAILURES ( DoResume ( target_state ) ) ; coordinator_loop ( ) -> RunUntilIdle ( ) ; ASSERT_TRUE ( DeviceHasPendingMessages ( sys_proxy_controller_remote_ ) ) ; ASSERT_NO_FATAL_FAILURES ( CheckResumeReceived ( sys_proxy_controller_remote_ , target_state , ZX_OK ) ) ; coordinator_loop ( ) -> RunUntilIdle ( ) ; ASSERT_EQ ( coordinator_ . sys_device ( ) -> state ( ) , Device :: State :: kActive ) ; ASSERT_TRUE ( DeviceHasPendingMessages ( platform_bus_controller_remote ( ) ) ) ; ASSERT_NO_FATAL_FAILURES ( CheckResumeReceived ( platform_bus_controller_remote ( ) , target_state , ZX_OK ) ) ; coordinator_loop ( ) -> RunUntilIdle ( ) ; ASSERT_EQ ( platform_bus ( ) -> state ( ) , Device :: State :: kActive ) ; size_t num_to_resume = std :: size ( devices ) ; while ( num_to_resume > 0 ) { bool made_progress = false ; for ( size_t i = 0 ; i < std :: size ( devices ) ; ++ i ) { auto & desc = devices [ i ] ; if ( desc . resumed ) { continue ; } if ( ! DeviceHasPendingMessages ( desc . index ) ) { continue ; } ASSERT_NO_FATAL_FAILURES ( CheckResumeReceived ( device ( desc . index ) -> controller_remote , target_state , ZX_OK ) ) ; coordinator_loop ( ) -> RunUntilIdle ( ) ; size_t parent_index = devices [ i ] . parent_desc_index ; for ( auto & other_desc : devices ) { if ( parent_index == UINT32_MAX ) { ASSERT_EQ ( platform_bus ( ) -> state ( ) , Device :: State :: kActive ) ; } else if ( other_desc . index == parent_index ) { ASSERT_EQ ( device ( desc . index ) -> device -> state ( ) , Device :: State :: kActive ) ; ASSERT_TRUE ( other_desc . resumed ) ; } else if ( other_desc . parent_desc_index == i ) { ASSERT_NE ( device ( other_desc . index ) -> device -> state ( ) , Device :: State :: kActive ) ; ASSERT_FALSE ( other_desc . resumed ) ; } } desc . resumed = true ; -- num_to_resume ; made_progress = true ; } ASSERT_TRUE ( made_progress ) ; coordinator_loop ( ) -> RunUntilIdle ( ) ; } }
Verify the resume order is correct
Verify the resume order is correct
// Index into the device desc array below.  UINT32_MAX = platform_bus() // index for use with device() /* protocol id */ // Mark all devices suspened. Otherwise resume will fail // Make sure all descendants of this device are not resumed yet. // We just need to check immediate children since this will // recursively enforce that property. // Make sure platform bus is resumed. // Make sure parent is resumed. // if it has children, its state should be Suspended but not Active. // Make sure we're not stuck waiting