// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <tuple>
#include <vector>

#include <mesos/http.hpp>

#include <mesos/v1/resources.hpp>

#include <mesos/v1/master/master.hpp>

#include <mesos/v1/scheduler/scheduler.hpp>

#include <process/clock.hpp>
#include <process/future.hpp>
#include <process/gmock.hpp>
#include <process/gtest.hpp>
#include <process/http.hpp>
#include <process/owned.hpp>
#include <process/reap.hpp>

#include <stout/gtest.hpp>
#include <stout/jsonify.hpp>
#include <stout/nothing.hpp>
#include <stout/stringify.hpp>
#include <stout/try.hpp>

#include "common/http.hpp"

#include "master/detector/standalone.hpp"

#include "slave/slave.hpp"

#include "slave/containerizer/fetcher.hpp"

#include "slave/containerizer/mesos/containerizer.hpp"

#include "tests/mesos.hpp"

namespace http = process::http;

using std::string;
using std::tuple;
using std::vector;

using mesos::master::detector::MasterDetector;
using mesos::master::detector::StandaloneMasterDetector;

using mesos::internal::slave::Fetcher;
using mesos::internal::slave::MesosContainerizer;
using mesos::internal::slave::Slave;

using process::Clock;
using process::TEST_AWAIT_TIMEOUT;
using process::Failure;
using process::Future;
using process::Owned;

using testing::_;
using testing::Return;
using testing::WithParamInterface;

