// 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 <fidl/fuchsia.io/cpp/wire.h>
#include <lib/ddk/binding.h>
#include <lib/ddk/driver.h>

#include <utility>
#include <vector>

#include <fbl/vector.h>
#include <zxtest/zxtest.h>

#include "multiple_device_test.h"

namespace fio = fuchsia_io;

namespace {

class FidlTransaction : public fidl::Transaction {
 public:
  FidlTransaction(FidlTransaction&&) = default;
  explicit FidlTransaction(zx_txid_t transaction_id, zx::unowned_channel channel)
      : txid_(transaction_id), channel_(std::move(channel)) {}

  std::unique_ptr<fidl::Transaction> TakeOwnership() override {
    return std::make_unique<FidlTransaction>(std::move(*this));
  }

  zx_status_t Reply(fidl::OutgoingMessage* message, fidl::WriteOptions write_options) override {
    ZX_ASSERT(txid_ != 0);
    message->set_txid(txid_);
    txid_ = 0;
    message->Write(channel_, std::move(write_options));
    return message->status();
  }

  void Close(zx_status_t epitaph) override { ZX_ASSERT(false); }

  void InternalError(fidl::UnbindInfo info, fidl::ErrorOrigin origin) override {
    detected_error_ = info;
  }

  ~FidlTransaction() override = default;

  const std::optional<fidl::UnbindInfo>& detected_error() const { return detected_error_; }

 private:
  zx_txid_t txid_;
  zx::unowned_channel channel_;
  std::optional<fidl::UnbindInfo> detected_error_;
};

class FakeCompositeDevhost : public fidl::WireServer<fuchsia_device_manager::DriverHostController> {
 public:
  FakeCompositeDevhost(
      const char* expected_name, size_t expected_fragments_count,
      fidl::ClientEnd<fuchsia_device_manager::Coordinator>* device_coordinator_client,
      fidl::ServerEnd<fuchsia_device_manager::DeviceController>* device_controller_server)
      : expected_name_(expected_name),
        expected_fragments_count_(expected_fragments_count),
        device_coordinator_client_(device_coordinator_client),
        device_controller_server_(device_controller_server) {}

  void CreateDevice(CreateDeviceRequestView request,
                    CreateDeviceCompleter::Sync& completer) override {
    if (request->type.is_composite()) {
      auto& composite = request->type.composite();
      if (strncmp(expected_name_, composite.name.data(), composite.name.size()) == 0 &&
          composite.fragments.count() == expected_fragments_count_) {
        *device_coordinator_client_ = std::move(request->coordinator);
        *device_controller_server_ = std::move(request->device_controller);
        completer.Reply(ZX_OK);
        return;
      }
    }
    completer.Reply(ZX_ERR_INTERNAL);
  }

  void Restart(RestartRequestView request, RestartCompleter::Sync& completer) override {}

 private:
  const char* expected_name_;
  size_t expected_fragments_count_;
  fidl::ClientEnd<fuchsia_device_manager::Coordinator>* device_coordinator_client_;
  fidl::ServerEnd<fuchsia_device_manager::DeviceController>* device_controller_server_;
};

class FakeNewProxyDevhost : public fidl::WireServer<fuchsia_device_manager::DriverHostController> {
 public:
  FakeNewProxyDevhost(
      fidl::ClientEnd<fuchsia_device_manager::Coordinator>* device_coordinator_client,
      fidl::ServerEnd<fuchsia_device_manager::DeviceController>* device_controller_server)
      : device_coordinator_client_(device_coordinator_client),
        device_controller_server_(device_controller_server) {}

  void CreateDevice(CreateDeviceRequestView request,
                    CreateDeviceCompleter::Sync& completer) override {
    if (request->type.is_new_proxy()) {
      *device_coordinator_client_ = std::move(request->coordinator);
      *device_controller_server_ = std::move(request->device_controller);
      completer.Reply(ZX_OK);
      return;
    }
    completer.Reply(ZX_ERR_INTERNAL);
  }

  void Restart(RestartRequestView request, RestartCompleter::Sync& completer) override {}

 private:
  fidl::ClientEnd<fuchsia_device_manager::Coordinator>* device_coordinator_client_;
  fidl::ServerEnd<fuchsia_device_manager::DeviceController>* device_controller_server_;
};

}  // namespace

// Reads a CreateDevice from remote, checks expectations, and sends
// a ZX_OK response.
void CheckCreateDeviceReceived(
    fidl::WireServer<fuchsia_device_manager::DriverHostController>* fake_dev_host,
    const fidl::ServerEnd<fdm::DriverHostController>& controller, DeviceState* composite) {
  uint8_t bytes[ZX_CHANNEL_MAX_MSG_BYTES];
  zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
  fidl_channel_handle_metadata_t handle_metadata[ZX_CHANNEL_MAX_MSG_HANDLES];
  fidl::IncomingMessage msg = fidl::MessageRead(
      controller.channel(), fidl::ChannelMessageStorageView{
                                .bytes = fidl::BufferSpan(bytes, std::size(bytes)),
                                .handles = handles,
                                .handle_metadata = handle_metadata,
                                .handle_capacity = ZX_CHANNEL_MAX_MSG_HANDLES,
                            });
  ASSERT_TRUE(msg.ok());

  auto* header = msg.header();
  FidlTransaction txn(header->txid, zx::unowned(controller.channel()));

  fidl::WireDispatch(fake_dev_host, std::move(msg), &txn);
  ASSERT_FALSE(txn.detected_error());
  ASSERT_TRUE(composite->coordinator_client.is_valid());
  ASSERT_TRUE(composite->controller_server.is_valid());
}

void CheckCreateCompositeDeviceReceived(
    const fidl::ServerEnd<fdm::DriverHostController>& controller, const char* expected_name,
    size_t expected_fragments_count, DeviceState* composite) {
  FakeCompositeDevhost fake(expected_name, expected_fragments_count, &composite->coordinator_client,
                            &composite->controller_server);
  CheckCreateDeviceReceived(&fake, controller, composite);
}

