Added QoS kill executor correction test. Review: https://reviews.apache.org/r/34721
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/02160a1c Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/02160a1c Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/02160a1c Branch: refs/heads/master Commit: 02160a1ceb7d54b851b623e669e6a648be5471c1 Parents: 8cbbf84 Author: Niklas Nielsen <[email protected]> Authored: Tue Jun 16 17:02:46 2015 -0700 Committer: Niklas Q. Nielsen <[email protected]> Committed: Tue Jun 16 17:02:47 2015 -0700 ---------------------------------------------------------------------- src/tests/mesos.cpp | 15 ++++++ src/tests/mesos.hpp | 5 ++ src/tests/oversubscription_tests.cpp | 89 +++++++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/02160a1c/src/tests/mesos.cpp ---------------------------------------------------------------------- diff --git a/src/tests/mesos.cpp b/src/tests/mesos.cpp index dbf8c7c..2cd2435 100644 --- a/src/tests/mesos.cpp +++ b/src/tests/mesos.cpp @@ -374,6 +374,21 @@ Try<PID<slave::Slave>> MesosTest::StartSlave( Try<PID<slave::Slave>> MesosTest::StartSlave( + mesos::slave::QoSController* qoSController, + const Option<slave::Flags>& flags) +{ + return cluster.slaves.start( + flags.isNone() ? CreateSlaveFlags() : flags.get(), + None(), + None(), + None(), + None(), + None(), + qoSController); +} + + +Try<PID<slave::Slave>> MesosTest::StartSlave( slave::Containerizer* containerizer, mesos::slave::QoSController* qoSController, const Option<slave::Flags>& flags) http://git-wip-us.apache.org/repos/asf/mesos/blob/02160a1c/src/tests/mesos.hpp ---------------------------------------------------------------------- diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp index 2a96618..9157ac0 100644 --- a/src/tests/mesos.hpp +++ b/src/tests/mesos.hpp @@ -199,6 +199,11 @@ protected: mesos::slave::ResourceEstimator* resourceEstimator, const Option<slave::Flags>& flags = None()); + // Starts a slave with the specified QoS Controller and flags. + virtual Try<process::PID<slave::Slave>> StartSlave( + mesos::slave::QoSController* qosController, + const Option<slave::Flags>& flags = None()); + // Starts a slave with the specified QoS Controller, // containerizer and flags. virtual Try<process::PID<slave::Slave>> StartSlave( http://git-wip-us.apache.org/repos/asf/mesos/blob/02160a1c/src/tests/oversubscription_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/oversubscription_tests.cpp b/src/tests/oversubscription_tests.cpp index 5c6bed7..c7a2dac 100644 --- a/src/tests/oversubscription_tests.cpp +++ b/src/tests/oversubscription_tests.cpp @@ -68,7 +68,7 @@ using testing::_; using testing::AtMost; using testing::DoAll; using testing::Eq; -using testing::Invoke; +using testing::InvokeWithoutArgs; using testing::Return; namespace mesos { @@ -263,7 +263,7 @@ TEST_F(OversubscriptionTest, ForwardUpdateSlaveMessage) Queue<Resources> estimations; EXPECT_CALL(resourceEstimator, oversubscribable()) - .WillOnce(Invoke(&estimations, &Queue<Resources>::get)); + .WillOnce(InvokeWithoutArgs(&estimations, &Queue<Resources>::get)); slave::Flags flags = CreateSlaveFlags(); Try<PID<Slave>> slave = StartSlave(&resourceEstimator, flags); @@ -327,7 +327,7 @@ TEST_F(OversubscriptionTest, RevocableOffer) Queue<Resources> estimations; EXPECT_CALL(resourceEstimator, oversubscribable()) - .WillOnce(Invoke(&estimations, &Queue<Resources>::get)); + .WillOnce(InvokeWithoutArgs(&estimations, &Queue<Resources>::get)); slave::Flags flags = CreateSlaveFlags(); @@ -421,7 +421,7 @@ TEST_F(OversubscriptionTest, RescindRevocableOffer) // We expect 2 calls for 2 estimations. EXPECT_CALL(resourceEstimator, oversubscribable()) .Times(2) - .WillRepeatedly(Invoke(&estimations, &Queue<Resources>::get)); + .WillRepeatedly(InvokeWithoutArgs(&estimations, &Queue<Resources>::get)); slave::Flags flags = CreateSlaveFlags(); @@ -759,7 +759,9 @@ TEST_F(OversubscriptionTest, ReceiveQoSCorrection) Queue<list<QoSCorrection>> corrections; EXPECT_CALL(controller, corrections()) - .WillRepeatedly(Invoke(&corrections, &Queue<list<QoSCorrection>>::get)); + .WillRepeatedly(InvokeWithoutArgs( + &corrections, + &Queue<list<QoSCorrection>>::get)); MockSlave slave(CreateSlaveFlags(), &detector, &containerizer, &controller); @@ -782,6 +784,83 @@ TEST_F(OversubscriptionTest, ReceiveQoSCorrection) wait(slave); } + +// This test verifies that a QoS controller can kill a running task +// and that a TASK_LOST with REASON_EXECUTOR_PREEMPTED is sent to the +// framework. +TEST_F(OversubscriptionTest, QoSCorrectionKill) +{ + Try<PID<Master>> master = StartMaster(); + ASSERT_SOME(master); + + MockQoSController controller; + + Queue<list<mesos::slave::QoSCorrection>> corrections; + + EXPECT_CALL(controller, corrections()) + .WillRepeatedly(InvokeWithoutArgs( + &corrections, + &Queue<list<mesos::slave::QoSCorrection>>::get)); + + Try<PID<Slave>> slave = StartSlave(&controller, CreateSlaveFlags()); + ASSERT_SOME(slave); + + MockScheduler sched; + MesosSchedulerDriver driver( + &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); + + Future<FrameworkID> frameworkId; + EXPECT_CALL(sched, registered(&driver, _, _)) + .WillOnce(FutureArg<1>(&frameworkId)); + + Future<vector<Offer>> offers; + EXPECT_CALL(sched, resourceOffers(&driver, _)) + .WillOnce(FutureArg<1>(&offers)) + .WillRepeatedly(Return()); // Ignore subsequent offers. + + driver.start(); + + AWAIT_READY(frameworkId); + + AWAIT_READY(offers); + EXPECT_NE(0u, offers.get().size()); + + TaskInfo task = createTask(offers.get()[0], "sleep 10"); + + Future<TaskStatus> status1; + Future<TaskStatus> status2; + EXPECT_CALL(sched, statusUpdate(&driver, _)) + .WillOnce(FutureArg<1>(&status1)) + .WillOnce(FutureArg<1>(&status2)) + .WillRepeatedly(Return()); // Ignore subsequent updates. + + driver.launchTasks(offers.get()[0].id(), {task}); + + AWAIT_READY(status1); + ASSERT_EQ(TASK_RUNNING, status1.get().state()); + + // Carry out kill correction. + QoSCorrection killCorrection; + + QoSCorrection::Kill* kill = killCorrection.mutable_kill(); + kill->mutable_framework_id()->CopyFrom(frameworkId.get()); + + // As we use a command executor to launch an actual sleep command, + // the executor id will be the task id. + kill->mutable_executor_id()->set_value(task.task_id().value()); + + corrections.put({killCorrection}); + + // Verify task status is TASK_LOST. + AWAIT_READY(status2); + ASSERT_EQ(TASK_LOST, status2.get().state()); + ASSERT_EQ(TaskStatus::REASON_EXECUTOR_PREEMPTED, status2.get().reason()); + + driver.stop(); + driver.join(); + + Shutdown(); +} } // namespace tests { } // namespace internal { } // namespace mesos {