namespace mesos {
namespace internal {
namespace tests {

enum ContainerLaunchType
{
  NORMAL,
  STANDALONE
};


// These tests are parameterized by:
// 1) The type of any parent container.
//    A NORMAL parent is launched with a framework and executor.
//    A STANDALONE parent is launched via `LAUNCH_CONTAINER`.
// 2) The type of any nested container.
//    A NORMAL nested container is launched via `LAUNCH_NESTED_CONTAINER`.
//    A STANDALONE nested contaienr is launched via `LAUNCH_CONTAINER`.
// 3) The content type of the HTTP request(s).
// 4) A tuple containing:
//    1) The isolators to enable during the test.
//    2) The launcher to use.
//    3) And, in case the isolator/launcher requires specific permissions
//       or capabilities, the last parameter is a free-form string used
//       to supply additional test filters.
class AgentContainerAPITest
  : public MesosTest,
    public WithParamInterface<
      tuple<
        ContainerLaunchType,
        ContainerLaunchType,
        ContentType,
        tuple<string, string, string>>>
{
public:
  // Helper function to post a request to the `/api/v1` agent endpoint
  // and return the response.
  Future<http::Response> post(
      const process::PID<slave::Slave>& pid,
      const v1::agent::Call& call)
  {
    ContentType contentType = std::get<2>(GetParam());

    http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
    headers["Accept"] = stringify(contentType);

    return http::post(
        pid,
        "api/v1",
        headers,
        serialize(contentType, call),
        stringify(contentType));
  }

  // Helper function to deserialize the response from the `/api/v1` agent
  // endpoint as a V1 response protobuf.
  Future<v1::agent::Response> deserialize(
      const Future<http::Response>& response)
  {
    ContentType contentType = std::get<2>(GetParam());

    return response
      .then([contentType](const http::Response& response)
            -> Future<v1::agent::Response> {
        if (response.status != http::OK().status) {
          return Failure(
              "Unexpected response status: " + response.status +
              ": " + response.body);
        }

        return mesos::internal::deserialize<v1::agent::Response>(
            contentType, response.body);
      });
  }

  // Helper function to launch a top level container based on the first
  // test parameter:
  //   * NORMAL mode will launch a scheduler, executor, and task in order
  //     to create a top level container and uses the `GET_CONTAINERS`
  //     agent API call to retrieve the ContainerID (this method assumes
  //     there is only one container present on the agent).
  //   * STANDALONE mode uses the `LAUNCH_CONTAINER` agent API to create
  //     a top level container. The ContainerID is generated by the callee.
  //
  // Returns the ContainerID of the created container.
  Try<v1::ContainerID> launchParentContainer(
      const process::PID<master::Master>& master,
      const process::PID<slave::Slave>& slave)
  {
    switch (std::get<0>(GetParam())) {
      case ContainerLaunchType::NORMAL: {
        normal = NormalParentContainerDependencies(master);

        // Launch a normal executor and sleep task.
        EXPECT_CALL(
            *(normal->scheduler), registered(normal->driver.get(), _, _));

        Future<vector<Offer>> offers;
        EXPECT_CALL(
            *(normal->scheduler), resourceOffers(normal->driver.get(), _))
          .WillOnce(FutureArg<1>(&offers))
          .WillRepeatedly(Return()); // Ignore subsequent offers.

        normal->driver->start();

        offers.await(TEST_AWAIT_TIMEOUT);
        if (!offers.isReady() || offers->empty()) {
          return Error("Failed to get offer(s)");
        }

        TaskInfo task = createTask(offers->front(), SLEEP_COMMAND(1000));

        Future<TaskStatus> statusRunning;
        EXPECT_CALL(*(normal->scheduler), statusUpdate(normal->driver.get(), _))
          .WillOnce(FutureArg<1>(&statusRunning))
          .WillRepeatedly(Return()); // Ignore subsequent status updates.

        normal->driver->launchTasks(offers->front().id(), {task});

        statusRunning.await(TEST_AWAIT_TIMEOUT);
        if (!statusRunning.isReady() &&
            statusRunning->state() != TASK_RUNNING) {
          return Error("Failed to launch parent container");
        }

        // Use the GET_CONTAINERS call to retrieve the ContainerID.
        v1::agent::Call call;
        call.set_type(v1::agent::Call::GET_CONTAINERS);

        Future<v1::agent::Response> containers = deserialize(post(slave, call));

        containers.await(TEST_AWAIT_TIMEOUT);
        if (!containers.isReady() ||
            containers->get_containers().containers_size() != 1u) {
          return Error("Failed to get parent ContainerID");
        }

        return containers->get_containers().containers(0).container_id();
      }

      case ContainerLaunchType::STANDALONE: {
        // TODO(josephw): The agent should not need to register with
        // the master to launch standalone containers.
        Future<SlaveRegisteredMessage> slaveRegisteredMessage =
          FUTURE_PROTOBUF(SlaveRegisteredMessage(), _, _);

        slaveRegisteredMessage.await(TEST_AWAIT_TIMEOUT);
        if (!slaveRegisteredMessage.isReady()) {
          return Error("Failed to register agent");
        }

        // Launch a standalone parent container.
        v1::ContainerID containerId;
        containerId.set_value(id::UUID::random().toString());

        v1::agent::Call call;
        call.set_type(v1::agent::Call::LAUNCH_CONTAINER);

        call.mutable_launch_container()->mutable_container_id()
          ->CopyFrom(containerId);

        call.mutable_launch_container()->mutable_command()
          ->set_value(SLEEP_COMMAND(1000));

        v1::Resources resources = v1::Resources::parse("cpus:0.1;mem:32").get();
        call.mutable_launch_container()->mutable_resources()
          ->CopyFrom(resources);

        Future<http::Response> response = post(slave, call);

        AWAIT_EXPECT_RESPONSE_STATUS_EQ(http::OK().status, response);

        return containerId;
      }
    }

    UNREACHABLE();
  }

  // Helper function to launch a nested container under the given ContainerID
  // based on the second test parameter:
  //   * NORMAL mode uses the (deprecated) `LAUNCH_NESTED_CONTAINER` API.
  //   * STANDALONE mode uses the `LAUNCH_CONTAINER` API.
  Future<http::Response> launchNestedContainer(
      const process::PID<slave::Slave>& slave,
      const v1::ContainerID& containerId,
      const Option<mesos::v1::CommandInfo>& commandInfo = None(),
      const Option<mesos::v1::ContainerInfo>& containerInfo = None())
  {
    v1::agent::Call call;

    switch (std::get<1>(GetParam())) {
      case ContainerLaunchType::NORMAL: {
        call.set_type(v1::agent::Call::LAUNCH_NESTED_CONTAINER);

        call.mutable_launch_nested_container()->mutable_container_id()
          ->CopyFrom(containerId);

        call.mutable_launch_nested_container()->mutable_command()
          ->set_value(SLEEP_COMMAND(100));

        if (commandInfo.isSome()) {
          call.mutable_launch_nested_container()->mutable_command()
            ->CopyFrom(commandInfo.get());
        }

        if (containerInfo.isSome()) {
          call.mutable_launch_nested_container()->mutable_container()
            ->CopyFrom(containerInfo.get());
        }
        break;
      }

      case ContainerLaunchType::STANDALONE: {
        call.set_type(v1::agent::Call::LAUNCH_CONTAINER);

        call.mutable_launch_container()->mutable_container_id()
          ->CopyFrom(containerId);

        call.mutable_launch_container()->mutable_command()
          ->set_value(SLEEP_COMMAND(100));

        if (commandInfo.isSome()) {
          call.mutable_launch_container()->mutable_command()
            ->CopyFrom(commandInfo.get());
        }

        if (containerInfo.isSome()) {
          call.mutable_launch_container()->mutable_container()
            ->CopyFrom(containerInfo.get());
        }
        break;
      }
    }

    return post(slave, call);
  }

  // Helper function to wait for a nested container to terminate,
  // based on the second test parameter:
  //   * NORMAL mode uses the (deprecated) `WAIT_NESTED_CONTAINER` API.
  //   * STANDALONE mode uses the `WAIT_CONTAINER` API.
  Future<http::Response> waitNestedContainer(
      const process::PID<slave::Slave>& slave,
      const v1::ContainerID& containerId)
  {
    v1::agent::Call call;

    switch (std::get<1>(GetParam())) {
      case ContainerLaunchType::NORMAL: {
        call.set_type(v1::agent::Call::WAIT_NESTED_CONTAINER);

        call.mutable_wait_nested_container()->mutable_container_id()
          ->CopyFrom(containerId);
        break;
      }

      case ContainerLaunchType::STANDALONE: {
        call.set_type(v1::agent::Call::WAIT_CONTAINER);

        call.mutable_wait_container()->mutable_container_id()
          ->CopyFrom(containerId);
        break;
      }
    }

    return post(slave, call);
  }

  // Helper function to check the response to a `WAIT_[NESTED_]CONTAINER`
  // call according to the given signal or lack of signal.
  // The expected response type is based on the second test parameter.
  // See `waitNestedContainer`.
  bool checkWaitContainerResponse(
      const Future<v1::agent::Response>& response,
      const Option<int>& signal)
  {
    switch (std::get<1>(GetParam())) {
      case ContainerLaunchType::NORMAL: {
        if (response->type() != v1::agent::Response::WAIT_NESTED_CONTAINER) {
          return false;
        }

        if (signal.isSome()) {
          if (!response->wait_nested_container().has_exit_status()) {
            return false;
          }

          if (response->wait_nested_container().exit_status() != signal.get()) {
            return false;
          }
        }
        break;
      }

      case ContainerLaunchType::STANDALONE: {
        if (response->type() != v1::agent::Response::WAIT_CONTAINER) {
          return false;
        }

        if (signal.isSome()) {
          if (!response->wait_container().has_exit_status()) {
            return false;
          }

          if (response->wait_container().exit_status() != signal.get()) {
            return false;
          }
        }
        break;
      }
    }

    return true;
  }

  // Helper function to kill a nested container, based on the second
  // test parameter:
  //   * NORMAL mode uses the (deprecated) `KILL_NESTED_CONTAINER` API.
  //   * STANDALONE mode uses the `KILL_CONTAINER` API.
  Future<http::Response> killNestedContainer(
      const process::PID<slave::Slave>& slave,
      const v1::ContainerID& containerId)
  {
    v1::agent::Call call;

    switch (std::get<1>(GetParam())) {
      case ContainerLaunchType::NORMAL: {
        call.set_type(v1::agent::Call::KILL_NESTED_CONTAINER);

        call.mutable_kill_nested_container()->mutable_container_id()
          ->CopyFrom(containerId);
        break;
      }

      case ContainerLaunchType::STANDALONE: {
        call.set_type(v1::agent::Call::KILL_CONTAINER);

        call.mutable_kill_container()->mutable_container_id()
          ->CopyFrom(containerId);
        break;
      }
    }

    return post(slave, call);
  }

  Future<http::Response> getContainers(
      const process::PID<slave::Slave>& slave)
  {
    v1::agent::Call call;
    call.set_type(v1::agent::Call::GET_CONTAINERS);
    call.mutable_get_containers()->set_show_nested(true);
    call.mutable_get_containers()->set_show_standalone(true);

    return post(slave, call);
  }

protected:
  void TearDown() override
  {
    if (normal.isSome()) {
      normal->driver->stop();
      normal->driver->join();

      normal = None();
    }

    MesosTest::TearDown();
  }

private:
  struct NormalParentContainerDependencies
  {
    NormalParentContainerDependencies(
        const process::PID<master::Master>& master)
      : scheduler(new MockScheduler())
    {
      // Enable checkpointing for the framework.
      FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
      framework.set_checkpoint(true);

      driver.reset(new MesosSchedulerDriver(
          scheduler.get(),
          framework,
          master,
          DEFAULT_CREDENTIAL));
    }

    // NOTE: These need to be pointers due to how each mock's copy constructor
    // is explicitly deleted (for good reason) and because `Option` requires
    // said copy constructors for certain operations.
    Owned<MockScheduler> scheduler;
    Owned<MesosSchedulerDriver> driver;
  };

  Option<NormalParentContainerDependencies> normal;
};


INSTANTIATE_TEST_CASE_P(
    ParentChildContainerTypeAndContentType,
    AgentContainerAPITest,
    ::testing::Combine(
      ::testing::Values(
        ContainerLaunchType::NORMAL,
        ContainerLaunchType::STANDALONE),
      ::testing::Values(
        ContainerLaunchType::NORMAL,
        ContainerLaunchType::STANDALONE),
      ::testing::Values(
        ContentType::JSON,
        ContentType::PROTOBUF),
      ::testing::Values(
        make_tuple(
            string("posix/cpu,posix/mem"),
            string("posix"),
            string()),
        make_tuple(
            string("cgroups/cpu,cgroups/mem,filesystem/linux,namespaces/pid"),
            string("linux"),
            string("ROOT_CGROUPS_")))));


// This test runs through the basic workflow of launching a nested container,
// killing the nested container, and retrieving the exit status (SIGKILL).
TEST_P_TEMP_DISABLED_ON_WINDOWS(AgentContainerAPITest, NestedContainerLaunch)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  Try<v1::ContainerID> parentContainerId =
    launchParentContainer(master.get()->pid, slave.get()->pid);