void CheckCreateNewProxyDeviceReceived(const fidl::ServerEnd<fdm::DriverHostController>& controller,
                                       DeviceState* new_proxy) {
  FakeNewProxyDevhost fake(&new_proxy->coordinator_client, &new_proxy->controller_server);
  CheckCreateDeviceReceived(&fake, controller, new_proxy);
}

// Helper for BindComposite for issuing an AddComposite for a composite with the
// given fragments.  It's assumed that these fragments are children of
// the platform_bus and have the given protocol_id
void BindCompositeDefineComposite(const fbl::RefPtr<Device>& platform_bus,
                                  const uint32_t* protocol_ids, size_t fragment_count,
                                  const zx_device_prop_t* props, size_t props_count,
                                  const char* name, zx_status_t expected_status = ZX_OK,
                                  const device_metadata_t* metadata = nullptr,
                                  size_t metadata_count = 0) {
  fidl::Arena allocator;
  std::vector<fuchsia_device_manager::wire::DeviceFragment> fragments = {};
  for (size_t i = 0; i < fragment_count; ++i) {
    // Define a union type to avoid violating the strict aliasing rule.

    zx_bind_inst_t always = BI_MATCH();
    zx_bind_inst_t protocol = BI_MATCH_IF(EQ, BIND_PROTOCOL, protocol_ids[i]);

    fuchsia_device_manager::wire::DeviceFragment fragment;  // = &fragments[i];
    fragment.name = ::fidl::StringView("unnamed-fragment");
    fragment.parts.Allocate(allocator, 1);
    fragment.parts[0].match_program.Allocate(allocator, 1);
    fragment.parts[0].match_program[0] = fuchsia_device_manager::wire::BindInstruction{
        .op = protocol.op,
        .arg = protocol.arg,
        .debug = always.debug,
    };
    fragments.push_back(fragment);
  }

  std::vector<fuchsia_device_manager::wire::DeviceProperty> props_list = {};
  for (size_t i = 0; i < props_count; i++) {
    props_list.push_back(fuchsia_device_manager::wire::DeviceProperty{
        .id = props[i].id,
        .reserved = props[i].reserved,
        .value = props[i].value,
    });
  }

  std::vector<fuchsia_device_manager::wire::DeviceMetadata> metadata_list = {};
  for (size_t i = 0; i < metadata_count; i++) {
    auto meta = fuchsia_device_manager::wire::DeviceMetadata{
        .key = metadata[i].type,
        .data = ::fidl::VectorView<uint8_t>::FromExternal(
            reinterpret_cast<uint8_t*>(const_cast<void*>(metadata[i].data)), metadata[i].length)};
    metadata_list.emplace_back(meta);
  }

  fuchsia_device_manager::wire::CompositeDeviceDescriptor comp_desc = {
      .props = ::fidl::VectorView<fuchsia_device_manager::wire::DeviceProperty>::FromExternal(
          props_list),
      .fragments =
          ::fidl::VectorView<fuchsia_device_manager::wire::DeviceFragment>::FromExternal(fragments),
      .primary_fragment_index = 0,
      .spawn_colocated = true,
      .metadata = ::fidl::VectorView<fuchsia_device_manager::wire::DeviceMetadata>::FromExternal(
          metadata_list),
  };

  Coordinator* coordinator = platform_bus->coordinator;
  ASSERT_EQ(coordinator->device_manager()->AddCompositeDevice(platform_bus, name, comp_desc),
            expected_status);
}

class CompositeTestCase : public MultipleDeviceTestCase {
 public:
  ~CompositeTestCase() override = default;

  void CheckCompositeCreation(const char* composite_name, const size_t* device_indexes,
                              size_t device_indexes_count, size_t* fragment_indexes_out,
                              DeviceState* composite_state);

  fbl::RefPtr<Device> GetCompositeDeviceFromFragment(const char* composite_name,
                                                     size_t fragment_index);

 protected:
  void SetUp() override {
    MultipleDeviceTestCase::SetUp();
    ASSERT_NOT_NULL(coordinator().fragment_driver());
  }
};

fbl::RefPtr<Device> CompositeTestCase::GetCompositeDeviceFromFragment(const char* composite_name,
                                                                      size_t fragment_index) {
  fbl::RefPtr<Device> composite_device;
  auto fragment_device = device(fragment_index)->device;
  for (auto& comp : fragment_device->fragments()) {
    if (!strcmp(comp.composite()->device()->name().data(), composite_name)) {
      composite_device = comp.composite()->device();
      break;
    }
  }
  return composite_device;
}

void CompositeTestCase::CheckCompositeCreation(const char* composite_name,
                                               const size_t* device_indexes,
                                               size_t device_indexes_count,
                                               size_t* fragment_indexes_out,
                                               DeviceState* composite) {
  for (size_t i = 0; i < device_indexes_count; ++i) {
    auto device_state = device(device_indexes[i]);
    // Check that the fragments got bound
    fbl::String driver = coordinator().fragment_driver()->libname;
    ASSERT_NO_FATAL_FAILURE(device_state->CheckBindDriverReceivedAndReply(driver.data()));
    coordinator_loop()->RunUntilIdle();

    // Synthesize the AddDevice request the fragment driver would send
    char name[32];
    snprintf(name, sizeof(name), "%s-comp-device-%zu", composite_name, i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(device_state->device, name, 0, driver, &fragment_indexes_out[i]));
  }
  // Make sure the composite comes up
  ASSERT_NO_FATAL_FAILURE(CheckCreateCompositeDeviceReceived(driver_host_server(), composite_name,
                                                             device_indexes_count, composite));
}

class CompositeAddOrderTestCase : public CompositeTestCase {
 public:
  enum class AddLocation {
    // Add the composite before any fragments
    BEFORE,
    // Add the composite after some fragments
    MIDDLE,
    // Add the composite after all fragments
    AFTER,
  };
  void ExecuteTest(AddLocation add);
};

