// 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 <fuchsia/modular/session/cpp/fidl.h>
#include <fuchsia/modular/testing/cpp/fidl.h>
#include <fuchsia/testing/modular/cpp/fidl.h>
#include <lib/vfs/cpp/composed_service_dir.h>
#include <lib/vfs/cpp/pseudo_dir.h>

#include <gmock/gmock.h>
#include <sdk/lib/modular/testing/cpp/fake_agent.h>

#include "src/modular/lib/modular_test_harness/cpp/fake_module.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_session_shell.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_story_shell.h"
#include "src/modular/lib/modular_test_harness/cpp/test_harness_fixture.h"
#include "src/modular/lib/pseudo_dir/pseudo_dir_server.h"

namespace {

const std::string kTestAgentUrl("fuchsia-pkg://fuchsia.com/fake_agent#meta/fake_agent.cmx");
const std::string kTestServiceName(fuchsia::testing::modular::TestProtocol::Name_);

// Configuration for testing |ComponentContext| DeprecatedConnectToAgentService().
struct ConnectToAgentServiceTestConfig {
  // The map of |service_name|->|agent_url| used to look up a service
  // handler |agent_url| by name.
  std::map<std::string, std::string> service_to_agent_map;

  // The session agents to pass to the modular configuration file.
  std::vector<std::string> session_agents;

  // If true, include the service_name in the |AgentServiceRequest|.
  // This is required for a successful connection.
  bool provide_service_name = false;

  // If true, include the specific handler (agent URL) in the
  // |AgentServiceRequest|. This is *not* required for a successful connection.
  bool provide_handler = false;

  // If true, include the service client-side channel in the
  // |AgentServiceRequest|. This is required for a successful connection.
  bool provide_channel = false;

  // If true, include the |AgentController| in the |AgentServiceRequest|.
  // This is required for a successful connection.
  bool provide_agent_controller = false;

  template <typename Interface>
  fuchsia::modular::AgentServiceRequest MakeAgentServiceRequest(
      std::string service_name, Interface service_request,
      fidl::InterfaceRequest<fuchsia::modular::AgentController> agent_controller) {
    fuchsia::modular::AgentServiceRequest agent_service_request;
    if (provide_service_name) {
      agent_service_request.set_service_name(service_name);
    }
    if (provide_handler) {
      agent_service_request.set_handler(kTestAgentUrl);
    }
    if (provide_channel) {
      agent_service_request.set_channel(service_request.TakeChannel());
    }
    if (provide_agent_controller) {
      agent_service_request.set_agent_controller(std::move(agent_controller));
    }
    return agent_service_request;
  }
};

class AgentServicesTest : public modular_testing::TestHarnessFixture {
 protected:
  AgentServicesTest() : fake_agent_(modular_testing::FakeAgent::CreateWithDefaultOptions()) {}

  fuchsia::modular::ComponentContextPtr StartTestHarness(
      ConnectToAgentServiceTestConfig test_config) {
    fuchsia::modular::testing::TestHarnessSpec spec;

    std::vector<fuchsia::modular::session::AgentServiceIndexEntry> agent_service_index;

    for (const auto& entry : test_config.service_to_agent_map) {
      fuchsia::modular::session::AgentServiceIndexEntry agent_service;
      agent_service.set_service_name(entry.first);
      agent_service.set_agent_url(entry.second);
      agent_service_index.emplace_back(std::move(agent_service));
    }

    spec.mutable_sessionmgr_config()->set_agent_service_index(std::move(agent_service_index));
    spec.mutable_sessionmgr_config()->set_session_agents(std::move(test_config.session_agents));

    fuchsia::modular::testing::InterceptSpec intercept_spec;
    intercept_spec.set_component_url(kTestAgentUrl);
    spec.mutable_components_to_intercept()->push_back(std::move(intercept_spec));

    test_harness().events().OnNewComponent =
        [this](fuchsia::sys::StartupInfo startup_info,
               fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent> component) {
          ASSERT_EQ(startup_info.launch_info.url, kTestAgentUrl);
          fake_agent_->BuildInterceptOptions().launch_handler(std::move(startup_info),
                                                              component.Bind());
        };
    fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>
        service_handler =
            [this](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
              if (fake_agent_service_handler_) {
                fake_agent_service_handler_(std::move(request));
              }
            };
    fake_agent_->AddAgentService(std::move(service_handler));
    test_harness()->Run(std::move(spec));

    fuchsia::modular::ComponentContextPtr component_context;
    fuchsia::modular::testing::ModularService modular_service;
    modular_service.set_component_context(component_context.NewRequest());
    test_harness()->ConnectToModularService(std::move(modular_service));

    return component_context;
  }