  ASSERT_SOME(parentContainerId);

  // Launch a nested container and wait for it to finish.
  v1::ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());
  containerId.mutable_parent()->CopyFrom(parentContainerId.get());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      launchNestedContainer(slave.get()->pid, containerId));

  Future<v1::agent::Response> wait =
    deserialize(waitNestedContainer(slave.get()->pid, containerId));

  EXPECT_TRUE(wait.isPending());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      killNestedContainer(slave.get()->pid, containerId));

  AWAIT_READY(wait);
  EXPECT_TRUE(checkWaitContainerResponse(wait, SIGKILL));
}


// This test launches a parent and nested container, simulates an agent
// failover, and then waits/kills the containers.
TEST_P_TEMP_DISABLED_ON_WINDOWS(AgentContainerAPITest, RecoverNestedContainer)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  Try<v1::ContainerID> parentContainerId =
    launchParentContainer(master.get()->pid, slave.get()->pid);

  ASSERT_SOME(parentContainerId);

  // Launch a nested container.
  v1::ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());
  containerId.mutable_parent()->CopyFrom(parentContainerId.get());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      launchNestedContainer(slave.get()->pid, containerId));

  // Simulate an agent failover.
  Future<SlaveReregisteredMessage> slaveReregisteredMessage =
    FUTURE_PROTOBUF(SlaveReregisteredMessage(), _, _);

  slave.get()->terminate();
  slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  AWAIT_READY(slaveReregisteredMessage);

  // Now kill and wait for the (recovered) container to exit.
  Future<v1::agent::Response> wait =
    deserialize(waitNestedContainer(slave.get()->pid, containerId));

  EXPECT_TRUE(wait.isPending());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      killNestedContainer(slave.get()->pid, containerId));

  AWAIT_READY(wait);
  EXPECT_TRUE(checkWaitContainerResponse(wait, SIGKILL));
}