class CompositeAddOrderSharedFragmentTestCase : public CompositeAddOrderTestCase {
 public:
  void ExecuteSharedFragmentTest(AddLocation dev1_add, AddLocation dev2_add) {
    size_t device_indexes[3];
    uint32_t protocol_id[] = {
        ZX_PROTOCOL_GPIO,
        ZX_PROTOCOL_I2C,
        ZX_PROTOCOL_ETHERNET,
    };
    static_assert(std::size(protocol_id) == std::size(device_indexes));

    const char* kCompositeDev1Name = "composite-dev1";
    const char* kCompositeDev2Name = "composite-dev2";
    auto do_add = [&](const char* devname) {
      ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                           std::size(protocol_id),
                                                           nullptr /* props */, 0, devname));
    };

    if (dev1_add == AddLocation::BEFORE) {
      ASSERT_NO_FATAL_FAILURE(do_add(kCompositeDev1Name));
    }

    if (dev2_add == AddLocation::BEFORE) {
      ASSERT_NO_FATAL_FAILURE(do_add(kCompositeDev2Name));
    }
    // Add the devices to construct the composite out of.
    for (size_t i = 0; i < std::size(device_indexes); ++i) {
      char name[32];
      snprintf(name, sizeof(name), "device-%zu", i);
      ASSERT_NO_FATAL_FAILURE(
          AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
      if (i == 0 && dev1_add == AddLocation::MIDDLE) {
        ASSERT_NO_FATAL_FAILURE(do_add(kCompositeDev1Name));
      }
      if (i == 0 && dev2_add == AddLocation::MIDDLE) {
        ASSERT_NO_FATAL_FAILURE(do_add(kCompositeDev2Name));
      }
    }

    if (dev1_add == AddLocation::AFTER) {
      ASSERT_NO_FATAL_FAILURE(do_add(kCompositeDev1Name));
    }

    DeviceState composite1, composite2;
    size_t fragment_device1_indexes[std::size(device_indexes)];
    size_t fragment_device2_indexes[std::size(device_indexes)];
    ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDev1Name, device_indexes,
                                                   std::size(device_indexes),
                                                   fragment_device1_indexes, &composite1));
    if (dev2_add == AddLocation::AFTER) {
      ASSERT_NO_FATAL_FAILURE(do_add(kCompositeDev2Name));
    }
    ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDev2Name, device_indexes,
                                                   std::size(device_indexes),
                                                   fragment_device2_indexes, &composite2));
  }
};

void CompositeAddOrderTestCase::ExecuteTest(AddLocation add) {
  size_t device_indexes[3];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
      ZX_PROTOCOL_ETHERNET,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDevName = "composite-dev";
  auto do_add = [&]() {
    ASSERT_NO_FATAL_FAILURE(
        BindCompositeDefineComposite(platform_bus()->device, protocol_id, std::size(protocol_id),
                                     nullptr /* props */, 0, kCompositeDevName));
  };

  if (add == AddLocation::BEFORE) {
    ASSERT_NO_FATAL_FAILURE(do_add());
  }

  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
    if (i == 0 && add == AddLocation::MIDDLE) {
      ASSERT_NO_FATAL_FAILURE(do_add());
    }
  }

  if (add == AddLocation::AFTER) {
    ASSERT_NO_FATAL_FAILURE(do_add());
  }

  DeviceState composite;
  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));
}
TEST_F(CompositeAddOrderTestCase, DefineBeforeDevices) {
  ASSERT_NO_FATAL_FAILURE(ExecuteTest(AddLocation::BEFORE));
}

TEST_F(CompositeAddOrderTestCase, DefineAfterDevices) {
  ASSERT_NO_FATAL_FAILURE(ExecuteTest(AddLocation::AFTER));
}

TEST_F(CompositeAddOrderTestCase, DefineInbetweenDevices) {
  ASSERT_NO_FATAL_FAILURE(ExecuteTest(AddLocation::MIDDLE));
}

TEST_F(CompositeAddOrderSharedFragmentTestCase, DefineDevice1BeforeDevice2Before) {
  ASSERT_NO_FATAL_FAILURE(ExecuteSharedFragmentTest(AddLocation::BEFORE, AddLocation::BEFORE));
}

TEST_F(CompositeAddOrderSharedFragmentTestCase, DefineDevice1BeforeDevice2After) {
  ASSERT_NO_FATAL_FAILURE(ExecuteSharedFragmentTest(AddLocation::BEFORE, AddLocation::AFTER));
}

TEST_F(CompositeAddOrderSharedFragmentTestCase, DefineDevice1MiddleDevice2Before) {
  ASSERT_NO_FATAL_FAILURE(ExecuteSharedFragmentTest(AddLocation::BEFORE, AddLocation::MIDDLE));
}

TEST_F(CompositeAddOrderSharedFragmentTestCase, DefineDevice1MiddleDevice2After) {
  ASSERT_NO_FATAL_FAILURE(ExecuteSharedFragmentTest(AddLocation::MIDDLE, AddLocation::AFTER));
}

TEST_F(CompositeAddOrderSharedFragmentTestCase, DefineDevice1AfterDevice2After) {
  ASSERT_NO_FATAL_FAILURE(ExecuteSharedFragmentTest(AddLocation::AFTER, AddLocation::AFTER));
}