  // Called by test functions to invoke ConnectToAgentService with various input configurations.
  //
  // |test_config| Input configurations and setup options.
  zx_status_t ExecuteConnectToAgentServiceTest(ConnectToAgentServiceTestConfig test_config) {
    fuchsia::modular::ComponentContextPtr component_context = StartTestHarness(test_config);

    // Client-side service pointer
    fuchsia::testing::modular::TestProtocolPtr service_ptr;
    auto service_name = kTestServiceName;
    auto service_request = service_ptr.NewRequest();
    zx_status_t service_status = ZX_OK;
    bool service_terminated = false;
    service_ptr.set_error_handler([&](zx_status_t status) {
      service_terminated = true;
      service_status = status;
    });

    bool got_request = false;
    fake_agent_service_handler_ =
        [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
          got_request = true;
        };

    fuchsia::modular::AgentControllerPtr agent_controller;
    auto agent_service_request = test_config.MakeAgentServiceRequest(
        service_name, std::move(service_request), agent_controller.NewRequest());
    component_context->DeprecatedConnectToAgentService(std::move(agent_service_request));

    RunLoopUntil([&] { return got_request || service_terminated; });
    fake_agent_service_handler_ = nullptr;  // Callback references local variables.

    // Speed up teardown of the test by eagerly terminating the fake agent.
    fake_agent_->Exit(0);

    // If we got the service request, then routing of the agent service request was successful, even
    // though at this point we have already closed the service channel.
    if (got_request) {
      return ZX_OK;
    } else {
      EXPECT_NE(service_status, ZX_OK);
    }
    return service_status;
  }

  std::unique_ptr<modular_testing::FakeAgent> fake_agent_;
  fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>
      fake_agent_service_handler_;
};

// Ensure Session Manager's ConnectToAgentService can successfully find an
// agent for a given session name, and connect to that agent's service.
TEST_F(AgentServicesTest, ValidAndSuccessfulOneEntry) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  test_config.provide_channel = true;
  test_config.provide_agent_controller = true;

  test_config.service_to_agent_map = {
      {kTestServiceName, kTestAgentUrl},
  };

  EXPECT_EQ(ZX_OK, ExecuteConnectToAgentServiceTest(test_config));
}

// Find agent and service successfully among multiple index entries.
TEST_F(AgentServicesTest, ValidAndSuccessfulMultipleEntries) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  test_config.provide_channel = true;
  test_config.provide_agent_controller = true;

  test_config.service_to_agent_map = {
      {"somenamespace.someappspace.SomeService",
       "fuchsia-pkg://fuchsia.com/some_agent#meta/some_agent.cmx"},
      {kTestServiceName, kTestAgentUrl},
      {"fuchsia.anotherappspace.AnotherService",
       "fuchsia-pkg://fuchsia.com/another_agent#meta/another_agent.cmx"},
  };

  EXPECT_EQ(ZX_OK, ExecuteConnectToAgentServiceTest(test_config));
}

// Find service successfully, from a specific handler. The index specifies this
// agent as the default handler, but should not be necessary.
//
// The handler must be a session agent.
TEST_F(AgentServicesTest, SpecificHandlerProvidedHasService) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  test_config.provide_handler = true;
  test_config.provide_channel = true;
  test_config.provide_agent_controller = true;
  test_config.session_agents = {kTestAgentUrl};

  test_config.service_to_agent_map = {
      {"somenamespace.someappspace.SomeService",
       "fuchsia-pkg://fuchsia.com/some_agent#meta/some_agent.cmx"},
      {kTestServiceName, kTestAgentUrl},
      {"fuchsia.anotherappspace.AnotherService",
       "fuchsia-pkg://fuchsia.com/another_agent#meta/another_agent.cmx"},
  };

  EXPECT_EQ(ZX_OK, ExecuteConnectToAgentServiceTest(test_config));
}