// This test checks that using the KILL or WAIT container calls on
// a non-existent ContainerID returns a 404 Not Found.
TEST_P_TEMP_DISABLED_ON_WINDOWS(AgentContainerAPITest, NestedContainerNotFound)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  // Wait for the agent to finish registering.
  Future<SlaveRegisteredMessage> slaveRegisteredMessage =
    FUTURE_PROTOBUF(SlaveRegisteredMessage(), _, _);
  AWAIT_READY(slaveRegisteredMessage);

  v1::ContainerID unknownContainerId;
  unknownContainerId.set_value(id::UUID::random().toString());
  unknownContainerId.mutable_parent()->set_value(id::UUID::random().toString());

  // Expect a 404 for waiting on unknown containers.
  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::NotFound().status,
      waitNestedContainer(slave.get()->pid, unknownContainerId));

  // Expect a 404 for waiting on unknown containers.
  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::NotFound().status,
      killNestedContainer(slave.get()->pid, unknownContainerId));
}


// This test runs tries to launch a nested container that fails upon
// launch (rather than validation) and expects a 400 Bad Request in response.
TEST_P_TEMP_DISABLED_ON_WINDOWS(
    AgentContainerAPITest, NestedContainerFailLaunch)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  Try<v1::ContainerID> parentContainerId =
    launchParentContainer(master.get()->pid, slave.get()->pid);

  ASSERT_SOME(parentContainerId);

  // Launch a nested container that needs to fetch a URI that
  // doesn't exist. The launch should therefore fail.
  v1::ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());
  containerId.mutable_parent()->CopyFrom(parentContainerId.get());

  mesos::v1::CommandInfo commandInfo;
  commandInfo.add_uris()->set_value("This file doesn't exist");

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::BadRequest().status,
      launchNestedContainer(slave.get()->pid, containerId, commandInfo));
}


