// 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"

class ResumeTestCase : public MultipleDeviceTestCase {
 public:
  void ResumeTest(SystemPowerState target_state);
  void StateTest(zx_status_t resume_status, Device::State want_device_state);
};

// Verify the device transitions in and out of the resuming state.
void ResumeTestCase::StateTest(zx_status_t resume_status, Device::State want_device_state) {
  size_t index;
  ASSERT_NO_FATAL_FAILURES(AddDevice(platform_bus(), "device", 0 /* protocol id */, "", &index));

  // Mark all devices suspended.
  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(index)->device->set_state(Device::State::kSuspended);
  ASSERT_NO_FATAL_FAILURES(DoResume(SystemPowerState::FULLY_ON));

  zx_txid_t txid;
  ASSERT_NO_FATAL_FAILURES(
      CheckResumeReceived(sys_proxy_controller_remote_, SystemPowerState::FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  ASSERT_NO_FATAL_FAILURES(
      CheckResumeReceived(platform_bus_controller_remote(), SystemPowerState::FULLY_ON, ZX_OK));
  coordinator_loop()->RunUntilIdle();
  // Check for the resume message without replying.
  ASSERT_NO_FATAL_FAILURES(
      CheckResumeReceived(device(index)->controller_remote, SystemPowerState::FULLY_ON, &txid));

  ASSERT_EQ(device(index)->device->state(), Device::State::kResuming);

  ASSERT_NO_FATAL_FAILURES(SendResumeReply(device(index)->controller_remote, resume_status, txid));
  coordinator_loop()->RunUntilIdle();

  ASSERT_EQ(device(index)->device->state(), want_device_state);
}

// Verify the resume order is correct
void ResumeTestCase::ResumeTest(SystemPowerState target_state) {
  struct DeviceDesc {
    // Index into the device desc array below.  UINT32_MAX = platform_bus()
    const size_t parent_desc_index;
    const char* const name;
    // index for use with device()
    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 /* protocol id */, "", &desc.index));
  }

  // Mark all devices suspended. Otherwise resume will fail
  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;
      // 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.
      for (auto& other_desc : devices) {
        if (parent_index == UINT32_MAX) {
          // Make sure platform bus is resumed.
          ASSERT_EQ(platform_bus()->state(), Device::State::kActive);
        } else if (other_desc.index == parent_index) {
          // Make sure parent is resumed.
          ASSERT_EQ(device(desc.index)->device->state(), Device::State::kActive);
          ASSERT_TRUE(other_desc.resumed);
        } else if (other_desc.parent_desc_index == i) {
          // if it has children, its state should be Suspended but not Active.
          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;
    }
    // Make sure we're not stuck waiting
    ASSERT_TRUE(made_progress);
    coordinator_loop()->RunUntilIdle();
  }
}

TEST_F(ResumeTestCase, FullyOnCheckOrder) {
  ASSERT_NO_FATAL_FAILURES(ResumeTest(SystemPowerState::FULLY_ON));
}

TEST_F(ResumeTestCase, ResumeSuccess) {
  ASSERT_NO_FATAL_FAILURES(StateTest(ZX_OK, Device::State::kActive));
}

TEST_F(ResumeTestCase, ResumeFail) {
  ASSERT_NO_FATAL_FAILURES(StateTest(ZX_ERR_BAD_STATE, Device::State::kSuspended));
}