// Find service successfully, from a specific handler. The index does not
// include the requested service, but it should not be needed since the
// handler is specified.
TEST_F(AgentServicesTest, SpecificHandlerProvidedHasServiceButNotInIndex) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  test_config.provide_handler = true;
  test_config.provide_channel = true;
  test_config.provide_agent_controller = true;
  test_config.session_agents = {kTestAgentUrl};

  test_config.service_to_agent_map = {
      {"somenamespace.someappspace.SomeService",
       "fuchsia-pkg://fuchsia.com/some_agent#meta/some_agent.cmx"},
      {"fuchsia.anotherappspace.AnotherService",
       "fuchsia-pkg://fuchsia.com/another_agent#meta/another_agent.cmx"},
  };

  EXPECT_EQ(ZX_OK, ExecuteConnectToAgentServiceTest(test_config));
}

// Find service successfully, from a specific handler. The index specifies
// a different agent as the handler, but that agent should not be used since
// a specific agent was specified.
TEST_F(AgentServicesTest, SpecificHandlerProvidedHasServiceButIndexHasDifferentHandler) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  test_config.provide_handler = true;
  test_config.provide_channel = true;
  test_config.provide_agent_controller = true;
  test_config.session_agents = {kTestAgentUrl};

  test_config.service_to_agent_map = {
      {kTestServiceName, "fuchsia-pkg://fuchsia.com/some_agent#meta/some_agent.cmx"},
      {"fuchsia.anotherappspace.AnotherService",
       "fuchsia-pkg://fuchsia.com/another_agent#meta/another_agent.cmx"},
  };

  EXPECT_EQ(ZX_OK, ExecuteConnectToAgentServiceTest(test_config));
}

// Bad request
TEST_F(AgentServicesTest, NoServiceNameProvided) {
  ConnectToAgentServiceTestConfig test_config;
  // test_config.provide_service_name = true;
  test_config.provide_channel = true;
  test_config.provide_agent_controller = true;

  test_config.service_to_agent_map = {
      {"fuchsia.anotherappspace.AnotherService",
       "fuchsia-pkg://fuchsia.com/another_agent#meta/another_agent.cmx"},
  };

  EXPECT_EQ(ZX_ERR_PEER_CLOSED, ExecuteConnectToAgentServiceTest(test_config));
}

// Bad request
TEST_F(AgentServicesTest, NoChannelProvided) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  // test_config.provide_channel = true;
  test_config.provide_agent_controller = true;

  EXPECT_EQ(ZX_ERR_PEER_CLOSED, ExecuteConnectToAgentServiceTest(test_config));
}

// Attempt to look up the agent based on the service name with no agent
// controller, but it is not in the index.
TEST_F(AgentServicesTest, NoAgentControllerProvided) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  test_config.provide_channel = true;
  // test_config.provide_agent_controller = true;

  EXPECT_EQ(ZX_ERR_NOT_FOUND, ExecuteConnectToAgentServiceTest(test_config));
}

// Attempt to look up the agent based on the service name, but it is not in
// the index.
TEST_F(AgentServicesTest, NoHandlerForService) {
  ConnectToAgentServiceTestConfig test_config;
  test_config.provide_service_name = true;
  test_config.provide_channel = true;
  test_config.provide_agent_controller = true;

  EXPECT_EQ(ZX_ERR_NOT_FOUND, ExecuteConnectToAgentServiceTest(test_config));
}

class AgentServicesSFWCompatTest : public modular_testing::TestHarnessFixture {
 protected:
  AgentServicesSFWCompatTest() {}

  fuchsia::modular::testing::TestHarnessSpec CreateSpecWithAgentServiceIndex(
      std::map<std::string, std::string> agent_service_index_map) {
    fuchsia::modular::testing::TestHarnessSpec spec;
    std::vector<fuchsia::modular::session::AgentServiceIndexEntry> agent_service_index;
    for (const auto& entry : agent_service_index_map) {
      fuchsia::modular::session::AgentServiceIndexEntry agent_service;
      agent_service.set_service_name(entry.first);
      agent_service.set_agent_url(entry.second);
      agent_service_index.emplace_back(std::move(agent_service));
    }
    spec.mutable_sessionmgr_config()->set_agent_service_index(std::move(agent_service_index));
    return spec;
  }

