Repository: mesos
Updated Branches:
  refs/heads/master 2d435fe84 -> 9ca2cc8ae


Added unit test for killing the default executor process.

Review: https://reviews.apache.org/r/61981


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/9ca2cc8a
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/9ca2cc8a
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/9ca2cc8a

Branch: refs/heads/master
Commit: 9ca2cc8ae751905f078b056b265fb4511ea8e5f4
Parents: 2d435fe
Author: Gilbert Song <songzihao1...@gmail.com>
Authored: Tue Aug 29 17:31:35 2017 -0700
Committer: Gilbert Song <songzihao1...@gmail.com>
Committed: Thu Aug 31 23:23:51 2017 -0700

----------------------------------------------------------------------
 src/tests/default_executor_tests.cpp | 129 ++++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9ca2cc8a/src/tests/default_executor_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/default_executor_tests.cpp 
b/src/tests/default_executor_tests.cpp
index 138c428..8b6edf7 100644
--- a/src/tests/default_executor_tests.cpp
+++ b/src/tests/default_executor_tests.cpp
@@ -49,6 +49,8 @@
 #include "tests/containerizer.hpp"
 #include "tests/mesos.hpp"
 
+#include "slave/containerizer/mesos/containerizer.hpp"
+
 using mesos::master::detector::MasterDetector;
 
 using mesos::v1::scheduler::Call;
@@ -71,6 +73,12 @@ using testing::DoAll;
 using testing::Return;
 using testing::WithParamInterface;
 
+using mesos::internal::slave::Containerizer;
+using mesos::internal::slave::Fetcher;
+using mesos::internal::slave::MesosContainerizer;
+
+using mesos::slave::ContainerTermination;
+
 namespace mesos {
 namespace internal {
 namespace tests {
@@ -1373,6 +1381,127 @@ TEST_P(DefaultExecutorTest, ReservedResources)
 }
 
 
+// This is a regression test for MESOS-7926. It verifies that if
+// the default executor process is killed, the future of the nested
+// container destroy will be discarded and that discard will
+// not propagate back to the executor container destroy, to make
+// sure the executor container destroy can be finished correctly.
+TEST_P(DefaultExecutorTest, SigkillExecutor)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  slave::Flags flags = CreateSlaveFlags();
+  flags.containerizers = GetParam();
+
+  Fetcher fetcher(flags);
+
+  Try<MesosContainerizer*> create =
+    MesosContainerizer::create(flags, true, &fetcher);
+
+  ASSERT_SOME(create);
+
+  Owned<Containerizer> containerizer(create.get());
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+
+  Try<Owned<cluster::Slave>> slave = StartSlave(
+      detector.get(),
+      containerizer.get(),
+      flags);
+
+  ASSERT_SOME(slave);
+
+  auto scheduler = std::make_shared<v1::MockHTTPScheduler>();
+
+  Future<Nothing> connected;
+  EXPECT_CALL(*scheduler, connected(_))
+    .WillOnce(DoAll(v1::scheduler::SendSubscribe(v1::DEFAULT_FRAMEWORK_INFO),
+                    FutureSatisfy(&connected)));
+
+  v1::scheduler::TestMesos mesos(
+      master.get()->pid,
+      ContentType::PROTOBUF,
+      scheduler);
+
+  AWAIT_READY(connected);
+
+  Future<v1::scheduler::Event::Subscribed> subscribed;
+  EXPECT_CALL(*scheduler, subscribed(_, _))
+    .WillOnce(FutureArg<1>(&subscribed));
+
+  Future<v1::scheduler::Event::Offers> offers;
+  EXPECT_CALL(*scheduler, offers(_, _))
+    .WillOnce(FutureArg<1>(&offers));
+
+  EXPECT_CALL(*scheduler, heartbeat(_))
+    .WillRepeatedly(Return()); // Ignore heartbeats.
+
+  AWAIT_READY(subscribed);
+
+  v1::FrameworkID frameworkId(subscribed->framework_id());
+  v1::ExecutorInfo executorInfo = v1::createExecutorInfo(
+      "test_default_executor",
+      None(),
+      "cpus:0.1;mem:32;disk:32",
+      v1::ExecutorInfo::DEFAULT);
+
+  // Update `executorInfo` with the subscribed `frameworkId`.
+  executorInfo.mutable_framework_id()->CopyFrom(frameworkId);
+
+  AWAIT_READY(offers);
+  ASSERT_FALSE(offers->offers().empty());
+
+  const v1::Offer& offer = offers->offers(0);
+  const v1::AgentID& agentId = offer.agent_id();
+
+  v1::TaskInfo taskInfo = v1::createTask(
+      agentId,
+      v1::Resources::parse("cpus:0.1;mem:32;disk:32").get(),
+      "sleep 1000");
+
+  Future<v1::scheduler::Event::Update> update;
+  EXPECT_CALL(*scheduler, update(_, _))
+    .WillOnce(FutureArg<1>(&update));
+
+  v1::Offer::Operation launchGroup = v1::LAUNCH_GROUP(
+      executorInfo,
+      v1::createTaskGroupInfo({taskInfo}));
+
+  mesos.send(v1::createCallAccept(frameworkId, offer, {launchGroup}));
+
+  AWAIT_READY(update);
+
+  ASSERT_EQ(TASK_RUNNING, update->status().state());
+  EXPECT_EQ(taskInfo.task_id(), update->status().task_id());
+  EXPECT_TRUE(update->status().has_timestamp());
+  ASSERT_TRUE(update->status().has_container_status());
+
+  v1::ContainerStatus status = update->status().container_status();
+
+  ASSERT_TRUE(status.has_container_id());
+  EXPECT_TRUE(status.container_id().has_parent());
+
+  v1::ContainerID executorContainerId = status.container_id().parent();
+
+  Future<Option<ContainerTermination>> wait =
+    containerizer->wait(devolve(executorContainerId));
+
+  Future<ContainerStatus> executorStatus =
+    containerizer->status(devolve(executorContainerId));
+
+  AWAIT_READY(executorStatus);
+  ASSERT_TRUE(executorStatus->has_executor_pid());
+
+  ASSERT_SOME(os::killtree(executorStatus->executor_pid(), SIGKILL));
+
+  AWAIT_READY(wait);
+  ASSERT_SOME(wait.get());
+  ASSERT_TRUE(wait.get()->has_status());
+  EXPECT_WTERMSIG_EQ(SIGKILL, wait.get()->status());
+}
+
+
 #ifdef __linux__
 // This test verifies that tasks from two different
 // task groups can share the same pid namespace.

Reply via email to