You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2015/09/14 19:58:58 UTC

[14/16] mesos git commit: Maintenance Primitives: Used V1 API for Master maintenance test.

Maintenance Primitives: Used V1 API for Master maintenance test.

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


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

Branch: refs/heads/master
Commit: bf82689f69a21286177d52d7d7e5d2f713c1e5b1
Parents: 388eaa5
Author: Joris Van Remoortere <jo...@gmail.com>
Authored: Tue Aug 25 18:50:21 2015 -0400
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Mon Sep 14 13:58:37 2015 -0400

----------------------------------------------------------------------
 src/tests/master_maintenance_tests.cpp | 152 +++++++++++++++++++++-------
 1 file changed, 118 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/bf82689f/src/tests/master_maintenance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_maintenance_tests.cpp b/src/tests/master_maintenance_tests.cpp
index a857ab9..8f39ac3 100644
--- a/src/tests/master_maintenance_tests.cpp
+++ b/src/tests/master_maintenance_tests.cpp
@@ -20,6 +20,12 @@
 
 #include <mesos/maintenance/maintenance.hpp>
 
+#include <mesos/v1/mesos.hpp>
+#include <mesos/v1/resources.hpp>
+#include <mesos/v1/scheduler.hpp>
+
+#include <mesos/v1/scheduler/scheduler.hpp>
+
 #include <process/clock.hpp>
 #include <process/future.hpp>
 #include <process/http.hpp>
@@ -37,6 +43,9 @@
 
 #include "common/protobuf_utils.hpp"
 
+#include "internal/devolve.hpp"
+#include "internal/evolve.hpp"
+
 #include "master/master.hpp"
 
 #include "slave/flags.hpp"
@@ -48,9 +57,14 @@ using mesos::internal::master::Master;
 
 using mesos::internal::slave::Slave;
 
+using mesos::v1::scheduler::Call;
+using mesos::v1::scheduler::Event;
+using mesos::v1::scheduler::Mesos;
+
 using process::Clock;
 using process::Future;
 using process::PID;
+using process::Queue;
 using process::Time;
 
 using process::http::BadRequest;
@@ -65,6 +79,7 @@ using mesos::internal::protobuf::maintenance::createWindow;
 using std::string;
 using std::vector;
 
+using testing::AtMost;
 using testing::DoAll;
 
 namespace mesos {
@@ -111,9 +126,40 @@ public:
   // Default unavailability.  Used when the test does not care
   // about the value of the unavailability.
   Unavailability unavailability;
+
+protected:
+  // Helper class for using EXPECT_CALL since the Mesos scheduler API
+  // is callback based.
+  class Callbacks
+  {
+  public:
+    MOCK_METHOD0(connected, void(void));
+    MOCK_METHOD0(disconnected, void(void));
+    MOCK_METHOD1(received, void(const std::queue<Event>&));
+  };
 };
 
 