  modular_testing::TestHarnessBuilder::InterceptOptions AddSandboxServices(
      std::vector<std::string> service_names,
      modular_testing::TestHarnessBuilder::InterceptOptions options) {
    for (auto service_name : service_names) {
      options.sandbox_services.push_back(service_name);
    }
    return options;
  }
};

// A version of FakeComponent, behaviorally similar to FakeAgent, with the added behavior of
// capturing the `requestor_url` parameter of Agent.Connect() calls and exposing them through
// `requestor_urls()`.
class RequestorIdCapturingAgent : public modular_testing::FakeComponent,
                                  fuchsia::modular::Agent,
                                  fuchsia::sys::ServiceProvider {
 public:
  RequestorIdCapturingAgent(modular_testing::FakeComponent::Args args)
      : FakeComponent(std::move(args)) {}

  static std::unique_ptr<RequestorIdCapturingAgent> CreateWithDefaultOptions() {
    return std::make_unique<RequestorIdCapturingAgent>(modular_testing::FakeComponent::Args{
        .url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});
  }

  std::vector<std::string> requestor_urls() const { return requestor_urls_; }

  template <typename Interface>
  void AddAgentService(fidl::InterfaceRequestHandler<Interface> handler) {
    service_name_to_handler_[Interface::Name_] = [handler = std::move(handler)](zx::channel req) {
      handler(fidl::InterfaceRequest<Interface>(std::move(req)));
    };
  }

  template <typename Interface>
  void AddPublicService(fidl::InterfaceRequestHandler<Interface> handler) {
    buffered_add_service_calls_.push_back([this, handler = std::move(handler)]() mutable {
      component_context()->outgoing()->AddPublicService(std::move(handler));
    });

    FlushAddServiceCallsIfRunning();
  }

 protected:
  // |modular_testing::FakeComponent|
  void OnCreate(fuchsia::sys::StartupInfo startup_info) {
    component_context()->outgoing()->AddPublicService<fuchsia::modular::Agent>(
        agent_bindings_.GetHandler(this));
    FlushAddServiceCallsIfRunning();
  }

  // |fuchsia::modular::Agent|
  void Connect(
      std::string requestor_id,
      fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> outgoing_services_request) override {
    requestor_urls_.push_back(requestor_id);
    agent_service_provider_bindings_.AddBinding(this, std::move(outgoing_services_request));
  }

  // |fuchsia::sys::ServiceProvider|
  void ConnectToService(std::string service_name, zx::channel request) override {
    auto it = service_name_to_handler_.find(service_name);
    if (it != service_name_to_handler_.end()) {
      it->second(std::move(request));
    }
  }

  void FlushAddServiceCallsIfRunning() {
    if (is_running()) {
      for (auto& call : buffered_add_service_calls_) {
        call();
      }
      buffered_add_service_calls_.clear();
    }
  }

  std::vector<std::string> requestor_urls_;

  fidl::BindingSet<fuchsia::modular::Agent> agent_bindings_;
  fidl::BindingSet<fuchsia::sys::ServiceProvider> agent_service_provider_bindings_;

  // A mapping of `service name -> service connection handle`.
  std::unordered_map<std::string, fit::function<void(zx::channel)>> service_name_to_handler_;
  std::vector<fit::closure> buffered_add_service_calls_;
};  // namespace