TEST_F(CompositeTestCase, AddMultipleSharedFragmentCompositeDevices) {
  size_t device_indexes[2];
  zx_status_t status = ZX_OK;
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }

  for (size_t i = 1; i <= 5; i++) {
    char composite_dev_name[32];
    snprintf(composite_dev_name, sizeof(composite_dev_name), "composite-dev-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        BindCompositeDefineComposite(platform_bus()->device, protocol_id, std::size(protocol_id),
                                     nullptr /* props */, 0, composite_dev_name));
  }

  DeviceState composite[5];
  size_t fragment_device_indexes[5][std::size(device_indexes)];
  for (size_t i = 1; i <= 5; i++) {
    char composite_dev_name[32];
    snprintf(composite_dev_name, sizeof(composite_dev_name), "composite-dev-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        CheckCompositeCreation(composite_dev_name, device_indexes, std::size(device_indexes),
                               fragment_device_indexes[i - 1], &composite[i - 1]));
  }
  auto device1 = device(device_indexes[1])->device;
  size_t count = 0;
  for (auto& child : device1->children()) {
    count++;
    char name[32];
    snprintf(name, sizeof(name), "composite-dev-%zu-comp-device-1", count);
    if (strcmp(child.name().data(), name)) {
      status = ZX_ERR_INTERNAL;
    }
  }
  ASSERT_OK(status);
  ASSERT_EQ(count, 5);
}