// This test attempts to give invalid ContainerInfo when launching a
// nested container. The invalid nested container LAUNCH call is expected
// to give a 400 Bad Request, but the parent container should be otherwise
// unaffected.
TEST_P_TEMP_DISABLED_ON_WINDOWS(
    AgentContainerAPITest, NestedContainerLaunchFalse)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  Try<v1::ContainerID> parentContainerId =
    launchParentContainer(master.get()->pid, slave.get()->pid);

  ASSERT_SOME(parentContainerId);

  // Try to launch an "unsupported" container.
  // In this case, we try to specify a nested container that expects
  // the Docker containerizer, even though the parent was made with
  // the Mesos containerizer.
  v1::ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());
  containerId.mutable_parent()->CopyFrom(parentContainerId.get());

  mesos::v1::ContainerInfo containerInfo;
  containerInfo.set_type(mesos::v1::ContainerInfo::DOCKER);

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::BadRequest().status,
      launchNestedContainer(
          slave.get()->pid, containerId, None(), containerInfo));
}


// This test launches three total layers of nested containers,
// one parent, nested, and double-nested container. Each nested container
// is killed and reaped like any other nested container.
TEST_P_TEMP_DISABLED_ON_WINDOWS(
    AgentContainerAPITest, TwoLevelNestedContainerLaunch)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  Try<v1::ContainerID> parentContainerId =
    launchParentContainer(master.get()->pid, slave.get()->pid);

  ASSERT_SOME(parentContainerId);

  // Launch the first nested container and wait for it to finish.
  v1::ContainerID childContainerId;
  childContainerId.set_value(id::UUID::random().toString());
  childContainerId.mutable_parent()->CopyFrom(parentContainerId.get());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      launchNestedContainer(slave.get()->pid, childContainerId));

  // Launch the second nested container underneath the first nested contaienr
  // and wait for it to finish.
  v1::ContainerID grandchildContainerId;
  grandchildContainerId.set_value(id::UUID::random().toString());
  grandchildContainerId.mutable_parent()->CopyFrom(childContainerId);

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      launchNestedContainer(slave.get()->pid, grandchildContainerId));

  // Start waiting for each nested container to exit.
  Future<v1::agent::Response> waitChild =
    deserialize(waitNestedContainer(slave.get()->pid, childContainerId));

  Future<v1::agent::Response> waitgrandChild =
    deserialize(waitNestedContainer(slave.get()->pid, grandchildContainerId));

  EXPECT_TRUE(waitChild.isPending());
  EXPECT_TRUE(waitgrandChild.isPending());

  // Kill the grandchild container.
  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      killNestedContainer(slave.get()->pid, grandchildContainerId));

  AWAIT_READY(waitgrandChild);
  EXPECT_TRUE(checkWaitContainerResponse(waitgrandChild, SIGKILL));

  // The child container should still be running.
  EXPECT_TRUE(waitChild.isPending());

  // Kill the child container.
  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      killNestedContainer(slave.get()->pid, childContainerId));

  AWAIT_READY(waitChild);
  EXPECT_TRUE(checkWaitContainerResponse(waitChild, SIGKILL));
}