// Test that an Agent service can be acquired from any of another Agent, a Module, Session or Story
// Shells, including testing that calls to the Agent.Connect() method (implemented by the agent)
// result in the correct requestor ids, even if those clients connect via their environment.
TEST_F(AgentServicesSFWCompatTest, ConnectToService_Success) {
  auto serving_agent = RequestorIdCapturingAgent::CreateWithDefaultOptions();

  // Intercept the following components in order to test their access to agent services
  // through their respective environments.
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  auto story_shell = modular_testing::FakeStoryShell::CreateWithDefaultOptions();
  auto module = modular_testing::FakeModule::CreateWithDefaultOptions();

  // Set up the test environment with TestProtocol being served by `serving_agent`.
  auto spec = CreateSpecWithAgentServiceIndex(
      {{fuchsia::testing::modular::TestProtocol::Name_, serving_agent->url()}});
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptComponent(serving_agent->BuildInterceptOptions());
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                agent->BuildInterceptOptions()));
  builder.InterceptSessionShell(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                   session_shell->BuildInterceptOptions()));
  builder.InterceptStoryShell(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                 story_shell->BuildInterceptOptions()));
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                module->BuildInterceptOptions()));

  // Instruct `serving_agent` to serve the TestProtocol, tracking the number of times
  // the service was successfully connected.
  int num_connections = 0;
  std::vector<zx::channel> protocol_requests;
  serving_agent->AddAgentService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
          [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
            ++num_connections;
            protocol_requests.push_back(request.TakeChannel());
          }));
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return agent->is_running() && session_shell->is_running(); });
  ASSERT_FALSE(serving_agent->is_running());

  // Create a story so that the story shell and module are both run.
  fuchsia::modular::Intent intent;
  intent.handler = module->url();
  intent.action = "action";
  modular_testing::AddModToStory(test_harness(), "storyName", "modName", std::move(intent));
  RunLoopUntil([&] { return story_shell->is_running() && module->is_running(); });

  // Attempt to connect to the test service from all of our different components.
  std::vector<fuchsia::testing::modular::TestProtocolPtr> protocol_ptrs;
  protocol_ptrs.push_back(
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>());
  protocol_ptrs.push_back(session_shell->component_context()
                              ->svc()
                              ->Connect<fuchsia::testing::modular::TestProtocol>());
  protocol_ptrs.push_back(
      story_shell->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>());
  protocol_ptrs.push_back(
      module->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>());

  // Track the number of those connection attempts failed.
  int num_errors = 0;
  for (auto& ptr : protocol_ptrs) {
    ptr.set_error_handler([&](zx_status_t) { ++num_errors; });
  }

  constexpr int kTotalRequests = 4;
  RunLoopUntil([&] { return num_connections + num_errors == kTotalRequests; });
  EXPECT_TRUE(serving_agent->is_running());
  EXPECT_EQ(num_connections, kTotalRequests);
  EXPECT_EQ(num_errors, 0);
  EXPECT_THAT(serving_agent->requestor_urls(),
              testing::UnorderedElementsAre(agent->url(), session_shell->url(), story_shell->url(),
                                            /* `module` path */ "modName"));
}

// Test that when a component tries to connect to a service through its environment,
// but the agent that serves that service can't be launched, an error is returned.
TEST_F(AgentServicesSFWCompatTest, ConnectToService_FailAgentNotPresent) {
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  // Set up the test environment with TestProtocol being served by `serving_agent`, but
  // under a name that will not match when `agent` tries to connect.
  auto spec = CreateSpecWithAgentServiceIndex(
      {{fuchsia::testing::modular::TestProtocol::Name_, "fuchsia-pkg://fuchsia.com/not/found"}});
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                agent->BuildInterceptOptions()));
  builder.BuildAndRun(test_harness());
  RunLoopUntil([&] { return agent->is_running(); });

  // Attempt to connect to the test service.
  bool saw_error = false;
  zx_status_t status = ZX_OK;
  auto ptr = agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();
  ptr.set_error_handler([&](zx_status_t s) {
    saw_error = true;
    status = s;
  });

  RunLoopUntil([&] { return saw_error; });
  // appmgr / sysmgr result in a peer closed error.
  EXPECT_EQ(status, ZX_ERR_PEER_CLOSED);
}