TEST_F(CompositeTestCase, SharedFragmentUnbinds) {
  size_t device_indexes[2];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDev1Name = "composite-dev-1";
  const char* kCompositeDev2Name = "composite-dev-2";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDev1Name));

  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDev2Name));

  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }

  DeviceState composite1, composite2;
  size_t fragment_device1_indexes[std::size(device_indexes)];
  size_t fragment_device2_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDev1Name, device_indexes,
                                                 std::size(device_indexes),
                                                 fragment_device1_indexes, &composite1));
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDev2Name, device_indexes,
                                                 std::size(device_indexes),
                                                 fragment_device2_indexes, &composite2));
  coordinator_loop()->RunUntilIdle();
  {
    auto device1 = device(device_indexes[1])->device;
    fbl::RefPtr<Device> comp_device1;
    fbl::RefPtr<Device> comp_device2;
    for (auto& comp : device1->fragments()) {
      auto comp_device = comp.composite()->device();
      if (!strcmp(comp_device->name().data(), kCompositeDev1Name)) {
        comp_device1 = comp_device;
        continue;
      }
      if (!strcmp(comp_device->name().data(), kCompositeDev2Name)) {
        comp_device2 = comp_device;
        continue;
      }
    }
    ASSERT_NOT_NULL(comp_device1);
    ASSERT_NOT_NULL(comp_device2);
  }
  // Remove device 0 and its children (fragment and composite devices).
  ASSERT_NO_FATAL_FAILURE(
      coordinator().device_manager()->ScheduleRemove(device(device_indexes[0])->device));
  coordinator_loop()->RunUntilIdle();

  auto device_zero = device(device_indexes[0]);
  auto fragment1 = device(fragment_device1_indexes[0]);
  auto fragment2 = device(fragment_device2_indexes[0]);

  // Check the fragments have received their unbind requests.
  ASSERT_NO_FATAL_FAILURE(fragment1->CheckUnbindReceived());
  ASSERT_NO_FATAL_FAILURE(fragment2->CheckUnbindReceived());

  // The device and composites should not have received any requests yet.
  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(composite1.HasPendingMessages());
  ASSERT_FALSE(composite2.HasPendingMessages());

  ASSERT_NO_FATAL_FAILURE(fragment1->SendUnbindReply());
  ASSERT_NO_FATAL_FAILURE(fragment2->SendUnbindReply());
  coordinator_loop()->RunUntilIdle();

  // The composites should start unbinding since the fragments finished unbinding.
  ASSERT_NO_FATAL_FAILURE(composite1.CheckUnbindReceivedAndReply());
  ASSERT_NO_FATAL_FAILURE(composite2.CheckUnbindReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  // We are still waiting for the composites to be removed.
  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(fragment1->HasPendingMessages());
  ASSERT_FALSE(fragment2->HasPendingMessages());

  // Finish removing the composites.
  ASSERT_NO_FATAL_FAILURE(composite1.CheckRemoveReceivedAndReply());
  ASSERT_NO_FATAL_FAILURE(composite2.CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_FALSE(device_zero->HasPendingMessages());

  // Finish removing the fragments.
  ASSERT_NO_FATAL_FAILURE(fragment1->CheckRemoveReceivedAndReply());
  ASSERT_NO_FATAL_FAILURE(fragment2->CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURE(device_zero->CheckRemoveReceivedAndReply());

  // Add the device back and verify the composite gets created again
  ASSERT_NO_FATAL_FAILURE(
      AddDevice(platform_bus()->device, "device-0", protocol_id[0], "", &device_indexes[0]));
  {
    auto device_state = device(device_indexes[0]);
    // Wait for the fragments to get bound
    fbl::String driver = coordinator().fragment_driver()->libname;
    ASSERT_NO_FATAL_FAILURE(device_state->CheckBindDriverReceivedAndReply(driver.data()));
    coordinator_loop()->RunUntilIdle();

    // Synthesize the AddDevice request the fragment driver would send
    ASSERT_NO_FATAL_FAILURE(AddDevice(device_state->device, "composite-dev1-comp-device-0", 0,
                                      driver, &fragment_device1_indexes[0]));
  }
  {
    auto device_state = device(device_indexes[0]);
    // Wait for the fragments to get bound
    fbl::String driver = coordinator().fragment_driver()->libname;
    ASSERT_NO_FATAL_FAILURE(device_state->CheckBindDriverReceivedAndReply(driver.data()));
    coordinator_loop()->RunUntilIdle();

    // Synthesize the AddDevice request the fragment driver would send
    ASSERT_NO_FATAL_FAILURE(AddDevice(device_state->device, "composite-dev2-comp-device-0", 0,
                                      driver, &fragment_device2_indexes[0]));
  }
  ASSERT_NO_FATAL_FAILURE(CheckCreateCompositeDeviceReceived(
      driver_host_server(), kCompositeDev1Name, std::size(device_indexes), &composite1));
  ASSERT_NO_FATAL_FAILURE(CheckCreateCompositeDeviceReceived(
      driver_host_server(), kCompositeDev2Name, std::size(device_indexes), &composite2));
}

TEST_F(CompositeTestCase, FragmentUnbinds) {
  size_t device_indexes[2];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDevName = "composite-dev";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDevName));

  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }
  DeviceState composite;
  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));
  coordinator_loop()->RunUntilIdle();

  {
    fbl::RefPtr<Device> comp_device =
        GetCompositeDeviceFromFragment(kCompositeDevName, device_indexes[1]);
    ASSERT_NOT_NULL(comp_device);
  }

  // Remove device 0 and its children (fragment and composite devices).
  ASSERT_NO_FATAL_FAILURE(
      coordinator().device_manager()->ScheduleRemove(device(device_indexes[0])->device));
  coordinator_loop()->RunUntilIdle();

  auto device_zero = device(device_indexes[0]);
  auto fragment = device(fragment_device_indexes[0]);

  // The device and composite should not have received an unbind request yet.
  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(composite.HasPendingMessages());

  // Check the fragment and composite are unbound.
  ASSERT_NO_FATAL_FAILURE(fragment->CheckUnbindReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(fragment->HasPendingMessages());

  ASSERT_NO_FATAL_FAILURE(composite.CheckUnbindReceivedAndReply());
  coordinator_loop()->RunUntilIdle();
  // Still waiting for the composite to be removed.
  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(fragment->HasPendingMessages());

  // Finish removing the composite.
  ASSERT_NO_FATAL_FAILURE(composite.CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_FALSE(device_zero->HasPendingMessages());

  // Finish removing the fragment.
  ASSERT_NO_FATAL_FAILURE(fragment->CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURE(device_zero->CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  // Add the device back and verify the composite gets created again
  ASSERT_NO_FATAL_FAILURE(
      AddDevice(platform_bus()->device, "device-0", protocol_id[0], "", &device_indexes[0]));
  {
    auto device_state = device(device_indexes[0]);
    // Wait for the fragments to get bound
    fbl::String driver = coordinator().fragment_driver()->libname;
    ASSERT_NO_FATAL_FAILURE(device_state->CheckBindDriverReceivedAndReply(driver.data()));
    coordinator_loop()->RunUntilIdle();

    // Synthesize the AddDevice request the fragment driver would send
    ASSERT_NO_FATAL_FAILURE(AddDevice(device_state->device, "fragment-device-0", 0, driver,
                                      &fragment_device_indexes[0]));
  }
  ASSERT_NO_FATAL_FAILURE(CheckCreateCompositeDeviceReceived(
      driver_host_server(), kCompositeDevName, std::size(device_indexes), &composite));
}

TEST_F(CompositeTestCase, SuspendOrder) {
  size_t device_indexes[2];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDevName = "composite-dev";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDevName));
  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }

  DeviceState composite;
  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));

  const uint32_t suspend_flags = DEVICE_SUSPEND_FLAG_POWEROFF;
  ASSERT_NO_FATAL_FAILURE(DoSuspend(suspend_flags));

  // Make sure none of the fragments have received their suspend requests
  ASSERT_FALSE(platform_bus()->HasPendingMessages());
  for (auto idx : device_indexes) {
    ASSERT_FALSE(device(idx)->HasPendingMessages());
  }
  for (auto idx : fragment_device_indexes) {
    ASSERT_FALSE(device(idx)->HasPendingMessages());
  }
  // The composite should have been the first to get one
  ASSERT_NO_FATAL_FAILURE(composite.CheckSuspendReceivedAndReply(suspend_flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();

  // Next, all of the internal fragment devices should have them, but none of the devices
  // themselves
  ASSERT_FALSE(platform_bus()->HasPendingMessages());
  for (auto idx : device_indexes) {
    ASSERT_FALSE(device(idx)->HasPendingMessages());
  }
  for (auto idx : fragment_device_indexes) {
    ASSERT_NO_FATAL_FAILURE(device(idx)->CheckSuspendReceivedAndReply(suspend_flags, ZX_OK));
  }
  coordinator_loop()->RunUntilIdle();

  // Next, the devices should get them
  ASSERT_FALSE(platform_bus()->HasPendingMessages());
  for (auto idx : device_indexes) {
    ASSERT_NO_FATAL_FAILURE(device(idx)->CheckSuspendReceivedAndReply(suspend_flags, ZX_OK));
  }
  coordinator_loop()->RunUntilIdle();

  // Finally, the platform bus driver, which is the parent of all of the devices
  ASSERT_NO_FATAL_FAILURE(platform_bus()->CheckSuspendReceivedAndReply(suspend_flags, ZX_OK));
  coordinator_loop()->RunUntilIdle();
}

TEST_F(CompositeTestCase, ResumeOrder) {
  size_t device_indexes[2];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDevName = "composite-dev";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDevName));
  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }

  size_t fragment_device_indexes[std::size(device_indexes)];
  DeviceState composite;
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));
  fbl::RefPtr<Device> comp_device =
      GetCompositeDeviceFromFragment(kCompositeDevName, device_indexes[1]);
  ASSERT_NOT_NULL(comp_device);

  // Put all the devices in suspended state
  coordinator().sys_device()->set_state(Device::State::kSuspended);
  coordinator().sys_device()->proxy()->set_state(Device::State::kSuspended);
  platform_bus()->device->set_state(Device::State::kSuspended);
  for (auto idx : device_indexes) {
    device(idx)->device->set_state(Device::State::kSuspended);
  }
  for (auto idx : fragment_device_indexes) {
    device(idx)->device->set_state(Device::State::kSuspended);
  }
  comp_device->set_state(Device::State::kSuspended);

  fuchsia_hardware_power_statecontrol::wire::SystemPowerState state =
      fuchsia_hardware_power_statecontrol::wire::SystemPowerState::kFullyOn;
  ASSERT_NO_FATAL_FAILURE(DoResume(state));

  // First, the sys proxy driver, which is the parent of all of the devices
  ASSERT_NO_FATAL_FAILURE(
      sys_proxy()->CheckResumeReceivedAndReply(SystemPowerState::kFullyOn, ZX_OK));
  coordinator_loop()->RunUntilIdle();

  // Then platform devices
  ASSERT_NO_FATAL_FAILURE(platform_bus()->CheckResumeReceivedAndReply(state, ZX_OK));
  coordinator_loop()->RunUntilIdle();

  // Next the devices
  for (auto idx : device_indexes) {
    ASSERT_NO_FATAL_FAILURE(device(idx)->CheckResumeReceivedAndReply(state, ZX_OK));
  }
  coordinator_loop()->RunUntilIdle();

  // Then the fragments
  for (auto idx : fragment_device_indexes) {
    ASSERT_NO_FATAL_FAILURE(device(idx)->CheckResumeReceivedAndReply(state, ZX_OK));
  }
  coordinator_loop()->RunUntilIdle();

  // Then finally the composite device itself
  ASSERT_NO_FATAL_FAILURE(composite.CheckResumeReceivedAndReply(state, ZX_OK));
  coordinator_loop()->RunUntilIdle();
}

