Added the test `HTTPCommandExecutorTest.TerminateWithACK`. Review: https://reviews.apache.org/r/52075/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/2158f3d8 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/2158f3d8 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/2158f3d8 Branch: refs/heads/master Commit: 2158f3d862e2df41883c05fe5c7184c880d14341 Parents: 850078e Author: Qian Zhang <zhang...@cn.ibm.com> Authored: Thu Sep 22 18:14:45 2016 -0700 Committer: Vinod Kone <vinodk...@gmail.com> Committed: Thu Sep 22 18:14:45 2016 -0700 ---------------------------------------------------------------------- src/slave/slave.hpp | 3 +- src/tests/command_executor_tests.cpp | 95 +++++++++++++++++++++++++++++++ src/tests/mock_slave.hpp | 5 ++ 3 files changed, 102 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/2158f3d8/src/slave/slave.hpp ---------------------------------------------------------------------- diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp index 265032e..3e7832c 100644 --- a/src/slave/slave.hpp +++ b/src/slave/slave.hpp @@ -287,7 +287,8 @@ public: const ContainerID& containerId, const process::Future<bool>& future); - void executorTerminated( + // Made 'virtual' for Slave mocking. + virtual void executorTerminated( const FrameworkID& frameworkId, const ExecutorID& executorId, const process::Future<Option< http://git-wip-us.apache.org/repos/asf/mesos/blob/2158f3d8/src/tests/command_executor_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/command_executor_tests.cpp b/src/tests/command_executor_tests.cpp index 07e5eb4..2bc4667 100644 --- a/src/tests/command_executor_tests.cpp +++ b/src/tests/command_executor_tests.cpp @@ -21,6 +21,8 @@ #include <mesos/mesos.hpp> +#include <mesos/slave/containerizer.hpp> + #include <process/future.hpp> #include <process/gmock.hpp> #include <process/gtest.hpp> @@ -31,15 +33,25 @@ #include "master/master.hpp" +#include "master/detector/standalone.hpp" + #include "slave/slave.hpp" +#include "slave/containerizer/mesos/containerizer.hpp" + #include "tests/mesos.hpp" +#include "tests/mock_slave.hpp" using mesos::internal::master::Master; +using mesos::internal::slave::Fetcher; +using mesos::internal::slave::MesosContainerizer; using mesos::internal::slave::Slave; using mesos::master::detector::MasterDetector; +using mesos::master::detector::StandaloneMasterDetector; + +using mesos::slave::ContainerTermination; using process::Future; using process::Owned; @@ -201,6 +213,89 @@ TEST_P(CommandExecutorTest, TaskKillingCapability) driver.join(); } + +class HTTPCommandExecutorTest + : public MesosTest {}; + + +// This test ensures that the HTTP command executor can self terminate +// after it gets the ACK for the terminal status update from agent. +TEST_F(HTTPCommandExecutorTest, TerminateWithACK) +{ + Try<Owned<cluster::Master>> master = StartMaster(); + ASSERT_SOME(master); + + slave::Flags flags = CreateSlaveFlags(); + flags.http_command_executor = true; + + Fetcher fetcher; + + Try<MesosContainerizer*> _containerizer = + MesosContainerizer::create(flags, false, &fetcher); + + CHECK_SOME(_containerizer); + Owned<MesosContainerizer> containerizer(_containerizer.get()); + + StandaloneMasterDetector detector(master.get()->pid); + + MockSlave slave(flags, &detector, containerizer.get()); + spawn(slave); + + MockScheduler sched; + MesosSchedulerDriver driver( + &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL); + + EXPECT_CALL(sched, registered(&driver, _, _)); + + Future<vector<Offer>> offers; + EXPECT_CALL(sched, resourceOffers(&driver, _)) + .WillOnce(FutureArg<1>(&offers)) + .WillRepeatedly(Return()); // Ignore subsequent offers. + + driver.start(); + + AWAIT_READY(offers); + EXPECT_EQ(1u, offers->size()); + + // Launch a short lived task. + TaskInfo task = createTask( + offers->front().slave_id(), + offers->front().resources(), + "sleep 1"); + + Future<TaskStatus> statusRunning; + Future<TaskStatus> statusFinished; + + EXPECT_CALL(sched, statusUpdate(_, _)) + .WillOnce(FutureArg<1>(&statusRunning)) + .WillOnce(FutureArg<1>(&statusFinished)); + + Future<Future<ContainerTermination>> termination; + EXPECT_CALL(slave, executorTerminated(_, _, _)) + .WillOnce(FutureArg<2>(&termination)); + + driver.launchTasks(offers->front().id(), {task}); + + // Scheduler should first receive TASK_RUNNING followed by TASK_FINISHED. + AWAIT_READY(statusRunning); + EXPECT_EQ(TASK_RUNNING, statusRunning->state()); + + AWAIT_READY(statusFinished); + EXPECT_EQ(TASK_FINISHED, statusFinished->state()); + + // The executor should self terminate with 0 as exit status once + // it gets the ACK for the terminal status update from agent. + AWAIT_READY(termination); + ASSERT_TRUE(termination.get().isReady()); + EXPECT_EQ(0, termination.get().get().status()); + + driver.stop(); + driver.join(); + + terminate(slave); + wait(slave); +} + } // namespace tests { } // namespace internal { } // namespace mesos { http://git-wip-us.apache.org/repos/asf/mesos/blob/2158f3d8/src/tests/mock_slave.hpp ---------------------------------------------------------------------- diff --git a/src/tests/mock_slave.hpp b/src/tests/mock_slave.hpp index 53e1c9e..39e836b 100644 --- a/src/tests/mock_slave.hpp +++ b/src/tests/mock_slave.hpp @@ -184,6 +184,11 @@ public: process::Future<ResourceUsage> unmocked_usage(); + MOCK_METHOD3(executorTerminated, void( + const FrameworkID& frameworkId, + const ExecutorID& executorId, + const process::Future<mesos::slave::ContainerTermination>& termination)); + private: Files files; MockGarbageCollector gc;