// Test that when a component tries to connect to a service through its environment,
// but that service is not available, the client encounters an error.
TEST_F(AgentServicesSFWCompatTest, ConnectToService_FailNoAgentMapping) {
  auto serving_agent = modular_testing::FakeAgent::CreateWithDefaultOptions();
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  // Set up the test environment with TestProtocol being served by `serving_agent`, but
  // under a name that will not match when `agent` tries to connect.
  auto spec =
      CreateSpecWithAgentServiceIndex({{"fuchsia.testing.modular.NotFound", serving_agent->url()}});
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptComponent(serving_agent->BuildInterceptOptions());
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                agent->BuildInterceptOptions()));

  // Instruct `serving_agent` to serve the TestProtocol.
  serving_agent->AddAgentService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
          [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
            FAIL() << "Did not expect service connection request to reach the agent.";
          }));
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return agent->is_running(); });
  ASSERT_FALSE(serving_agent->is_running());

  // Attempt to connect to the test service.
  bool saw_error = false;
  zx_status_t status = ZX_OK;
  auto ptr = agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();
  ptr.set_error_handler([&](zx_status_t s) {
    saw_error = true;
    status = s;
  });
  RunLoopUntil([&] { return saw_error; });
  EXPECT_FALSE(serving_agent->is_running());
  // appmgr / sysmgr result in a peer closed error.
  EXPECT_EQ(status, ZX_ERR_PEER_CLOSED);
}

// Test that an agent can publish its services using its outgoing directory, and that clients
// can connect to those services through either ComponentContext.ConnectToAgent*() or
// sys.ComponentContext.srv().Connect().
TEST_F(AgentServicesSFWCompatTest, PublishToOutgoingDirectory) {
  auto serving_agent = RequestorIdCapturingAgent::CreateWithDefaultOptions();

  // Intercept this agent and use it as a client to connect to `serving_agent`.
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  // Set up the test environment with TestProtocol being served by `serving_agent`.
  auto spec = CreateSpecWithAgentServiceIndex(
      {{fuchsia::testing::modular::TestProtocol::Name_, serving_agent->url()}});
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(serving_agent->url());

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptComponent(serving_agent->BuildInterceptOptions());
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                agent->BuildInterceptOptions()));

  // Instruct `serving_agent` to serve the TestProtocol, tracking the number of times
  // the service was successfully connected.
  int num_connections = 0;
  std::vector<zx::channel> protocol_requests;
  // Note that TestProtocol is being served using a sys.OutgoingDirectory.
  serving_agent->AddPublicService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
          [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
            ++num_connections;
            protocol_requests.push_back(request.TakeChannel());
          }));
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return agent->is_running(); });

  // Attempt to connect to the test service in all ways that are currently supported.
  std::vector<fuchsia::testing::modular::TestProtocolPtr> protocol_ptrs;
  std::vector<fuchsia::modular::AgentControllerPtr> agent_controllers;

  // Method 1: Connect using `agent`'s incoming directory
  protocol_ptrs.push_back(
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>());

  // Method 2: Connect using fuchsia.modular.ComponentContext/DeprecatedConnectToAgentService().
  fuchsia::modular::AgentServiceRequest agent_service_request;
  protocol_ptrs.emplace_back();
  agent_controllers.emplace_back();
  agent_service_request.set_service_name(fuchsia::testing::modular::TestProtocol::Name_);
  agent_service_request.set_channel(protocol_ptrs.back().NewRequest().TakeChannel());
  agent_service_request.set_agent_controller(agent_controllers.back().NewRequest());
  agent_service_request.set_handler(serving_agent->url());
  agent->modular_component_context()->DeprecatedConnectToAgentService(
      std::move(agent_service_request));

  // Track the number of those connection attempts failed.
  int num_errors = 0;
  for (auto& ptr : protocol_ptrs) {
    ptr.set_error_handler([&](zx_status_t) { ++num_errors; });
  }

  constexpr int kTotalRequests = 2;
  RunLoopUntil([&] { return num_connections + num_errors == kTotalRequests; });
  EXPECT_TRUE(serving_agent->is_running());
  EXPECT_EQ(num_connections, kTotalRequests);
  EXPECT_EQ(num_errors, 0);
}