// Make sure we receive devfs notifications when composite devices appear
TEST_F(CompositeTestCase, DevfsNotifications) {
  fidl::ClientEnd<fuchsia_io::DirectoryWatcher> client_end;
  {
    zx::status server = fidl::CreateEndpoints<fuchsia_io::DirectoryWatcher>(&client_end);
    ASSERT_OK(server.status_value());
    ASSERT_OK(devfs_watch(coordinator().root_device()->self, std::move(server.value()),
                          fio::wire::WatchMask::kAdded));
  }

  size_t device_indexes[2];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDevName = "composite-dev";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDevName));
  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }

  DeviceState composite;
  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));

  uint8_t msg[fio::wire::kMaxFilename + 2];
  uint32_t msg_len = 0;
  ASSERT_OK(client_end.channel().read(0, msg, nullptr, sizeof(msg), 0, &msg_len, nullptr));
  ASSERT_EQ(msg_len, 2 + strlen(kCompositeDevName));
  ASSERT_EQ(static_cast<fio::wire::WatchEvent>(msg[0]), fio::wire::WatchEvent::kAdded);
  ASSERT_EQ(msg[1], strlen(kCompositeDevName));
  ASSERT_BYTES_EQ(reinterpret_cast<const uint8_t*>(kCompositeDevName), msg + 2, msg[1]);
}

// Make sure the path returned by GetTopologicalPath is accurate
TEST_F(CompositeTestCase, Topology) {
  size_t device_indexes[2];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDevName = "composite-dev";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDevName));
  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }

  DeviceState composite;
  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));

  Devnode* dn = coordinator().root_device()->self;
  fbl::RefPtr<Device> composite_dev;
  ASSERT_OK(devfs_walk(dn, "composite-dev", &composite_dev));

  char path_buf[PATH_MAX];
  ASSERT_OK(coordinator().GetTopologicalPath(composite_dev, path_buf, sizeof(path_buf)));
  ASSERT_STREQ(path_buf, "/dev/composite-dev");
}

class CompositeMetadataTestCase : public CompositeTestCase {
 public:
  enum class AddLocation {
    // Add the composite before any fragments
    BEFORE,
    // Add the composite after some fragments
    MIDDLE,
    // Add the composite after all fragments
    AFTER,
  };
  static constexpr uint32_t kMetadataKey = 999;
  static constexpr char kMetadataStr[] = "composite-metadata";

  void AddCompositeDevice(AddLocation add = AddLocation::BEFORE);

  static void VerifyMetadata(void* data, size_t len) {
    ASSERT_EQ(strlen(kMetadataStr) + 1, len);
    ASSERT_BYTES_EQ(data, kMetadataStr, len);
  }

  fbl::RefPtr<Device> composite_device;

  // Hold reference to remote channels so that they do not close
  DeviceState composite;
};

void CompositeMetadataTestCase::AddCompositeDevice(AddLocation add) {
  size_t device_indexes[3];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
      ZX_PROTOCOL_ETHERNET,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const device_metadata_t metadata[] = {
      {
          .type = kMetadataKey,
          .data = const_cast<char*>(kMetadataStr),
          .length = strlen(kMetadataStr) + 1,
      },
  };

  const char* kCompositeDevName = "composite-dev";
  auto do_add = [&]() {
    ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(
        platform_bus()->device, protocol_id, std::size(protocol_id), nullptr /* props */, 0,
        kCompositeDevName, ZX_OK, metadata, std::size(metadata)));
  };

  if (add == AddLocation::BEFORE) {
    ASSERT_NO_FATAL_FAILURE(do_add());
  }

  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
    if (i == 0 && add == AddLocation::MIDDLE) {
      ASSERT_NO_FATAL_FAILURE(do_add());
    }
  }

  if (add == AddLocation::AFTER) {
    ASSERT_NO_FATAL_FAILURE(do_add());
  }

  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));
  composite_device = GetCompositeDeviceFromFragment(kCompositeDevName, device_indexes[0]);
  ASSERT_NOT_NULL(composite_device);
}

TEST_F(CompositeMetadataTestCase, AddAndGetMetadata) {
  char buf[32] = "";
  size_t len = 0;
  ASSERT_NO_FATAL_FAILURE(AddCompositeDevice());
  ASSERT_OK(platform_bus()->device->coordinator->GetMetadata(composite_device, kMetadataKey, buf,
                                                             32, &len));
  VerifyMetadata(buf, len);
}

TEST_F(CompositeMetadataTestCase, FailGetMetadata) {
  size_t len = 0;
  ASSERT_NO_FATAL_FAILURE(AddCompositeDevice());
  ASSERT_EQ(platform_bus()->device->coordinator->GetMetadata(composite_device, kMetadataKey + 1,
                                                             nullptr, 0, &len),
            ZX_ERR_NOT_FOUND);
}