+// Enqueues all received events into a libprocess queue.
+// TODO(jmlvanre): Factor this common code out of tests into V1
+// helper.
+ACTION_P(Enqueue, queue)
+{
+  std::queue<Event> events = arg0;
+  while (!events.empty()) {
+    // Note that we currently drop HEARTBEATs because most of these tests
+    // are not designed to deal with heartbeats.
+    // TODO(vinod): Implement DROP_HTTP_CALLS that can filter heartbeats.
+    if (events.front().type() == Event::HEARTBEAT) {
+      VLOG(1) << "Ignoring HEARTBEAT event";
+    } else {
+      queue->put(events.front());
+    }
+    events.pop();
+  }
+}
+
+
 // Posts valid and invalid schedules to the maintenance schedule endpoint.
 TEST_F(MasterMaintenanceTest, UpdateSchedule)
 {
@@ -304,7 +350,10 @@ TEST_F(MasterMaintenanceTest, FailToUnscheduleDeactivatedMachines)
 // slave is scheduled to go down for maintenance.
 TEST_F(MasterMaintenanceTest, PendingUnavailabilityTest)
 {
-  Try<PID<Master>> master = StartMaster();
+  master::Flags flags = CreateMasterFlags();
+  flags.authenticate_frameworks = false;
+
+  Try<PID<Master>> master = StartMaster(flags);
   ASSERT_SOME(master);
 
   MockExecutor exec(DEFAULT_EXECUTOR_ID);
@@ -312,36 +361,49 @@ TEST_F(MasterMaintenanceTest, PendingUnavailabilityTest)
   Try<PID<Slave>> slave = StartSlave(&exec);
   ASSERT_SOME(slave);
 
-  MockScheduler sched;
-  MesosSchedulerDriver driver(
-      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+  Callbacks callbacks;
+
+  Future<Nothing> connected;
+  EXPECT_CALL(callbacks, connected())
+    .WillOnce(FutureSatisfy(&connected));
 
-  EXPECT_CALL(sched, registered(&driver, _, _))
-    .Times(1);
+  Mesos mesos(
+      master.get(),
+      lambda::bind(&Callbacks::connected, lambda::ref(callbacks)),
+      lambda::bind(&Callbacks::disconnected, lambda::ref(callbacks)),
+      lambda::bind(&Callbacks::received, lambda::ref(callbacks), lambda::_1));
 
-  // Intercept offers sent to the scheduler.
-  Future<vector<Offer>> normalOffers;
-  Future<vector<Offer>> unavailabilityOffers;
-  EXPECT_CALL(sched, resourceOffers(&driver, _))
-    .WillOnce(FutureArg<1>(&normalOffers))
-    .WillOnce(FutureArg<1>(&unavailabilityOffers))
-    .WillRepeatedly(Return()); // Ignore subsequent offers.
+  AWAIT_READY(connected);
 
-  // The original offers should be rescinded when the unavailability
-  // is changed.
-  Future<Nothing> offerRescinded;
-  EXPECT_CALL(sched, offerRescinded(&driver, _))
-    .WillOnce(FutureSatisfy(&offerRescinded));
+  Queue<Event> events;
+
+  EXPECT_CALL(callbacks, received(_))
+    .WillRepeatedly(Enqueue(&events));
+
+  {
+    Call call;
+    call.set_type(Call::SUBSCRIBE);
+
+    Call::Subscribe* subscribe = call.mutable_subscribe();
+    subscribe->mutable_framework_info()->CopyFrom(DEFAULT_V1_FRAMEWORK_INFO);
+
+    mesos.send(call);
+  }
+
+  Future<Event> event = events.get();
+  AWAIT_READY(event);
+  EXPECT_EQ(Event::SUBSCRIBED, event.get().type());
 
-  // Start the test.
-  driver.start();
+  v1::FrameworkID id(event.get().subscribed().framework_id());
 
-  // Wait for some normal offers.
-  AWAIT_READY(normalOffers);
-  EXPECT_NE(0u, normalOffers.get().size());
+  event = events.get();
+  AWAIT_READY(event);
+  EXPECT_EQ(Event::OFFERS, event.get().type());
+  EXPECT_NE(0, event.get().offers().offers().size());
+  const size_t numberOfOffers = event.get().offers().offers().size();
 
-  // Check that unavailability is not set.
-  foreach (const Offer& offer, normalOffers.get()) {
+  // Regular offers shouldn't have unavailability.
+  foreach (const v1::Offer& offer, event.get().offers().offers()) {
     EXPECT_FALSE(offer.has_unavailability());
   }
 
@@ -372,19 +434,41 @@ TEST_F(MasterMaintenanceTest, PendingUnavailabilityTest)
 
   AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
 
-  // Wait for some offers.
-  AWAIT_READY(unavailabilityOffers);
-  EXPECT_NE(0u, unavailabilityOffers.get().size());
+  // The original offers should be rescinded when the unavailability
+  // is changed. We expect as many rescind events as we received
+  // original offers.
+  for (size_t offerNumber = 0; offerNumber < numberOfOffers; ++offerNumber) {
+    event = events.get();
+    AWAIT_READY(event);
+    EXPECT_EQ(Event::RESCIND, event.get().type());
+  }
 
-  // Check that each offer has an unavailability.
-  foreach (const Offer& offer, unavailabilityOffers.get()) {
+  event = events.get();
+  AWAIT_READY(event);
+  EXPECT_EQ(Event::OFFERS, event.get().type());
+  EXPECT_NE(0, event.get().offers().offers().size());
+
+  // Make sure the new offers have the unavailability set.
+  foreach (const v1::Offer& offer, event.get().offers().offers()) {
     EXPECT_TRUE(offer.has_unavailability());
-    EXPECT_EQ(unavailability.start(), offer.unavailability().start());
-    EXPECT_EQ(unavailability.duration(), offer.unavailability().duration());
+    EXPECT_EQ(
+        unavailability.start().nanoseconds(),
+        offer.unavailability().start().nanoseconds());
+
+    EXPECT_EQ(
+        unavailability.duration().nanoseconds(),
+        offer.unavailability().duration().nanoseconds());
   }
 
-  driver.stop();
-  driver.join();
+  // We also expect an inverse offer for the slave to go under
+  // maintenance.
+  event = events.get();
+  AWAIT_READY(event);
+  EXPECT_EQ(Event::OFFERS, event.get().type());
+  EXPECT_NE(0, event.get().offers().inverse_offers().size());
+
+  EXPECT_CALL(exec, shutdown(_))
+    .Times(AtMost(1));
 
   Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
 }