// If an agent exposes a service via both its outgoing directory and through fuchsia.modular.Agent,
// prefer the outgoing directory.
TEST_F(AgentServicesSFWCompatTest, PublishToOugoingDirectoryPrioritizesOutoingDirectory) {
  auto serving_agent = RequestorIdCapturingAgent::CreateWithDefaultOptions();

  // Intercept this agent and use it as a client to connect to `serving_agent`.
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  // Set up the test environment with TestProtocol being served by `serving_agent`.
  auto spec = CreateSpecWithAgentServiceIndex(
      {{fuchsia::testing::modular::TestProtocol::Name_, serving_agent->url()}});
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptComponent(serving_agent->BuildInterceptOptions());
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                agent->BuildInterceptOptions()));

  // Publish the service as both an outgoing/public service and an agent service.
  bool saw_agent_connection = false;
  bool saw_outgoing_connection = false;
  serving_agent->AddAgentService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
          [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
            saw_agent_connection = true;
          }));
  serving_agent->AddPublicService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
          [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
            saw_outgoing_connection = true;
          }));
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return agent->is_running(); });
  ASSERT_FALSE(serving_agent->is_running());

  auto protocol_ptr =
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();

  RunLoopUntil([&] { return saw_agent_connection || saw_outgoing_connection; });
  EXPECT_TRUE(saw_outgoing_connection);
  EXPECT_FALSE(saw_agent_connection);
}

class NoAgentProtocolAgent : public RequestorIdCapturingAgent {
 public:
  NoAgentProtocolAgent(modular_testing::FakeComponent::Args args)
      : RequestorIdCapturingAgent(std::move(args)) {}

  static std::unique_ptr<NoAgentProtocolAgent> CreateWithDefaultOptions() {
    return std::make_unique<NoAgentProtocolAgent>(modular_testing::FakeComponent::Args{
        .url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});
  }

 private:
  // |modular_testing::FakeComponent|
  void OnCreate(fuchsia::sys::StartupInfo startup_info) {
    // Don't publish the fuchsia.modular.Agent service!
    FlushAddServiceCallsIfRunning();
  }
};

// Test that an agent can still serve through its outgoing directory even if it does *not* publish
// the fuchsia.modular.Agent protocol at all.
TEST_F(AgentServicesSFWCompatTest, PublishToOutgoingDirectoryStillWorksWithoutAgentProtocol) {
  auto serving_agent = NoAgentProtocolAgent::CreateWithDefaultOptions();

  // Intercept this agent and use it as a client to connect to `serving_agent`.
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  // Set up the test environment with TestProtocol being served by `serving_agent`.
  auto spec = CreateSpecWithAgentServiceIndex(
      {{fuchsia::testing::modular::TestProtocol::Name_, serving_agent->url()}});
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptComponent(serving_agent->BuildInterceptOptions());
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                agent->BuildInterceptOptions()));

  // Publish the service as an outgoing/public service.
  bool saw_outgoing_connection = false;
  serving_agent->AddPublicService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
          [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
            saw_outgoing_connection = true;
          }));
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return agent->is_running(); });
  ASSERT_FALSE(serving_agent->is_running());

  auto protocol_ptr =
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();

  RunLoopUntil([&] { return saw_outgoing_connection; });
}

class BuggyOutgoingDirAgent {
 public:
  BuggyOutgoingDirAgent(modular_testing::FakeComponent::Args args)
      : args_(std::move(args)), hidden_service_dir_(new vfs::PseudoDir()) {}

  static std::unique_ptr<BuggyOutgoingDirAgent> CreateWithDefaultOptions() {
    return std::make_unique<BuggyOutgoingDirAgent>(modular_testing::FakeComponent::Args{
        .url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});
  }

  modular_testing::TestHarnessBuilder::InterceptOptions BuildInterceptOptions(
      async_dispatcher_t* dispatcher = nullptr) {
    modular_testing::TestHarnessBuilder::InterceptOptions options;
    options.url = args_.url;
    options.sandbox_services = args_.sandbox_services;
    options.launch_handler =
        [this, dispatcher](fuchsia::sys::StartupInfo startup_info,
                           fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent>
                               intercepted_component) {
          intercepted_component_ptr_.Bind(std::move(intercepted_component), dispatcher);
          intercepted_component_ptr_.events().OnKill = [this] { OnDestroy(); };

          OnCreate(std::move(startup_info));
        };
    return options;
  }