TEST_F(CompositeMetadataTestCase, FailGetMetadataFromParent) {
  size_t len = 0;
  ASSERT_NO_FATAL_FAILURE(AddCompositeDevice());
  fbl::RefPtr<Device> parent =
      composite_device->composite()->bound_fragments().front().bound_device();
  ASSERT_EQ(
      platform_bus()->device->coordinator->GetMetadata(parent, kMetadataKey, nullptr, 0, &len),
      ZX_ERR_NOT_FOUND);
}

TEST_F(CompositeMetadataTestCase, DefineAfterDevices) {
  char buf[32] = "";
  size_t len = 0;
  ASSERT_NO_FATAL_FAILURE(AddCompositeDevice(AddLocation::AFTER));
  ASSERT_OK(platform_bus()->device->coordinator->GetMetadata(composite_device, kMetadataKey, buf,
                                                             32, &len));
  VerifyMetadata(buf, len);
}

TEST_F(CompositeMetadataTestCase, DefineInBetweenDevices) {
  char buf[32] = "";
  size_t len = 0;
  ASSERT_NO_FATAL_FAILURE(AddCompositeDevice(AddLocation::MIDDLE));
  ASSERT_OK(platform_bus()->device->coordinator->GetMetadata(composite_device, kMetadataKey, buf,
                                                             32, &len));
  VerifyMetadata(buf, len);
}

TEST_F(CompositeMetadataTestCase, GetMetadataFromChild) {
  char buf[32] = "";
  size_t len = 0;
  size_t child_index = 0;
  ASSERT_NO_FATAL_FAILURE(AddCompositeDevice());
  ASSERT_NO_FATAL_FAILURE(
      AddDevice(composite_device, "child", ZX_PROTOCOL_AUDIO, "", &child_index));
  fbl::RefPtr<Device> child = device(child_index)->device;
  ASSERT_OK(platform_bus()->device->coordinator->GetMetadata(child, kMetadataKey, buf, 32, &len));
  VerifyMetadata(buf, len);
}

// Make sure metadata exists after composite device is destroyed and re-created
// due to fragment removal and addition
TEST_F(CompositeMetadataTestCase, GetMetadataAfterCompositeReassemble) {
  char buf[32] = "";
  size_t len = 0;
  size_t device_indexes[3];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
      ZX_PROTOCOL_ETHERNET,
  };

  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const device_metadata_t metadata[] = {
      {
          .type = kMetadataKey,
          .data = const_cast<char*>(kMetadataStr),
          .length = strlen(kMetadataStr) + 1,
      },
  };

  const char* kCompositeDevName = "composite-dev";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(
      platform_bus()->device, protocol_id, std::size(protocol_id), nullptr /* props */, 0,
      kCompositeDevName, ZX_OK, metadata, std::size(metadata)));

  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(
        AddDevice(platform_bus()->device, name, protocol_id[i], "", &device_indexes[i]));
  }

  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));
  composite_device = GetCompositeDeviceFromFragment(kCompositeDevName, device_indexes[0]);
  ASSERT_NOT_NULL(composite_device);

  // Get and verify metadata
  ASSERT_OK(platform_bus()->device->coordinator->GetMetadata(composite_device, kMetadataKey, buf,
                                                             32, &len));
  VerifyMetadata(buf, len);

  // Remove device 0 and its children (fragment and composite devices).
  ASSERT_NO_FATAL_FAILURE(
      coordinator().device_manager()->ScheduleRemove(device(device_indexes[0])->device));
  coordinator_loop()->RunUntilIdle();

  auto device_zero = device(device_indexes[0]);
  auto fragment = device(fragment_device_indexes[0]);

  // The device and composite should not have received an unbind request yet.
  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(composite.HasPendingMessages());

  // Check the fragment and composite are unbound.
  ASSERT_NO_FATAL_FAILURE(fragment->CheckUnbindReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(fragment->HasPendingMessages());

  ASSERT_NO_FATAL_FAILURE(composite.CheckUnbindReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  // Still waiting for the composite to be removed.
  ASSERT_FALSE(device_zero->HasPendingMessages());
  ASSERT_FALSE(fragment->HasPendingMessages());

  // Finish removing the composite.
  ASSERT_NO_FATAL_FAILURE(composite.CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_FALSE(device_zero->HasPendingMessages());

  // Finish removing the fragment.
  ASSERT_NO_FATAL_FAILURE(fragment->CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  ASSERT_NO_FATAL_FAILURE(device_zero->CheckRemoveReceivedAndReply());
  coordinator_loop()->RunUntilIdle();

  // Add the device back and verify the composite gets created again
  ASSERT_NO_FATAL_FAILURE(
      AddDevice(platform_bus()->device, "device-0", protocol_id[0], "", &device_indexes[0]));
  {
    auto device_state = device(device_indexes[0]);
    // Wait for the fragments to get bound
    fbl::String driver = coordinator().fragment_driver()->libname;
    ASSERT_NO_FATAL_FAILURE(device_state->CheckBindDriverReceivedAndReply(driver.data()));
    coordinator_loop()->RunUntilIdle();

    // Synthesize the AddDevice request the fragment driver would send
    ASSERT_NO_FATAL_FAILURE(AddDevice(device_state->device, "fragment-device-0", 0, driver,
                                      &fragment_device_indexes[0]));
  }
  ASSERT_NO_FATAL_FAILURE(CheckCreateCompositeDeviceReceived(
      driver_host_server(), kCompositeDevName, std::size(device_indexes), &composite));

  composite_device = GetCompositeDeviceFromFragment(kCompositeDevName, device_indexes[0]);
  ASSERT_NOT_NULL(composite_device);

  // Get and verify metadata again
  ASSERT_OK(platform_bus()->device->coordinator->GetMetadata(composite_device, kMetadataKey, buf,
                                                             32, &len));
  VerifyMetadata(buf, len);
}

// Tests that a composite is not created until the fragment devices finish initializing.
TEST_F(CompositeTestCase, FragmentDeviceInit) {
  size_t device_indexes[2];
  uint32_t protocol_id[] = {
      ZX_PROTOCOL_GPIO,
      ZX_PROTOCOL_I2C,
  };
  static_assert(std::size(protocol_id) == std::size(device_indexes));

  const char* kCompositeDevName = "composite-dev";
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, protocol_id,
                                                       std::size(protocol_id), nullptr /* props */,
                                                       0, kCompositeDevName));

  // Add the devices to construct the composite out of.
  for (size_t i = 0; i < std::size(device_indexes); ++i) {
    char name[32];
    snprintf(name, sizeof(name), "device-%zu", i);
    ASSERT_NO_FATAL_FAILURE(AddDevice(platform_bus()->device, name, protocol_id[i], "",
                                      true /* has_init */, false /* reply_to_init */,
                                      true /* always_init */, zx::vmo() /* inspect */,
                                      &device_indexes[i]));
    auto index = device_indexes[i];
    ASSERT_FALSE(device(index)->device->is_visible());
    ASSERT_NO_FATAL_FAILURE(device(index)->CheckInitReceived());
    ASSERT_EQ(Device::State::kInitializing, device(index)->device->state());
    coordinator_loop()->RunUntilIdle();
  }

  for (uint64_t index : device_indexes) {
    // Check that the fragment isn't being bound yet.
    ASSERT_FALSE(device(index)->HasPendingMessages());

    ASSERT_NO_FATAL_FAILURE(device(index)->SendInitReply());
    coordinator_loop()->RunUntilIdle();

    ASSERT_TRUE(device(index)->device->is_visible());
    ASSERT_EQ(Device::State::kActive, device(index)->device->state());
  }

  DeviceState composite;
  size_t fragment_device_indexes[std::size(device_indexes)];
  ASSERT_NO_FATAL_FAILURE(CheckCompositeCreation(kCompositeDevName, device_indexes,
                                                 std::size(device_indexes), fragment_device_indexes,
                                                 &composite));
  coordinator_loop()->RunUntilIdle();

  {
    fbl::RefPtr<Device> comp_device =
        GetCompositeDeviceFromFragment(kCompositeDevName, device_indexes[1]);
    ASSERT_NOT_NULL(comp_device);
    ASSERT_EQ(Device::State::kActive, comp_device->state());
  }
}

TEST_F(CompositeTestCase, DeviceIteratorCompositeChild) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURE(
      AddDevice(platform_bus()->device, "parent-device", 1 /* protocol id */, "", &parent_index));

  uint32_t protocol_id = 1;
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, &protocol_id, 1,
                                                       nullptr, 0, "composite"));

  DeviceState composite;
  size_t fragment_device_indexes;
  ASSERT_NO_FATAL_FAILURE(
      CheckCompositeCreation("composite", &parent_index, 1, &fragment_device_indexes, &composite));

  ASSERT_FALSE(device(parent_index)->device->children().is_empty());
  for (auto& d : device(parent_index)->device->children()) {
    ASSERT_EQ(d.name(), "composite-comp-device-0");
  }
}