// This test runs tries to send multiple calls to launch the same container
// The first call is expected to succeed with 200 OK, and subsequent calls
// should return 202 Accepted.
TEST_P_TEMP_DISABLED_ON_WINDOWS(
    AgentContainerAPITest, NestedContainerIdempotentLaunch)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  Try<v1::ContainerID> parentContainerId =
    launchParentContainer(master.get()->pid, slave.get()->pid);

  ASSERT_SOME(parentContainerId);

  // Launch a nested container and wait for it to finish.
  v1::ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());
  containerId.mutable_parent()->CopyFrom(parentContainerId.get());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      launchNestedContainer(slave.get()->pid, containerId));

  // NOTE: There should be an even number of launch requests to guard
  // against regression related to MESOS-6214. e.g. If a launch request
  // detects the container is already running, the containerizer should
  // not accidentally destroy the container.
  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::Accepted().status,
      launchNestedContainer(slave.get()->pid, containerId));

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::Accepted().status,
      launchNestedContainer(slave.get()->pid, containerId));

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::Accepted().status,
      launchNestedContainer(slave.get()->pid, containerId));

  Future<v1::agent::Response> wait =
    deserialize(waitNestedContainer(slave.get()->pid, containerId));

  EXPECT_TRUE(wait.isPending());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      killNestedContainer(slave.get()->pid, containerId));

  AWAIT_READY(wait);
  EXPECT_TRUE(checkWaitContainerResponse(wait, SIGKILL));
}


// This test verifies the GET_CONTAINERS API call.
TEST_P_TEMP_DISABLED_ON_WINDOWS(AgentContainerAPITest, GetContainers)
{
  Try<Owned<cluster::Master>> master = StartMaster();
  ASSERT_SOME(master);

  Owned<MasterDetector> detector = master.get()->createDetector();

  slave::Flags slaveFlags = CreateSlaveFlags();
  slaveFlags.launcher = std::get<1>(std::get<3>(GetParam()));
  slaveFlags.isolation = std::get<0>(std::get<3>(GetParam()));

  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
  ASSERT_SOME(slave);

  Try<v1::ContainerID> parentContainerId =
    launchParentContainer(master.get()->pid, slave.get()->pid);

  ASSERT_SOME(parentContainerId);

  // Launch a nested container and wait for it to finish.
  v1::ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());
  containerId.mutable_parent()->CopyFrom(parentContainerId.get());

  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
      http::OK().status,
      launchNestedContainer(slave.get()->pid, containerId));

  Future<v1::agent::Response> response =
    deserialize(getContainers(slave.get()->pid));

  ASSERT_EQ(v1::agent::Response::GET_CONTAINERS, response->type());
  EXPECT_EQ(2, response->get_containers().containers_size());
}

} // namespace tests {
} // namespace internal {
} // namespace mesos {