  template <typename Interface>
  void AddPublicService(fidl::InterfaceRequestHandler<Interface> handler) {
    hidden_service_dir_->AddEntry(Interface::Name_,
                                  std::make_unique<vfs::Service>(std::move(handler)));
  }

  bool is_running() { return is_running_; }
  const std::string& url() { return args_.url; }

 protected:
  void OnCreate(fuchsia::sys::StartupInfo startup_info) {
    // Configure a ComposedServiceDir which exhibits fxbug.dev/55769.
    //
    // outgoing_dir (type: PseudoDir, serves: LaunchInfo.directory_request)
    //   svc/ -> composed_service_dir (type: ComposedServiceDir)
    //           with fallback: hidden_service_dir_ (type: PseudoDir)
    fuchsia::io::DirectoryPtr hidden_service_dir_ptr;
    hidden_service_dir_->Serve(fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE |
                                   fuchsia::io::OPEN_FLAG_DIRECTORY,
                               hidden_service_dir_ptr.NewRequest().TakeChannel());

    auto composed_service_dir = std::make_unique<vfs::ComposedServiceDir>();
    composed_service_dir->set_fallback(std::move(hidden_service_dir_ptr));

    auto outgoing_dir = std::make_unique<vfs::PseudoDir>();
    outgoing_dir->AddEntry("svc", std::move(composed_service_dir));
    outgoing_dir_server_ = std::make_unique<modular::PseudoDirServer>(std::move(outgoing_dir));
    outgoing_dir_server_->Serve(std::move(startup_info.launch_info.directory_request));

    is_running_ = true;
  }

  void OnDestroy() { is_running_ = false; }

  modular_testing::FakeComponent::Args args_;
  std::unique_ptr<modular::PseudoDirServer> outgoing_dir_server_;
  std::unique_ptr<vfs::PseudoDir> hidden_service_dir_;
  fuchsia::modular::testing::InterceptedComponentPtr intercepted_component_ptr_;

  bool is_running_ = false;
};

// Test that an agent that:
//  * Does NOT publish fuchsia.modular.Agent
//  * Serves an outgoing directory implementation with a bug (fxbug.dev/55769)
//    resulting in it not returning directory entries from ReadDirents()
//  * But still serves a service in that directory
//
// will result in successful connections to the service.
//
// TODO(fxbug.dev/55769): Once fixed, remove this test and the class BuggyOutgoingDirAgent.
TEST_F(AgentServicesSFWCompatTest, PublishToBuggyOutgoingDirectoryStillWorksWithoutAgentProtocol) {
  auto serving_agent = BuggyOutgoingDirAgent::CreateWithDefaultOptions();

  // Intercept this agent and use it as a client to connect to `serving_agent`.
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  // Set up the test environment with TestProtocol being served by `serving_agent`.
  auto spec = CreateSpecWithAgentServiceIndex(
      {{fuchsia::testing::modular::TestProtocol::Name_, serving_agent->url()}});
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());
  spec.mutable_sessionmgr_config()->mutable_session_agents()->push_back(serving_agent->url());

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptComponent(serving_agent->BuildInterceptOptions());
  builder.InterceptComponent(AddSandboxServices({fuchsia::testing::modular::TestProtocol::Name_},
                                                agent->BuildInterceptOptions()));

  // Publish fuchsia.modular.Agent so that the test can wait until after sessionmgr has
  // observed its request for fuchsia.modular.Agent close. The workaround relies on
  // the the Agent channel being closed.
  bool saw_agent_service_request = false;
  serving_agent->AddPublicService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::modular::Agent>)>(
          [&](fidl::InterfaceRequest<fuchsia::modular::Agent> request) {
            saw_agent_service_request = true;
            request.Close(ZX_ERR_NOT_FOUND);
          }));

  // Publish the service as an outgoing/public service.
  bool saw_test_protocol_request = false;
  serving_agent->AddPublicService(
      fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
          [&](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
            saw_test_protocol_request = true;
          }));
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return agent->is_running() && serving_agent->is_running(); });
  RunLoopUntil([&] { return saw_agent_service_request; });

  auto protocol_ptr =
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();

  RunLoopUntil([&] { return saw_test_protocol_request; });
}

}  // namespace