TEST_F(CompositeTestCase, DeviceIteratorCompositeChildNoFragment) {
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  ASSERT_OK(endpoints.status_value());

  size_t parent_index;
  ASSERT_NO_FATAL_FAILURE(AddDevice(platform_bus()->device, "parent-device", 1 /* protocol id */,
                                    "", true, true, true, std::move(endpoints->client), zx::vmo(),
                                    &parent_index));

  // If a parent device has these properties, any composite devices will be
  // created without an intermediate fragment device.
  ASSERT_TRUE(device(parent_index)->device->has_outgoing_directory());
  ASSERT_TRUE(device(parent_index)->device->flags & DEV_CTX_MUST_ISOLATE);

  uint32_t protocol_id = 1;
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, &protocol_id, 1,
                                                       nullptr, 0, "composite"));

  DeviceState new_proxy;
  ASSERT_NO_FATAL_FAILURE(CheckCreateNewProxyDeviceReceived(driver_host_server(), &new_proxy));

  // Make sure the composite comes up
  DeviceState composite;
  ASSERT_NO_FATAL_FAILURE(
      CheckCreateCompositeDeviceReceived(driver_host_server(), "composite", 1, &composite));

  ASSERT_FALSE(device(parent_index)->device->children().is_empty());
  for (auto& d : device(parent_index)->device->children()) {
    ASSERT_EQ(d.name(), "composite");
  }
}

TEST_F(CompositeTestCase, DeviceIteratorCompositeSibling) {
  size_t parent_index;
  ASSERT_NO_FATAL_FAILURE(
      AddDevice(platform_bus()->device, "parent-device", 1 /* protocol id */, "", &parent_index));

  uint32_t protocol_id = 1;
  ASSERT_NO_FATAL_FAILURE(BindCompositeDefineComposite(platform_bus()->device, &protocol_id, 1,
                                                       nullptr, 0, "composite"));
  DeviceState composite;
  size_t fragment_device_indexes;
  ASSERT_NO_FATAL_FAILURE(
      CheckCompositeCreation("composite", &parent_index, 1, &fragment_device_indexes, &composite));

  size_t child_index;
  ASSERT_NO_FATAL_FAILURE(
      AddDevice(device(parent_index)->device, "sibling-device", 0, "", &child_index));

  ASSERT_TRUE(device(child_index)->device->children().is_empty());
}

TEST_F(CompositeTestCase, DeviceIteratorOrphanFragment) {
  size_t index;
  fbl::String driver = coordinator().fragment_driver()->libname;
  ASSERT_NO_FATAL_FAILURE(AddDevice(platform_bus()->device, "fragment-device", 0, driver, &index));

  device(index)->device->DetachFromParent();

  ASSERT_TRUE(device(index)->device->children().is_empty());
}
