You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2013/05/26 18:57:26 UTC

[01/28] git commit: Renamed tests/zookeeper_test.hpp|cpp to zookeeper.hpp|cpp.

Updated Branches:
  refs/heads/master 304835d76 -> 4392c6e3b


Renamed tests/zookeeper_test.hpp|cpp to zookeeper.hpp|cpp.

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


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

Branch: refs/heads/master
Commit: b553a075caa13086a7be936f2feb088ab0a42f5a
Parents: 1d71e42
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sun May 5 16:31:47 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/Makefile.am                         |    4 +-
 src/tests/allocator_zookeeper_tests.cpp |    2 +-
 src/tests/group_tests.cpp               |    2 +-
 src/tests/master_detector_tests.cpp     |    2 +-
 src/tests/state_tests.cpp               |    2 +-
 src/tests/zookeeper.cpp                 |  173 ++++++++++++++++++++++++++
 src/tests/zookeeper.hpp                 |  137 ++++++++++++++++++++
 src/tests/zookeeper_test.cpp            |  173 --------------------------
 src/tests/zookeeper_test.hpp            |  137 --------------------
 src/tests/zookeeper_tests.cpp           |    2 +-
 10 files changed, 317 insertions(+), 317 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index fe31707..bc0c5c6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -230,7 +230,7 @@ libmesos_no_third_party_la_SOURCES += common/attributes.hpp		\
         slave/reaper.hpp						\
 	slave/slave.hpp							\
 	tests/environment.hpp tests/script.hpp				\
-	tests/zookeeper_test.hpp tests/flags.hpp tests/utils.hpp	\
+	tests/zookeeper.hpp tests/flags.hpp tests/utils.hpp		\
 	tests/cluster.hpp						\
 	tests/isolator.hpp						\
 	tests/zookeeper_test_server.hpp zookeeper/authentication.hpp	\
@@ -823,7 +823,7 @@ if OS_LINUX
 endif
 
 if HAS_JAVA
-  mesos_tests_SOURCES += tests/zookeeper_test.cpp		\
+  mesos_tests_SOURCES += tests/zookeeper.cpp			\
                          tests/zookeeper_test_server.cpp	\
                          tests/zookeeper_tests.cpp		\
                          tests/allocator_zookeeper_tests.cpp

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/allocator_zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_zookeeper_tests.cpp b/src/tests/allocator_zookeeper_tests.cpp
index 962e876..d03a564 100644
--- a/src/tests/allocator_zookeeper_tests.cpp
+++ b/src/tests/allocator_zookeeper_tests.cpp
@@ -27,8 +27,8 @@
 #include "master/allocator.hpp"
 #include "master/master.hpp"
 
-#include "tests/zookeeper_test.hpp"
 #include "tests/utils.hpp"
+#include "tests/zookeeper.hpp"
 
 #include "zookeeper/url.hpp"
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/group_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/group_tests.cpp b/src/tests/group_tests.cpp
index 3e442cd..d32b74f 100644
--- a/src/tests/group_tests.cpp
+++ b/src/tests/group_tests.cpp
@@ -27,7 +27,7 @@
 #include <stout/option.hpp>
 
 #include "tests/utils.hpp"
-#include "tests/zookeeper_test.hpp"
+#include "tests/zookeeper.hpp"
 
 #include "zookeeper/authentication.hpp"
 #include "zookeeper/group.hpp"

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/master_detector_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_detector_tests.cpp b/src/tests/master_detector_tests.cpp
index 1739823..c9d6d20 100644
--- a/src/tests/master_detector_tests.cpp
+++ b/src/tests/master_detector_tests.cpp
@@ -50,7 +50,7 @@
 
 #include "tests/utils.hpp"
 #ifdef MESOS_HAS_JAVA
-#include "tests/zookeeper_test.hpp"
+#include "tests/zookeeper.hpp"
 #endif
 
 using namespace mesos;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/state_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/state_tests.cpp b/src/tests/state_tests.cpp
index eb124fd..9066025 100644
--- a/src/tests/state_tests.cpp
+++ b/src/tests/state_tests.cpp
@@ -41,7 +41,7 @@
 
 #include "tests/utils.hpp"
 #ifdef MESOS_HAS_JAVA
-#include "tests/zookeeper_test.hpp"
+#include "tests/zookeeper.hpp"
 #endif
 
 using namespace mesos;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/zookeeper.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper.cpp b/src/tests/zookeeper.cpp
new file mode 100644
index 0000000..3d11209
--- /dev/null
+++ b/src/tests/zookeeper.cpp
@@ -0,0 +1,173 @@
+/**
+ * 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 <signal.h>
+
+#include <gtest/gtest.h>
+
+#include <queue>
+
+#include <tr1/functional>
+
+#include <jvm/jvm.hpp>
+
+#include <jvm/org/apache/log4j.hpp>
+#include <jvm/org/apache/log4j.hpp>
+
+#include <stout/lambda.hpp>
+
+#include "common/lock.hpp"
+
+#include "logging/logging.hpp"
+
+#include "tests/utils.hpp"
+#include "tests/zookeeper.hpp"
+#include "tests/zookeeper_test_server.hpp"
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+const Duration ZooKeeperTest::NO_TIMEOUT = Milliseconds(5000);
+
+
+void ZooKeeperTest::SetUpTestCase()
+{
+  if (!Jvm::created()) {
+    std::string zkHome = flags.build_dir +
+      "/third_party/zookeeper-" ZOOKEEPER_VERSION;
+
+    std::string classpath = "-Djava.class.path=" +
+      zkHome + "/zookeeper-" ZOOKEEPER_VERSION ".jar:" +
+      zkHome + "/lib/log4j-1.2.15.jar";
+
+    LOG(INFO) << "Using classpath setup: " << classpath << std::endl;
+
+    std::vector<std::string> options;
+    options.push_back(classpath);
+    Try<Jvm*> jvm = Jvm::create(options);
+    CHECK_SOME(jvm);
+
+    if (!flags.verbose) {
+      // Silence server logs.
+      org::apache::log4j::Logger::getRootLogger()
+        .setLevel(org::apache::log4j::Level::OFF);
+
+      // Silence client logs.
+      // TODO(jsirois): Create C++ ZooKeeper::setLevel.
+      zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR);
+    }
+  }
+}
+
+
+void ZooKeeperTest::SetUp()
+{
+  server->startNetwork();
+}
+
+
+ZooKeeperTest::TestWatcher::TestWatcher()
+{
+  pthread_mutexattr_t attr;
+  pthread_mutexattr_init(&attr);
+  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+  pthread_mutex_init(&mutex, &attr);
+  pthread_mutexattr_destroy(&attr);
+  pthread_cond_init(&cond, 0);
+}
+
+
+ZooKeeperTest::TestWatcher::~TestWatcher()
+{
+  pthread_mutex_destroy(&mutex);
+  pthread_cond_destroy(&cond);
+}
+
+
+void ZooKeeperTest::TestWatcher::process(
+    ZooKeeper* zk,
+    int type,
+    int state,
+    const std::string& path)
+{
+  Lock lock(&mutex);
+  events.push(Event(type, state, path));
+  pthread_cond_signal(&cond);
+}
+
+
+static bool isSessionState(
+    const ZooKeeperTest::TestWatcher::Event& event,
+    int state)
+{
+  return event.type == ZOO_SESSION_EVENT && event.state == state;
+}
+
+
+void ZooKeeperTest::TestWatcher::awaitSessionEvent(int state)
+{
+  awaitEvent(lambda::bind(&isSessionState, lambda::_1, state));
+}
+
+
+static bool isCreated(
+    const ZooKeeperTest::TestWatcher::Event& event,
+    const std::string& path)
+{
+  return event.type == ZOO_CHILD_EVENT && event.path == path;
+}
+
+
+void ZooKeeperTest::TestWatcher::awaitCreated(const std::string& path)
+{
+  awaitEvent(lambda::bind(&isCreated, lambda::_1, path));
+}
+
+
+ZooKeeperTest::TestWatcher::Event
+ZooKeeperTest::TestWatcher::awaitEvent()
+{
+  Lock lock(&mutex);
+  while (true) {
+    while (events.empty()) {
+      pthread_cond_wait(&cond, &mutex);
+    }
+    Event event = events.front();
+    events.pop();
+    return event;
+  }
+}
+
+
+ZooKeeperTest::TestWatcher::Event
+ZooKeeperTest::TestWatcher::awaitEvent(
+    const std::tr1::function<bool(Event)>& matches)
+{
+  while (true) {
+    Event event = awaitEvent();
+    if (matches(event)) {
+      return event;
+    }
+  }
+}
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {
+

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/zookeeper.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper.hpp b/src/tests/zookeeper.hpp
new file mode 100644
index 0000000..17e0886
--- /dev/null
+++ b/src/tests/zookeeper.hpp
@@ -0,0 +1,137 @@
+/**
+ * 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.
+ */
+
+#ifndef __TESTS_ZOOKEEPER_HPP__
+#define __TESTS_ZOOKEEPER_HPP__
+
+#include <pthread.h>
+
+#include <gtest/gtest.h>
+
+#include <queue>
+
+#include <tr1/functional>
+
+#include <stout/duration.hpp>
+
+#include "tests/utils.hpp"
+#include "tests/zookeeper_test_server.hpp"
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+// Helper for invoking ZooKeeper::get(path, ...) in order to check the
+// data stored at a specified znode path.
+inline ::testing::AssertionResult AssertZKGet(
+    const char* expectedExpr,
+    const char* zkExpr,
+    const char* pathExpr,
+    const std::string& expected,
+    ZooKeeper* zk,
+    const std::string& path)
+{
+  std::string result;
+  int code = zk->get(path, false, &result, NULL);
+  if (code == ZOK) {
+    if (expected == result) {
+      return ::testing::AssertionSuccess();
+    } else {
+      return ::testing::AssertionFailure()
+        << "Expected data at znode '" << pathExpr << "' "
+        << "to be '" << expected << "', but actually '" << result << "'";
+    }
+  } else {
+    return ::testing::AssertionFailure()
+      << "(" << zkExpr << ").get(" << pathExpr << ", ...): "
+      << zk->message(code);
+  }
+}
+
+#define ASSERT_ZK_GET(expected, zk, path)                               \
+  ASSERT_PRED_FORMAT3(mesos::internal::tests::AssertZKGet, expected, zk, path)
+
+
+// A fixture for tests that need to interact with a ZooKeeper server
+// ensemble. Tests can access the in process ZooKeeperTestServer via
+// the variable 'server'. This test fixture ensures the server is
+// started before each test and shutdown after it so that each test is
+// presented with a ZooKeeper ensemble with no data or watches.
+class ZooKeeperTest : public MesosTest
+{
+public:
+  // A watcher that is useful to install in a ZooKeeper client for
+  // tests. Allows easy blocking on expected events.
+  class TestWatcher : public Watcher
+  {
+  public:
+    // Encapsulates all the state of a ZooKeeper watcher event.
+    struct Event {
+      Event(int _type, int _state, const std::string& _path)
+          : type(_type), state(_state), path(_path) {}
+      const int type;
+      const int state;
+      const std::string path;
+    };
+
+    TestWatcher();
+    virtual ~TestWatcher();
+
+    virtual void process(
+        ZooKeeper* zk,
+        int type,
+        int state,
+        const std::string& path);
+
+    // Blocks until the session event of the given state fires.
+    void awaitSessionEvent(int state);
+
+    // Blocks until a node appears at the given path.
+    void awaitCreated(const std::string& path);
+
+    // Blocks until an event is fired matching the given predicate.
+    Event awaitEvent(const std::tr1::function<bool(Event)>& matches);
+
+    // Blocks until an event is fired.
+    Event awaitEvent();
+
+  private:
+    std::queue<Event> events;
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+  };
+
+  ZooKeeperTest() : server(new ZooKeeperTestServer()) {}
+  virtual ~ZooKeeperTest() { delete server; }
+
+  static void SetUpTestCase();
+
+protected:
+  virtual void SetUp();
+
+  // A very long session timeout that simulates no timeout for test cases.
+  static const Duration NO_TIMEOUT;
+
+  ZooKeeperTestServer* server;
+};
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __ZOOKEEPER_TEST_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/zookeeper_test.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test.cpp b/src/tests/zookeeper_test.cpp
deleted file mode 100644
index 90c6aba..0000000
--- a/src/tests/zookeeper_test.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * 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 <signal.h>
-
-#include <gtest/gtest.h>
-
-#include <queue>
-
-#include <tr1/functional>
-
-#include <jvm/jvm.hpp>
-
-#include <jvm/org/apache/log4j.hpp>
-#include <jvm/org/apache/log4j.hpp>
-
-#include <stout/lambda.hpp>
-
-#include "common/lock.hpp"
-
-#include "logging/logging.hpp"
-
-#include "tests/utils.hpp"
-#include "tests/zookeeper_test.hpp"
-#include "tests/zookeeper_test_server.hpp"
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-const Duration ZooKeeperTest::NO_TIMEOUT = Milliseconds(5000);
-
-
-void ZooKeeperTest::SetUpTestCase()
-{
-  if (!Jvm::created()) {
-    std::string zkHome = flags.build_dir +
-      "/third_party/zookeeper-" ZOOKEEPER_VERSION;
-
-    std::string classpath = "-Djava.class.path=" +
-      zkHome + "/zookeeper-" ZOOKEEPER_VERSION ".jar:" +
-      zkHome + "/lib/log4j-1.2.15.jar";
-
-    LOG(INFO) << "Using classpath setup: " << classpath << std::endl;
-
-    std::vector<std::string> options;
-    options.push_back(classpath);
-    Try<Jvm*> jvm = Jvm::create(options);
-    CHECK_SOME(jvm);
-
-    if (!flags.verbose) {
-      // Silence server logs.
-      org::apache::log4j::Logger::getRootLogger()
-        .setLevel(org::apache::log4j::Level::OFF);
-
-      // Silence client logs.
-      // TODO(jsirois): Create C++ ZooKeeper::setLevel.
-      zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR);
-    }
-  }
-}
-
-
-void ZooKeeperTest::SetUp()
-{
-  server->startNetwork();
-}
-
-
-ZooKeeperTest::TestWatcher::TestWatcher()
-{
-  pthread_mutexattr_t attr;
-  pthread_mutexattr_init(&attr);
-  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
-  pthread_mutex_init(&mutex, &attr);
-  pthread_mutexattr_destroy(&attr);
-  pthread_cond_init(&cond, 0);
-}
-
-
-ZooKeeperTest::TestWatcher::~TestWatcher()
-{
-  pthread_mutex_destroy(&mutex);
-  pthread_cond_destroy(&cond);
-}
-
-
-void ZooKeeperTest::TestWatcher::process(
-    ZooKeeper* zk,
-    int type,
-    int state,
-    const std::string& path)
-{
-  Lock lock(&mutex);
-  events.push(Event(type, state, path));
-  pthread_cond_signal(&cond);
-}
-
-
-static bool isSessionState(
-    const ZooKeeperTest::TestWatcher::Event& event,
-    int state)
-{
-  return event.type == ZOO_SESSION_EVENT && event.state == state;
-}
-
-
-void ZooKeeperTest::TestWatcher::awaitSessionEvent(int state)
-{
-  awaitEvent(lambda::bind(&isSessionState, lambda::_1, state));
-}
-
-
-static bool isCreated(
-    const ZooKeeperTest::TestWatcher::Event& event,
-    const std::string& path)
-{
-  return event.type == ZOO_CHILD_EVENT && event.path == path;
-}
-
-
-void ZooKeeperTest::TestWatcher::awaitCreated(const std::string& path)
-{
-  awaitEvent(lambda::bind(&isCreated, lambda::_1, path));
-}
-
-
-ZooKeeperTest::TestWatcher::Event
-ZooKeeperTest::TestWatcher::awaitEvent()
-{
-  Lock lock(&mutex);
-  while (true) {
-    while (events.empty()) {
-      pthread_cond_wait(&cond, &mutex);
-    }
-    Event event = events.front();
-    events.pop();
-    return event;
-  }
-}
-
-
-ZooKeeperTest::TestWatcher::Event
-ZooKeeperTest::TestWatcher::awaitEvent(
-    const std::tr1::function<bool(Event)>& matches)
-{
-  while (true) {
-    Event event = awaitEvent();
-    if (matches(event)) {
-      return event;
-    }
-  }
-}
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {
-

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/zookeeper_test.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test.hpp b/src/tests/zookeeper_test.hpp
deleted file mode 100644
index 7bd396b..0000000
--- a/src/tests/zookeeper_test.hpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * 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.
- */
-
-#ifndef __ZOOKEEPER_TEST_HPP__
-#define __ZOOKEEPER_TEST_HPP__
-
-#include <pthread.h>
-
-#include <gtest/gtest.h>
-
-#include <queue>
-
-#include <tr1/functional>
-
-#include <stout/duration.hpp>
-
-#include "tests/utils.hpp"
-#include "tests/zookeeper_test_server.hpp"
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-// Helper for invoking ZooKeeper::get(path, ...) in order to check the
-// data stored at a specified znode path.
-inline ::testing::AssertionResult AssertZKGet(
-    const char* expectedExpr,
-    const char* zkExpr,
-    const char* pathExpr,
-    const std::string& expected,
-    ZooKeeper* zk,
-    const std::string& path)
-{
-  std::string result;
-  int code = zk->get(path, false, &result, NULL);
-  if (code == ZOK) {
-    if (expected == result) {
-      return ::testing::AssertionSuccess();
-    } else {
-      return ::testing::AssertionFailure()
-        << "Expected data at znode '" << pathExpr << "' "
-        << "to be '" << expected << "', but actually '" << result << "'";
-    }
-  } else {
-    return ::testing::AssertionFailure()
-      << "(" << zkExpr << ").get(" << pathExpr << ", ...): "
-      << zk->message(code);
-  }
-}
-
-#define ASSERT_ZK_GET(expected, zk, path)                               \
-  ASSERT_PRED_FORMAT3(mesos::internal::tests::AssertZKGet, expected, zk, path)
-
-
-// A fixture for tests that need to interact with a ZooKeeper server
-// ensemble. Tests can access the in process ZooKeeperTestServer via
-// the variable 'server'. This test fixture ensures the server is
-// started before each test and shutdown after it so that each test is
-// presented with a ZooKeeper ensemble with no data or watches.
-class ZooKeeperTest : public MesosTest
-{
-public:
-  // A watcher that is useful to install in a ZooKeeper client for
-  // tests. Allows easy blocking on expected events.
-  class TestWatcher : public Watcher
-  {
-  public:
-    // Encapsulates all the state of a ZooKeeper watcher event.
-    struct Event {
-      Event(int _type, int _state, const std::string& _path)
-          : type(_type), state(_state), path(_path) {}
-      const int type;
-      const int state;
-      const std::string path;
-    };
-
-    TestWatcher();
-    virtual ~TestWatcher();
-
-    virtual void process(
-        ZooKeeper* zk,
-        int type,
-        int state,
-        const std::string& path);
-
-    // Blocks until the session event of the given state fires.
-    void awaitSessionEvent(int state);
-
-    // Blocks until a node appears at the given path.
-    void awaitCreated(const std::string& path);
-
-    // Blocks until an event is fired matching the given predicate.
-    Event awaitEvent(const std::tr1::function<bool(Event)>& matches);
-
-    // Blocks until an event is fired.
-    Event awaitEvent();
-
-  private:
-    std::queue<Event> events;
-    pthread_mutex_t mutex;
-    pthread_cond_t cond;
-  };
-
-  ZooKeeperTest() : server(new ZooKeeperTestServer()) {}
-  virtual ~ZooKeeperTest() { delete server; }
-
-  static void SetUpTestCase();
-
-protected:
-  virtual void SetUp();
-
-  // A very long session timeout that simulates no timeout for test cases.
-  static const Duration NO_TIMEOUT;
-
-  ZooKeeperTestServer* server;
-};
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __ZOOKEEPER_TEST_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/b553a075/src/tests/zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_tests.cpp b/src/tests/zookeeper_tests.cpp
index 5193d03..27a6048 100644
--- a/src/tests/zookeeper_tests.cpp
+++ b/src/tests/zookeeper_tests.cpp
@@ -25,7 +25,7 @@
 #include <stout/strings.hpp>
 
 #include "tests/utils.hpp"
-#include "tests/zookeeper_test.hpp"
+#include "tests/zookeeper.hpp"
 
 using namespace mesos::internal;
 using namespace mesos::internal::tests;


[22/28] git commit: Refactored base 'State' implementation to be serialization agnostic and use a 'Storage' instance. Changed the LevelDB and ZooKeeper implementations to implement 'Storage' instead of 'State'. Provided a protobuf specific implementation

Posted by be...@apache.org.
Refactored base 'State' implementation to be serialization agnostic
and use a 'Storage' instance. Changed the LevelDB and ZooKeeper
implementations to implement 'Storage' instead of 'State'. Provided a
protobuf specific implementation on top of 'State'. Updated code
(including JNI) and tests accordingly.

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


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

Branch: refs/heads/master
Commit: 33f4ff4b138dbe11abd2014e1e2b44dd8444a0b3
Parents: 1e35e9e
Author: Benjamin Hindman <be...@twitter.com>
Authored: Mon Jan 14 15:45:29 2013 -0800
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 09:28:36 2013 -0700

----------------------------------------------------------------------
 src/Makefile.am                                    |   20 +-
 src/java/jni/org_apache_mesos_state_Variable.cpp   |   22 +-
 .../jni/org_apache_mesos_state_ZooKeeperState.cpp  |  318 ++++++++++---
 .../src/org/apache/mesos/state/InMemoryState.java  |   21 +-
 src/java/src/org/apache/mesos/state/State.java     |   22 +-
 .../src/org/apache/mesos/state/ZooKeeperState.java |  113 +++--
 src/master/registry.hpp                            |   24 +
 src/master/registry.proto                          |   32 ++
 src/messages/messages.hpp                          |   40 ++
 src/messages/messages.proto                        |    6 -
 src/state/leveldb.cpp                              |   77 +++-
 src/state/leveldb.hpp                              |   77 ++--
 src/state/protobuf.hpp                             |  166 +++++++
 src/state/serializer.hpp                           |   67 ---
 src/state/state.hpp                                |  183 +++----
 src/state/storage.hpp                              |   60 +++
 src/state/zookeeper.cpp                            |  175 +++++--
 src/state/zookeeper.hpp                            |   99 ++--
 src/tests/state_tests.cpp                          |  383 ++++++++++-----
 19 files changed, 1330 insertions(+), 575 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f7794e..7c740fd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -129,6 +129,10 @@ STATE_PROTOS = messages/state.pb.cc messages/state.pb.h
 BUILT_SOURCES += $(STATE_PROTOS)
 CLEANFILES += $(STATE_PROTOS)
 
+REGISTRY_PROTOS = master/registry.pb.cc master/registry.pb.h
+
+BUILT_SOURCES += $(REGISTRY_PROTOS)
+CLEANFILES += $(REGISTRY_PROTOS)
 
 # Targets for generating protocol buffer code.
 %.pb.cc %.pb.h: $(top_srcdir)/include/mesos/%.proto
@@ -153,7 +157,10 @@ $(PYTHON_PROTOS): $(MESOS_PROTO)
 # libraries themselves.
 noinst_LTLIBRARIES += libmesos_no_third_party.la
 
-nodist_libmesos_no_third_party_la_SOURCES = $(CXX_PROTOS) $(MESSAGES_PROTOS)
+nodist_libmesos_no_third_party_la_SOURCES = 	\
+  $(CXX_PROTOS) 				\
+  $(MESSAGES_PROTOS) 				\
+  $(REGISTRY_PROTOS)
 
 libmesos_no_third_party_la_SOURCES =					\
 	sched/sched.cpp							\
@@ -162,6 +169,8 @@ libmesos_no_third_party_la_SOURCES =					\
 	master/drf_sorter.cpp						\
 	master/http.cpp							\
 	master/master.cpp						\
+	master/registry.hpp						\
+	master/registry.proto                                           \
 	slave/constants.cpp						\
 	slave/gc.cpp							\
 	slave/monitor.cpp						\
@@ -278,8 +287,13 @@ libmesos_no_third_party_la_LIBADD += liblog.la
 # include the leveldb headers.
 noinst_LTLIBRARIES += libstate.la
 libstate_la_SOURCES = state/leveldb.cpp state/zookeeper.cpp
-libstate_la_SOURCES += state/leveldb.hpp state/serializer.hpp	\
-  state/state.hpp state/zookeeper.hpp messages/state.hpp	\
+libstate_la_SOURCES += 			\
+  state/leveldb.hpp			\
+  state/protobuf.hpp			\
+  state/state.hpp 			\
+  state/storage.hpp 			\
+  state/zookeeper.hpp 			\
+  messages/state.hpp			\
   messages/state.proto
 nodist_libstate_la_SOURCES = $(STATE_PROTOS)
 libstate_la_CPPFLAGS = -I../$(LEVELDB)/include $(MESOS_CPPFLAGS)

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/java/jni/org_apache_mesos_state_Variable.cpp
----------------------------------------------------------------------
diff --git a/src/java/jni/org_apache_mesos_state_Variable.cpp b/src/java/jni/org_apache_mesos_state_Variable.cpp
index eacb110..4d840ce 100644
--- a/src/java/jni/org_apache_mesos_state_Variable.cpp
+++ b/src/java/jni/org_apache_mesos_state_Variable.cpp
@@ -20,13 +20,13 @@ JNIEXPORT jbyteArray JNICALL Java_org_apache_mesos_state_Variable_value
 
   jfieldID __variable = env->GetFieldID(clazz, "__variable", "J");
 
-  Variable<std::string>* variable =
-    (Variable<std::string>*) env->GetLongField(thiz, __variable);
+  Variable* variable = (Variable*) env->GetLongField(thiz, __variable);
+
+  const std::string& value = variable->value();
 
   // byte[] value = ..;
-  jbyteArray jvalue = env->NewByteArray((*variable)->size());
-  env->SetByteArrayRegion(
-      jvalue, 0, (*variable)->size(), (jbyte*) (*variable)->data());
+  jbyteArray jvalue = env->NewByteArray(value.size());
+  env->SetByteArrayRegion(jvalue, 0, value.size(), (jbyte*) value.data());
 
   return jvalue;
 }
@@ -44,15 +44,14 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_Variable_mutate
 
   jfieldID __variable = env->GetFieldID(clazz, "__variable", "J");
 
-  // Create a copy of the old variable to support the immutable Java API.
-  Variable<std::string>* variable = new Variable<std::string>(
-      *((Variable<std::string>*) env->GetLongField(thiz, __variable)));
+  Variable* variable = (Variable*) env->GetLongField(thiz, __variable);
 
   jbyte* value = env->GetByteArrayElements(jvalue, NULL);
   jsize length = env->GetArrayLength(jvalue);
 
-  // Update the value of the new copy.
-  (*variable)->assign((const char*) value, length);
+  // Mutate the variable and save a copy of the result.
+  variable =
+    new Variable(variable->mutate(std::string((const char*) value, length)));
 
   env->ReleaseByteArrayElements(jvalue, value, 0);
 
@@ -80,8 +79,7 @@ JNIEXPORT void JNICALL Java_org_apache_mesos_state_Variable_finalize
 
   jfieldID __variable = env->GetFieldID(clazz, "__variable", "J");
 
-  Variable<std::string>* variable =
-    (Variable<std::string>*) env->GetLongField(thiz, __variable);
+  Variable* variable = (Variable*) env->GetLongField(thiz, __variable);
 
   delete variable;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/java/jni/org_apache_mesos_state_ZooKeeperState.cpp
----------------------------------------------------------------------
diff --git a/src/java/jni/org_apache_mesos_state_ZooKeeperState.cpp b/src/java/jni/org_apache_mesos_state_ZooKeeperState.cpp
index 5abf3ef..c3282c0 100644
--- a/src/java/jni/org_apache_mesos_state_ZooKeeperState.cpp
+++ b/src/java/jni/org_apache_mesos_state_ZooKeeperState.cpp
@@ -48,11 +48,16 @@ JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState_initialize__Lj
 
   string znode = construct<string>(env, jznode);
 
-   // Create the C++ State and initialize the __state variable.
-  State<>* state = new ZooKeeperState<>(servers, timeout, znode);
+   // Create the C++ Storage and State instances and initialize the
+   // __storage and __state variables.
+  Storage* storage = new ZooKeeperStorage(servers, timeout, znode);
+  State* state = new State(storage);
 
   clazz = env->GetObjectClass(thiz);
 
+  jfieldID __storage = env->GetFieldID(clazz, "__storage", "J");
+  env->SetLongField(thiz, __storage, (jlong) storage);
+
   jfieldID __state = env->GetFieldID(clazz, "__state", "J");
   env->SetLongField(thiz, __state, (jlong) state);
 }
@@ -87,7 +92,7 @@ JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState_initialize__Lj
   string znode = construct<string>(env, jznode);
 
   // Create the C++ State.
-  State<>* state = NULL;
+  Storage* storage = NULL;
   if (jscheme != NULL && jcredentials != NULL) {
     string scheme = construct<string>(env, jscheme);
 
@@ -100,16 +105,21 @@ JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState_initialize__Lj
 
     zookeeper::Authentication authentication(scheme, credentials);
 
-    state = new ZooKeeperState<>(servers, timeout, znode, authentication);
+    storage = new ZooKeeperStorage(servers, timeout, znode, authentication);
   } else {
-    state = new ZooKeeperState<>(servers, timeout, znode);
+    storage = new ZooKeeperStorage(servers, timeout, znode);
   }
 
-  CHECK(state != NULL);
+  CHECK(storage != NULL);
+
+  State* state = new State(storage);
 
-  // Initialize the __state variable.
+  // Initialize the __storage and __state variables.
   clazz = env->GetObjectClass(thiz);
 
+  jfieldID __storage = env->GetFieldID(clazz, "__storage", "J");
+  env->SetLongField(thiz, __storage, (jlong) storage);
+
   jfieldID __state = env->GetFieldID(clazz, "__state", "J");
   env->SetLongField(thiz, __state, (jlong) state);
 }
@@ -127,18 +137,24 @@ JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState_finalize
 
   jfieldID __state = env->GetFieldID(clazz, "__state", "J");
 
-  State<>* state = (State<>*) env->GetLongField(thiz, __state);
+  State* state = (State*) env->GetLongField(thiz, __state);
 
   delete state;
+
+  jfieldID __storage = env->GetFieldID(clazz, "__storage", "J");
+
+  Storage* storage = (Storage*) env->GetLongField(thiz, __storage);
+
+  delete storage;
 }
 
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __get
+ * Method:    __fetch
  * Signature: (Ljava/lang/String;)J
  */
-JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get
+JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch
   (JNIEnv* env, jobject thiz, jstring jname)
 {
   string name = construct<string>(env, jname);
@@ -147,10 +163,9 @@ JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get
 
   jfieldID __state = env->GetFieldID(clazz, "__state", "J");
 
-  State<>* state = (State<>*) env->GetLongField(thiz, __state);
+  State* state = (State*) env->GetLongField(thiz, __state);
 
-  Future<Variable<string> >* future =
-    new Future<Variable<string> >(state->get<string>(name));
+  Future<Variable>* future = new Future<Variable>(state->fetch(name));
 
   return (jlong) future;
 }
@@ -158,13 +173,13 @@ JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __get_cancel
+ * Method:    __fetch_cancel
  * Signature: (J)Z
  */
-JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1cancel
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1cancel
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Variable<string> >* future = (Future<Variable<string> >*) jfuture;
+  Future<Variable>* future = (Future<Variable>*) jfuture;
 
   if (!future->isDiscarded()) {
     future->discard();
@@ -177,13 +192,13 @@ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1c
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __get_is_cancelled
+ * Method:    __fetch_is_cancelled
  * Signature: (J)Z
  */
-JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1is_1cancelled
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1is_1cancelled
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Variable<string> >* future = (Future<Variable<string> >*) jfuture;
+  Future<Variable>* future = (Future<Variable>*) jfuture;
 
   return (jboolean) future->isDiscarded();
 }
@@ -191,13 +206,13 @@ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1i
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __get_is_done
+ * Method:    __fetch_is_done
  * Signature: (J)Z
  */
-JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1is_1done
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1is_1done
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Variable<string> >* future = (Future<Variable<string> >*) jfuture;
+  Future<Variable>* future = (Future<Variable>*) jfuture;
 
   return (jboolean) !future->isPending();
 }
@@ -205,13 +220,13 @@ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1i
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __get_get
+ * Method:    __fetch_get
  * Signature: (J)Lorg/apache/mesos/state/Variable;
  */
-JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1get
+JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1get
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Variable<string> >* future = (Future<Variable<string> >*) jfuture;
+  Future<Variable>* future = (Future<Variable>*) jfuture;
 
   future->await();
 
@@ -227,7 +242,7 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1ge
 
   CHECK(future->isReady());
 
-  Variable<string>* variable = new Variable<string>(future->get());
+  Variable* variable = new Variable(future->get());
 
   // Variable variable = new Variable();
   jclass clazz = env->FindClass("org/apache/mesos/state/Variable");
@@ -244,13 +259,13 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1ge
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __get_get_timeout
+ * Method:    __fetch_get_timeout
  * Signature: (JJLjava/util/concurrent/TimeUnit;)Lorg/apache/mesos/state/Variable;
  */
-JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1get_1timeout
+JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1get_1timeout
   (JNIEnv* env, jobject thiz, jlong jfuture, jlong jtimeout, jobject junit)
 {
-  Future<Variable<string> >* future = (Future<Variable<string> >*) jfuture;
+  Future<Variable>* future = (Future<Variable>*) jfuture;
 
   jclass clazz = env->GetObjectClass(junit);
 
@@ -273,7 +288,7 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1ge
     }
 
     CHECK(future->isReady());
-    Variable<string>* variable = new Variable<string>(future->get());
+    Variable* variable = new Variable(future->get());
 
     // Variable variable = new Variable();
     clazz = env->FindClass("org/apache/mesos/state/Variable");
@@ -296,13 +311,13 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1ge
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __get_finalize
+ * Method:    __fetch_finalize
  * Signature: (J)V
  */
-JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1finalize
+JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1finalize
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Variable<string> >* future = (Future<Variable<string> >*) jfuture;
+  Future<Variable>* future = (Future<Variable>*) jfuture;
 
   delete future;
 }
@@ -310,27 +325,26 @@ JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1get_1final
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __set
+ * Method:    __store
  * Signature: (Lorg/apache/mesos/state/Variable;)J
  */
-JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set
+JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1store
   (JNIEnv* env, jobject thiz, jobject jvariable)
 {
   jclass clazz = env->GetObjectClass(jvariable);
 
   jfieldID __variable = env->GetFieldID(clazz, "__variable", "J");
 
-  Variable<string>* variable = (Variable<string>*)
-    env->GetLongField(jvariable, __variable);
+  Variable* variable = (Variable*) env->GetLongField(jvariable, __variable);
 
   clazz = env->GetObjectClass(thiz);
 
   jfieldID __state = env->GetFieldID(clazz, "__state", "J");
 
-  State<>* state = (State<>*) env->GetLongField(thiz, __state);
+  State* state = (State*) env->GetLongField(thiz, __state);
 
-  Future<Option<Variable<string> > >* future =
-    new Future<Option<Variable<string> > >(state->set(*variable));
+  Future<Option<Variable> >* future =
+    new Future<Option<Variable> >(state->store(*variable));
 
   return (jlong) future;
 }
@@ -338,14 +352,13 @@ JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __set_cancel
+ * Method:    __store_cancel
  * Signature: (J)Z
  */
-JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1cancel
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1store_1cancel
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Option<Variable<string> > >* future =
-    (Future<Option<Variable<string> > >*) jfuture;
+  Future<Option<Variable> >* future = (Future<Option<Variable> >*) jfuture;
 
   if (!future->isDiscarded()) {
     future->discard();
@@ -358,14 +371,13 @@ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1c
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __set_is_cancelled
+ * Method:    __store_is_cancelled
  * Signature: (J)Z
  */
-JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1is_1cancelled
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1store_1is_1cancelled
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Option<Variable<string> > >* future =
-    (Future<Option<Variable<string> > >*) jfuture;
+  Future<Option<Variable> >* future = (Future<Option<Variable> >*) jfuture;
 
   return (jboolean) future->isDiscarded();
 }
@@ -373,14 +385,13 @@ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1i
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __set_is_done
+ * Method:    __store_is_done
  * Signature: (J)Z
  */
-JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1is_1done
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1store_1is_1done
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Option<Variable<string> > >* future =
-    (Future<Option<Variable<string> > >*) jfuture;
+  Future<Option<Variable> >* future = (Future<Option<Variable> >*) jfuture;
 
   return (jboolean) !future->isPending();
 }
@@ -388,14 +399,13 @@ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1i
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __set_get
+ * Method:    __store_get
  * Signature: (J)Lorg/apache/mesos/state/Variable;
  */
-JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1get
+JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1store_1get
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Option<Variable<string> > >* future =
-    (Future<Option<Variable<string> > >*) jfuture;
+  Future<Option<Variable> >* future = (Future<Option<Variable> >*) jfuture;
 
   future->await();
 
@@ -412,7 +422,7 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1ge
   CHECK(future->isReady());
 
   if (future->get().isSome()) {
-    Variable<string>* variable = new Variable<string>(future->get().get());
+    Variable* variable = new Variable(future->get().get());
 
     // Variable variable = new Variable();
     jclass clazz = env->FindClass("org/apache/mesos/state/Variable");
@@ -432,14 +442,13 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1ge
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __set_get_timeout
+ * Method:    __store_get_timeout
  * Signature: (JJLjava/util/concurrent/TimeUnit;)Lorg/apache/mesos/state/Variable;
  */
-JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1get_1timeout
+JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1store_1get_1timeout
   (JNIEnv* env, jobject thiz, jlong jfuture, jlong jtimeout, jobject junit)
 {
-  Future<Option<Variable<string> > >* future =
-    (Future<Option<Variable<string> > >*) jfuture;
+  Future<Option<Variable> >* future = (Future<Option<Variable> >*) jfuture;
 
   jclass clazz = env->GetObjectClass(junit);
 
@@ -464,7 +473,7 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1ge
     CHECK(future->isReady());
 
     if (future->get().isSome()) {
-      Variable<string>* variable = new Variable<string>(future->get().get());
+      Variable* variable = new Variable(future->get().get());
 
       // Variable variable = new Variable();
       clazz = env->FindClass("org/apache/mesos/state/Variable");
@@ -490,14 +499,186 @@ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1ge
 
 /*
  * Class:     org_apache_mesos_state_ZooKeeperState
- * Method:    __set_finalize
+ * Method:    __store_finalize
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1store_1finalize
+  (JNIEnv* env, jobject thiz, jlong jfuture)
+{
+  Future<Option<Variable> >* future = (Future<Option<Variable> >*) jfuture;
+
+  delete future;
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_ZooKeeperState
+ * Method:    __expunge
+ * Signature: (Lorg/apache/mesos/state/Variable;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge
+  (JNIEnv* env, jobject thiz, jobject jvariable)
+{
+  jclass clazz = env->GetObjectClass(jvariable);
+
+  jfieldID __variable = env->GetFieldID(clazz, "__variable", "J");
+
+  Variable* variable = (Variable*) env->GetLongField(jvariable, __variable);
+
+  clazz = env->GetObjectClass(thiz);
+
+  jfieldID __state = env->GetFieldID(clazz, "__state", "J");
+
+  State* state = (State*) env->GetLongField(thiz, __state);
+
+  Future<bool>* future = new Future<bool>(state->expunge(*variable));
+
+  return (jlong) future;
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_ZooKeeperState
+ * Method:    __expunge_cancel
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1cancel
+  (JNIEnv* env, jobject thiz, jlong jfuture)
+{
+  Future<bool>* future = (Future<bool>*) jfuture;
+
+  if (!future->isDiscarded()) {
+    future->discard();
+    return (jboolean) future->isDiscarded();
+  }
+
+  return (jboolean) true;
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_ZooKeeperState
+ * Method:    __expunge_is_cancelled
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1is_1cancelled
+  (JNIEnv* env, jobject thiz, jlong jfuture)
+{
+  Future<bool>* future = (Future<bool>*) jfuture;
+
+  return (jboolean) future->isDiscarded();
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_ZooKeeperState
+ * Method:    __expunge_is_done
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1is_1done
+  (JNIEnv* env, jobject thiz, jlong jfuture)
+{
+  Future<bool>* future = (Future<bool>*) jfuture;
+
+  return (jboolean) !future->isPending();
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_ZooKeeperState
+ * Method:    __expunge_get
+ * Signature: (J)Ljava/lang/Boolean;
+ */
+JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1get
+  (JNIEnv* env, jobject thiz, jlong jfuture)
+{
+  Future<bool>* future = (Future<bool>*) jfuture;
+
+  future->await();
+
+  if (future->isFailed()) {
+    jclass clazz = env->FindClass("java/util/concurrent/ExecutionException");
+    env->ThrowNew(clazz, future->failure().c_str());
+    return NULL;
+  } else if (future->isDiscarded()) {
+    jclass clazz = env->FindClass("java/util/concurrent/CancellationException");
+    env->ThrowNew(clazz, "Future was discarded");
+    return NULL;
+  }
+
+  CHECK(future->isReady());
+
+  if (future->get()) {
+    jclass clazz = env->FindClass("java/lang/Boolean");
+    jfieldID TRUE = env->GetStaticFieldID(clazz, "TRUE", "Ljava/lang/Boolean;");
+    return env->GetStaticObjectField(clazz, TRUE);
+  }
+
+  jclass clazz = env->FindClass("java/lang/Boolean");
+  jfieldID FALSE = env->GetStaticFieldID(clazz, "FALSE", "Ljava/lang/Boolean;");
+  return env->GetStaticObjectField(clazz, FALSE);
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_ZooKeeperState
+ * Method:    __expunge_get_timeout
+ * Signature: (JJLjava/util/concurrent/TimeUnit;)Ljava/lang/Boolean;
+ */
+JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1get_1timeout
+  (JNIEnv* env, jobject thiz, jlong jfuture, jlong jtimeout, jobject junit)
+{
+  Future<bool>* future = (Future<bool>*) jfuture;
+
+  jclass clazz = env->GetObjectClass(junit);
+
+  // long seconds = unit.toSeconds(time);
+  jmethodID toSeconds = env->GetMethodID(clazz, "toSeconds", "(J)J");
+
+  jlong jseconds = env->CallLongMethod(junit, toSeconds, jtimeout);
+
+  Seconds seconds(jseconds);
+
+  if (future->await(seconds)) {
+    if (future->isFailed()) {
+      clazz = env->FindClass("java/util/concurrent/ExecutionException");
+      env->ThrowNew(clazz, future->failure().c_str());
+      return NULL;
+    } else if (future->isDiscarded()) {
+      clazz = env->FindClass("java/util/concurrent/CancellationException");
+      env->ThrowNew(clazz, "Future was discarded");
+      return NULL;
+    }
+
+    CHECK(future->isReady());
+
+    if (future->get()) {
+      jclass clazz = env->FindClass("java/lang/Boolean");
+      jfieldID TRUE = env->GetStaticFieldID(clazz, "TRUE", "Ljava/lang/Boolean;");
+      return env->GetStaticObjectField(clazz, TRUE);
+    }
+
+    jclass clazz = env->FindClass("java/lang/Boolean");
+    jfieldID FALSE = env->GetStaticFieldID(clazz, "FALSE", "Ljava/lang/Boolean;");
+    return env->GetStaticObjectField(clazz, FALSE);
+  }
+
+  clazz = env->FindClass("java/util/concurrent/TimeoutException");
+  env->ThrowNew(clazz, "Failed to wait for future within timeout");
+
+  return NULL;
+}
+
+
+/*
+ * Class:     org_apache_mesos_state_ZooKeeperState
+ * Method:    __expunge_finalize
  * Signature: (J)V
  */
-JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1set_1finalize
+JNIEXPORT void JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1finalize
   (JNIEnv* env, jobject thiz, jlong jfuture)
 {
-  Future<Option<Variable<string> > >* future =
-    (Future<Option<Variable<string> > >*) jfuture;
+  Future<bool>* future = (Future<bool>*) jfuture;
 
   delete future;
 }
@@ -515,9 +696,10 @@ JNIEXPORT jlong JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1names
 
   jfieldID __state = env->GetFieldID(clazz, "__state", "J");
 
-  State<>* state = (State<>*) env->GetLongField(thiz, __state);
+  State* state = (State*) env->GetLongField(thiz, __state);
 
-  Future<vector<string> >* future = new Future<vector<string> >(state->names());
+  Future<vector<string> >* future =
+    new Future<vector<string> >(state->names());
 
   return (jlong) future;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/java/src/org/apache/mesos/state/InMemoryState.java
----------------------------------------------------------------------
diff --git a/src/java/src/org/apache/mesos/state/InMemoryState.java b/src/java/src/org/apache/mesos/state/InMemoryState.java
index 5de921e..7addd2d 100644
--- a/src/java/src/org/apache/mesos/state/InMemoryState.java
+++ b/src/java/src/org/apache/mesos/state/InMemoryState.java
@@ -32,7 +32,7 @@ import java.util.concurrent.FutureTask;
  */
 public class InMemoryState implements State {
   @Override
-  public Future<Variable> get(String name) {
+  public Future<Variable> fetch(String name) {
     Entry entry = entries.get(name); // Is null if doesn't exist.
 
     if (entry == null) {
@@ -40,17 +40,21 @@ public class InMemoryState implements State {
       entry.name = name;
       entry.uuid = UUID.randomUUID();
       entry.value = new byte[0];
-      entries.put(name, entry);
-      entry = entries.putIfAbsent(name, entry);
+
+      // We use 'putIfAbsent' because multiple threads might be
+      // attempting to fetch a "new" variable at the same time.
+      if (entries.putIfAbsent(name, entry) != null) {
+        return fetch(name);
+      }
     }
 
-    assert entry != null; // ConcurrentMap.putIfAbsent should not return null.
+    assert entry != null;
 
     return futureFrom((Variable) new InMemoryVariable(entry));
   }
 
   @Override
-  public Future<Variable> set(Variable v) {
+  public Future<Variable> store(Variable v) {
     InMemoryVariable variable = (InMemoryVariable) v;
 
     Entry entry = new Entry();
@@ -66,6 +70,13 @@ public class InMemoryState implements State {
   }
 
   @Override
+  public Future<Boolean> expunge(Variable v) {
+    InMemoryVariable variable = (InMemoryVariable) v;
+
+    return futureFrom(entries.remove(variable.entry.name, variable.entry));
+  }
+
+  @Override
   public Future<Iterator<String>> names() {
     return futureFrom(entries.keySet().iterator());
   }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/java/src/org/apache/mesos/state/State.java
----------------------------------------------------------------------
diff --git a/src/java/src/org/apache/mesos/state/State.java b/src/java/src/org/apache/mesos/state/State.java
index 81b8685..dccb0ff 100644
--- a/src/java/src/org/apache/mesos/state/State.java
+++ b/src/java/src/org/apache/mesos/state/State.java
@@ -30,18 +30,18 @@ import java.util.concurrent.Future;
  * fetched. Varying implementations of state provide varying
  * replicated guarantees.
  *
- * Note that the semantics of 'get' and 'set' provide atomicity. That
- * is, you can not set a variable that has changed since you did the
- * last get. That is, if a set succeeds then no other writes have been
- * performed on the variable since your get.
+ * Note that the semantics of 'fetch' and 'store' provide
+ * atomicity. That is, you can not store a variable that has changed
+ * since you did the last fetch. That is, if a store succeeds then no
+ * other writes have been performed on the variable since your fetch.
  *
  * Example:
  *
  *   State state = new ZooKeeperState();
- *   Future<Variable> variable = state.get("machines");
+ *   Future<Variable> variable = state.fetch("machines");
  *   Variable machines = variable.get();
  *   machines = machines.mutate(...);
- *   variable = state.set(machines);
+ *   variable = state.store(machines);
  *   machines = variable.get();
  */
 public interface State {
@@ -49,14 +49,20 @@ public interface State {
    * Returns an immutable "variable" representing the current value
    * from the state associated with the specified name.
    */
-  Future<Variable> get(String name);
+  Future<Variable> fetch(String name);
 
   /**
    * Returns an immutable "variable" representing the current value in
    * the state if updating the specified variable in the state was
    * successful, otherwise returns null.
    */
-  Future<Variable> set(Variable variable);
+  Future<Variable> store(Variable variable);
+
+  /**
+   * Returns true if successfully expunged the variable from the state
+   * or false if the variable did not exist or was no longer valid.
+   */
+  Future<Boolean> expunge(Variable variable);
 
   /**
    * Returns an iterator of variable names in the state.

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/java/src/org/apache/mesos/state/ZooKeeperState.java
----------------------------------------------------------------------
diff --git a/src/java/src/org/apache/mesos/state/ZooKeeperState.java b/src/java/src/org/apache/mesos/state/ZooKeeperState.java
index 1ef591a..999d593 100644
--- a/src/java/src/org/apache/mesos/state/ZooKeeperState.java
+++ b/src/java/src/org/apache/mesos/state/ZooKeeperState.java
@@ -73,86 +73,125 @@ public class ZooKeeperState implements State {
   }
 
   @Override
-  public Future<Variable> get(final String name) {
-    final long future = __get(name); // Asynchronously start the operation.
+  public Future<Variable> fetch(final String name) {
+    final long future = __fetch(name); // Asynchronously start the operation.
     return new Future<Variable>() {
       @Override
       public boolean cancel(boolean mayInterruptIfRunning) {
         if (mayInterruptIfRunning) {
-          return __get_cancel(future);
+          return __fetch_cancel(future);
         }
         return false; // Should not interrupt and already running (or finished).
       }
 
       @Override
       public boolean isCancelled() {
-        return __get_is_cancelled(future);
+        return __fetch_is_cancelled(future);
       }
 
       @Override
       public boolean isDone() {
-        return __get_is_done(future);
+        return __fetch_is_done(future);
       }
 
       @Override
       public Variable get() throws InterruptedException, ExecutionException {
-        return __get_get(future);
+        return __fetch_get(future);
       }
 
       @Override
       public Variable get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
-        return __get_get_timeout(future, timeout, unit);
+        return __fetch_get_timeout(future, timeout, unit);
       }
 
       @Override
       protected void finalize() {
-        __get_finalize(future);
+        __fetch_finalize(future);
       }
     };
   }
 
   @Override
-  public Future<Variable> set(Variable variable) {
-    final long future = __set(variable); // Asynchronously start the operation.
+  public Future<Variable> store(Variable variable) {
+    final long future = __store(variable); // Asynchronously start the operation.
     return new Future<Variable>() {
       @Override
       public boolean cancel(boolean mayInterruptIfRunning) {
         if (mayInterruptIfRunning) {
-          return __set_cancel(future);
+          return __store_cancel(future);
         }
         return false; // Should not interrupt and already running (or finished).
       }
 
       @Override
       public boolean isCancelled() {
-        return __set_is_cancelled(future);
+        return __store_is_cancelled(future);
       }
 
       @Override
       public boolean isDone() {
-        return __set_is_done(future);
+        return __store_is_done(future);
       }
 
       @Override
       public Variable get() throws InterruptedException, ExecutionException {
-        return __set_get(future);
+        return __store_get(future);
       }
 
       @Override
       public Variable get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
-        return __set_get_timeout(future, timeout, unit);
+        return __store_get_timeout(future, timeout, unit);
       }
 
       @Override
       protected void finalize() {
-        __set_finalize(future);
+        __store_finalize(future);
       }
     };
   }
 
   @Override
+  public Future<Boolean> expunge(Variable variable) {
+    final long future = __expunge(variable); // Asynchronously start the operation.
+    return new Future<Boolean>() {
+      @Override
+      public boolean cancel(boolean mayInterruptIfRunning) {
+        if (mayInterruptIfRunning) {
+          return __expunge_cancel(future);
+        }
+        return false; // Should not interrupt and already running (or finished).
+      }
+
+      @Override
+      public boolean isCancelled() {
+        return __expunge_is_cancelled(future);
+      }
+
+      @Override
+      public boolean isDone() {
+        return __expunge_is_done(future);
+      }
+
+      @Override
+      public Boolean get() throws InterruptedException, ExecutionException {
+        return __expunge_get(future);
+      }
+
+      @Override
+      public Boolean get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        return __expunge_get_timeout(future, timeout, unit);
+      }
+
+      @Override
+      protected void finalize() {
+        __expunge_finalize(future);
+      }
+    };
+  }
+
   public Future<Iterator<String>> names() {
     final long future = __names(); // Asynchronously start the operation.
     return new Future<Iterator<String>>() {
@@ -206,24 +245,33 @@ public class ZooKeeperState implements State {
 
   protected native void finalize();
 
-  // Native implementations of get, set, and names.
-  private native long __get(String name);
-  private native boolean __get_cancel(long future);
-  private native boolean __get_is_cancelled(long future);
-  private native boolean __get_is_done(long future);
-  private native Variable __get_get(long future);
-  private native Variable __get_get_timeout(
+  // Native implementations of 'fetch', 'store', 'expunge', and 'names'.
+  private native long __fetch(String name);
+  private native boolean __fetch_cancel(long future);
+  private native boolean __fetch_is_cancelled(long future);
+  private native boolean __fetch_is_done(long future);
+  private native Variable __fetch_get(long future);
+  private native Variable __fetch_get_timeout(
+      long future, long timeout, TimeUnit unit);
+  private native void __fetch_finalize(long future);
+
+  private native long __store(Variable variable);
+  private native boolean __store_cancel(long future);
+  private native boolean __store_is_cancelled(long future);
+  private native boolean __store_is_done(long future);
+  private native Variable __store_get(long future);
+  private native Variable __store_get_timeout(
       long future, long timeout, TimeUnit unit);
-  private native void __get_finalize(long future);
-
-  private native long __set(Variable variable);
-  private native boolean __set_cancel(long future);
-  private native boolean __set_is_cancelled(long future);
-  private native boolean __set_is_done(long future);
-  private native Variable __set_get(long future);
-  private native Variable __set_get_timeout(
+  private native void __store_finalize(long future);
+
+  private native long __expunge(Variable variable);
+  private native boolean __expunge_cancel(long future);
+  private native boolean __expunge_is_cancelled(long future);
+  private native boolean __expunge_is_done(long future);
+  private native Boolean __expunge_get(long future);
+  private native Boolean __expunge_get_timeout(
       long future, long timeout, TimeUnit unit);
-  private native void __set_finalize(long future);
+  private native void __expunge_finalize(long future);
 
   private native long __names();
   private native boolean __names_cancel(long future);
@@ -234,5 +282,6 @@ public class ZooKeeperState implements State {
       long future, long timeout, TimeUnit unit);
   private native void __names_finalize(long future);
 
+  private long __storage;
   private long __state;
 };

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/master/registry.hpp
----------------------------------------------------------------------
diff --git a/src/master/registry.hpp b/src/master/registry.hpp
new file mode 100644
index 0000000..d3cbe56
--- /dev/null
+++ b/src/master/registry.hpp
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ */
+
+#ifndef __MASTER_REGISTRY_HPP__
+#define __MASTER_REGISTRY_HPP__
+
+#include "master/registry.pb.h"
+
+#endif // __MASTER_REGISTRY_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/master/registry.proto
----------------------------------------------------------------------
diff --git a/src/master/registry.proto b/src/master/registry.proto
new file mode 100644
index 0000000..877bfa1
--- /dev/null
+++ b/src/master/registry.proto
@@ -0,0 +1,32 @@
+/**
+ * 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.
+ */
+
+import "mesos.proto";
+
+package mesos.internal.registry;
+
+message Slave {
+  // TODO(benh): Add other information here that is internal to Mesos
+  // and shouldn't be exposed in SlaveInfo.
+  required SlaveInfo info = 2;
+}
+
+
+message Registry {
+  repeated Slave slaves = 1;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/messages/messages.hpp
----------------------------------------------------------------------
diff --git a/src/messages/messages.hpp b/src/messages/messages.hpp
index 285cc65..98038c0 100644
--- a/src/messages/messages.hpp
+++ b/src/messages/messages.hpp
@@ -19,6 +19,46 @@
 #ifndef __MESSAGES_HPP__
 #define __MESSAGES_HPP__
 
+#include <google/protobuf/message.h>
+
+#include <google/protobuf/io/zero_copy_stream_impl.h> // For ArrayInputStream.
+
+#include <string>
+
+#include <stout/try.hpp>
+
 #include "messages/messages.pb.h"
 
+namespace messages {
+
+template <typename T>
+Try<T> deserialize(const std::string& value)
+{
+  T t;
+  (void) static_cast<google::protobuf::Message*>(&t);
+
+  google::protobuf::io::ArrayInputStream stream(value.data(), value.size());
+  if (!t.ParseFromZeroCopyStream(&stream)) {
+    return Try<T>::error(
+        "Failed to deserialize " + t.GetDescriptor()->full_name());
+  }
+  return t;
+}
+
+
+template <typename T>
+Try<std::string> serialize(const T& t)
+{
+  (void) static_cast<const google::protobuf::Message*>(&t);
+
+  std::string value;
+  if (!t.SerializeToString(&value)) {
+    return Try<std::string>::error(
+        "Failed to serialize " + t.GetDescriptor()->full_name());
+  }
+  return value;
+}
+
+} // namespace messages {
+
 #endif // __MESSAGES_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/messages/messages.proto
----------------------------------------------------------------------
diff --git a/src/messages/messages.proto b/src/messages/messages.proto
index 3f02474..2c196ee 100644
--- a/src/messages/messages.proto
+++ b/src/messages/messages.proto
@@ -73,12 +73,6 @@ message StatusUpdateRecord {
 }
 
 
-message Slaves
-{
-  repeated SlaveInfo infos = 1;
-}
-
-
 message SubmitSchedulerRequest
 {
   required string name = 1;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/leveldb.cpp
----------------------------------------------------------------------
diff --git a/src/state/leveldb.cpp b/src/state/leveldb.cpp
index 5b3fe91..69d5714 100644
--- a/src/state/leveldb.cpp
+++ b/src/state/leveldb.cpp
@@ -2,6 +2,8 @@
 
 #include <google/protobuf/message.h>
 
+#include <google/protobuf/io/zero_copy_stream_impl.h> // For ArrayInputStream.
+
 #include <string>
 #include <vector>
 
@@ -20,7 +22,7 @@
 #include "messages/state.hpp"
 
 #include "state/leveldb.hpp"
-#include "state/state.hpp"
+#include "state/storage.hpp"
 
 using namespace process;
 
@@ -31,17 +33,17 @@ namespace mesos {
 namespace internal {
 namespace state {
 
-LevelDBStateProcess::LevelDBStateProcess(const string& _path)
+LevelDBStorageProcess::LevelDBStorageProcess(const string& _path)
   : path(_path), db(NULL) {}
 
 
-LevelDBStateProcess::~LevelDBStateProcess()
+LevelDBStorageProcess::~LevelDBStorageProcess()
 {
-  delete db; // Might be null if open failed in LevelDBStateProcess::initialize.
+  delete db; // NULL if open failed in LevelDBStorageProcess::initialize.
 }
 
 
-void LevelDBStateProcess::initialize()
+void LevelDBStorageProcess::initialize()
 {
   leveldb::Options options;
   options.create_if_missing = true;
@@ -58,7 +60,7 @@ void LevelDBStateProcess::initialize()
 }
 
 
-Future<vector<string> > LevelDBStateProcess::names()
+Future<vector<string> > LevelDBStorageProcess::names()
 {
   if (error.isSome()) {
     return Future<vector<string> >::failed(error.get());
@@ -81,13 +83,13 @@ Future<vector<string> > LevelDBStateProcess::names()
 }
 
 
-Future<Option<Entry> > LevelDBStateProcess::fetch(const string& name)
+Future<Option<Entry> > LevelDBStorageProcess::get(const string& name)
 {
   if (error.isSome()) {
     return Future<Option<Entry> >::failed(error.get());
   }
 
-  Try<Option<Entry> > option = get(name);
+  Try<Option<Entry> > option = read(name);
 
   if (option.isError()) {
     return Future<Option<Entry> >::failed(option.error());
@@ -97,16 +99,16 @@ Future<Option<Entry> > LevelDBStateProcess::fetch(const string& name)
 }
 
 
-Future<bool> LevelDBStateProcess::swap(const Entry& entry, const UUID& uuid)
+Future<bool> LevelDBStorageProcess::set(const Entry& entry, const UUID& uuid)
 {
   if (error.isSome()) {
     return Future<bool>::failed(error.get());
   }
 
-  // We do a fetch first to make sure the version has not changed. This
+  // We do a read first to make sure the version has not changed. This
   // could be optimized in the future, for now it will probably hit
   // the cache anyway.
-  Try<Option<Entry> > option = get(entry.name());
+  Try<Option<Entry> > option = read(entry.name());
 
   if (option.isError()) {
     return Future<bool>::failed(option.error());
@@ -118,11 +120,11 @@ Future<bool> LevelDBStateProcess::swap(const Entry& entry, const UUID& uuid)
     }
   }
 
-  // Note that there is no need to do the DB::Get and DB::Put
-  // "atomically" because only one db can be opened at a time, so
-  // there can not be any writes that occur concurrently.
+  // Note that the read (i.e., DB::Get) and the write (i.e., DB::Put)
+  // are inherently "atomic" because only one db can be opened at a
+  // time, so there can not be any writes that occur concurrently.
 
-  Try<bool> result = put(entry);
+  Try<bool> result = write(entry);
 
   if (result.isError()) {
     return Future<bool>::failed(result.error());
@@ -132,7 +134,48 @@ Future<bool> LevelDBStateProcess::swap(const Entry& entry, const UUID& uuid)
 }
 
 
-Try<Option<Entry> > LevelDBStateProcess::get(const string& name)
+Future<bool> LevelDBStorageProcess::expunge(const Entry& entry)
+{
+  if (error.isSome()) {
+    return Future<bool>::failed(error.get());
+  }
+
+  // We do a read first to make sure the version has not changed. This
+  // could be optimized in the future, for now it will probably hit
+  // the cache anyway.
+  Try<Option<Entry> > option = read(entry.name());
+
+  if (option.isError()) {
+    return Future<bool>::failed(option.error());
+  }
+
+  if (option.get().isNone()) {
+    return false;
+  }
+
+  if (UUID::fromBytes(option.get().get().uuid()) !=
+      UUID::fromBytes(entry.uuid())) {
+    return false;
+  }
+
+  // Note that the read (i.e., DB::Get) and DB::Delete are inherently
+  // "atomic" because only one db can be opened at a time, so there
+  // can not be any writes that occur concurrently.
+
+  leveldb::WriteOptions options;
+  options.sync = true;
+
+  leveldb::Status status = db->Delete(options, entry.name());
+
+  if (!status.ok()) {
+    return Future<bool>::failed(status.ToString());
+  }
+
+  return true;
+}
+
+
+Try<Option<Entry> > LevelDBStorageProcess::read(const string& name)
 {
   CHECK(error.isNone());
 
@@ -160,7 +203,7 @@ Try<Option<Entry> > LevelDBStateProcess::get(const string& name)
 }
 
 
-Try<bool> LevelDBStateProcess::put(const Entry& entry)
+Try<bool> LevelDBStorageProcess::write(const Entry& entry)
 {
   CHECK(error.isNone());
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/leveldb.hpp
----------------------------------------------------------------------
diff --git a/src/state/leveldb.hpp b/src/state/leveldb.hpp
index 94f306b..14a94cc 100644
--- a/src/state/leveldb.hpp
+++ b/src/state/leveldb.hpp
@@ -14,8 +14,7 @@
 
 #include "messages/state.hpp"
 
-#include "state/serializer.hpp"
-#include "state/state.hpp"
+#include "state/storage.hpp"
 
 // Forward declarations.
 namespace leveldb { class DB; }
@@ -26,46 +25,44 @@ namespace internal {
 namespace state {
 
 // More forward declarations.
-class LevelDBStateProcess;
+class LevelDBStorageProcess;
 
 
-template <typename Serializer = StringSerializer>
-class LevelDBState : public State<Serializer>
+class LevelDBStorage : public Storage
 {
 public:
-  LevelDBState(const std::string& path);
-  virtual ~LevelDBState();
+  LevelDBStorage(const std::string& path);
+  virtual ~LevelDBStorage();
 
-  // State implementation.
+  // Storage implementation.
+  virtual process::Future<Option<Entry> > get(const std::string& name);
+  virtual process::Future<bool> set(const Entry& entry, const UUID& uuid);
+  virtual process::Future<bool> expunge(const Entry& entry);
   virtual process::Future<std::vector<std::string> > names();
 
-protected:
-  // More State implementation.
-  virtual process::Future<Option<Entry> > fetch(const std::string& name);
-  virtual process::Future<bool> swap(const Entry& entry, const UUID& uuid);
-
 private:
-  LevelDBStateProcess* process;
+  LevelDBStorageProcess* process;
 };
 
 
-class LevelDBStateProcess : public process::Process<LevelDBStateProcess>
+class LevelDBStorageProcess : public process::Process<LevelDBStorageProcess>
 {
 public:
-  LevelDBStateProcess(const std::string& path);
-  virtual ~LevelDBStateProcess();
+  LevelDBStorageProcess(const std::string& path);
+  virtual ~LevelDBStorageProcess();
 
   virtual void initialize();
 
-  // State implementation.
+  // Storage implementation.
+  process::Future<Option<Entry> > get(const std::string& name);
+  process::Future<bool> set(const Entry& entry, const UUID& uuid);
+  process::Future<bool> expunge(const Entry& entry);
   process::Future<std::vector<std::string> > names();
-  process::Future<Option<Entry> > fetch(const std::string& name);
-  process::Future<bool> swap(const Entry& entry, const UUID& uuid);
 
 private:
   // Helpers for interacting with leveldb.
-  Try<Option<Entry> > get(const std::string& name);
-  Try<bool> put(const Entry& entry);
+  Try<Option<Entry> > read(const std::string& name);
+  Try<bool> write(const Entry& entry);
 
   const std::string path;
   leveldb::DB* db;
@@ -74,16 +71,14 @@ private:
 };
 
 
-template <typename Serializer>
-LevelDBState<Serializer>::LevelDBState(const std::string& path)
+inline LevelDBStorage::LevelDBStorage(const std::string& path)
 {
-  process = new LevelDBStateProcess(path);
+  process = new LevelDBStorageProcess(path);
   process::spawn(process);
 }
 
 
-template <typename Serializer>
-LevelDBState<Serializer>::~LevelDBState()
+inline LevelDBStorage::~LevelDBStorage()
 {
   process::terminate(process);
   process::wait(process);
@@ -91,27 +86,31 @@ LevelDBState<Serializer>::~LevelDBState()
 }
 
 
-template <typename Serializer>
-process::Future<std::vector<std::string> > LevelDBState<Serializer>::names()
+inline process::Future<Option<Entry> > LevelDBStorage::get(
+    const std::string& name)
 {
-  return process::dispatch(process, &LevelDBStateProcess::names);
+  return process::dispatch(process, &LevelDBStorageProcess::get, name);
 }
 
 
-template <typename Serializer>
-process::Future<Option<Entry> > LevelDBState<Serializer>::fetch(
-    const std::string& name)
+inline process::Future<bool> LevelDBStorage::set(
+    const Entry& entry,
+    const UUID& uuid)
 {
-  return process::dispatch(process, &LevelDBStateProcess::fetch, name);
+  return process::dispatch(process, &LevelDBStorageProcess::set, entry, uuid);
 }
 
 
-template <typename Serializer>
-process::Future<bool> LevelDBState<Serializer>::swap(
-    const Entry& entry,
-    const UUID& uuid)
+inline process::Future<bool> LevelDBStorage::expunge(
+    const Entry& entry)
+{
+  return process::dispatch(process, &LevelDBStorageProcess::expunge, entry);
+}
+
+
+inline process::Future<std::vector<std::string> > LevelDBStorage::names()
 {
-  return process::dispatch(process, &LevelDBStateProcess::swap, entry, uuid);
+  return process::dispatch(process, &LevelDBStorageProcess::names);
 }
 
 } // namespace state {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/protobuf.hpp
----------------------------------------------------------------------
diff --git a/src/state/protobuf.hpp b/src/state/protobuf.hpp
new file mode 100644
index 0000000..75e082b
--- /dev/null
+++ b/src/state/protobuf.hpp
@@ -0,0 +1,166 @@
+/**
+ * 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.
+ */
+
+#ifndef __STATE_PROTOBUF_HPP__
+#define __STATE_PROTOBUF_HPP__
+
+#include <string>
+
+#include <process/future.hpp>
+
+#include <stout/lambda.hpp>
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+#include <stout/uuid.hpp>
+
+#include "messages/messages.hpp"
+#include "messages/state.hpp"
+
+#include "state/state.hpp"
+#include "state/storage.hpp"
+
+namespace mesos {
+namespace internal {
+namespace state {
+namespace protobuf {
+
+template <typename T>
+class Variable
+{
+public:
+  T get() const
+  {
+    return t;
+  }
+
+  Variable mutate(const T& t) const
+  {
+    Variable variable(*this);
+    variable.t = t;
+    return variable;
+  }
+
+private:
+  friend class State; // Creates and manages variables.
+
+  Variable(const state::Variable& _variable, const T& _t)
+    : variable(_variable), t(_t)
+  {}
+
+  state::Variable variable; // Not const to keep Variable assignable.
+  T t;
+};
+
+
+class State : public state::State
+{
+public:
+  State(Storage* storage) : state::State(storage) {}
+  virtual ~State() {}
+
+  // Returns a variable from the state, creating a new one if one
+  // previously did not exist (or an error if one occurs).
+  template <typename T>
+  process::Future<Variable<T> > fetch(const std::string& name);
+
+  // Returns the variable specified if it was successfully stored in
+  // the state, otherwise returns none if the version of the variable
+  // was no longer valid, or an error if one occurs.
+  template <typename T>
+  process::Future<Option<Variable<T> > > store(const Variable<T>& variable);
+
+  // Expunges the variable from the state.
+  template <typename T>
+  process::Future<bool> expunge(const Variable<T>& variable);
+
+private:
+  // Helpers to handle future results from fetch and swap. We make
+  // these static members of State for friend access to Variable's
+  // constructor.
+  template <typename T>
+  static process::Future<Variable<T> > _fetch(
+      const state::Variable& option);
+
+  template <typename T>
+  static process::Future<Option<Variable<T> > > _store(
+      const T& t,
+      const Option<state::Variable>& variable);
+};
+
+
+template <typename T>
+process::Future<Variable<T> > State::fetch(const std::string& name)
+{
+  return state::State::fetch(name)
+    .then(lambda::bind(&State::template _fetch<T>, lambda::_1));
+}
+
+
+template <typename T>
+process::Future<Variable<T> > State::_fetch(
+    const state::Variable& variable)
+{
+  Try<T> t = messages::deserialize<T>(variable.value());
+  if (t.isError()) {
+    return process::Future<Variable<T> >::failed(t.error());
+  }
+
+  return Variable<T>(variable, t.get());
+}
+
+
+template <typename T>
+process::Future<Option<Variable<T> > > State::store(
+    const Variable<T>& variable)
+{
+  Try<std::string> value = messages::serialize(variable.t);
+
+  if (value.isError()) {
+    return process::Future<Option<Variable<T> > >::failed(value.error());
+  }
+
+  return state::State::store(variable.variable.mutate(value.get()))
+    .then(lambda::bind(&State::template _store<T>, variable.t, lambda::_1));
+}
+
+
+template <typename T>
+process::Future<Option<Variable<T> > > State::_store(
+    const T& t,
+    const Option<state::Variable>& variable)
+{
+  if (variable.isSome()) {
+    return Option<Variable<T> >::some(Variable<T>(variable.get(), t));
+  }
+
+  return None();
+}
+
+
+template <typename T>
+process::Future<bool> State::expunge(const Variable<T>& variable)
+{
+  return state::State::expunge(variable.variable);
+}
+
+} // namespace protobuf {
+} // namespace state {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __STATE_PROTOBUF_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/serializer.hpp
----------------------------------------------------------------------
diff --git a/src/state/serializer.hpp b/src/state/serializer.hpp
deleted file mode 100644
index bd8c5df..0000000
--- a/src/state/serializer.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef __STATE_SERIALIZER_HPP__
-#define __STATE_SERIALIZER_HPP__
-
-#include <google/protobuf/message.h>
-
-#include <google/protobuf/io/zero_copy_stream_impl.h> // For ArrayInputStream.
-
-#include <string>
-
-#include <stout/error.hpp>
-#include <stout/try.hpp>
-
-namespace mesos {
-namespace internal {
-namespace state {
-
-struct StringSerializer
-{
-  template <typename T>
-  static Try<std::string> deserialize(const std::string& value)
-  {
-    return value;
-  }
-
-  template <typename T>
-  static Try<std::string> serialize(const std::string& value)
-  {
-    return value;
-  }
-};
-
-
-struct ProtobufSerializer
-{
-  template <typename T>
-  static Try<T> deserialize(const std::string& value)
-  {
-    T t;
-    (void)static_cast<google::protobuf::Message*>(&t);
-
-    google::protobuf::io::ArrayInputStream stream(value.data(), value.size());
-    if (!t.ParseFromZeroCopyStream(&stream)) {
-      return Error(
-          "Failed to deserialize " + t.GetDescriptor()->full_name());
-    }
-    return t;
-  }
-
-  template <typename T>
-  static Try<std::string> serialize(const T& t)
-  {
-    // TODO(benh): Actually store the descriptor so that we can verify
-    // type information (and compatibility) when we deserialize.
-    std::string value;
-    if (!t.SerializeToString(&value)) {
-      return Error(
-          "Failed to serialize " + t.GetDescriptor()->full_name());
-    }
-    return value;
-  }
-};
-
-} // namespace state {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __STATE_SERIALIZER_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/state.hpp
----------------------------------------------------------------------
diff --git a/src/state/state.hpp b/src/state/state.hpp
index c616e00..b3abf89 100644
--- a/src/state/state.hpp
+++ b/src/state/state.hpp
@@ -24,16 +24,15 @@
 
 #include <process/future.hpp>
 
+#include <stout/lambda.hpp>
 #include <stout/none.hpp>
 #include <stout/option.hpp>
 #include <stout/try.hpp>
 #include <stout/uuid.hpp>
 
-#include "logging/logging.hpp"
-
 #include "messages/state.hpp"
 
-#include "state/serializer.hpp"
+#include "state/storage.hpp"
 
 namespace mesos {
 namespace internal {
@@ -46,187 +45,153 @@ namespace state {
 // fetched. Varying implementations of state provide varying
 // replicated guarantees.
 //
-// Note that the semantics of 'get' and 'set' provide atomicity. That
-// is, you can not set a variable that has changed since you did the
-// last get. That is, if a set succeeds then no other writes have been
-// performed on the variable since your get.
-
+// Note that the semantics of 'fetch' and 'store' provide
+// atomicity. That is, you can not store a variable that has changed
+// since you did the last fetch. That is, if a store succeeds then no
+// other writes have been performed on the variable since your fetch.
+//
 // Example:
-
-//   State<ProtobufSerializer>* state = new ZooKeeperState<ProtobufSerializer>();
-//   Future<Variable<Slaves> > variable = state->get<Slaves>("slaves");
-//   Variable<Slaves> slaves = variable.get();
-//   slaves->add_infos()->MergeFrom(info);
-//   Future<bool> set = state->set(&slaves);
+//
+//   Storage* storage = new ZooKeeperStorage();
+//   State* state = new State(storage);
+//   Future<Variable> variable = state->fetch("slaves");
+//   std::string value = update(variable.value());
+//   variable = variable.mutate(value);
+//   state->store(variable);
 
 // Forward declarations.
-template <typename Serializer>
 class State;
-class ZooKeeperStateProcess;
 
 
-template <typename T>
+// Wrapper around a state "entry" to force immutability.
 class Variable
 {
 public:
-  T* operator -> ()
+  std::string value() const
   {
-    return &t;
+    return entry.value();
+  }
+
+  Variable mutate(const std::string& value) const
+  {
+    Variable variable(*this);
+    variable.entry.set_value(value);
+    return variable;
   }
 
 private:
-  template <typename Serializer>
   friend class State; // Creates and manages variables.
 
-  Variable(const Entry& _entry, const T& _t)
-    : entry(_entry), t(_t)
+  Variable(const Entry& _entry)
+    : entry(_entry)
   {}
 
-  Entry entry; // Not const so Variable is copyable.
-  T t;
+  Entry entry; // Not const to keep Variable assignable.
 };
 
 
-template <typename Serializer = StringSerializer>
 class State
 {
 public:
-  State() {}
+  State(Storage* _storage) : storage(_storage) {}
   virtual ~State() {}
 
   // Returns a variable from the state, creating a new one if one
   // previously did not exist (or an error if one occurs).
-  template <typename T>
-  process::Future<Variable<T> > get(const std::string& name);
+  process::Future<Variable> fetch(const std::string& name);
 
-  // Returns true if the variable was successfully set in the state,
-  // otherwise false if the version of the variable was no longer
-  // valid (or an error if one occurs).
-  template <typename T>
-  process::Future<Option<Variable<T> > > set(const Variable<T>& variable);
+  // Returns the variable specified if it was successfully stored in
+  // the state, otherwise returns none if the version of the variable
+  // was no longer valid, or an error if one occurs.
+  process::Future<Option<Variable> > store(const Variable& variable);
 
-  // Returns the collection of variable names in the state.
-  virtual process::Future<std::vector<std::string> > names() = 0;
+  // Returns true if successfully expunged the variable from the state.
+  process::Future<bool> expunge(const Variable& variable);
 
-protected:
-  // Fetch and swap state entries, factored out to allow State
-  // implementations to be agnostic of Variable which is templated.
-  virtual process::Future<Option<Entry> > fetch(const std::string& name) = 0;
-  virtual process::Future<bool> swap(const Entry& entry, const UUID& uuid) = 0;
+  // Returns the collection of variable names in the state.
+  process::Future<std::vector<std::string> > names();
 
 private:
   // Helpers to handle future results from fetch and swap. We make
   // these static members of State for friend access to Variable's
   // constructor.
-  template <typename T>
-  static process::Future<Variable<T> > _get(
+  static process::Future<Variable> _fetch(
       const std::string& name,
       const Option<Entry>& option);
 
-  template <typename T>
-  static process::Future<Option<Variable<T> > > _set(
+  static process::Future<Option<Variable> > _store(
       const Entry& entry,
-      const T& t,
       const bool& b); // TODO(benh): Remove 'const &' after fixing libprocess.
+
+  Storage* storage;
 };
 
 
-template <typename Serializer>
-template <typename T>
-process::Future<Variable<T> > State<Serializer>::_get(
+inline process::Future<Variable> State::fetch(const std::string& name)
+{
+  return storage->get(name)
+    .then(lambda::bind(&State::_fetch, name, lambda::_1));
+}
+
+
+inline process::Future<Variable> State::_fetch(
     const std::string& name,
     const Option<Entry>& option)
 {
   if (option.isSome()) {
-    const Entry& entry = option.get();
-
-    Try<T> t = Serializer::template deserialize<T>(entry.value());
-
-    if (t.isError()) {
-      return process::Future<Variable<T> >::failed(t.error());
-    }
-
-    return Variable<T>(entry, t.get());
+    return Variable(option.get());
   }
 
-  // Otherwise, construct a Variable out of a new Entry with a default
-  // value for T (and a random UUID to start).
-  T t;
+  // Otherwise, construct a Variable with a new Entry (with a random
+  // UUID and no value to start).
+  Entry entry;
+  entry.set_name(name);
+  entry.set_uuid(UUID::random().toBytes());
+
+  return Variable(entry);
+}
 
-  Try<std::string> value = Serializer::template serialize<T>(t);
 
-  if (value.isError()) {
-    return process::Future<Variable<T> >::failed(value.error());
-  }
+inline process::Future<Option<Variable> > State::store(const Variable& variable)
+{
+  // Note that we try and swap an entry even if the value didn't change!
+  UUID uuid = UUID::fromBytes(variable.entry.uuid());
 
+  // Create a new entry to replace the existing entry provided the
+  // UUID matches.
   Entry entry;
-  entry.set_name(name);
+  entry.set_name(variable.entry.name());
   entry.set_uuid(UUID::random().toBytes());
-  entry.set_value(value.get());
+  entry.set_value(variable.entry.value());
 
-  return Variable<T>(entry, t);
+  return storage->set(entry, uuid)
+    .then(lambda::bind(&State::_store, entry, lambda::_1));
 }
 
 
-template <typename Serializer>
-template <typename T>
-process::Future<Option<Variable<T> > > State<Serializer>::_set(
+inline process::Future<Option<Variable > > State::_store(
     const Entry& entry,
-    const T& t,
     const bool& b) // TODO(benh): Remove 'const &' after fixing libprocess.
 {
   if (b) {
-    return Option<Variable<T> >::some(Variable<T>(entry, t));
+    return Option<Variable>::some(Variable(entry));
   }
 
   return None();
 }
 
 
-template <typename Serializer>
-template <typename T>
-process::Future<Variable<T> > State<Serializer>::get(const std::string& name)
+inline process::Future<bool> State::expunge(const Variable& variable)
 {
-  return fetch(name)
-    .then(std::tr1::bind(&State<Serializer>::template _get<T>,
-                         name,
-                         std::tr1::placeholders::_1));
+  return storage->expunge(variable.entry);
 }
 
 
-template <typename Serializer>
-template <typename T>
-process::Future<Option<Variable<T> > > State<Serializer>::set(
-      const Variable<T>& variable)
+inline process::Future<std::vector<std::string> > State::names()
 {
-  Try<std::string> value = Serializer::template serialize<T>(variable.t);
-
-  if (value.isError()) {
-    return process::Future<Option<Variable<T> > >::failed(value.error());
-  }
-
-  // Note that we try and swap an entry even if the value didn't change!
-  UUID uuid = UUID::fromBytes(variable.entry.uuid());
-
-  // Create a new entry that should be replace the existing entry
-  // provided the UUID matches.
-  Entry entry;
-  entry.set_name(variable.entry.name());
-  entry.set_uuid(UUID::random().toBytes());
-  entry.set_value(value.get());
-
-  std::tr1::function<
-  process::Future<Option<Variable<T> > >(const bool&)> _set =
-    std::tr1::bind(&State<Serializer>::template _set<T>,
-                   entry,
-                   variable.t,
-                   std::tr1::placeholders::_1);
-
-  return swap(entry, uuid).then(_set);
+  return storage->names();
 }
 
-
-
 } // namespace state {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/storage.hpp
----------------------------------------------------------------------
diff --git a/src/state/storage.hpp b/src/state/storage.hpp
new file mode 100644
index 0000000..a137075
--- /dev/null
+++ b/src/state/storage.hpp
@@ -0,0 +1,60 @@
+/**
+ * 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.
+ */
+
+#ifndef __STATE_STORAGE_HPP__
+#define __STATE_STORAGE_HPP__
+
+#include <string>
+#include <vector>
+
+#include <process/future.hpp>
+
+#include <stout/option.hpp>
+#include <stout/uuid.hpp>
+
+#include "messages/state.hpp"
+
+namespace mesos {
+namespace internal {
+namespace state {
+
+class Storage
+{
+public:
+  Storage() {}
+  virtual ~Storage() {}
+
+  // Get and set state entries, factored out to allow Storage
+  // implementations to be agnostic of Variable. Note that set acts
+  // like a "test-and-set" by requiring the existing entry to have the
+  // specified UUID.
+  virtual process::Future<Option<Entry> > get(const std::string& name) = 0;
+  virtual process::Future<bool> set(const Entry& entry, const UUID& uuid) = 0;
+
+  // Returns true if successfully expunged the variable from the state.
+  virtual process::Future<bool> expunge(const Entry& entry) = 0;
+
+  // Returns the collection of variable names in the state.
+  virtual process::Future<std::vector<std::string> > names() = 0;
+};
+
+} // namespace state {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __STATE_STORAGE_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/zookeeper.cpp
----------------------------------------------------------------------
diff --git a/src/state/zookeeper.cpp b/src/state/zookeeper.cpp
index 07339ff..1801fce 100644
--- a/src/state/zookeeper.cpp
+++ b/src/state/zookeeper.cpp
@@ -1,5 +1,7 @@
 #include <google/protobuf/message.h>
 
+#include <google/protobuf/io/zero_copy_stream_impl.h> // For ArrayInputStream.
+
 #include <queue>
 #include <string>
 #include <vector>
@@ -21,7 +23,7 @@
 
 #include "messages/state.hpp"
 
-#include "state/state.hpp"
+#include "state/storage.hpp"
 #include "state/zookeeper.hpp"
 
 #include "zookeeper/authentication.hpp"
@@ -53,7 +55,7 @@ void fail(queue<T*>* queue, const string& message)
 }
 
 
-ZooKeeperStateProcess::ZooKeeperStateProcess(
+ZooKeeperStorageProcess::ZooKeeperStorageProcess(
     const string& _servers,
     const Duration& _timeout,
     const string& _znode,
@@ -71,27 +73,27 @@ ZooKeeperStateProcess::ZooKeeperStateProcess(
 {}
 
 
-ZooKeeperStateProcess::~ZooKeeperStateProcess()
+ZooKeeperStorageProcess::~ZooKeeperStorageProcess()
 {
-  fail(&pending.names, "No longer managing state");
-  fail(&pending.fetches, "No longer managing state");
-  fail(&pending.swaps, "No longer managing state");
+  fail(&pending.names, "No longer managing storage");
+  fail(&pending.gets, "No longer managing storage");
+  fail(&pending.sets, "No longer managing storage");
 
   delete zk;
   delete watcher;
 }
 
 
-void ZooKeeperStateProcess::initialize()
+void ZooKeeperStorageProcess::initialize()
 {
   // Doing initialization here allows to avoid the race between
   // instantiating the ZooKeeper instance and being spawned ourself.
-  watcher = new ProcessWatcher<ZooKeeperStateProcess>(self());
+  watcher = new ProcessWatcher<ZooKeeperStorageProcess>(self());
   zk = new ZooKeeper(servers, timeout, watcher);
 }
 
 
-Future<vector<string> > ZooKeeperStateProcess::names()
+Future<vector<string> > ZooKeeperStorageProcess::names()
 {
   if (error.isSome()) {
     return Future<vector<string> >::failed(error.get());
@@ -115,22 +117,22 @@ Future<vector<string> > ZooKeeperStateProcess::names()
 }
 
 
-Future<Option<Entry> > ZooKeeperStateProcess::fetch(const string& name)
+Future<Option<Entry> > ZooKeeperStorageProcess::get(const string& name)
 {
   if (error.isSome()) {
     return Future<Option<Entry> >::failed(error.get());
   } else if (state != CONNECTED) {
-    Fetch* fetch = new Fetch(name);
-    pending.fetches.push(fetch);
-    return fetch->promise.future();
+    Get* get = new Get(name);
+    pending.gets.push(get);
+    return get->promise.future();
   }
 
-  Result<Option<Entry> > result = doFetch(name);
+  Result<Option<Entry> > result = doGet(name);
 
   if (result.isNone()) { // Try again later.
-    Fetch* fetch = new Fetch(name);
-    pending.fetches.push(fetch);
-    return fetch->promise.future();
+    Get* get = new Get(name);
+    pending.gets.push(get);
+    return get->promise.future();
   } else if (result.isError()) {
     return Future<Option<Entry> >::failed(result.error());
   }
@@ -139,22 +141,46 @@ Future<Option<Entry> > ZooKeeperStateProcess::fetch(const string& name)
 }
 
 
-Future<bool> ZooKeeperStateProcess::swap(const Entry& entry, const UUID& uuid)
+Future<bool> ZooKeeperStorageProcess::set(const Entry& entry, const UUID& uuid)
+{
+  if (error.isSome()) {
+    return Future<bool>::failed(error.get());
+  } else if (state != CONNECTED) {
+    Set* set = new Set(entry, uuid);
+    pending.sets.push(set);
+    return set->promise.future();
+  }
+
+  Result<bool> result = doSet(entry, uuid);
+
+  if (result.isNone()) { // Try again later.
+    Set* set = new Set(entry, uuid);
+    pending.sets.push(set);
+    return set->promise.future();
+  } else if (result.isError()) {
+    return Future<bool>::failed(result.error());
+  }
+
+  return result.get();
+}
+
+
+Future<bool> ZooKeeperStorageProcess::expunge(const Entry& entry)
 {
   if (error.isSome()) {
     return Future<bool>::failed(error.get());
   } else if (state != CONNECTED) {
-    Swap* swap = new Swap(entry, uuid);
-    pending.swaps.push(swap);
-    return swap->promise.future();
+    Expunge* expunge = new Expunge(entry);
+    pending.expunges.push(expunge);
+    return expunge->promise.future();
   }
 
-  Result<bool> result = doSwap(entry, uuid);
+  Result<bool> result = doExpunge(entry);
 
   if (result.isNone()) { // Try again later.
-    Swap* swap = new Swap(entry, uuid);
-    pending.swaps.push(swap);
-    return swap->promise.future();
+    Expunge* expunge = new Expunge(entry);
+    pending.expunges.push(expunge);
+    return expunge->promise.future();
   } else if (result.isError()) {
     return Future<bool>::failed(result.error());
   }
@@ -163,7 +189,7 @@ Future<bool> ZooKeeperStateProcess::swap(const Entry& entry, const UUID& uuid)
 }
 
 
-void ZooKeeperStateProcess::connected(bool reconnect)
+void ZooKeeperStorageProcess::connected(bool reconnect)
 {
   if (!reconnect) {
     // Authenticate if necessary (and we are connected for the first
@@ -196,43 +222,43 @@ void ZooKeeperStateProcess::connected(bool reconnect)
     delete names;
   }
 
-  while (!pending.fetches.empty()) {
-    Fetch* fetch = pending.fetches.front();
-    Result<Option<Entry> > result = doFetch(fetch->name);
+  while (!pending.gets.empty()) {
+    Get* get = pending.gets.front();
+    Result<Option<Entry> > result = doGet(get->name);
     if (result.isNone()) {
       return; // Try again later.
     } else if (result.isError()) {
-      fetch->promise.fail(result.error());
+      get->promise.fail(result.error());
     } else {
-      fetch->promise.set(result.get());
+      get->promise.set(result.get());
     }
-    pending.fetches.pop();
-    delete fetch;
+    pending.gets.pop();
+    delete get;
   }
 
-  while (!pending.swaps.empty()) {
-    Swap* swap = pending.swaps.front();
-    Result<bool> result = doSwap(swap->entry, swap->uuid);
+  while (!pending.sets.empty()) {
+    Set* set = pending.sets.front();
+    Result<bool> result = doSet(set->entry, set->uuid);
     if (result.isNone()) {
       return; // Try again later.
     } else if (result.isError()) {
-      swap->promise.fail(result.error());
+      set->promise.fail(result.error());
     } else {
-      swap->promise.set(result.get());
+      set->promise.set(result.get());
     }
-    pending.swaps.pop();
-    delete swap;
+    pending.sets.pop();
+    delete set;
   }
 }
 
 
-void ZooKeeperStateProcess::reconnecting()
+void ZooKeeperStorageProcess::reconnecting()
 {
   state = CONNECTING;
 }
 
 
-void ZooKeeperStateProcess::expired()
+void ZooKeeperStorageProcess::expired()
 {
   state = DISCONNECTED;
 
@@ -243,25 +269,25 @@ void ZooKeeperStateProcess::expired()
 }
 
 
-void ZooKeeperStateProcess::updated(const string& path)
+void ZooKeeperStorageProcess::updated(const string& path)
 {
   LOG(FATAL) << "Unexpected ZooKeeper event";
 }
 
 
-void ZooKeeperStateProcess::created(const string& path)
+void ZooKeeperStorageProcess::created(const string& path)
 {
   LOG(FATAL) << "Unexpected ZooKeeper event";
 }
 
 
-void ZooKeeperStateProcess::deleted(const string& path)
+void ZooKeeperStorageProcess::deleted(const string& path)
 {
   LOG(FATAL) << "Unexpected ZooKeeper event";
 }
 
 
-Result<vector<string> > ZooKeeperStateProcess::doNames()
+Result<vector<string> > ZooKeeperStorageProcess::doNames()
 {
   // Get all children to determine current memberships.
   vector<string> results;
@@ -284,7 +310,7 @@ Result<vector<string> > ZooKeeperStateProcess::doNames()
 }
 
 
-Result<Option<Entry> > ZooKeeperStateProcess::doFetch(const string& name)
+Result<Option<Entry> > ZooKeeperStorageProcess::doGet(const string& name)
 {
   CHECK(error.isNone()) << ": " << error.get();
   CHECK(state == CONNECTED);
@@ -317,7 +343,7 @@ Result<Option<Entry> > ZooKeeperStateProcess::doFetch(const string& name)
 }
 
 
-Result<bool> ZooKeeperStateProcess::doSwap(const Entry& entry, const UUID& uuid)
+Result<bool> ZooKeeperStorageProcess::doSet(const Entry& entry, const UUID& uuid)
 {
   CHECK(error.isNone()) << ": " << error.get();
   CHECK(state == CONNECTED);
@@ -397,7 +423,7 @@ Result<bool> ZooKeeperStateProcess::doSwap(const Entry& entry, const UUID& uuid)
     return false;
   }
 
-  // Okay, do a set, we get atomic swap by requiring 'stat.version'.
+  // Okay, do the set, we get atomicity by requiring 'stat.version'.
   code = zk->set(znode + "/" + entry.name(), data, stat.version);
 
   if (code == ZBADVERSION) {
@@ -414,6 +440,57 @@ Result<bool> ZooKeeperStateProcess::doSwap(const Entry& entry, const UUID& uuid)
   return true;
 }
 
+
+Result<bool> ZooKeeperStorageProcess::doExpunge(const Entry& entry)
+{
+  CHECK(error.isNone()) << ": " << error.get();
+  CHECK(state == CONNECTED);
+
+  string result;
+  Stat stat;
+
+  int code = zk->get(znode + "/" + entry.name(), false, &result, &stat);
+
+  if (code == ZNONODE) {
+    return false;
+  } else if (code == ZINVALIDSTATE || (code != ZOK && zk->retryable(code))) {
+    CHECK(zk->getState() != ZOO_AUTH_FAILED_STATE);
+    return None(); // Try again later.
+  } else if (code != ZOK) {
+    return Error(
+        "Failed to get '" + znode + "/" + entry.name() +
+        "' in ZooKeeper: " + zk->message(code));
+  }
+
+  google::protobuf::io::ArrayInputStream stream(result.data(), result.size());
+
+  Entry current;
+
+  if (!current.ParseFromZeroCopyStream(&stream)) {
+    return Error("Failed to deserialize Entry");
+  }
+
+  if (UUID::fromBytes(current.uuid()) != UUID::fromBytes(entry.uuid())) {
+    return false;
+  }
+
+  // Okay, do the remove, we get atomicity by requiring 'stat.version'.
+  code = zk->remove(znode + "/" + entry.name(), stat.version);
+
+  if (code == ZBADVERSION) {
+    return false;
+  } else if (code == ZINVALIDSTATE || (code != ZOK && zk->retryable(code))) {
+    CHECK(zk->getState() != ZOO_AUTH_FAILED_STATE);
+    return None(); // Try again later.
+  } else if (code != ZOK) {
+    return Error(
+        "Failed to remove '" + znode + "/" + entry.name() +
+        "' in ZooKeeper: " + zk->message(code));
+  }
+
+  return true;
+}
+
 } // namespace state {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/state/zookeeper.hpp
----------------------------------------------------------------------
diff --git a/src/state/zookeeper.hpp b/src/state/zookeeper.hpp
index 1e332ed..90b6607 100644
--- a/src/state/zookeeper.hpp
+++ b/src/state/zookeeper.hpp
@@ -17,8 +17,7 @@
 
 #include "messages/state.hpp"
 
-#include "state/serializer.hpp"
-#include "state/state.hpp"
+#include "state/storage.hpp"
 
 #include "zookeeper/authentication.hpp"
 #include "zookeeper/watcher.hpp"
@@ -29,51 +28,49 @@ namespace internal {
 namespace state {
 
 // Forward declarations.
-class ZooKeeperStateProcess;
+class ZooKeeperStorageProcess;
 
 
-template <typename Serializer = StringSerializer>
-class ZooKeeperState : public State<Serializer>
+class ZooKeeperStorage : public Storage
 {
 public:
   // TODO(benh): Just take a zookeeper::URL.
-  ZooKeeperState(
+  ZooKeeperStorage(
       const std::string& servers,
       const Duration& timeout,
       const std::string& znode,
       const Option<zookeeper::Authentication>& auth =
       Option<zookeeper::Authentication>());
-  virtual ~ZooKeeperState();
+  virtual ~ZooKeeperStorage();
 
-  // State implementation.
+  // Storage implementation.
+  virtual process::Future<Option<Entry> > get(const std::string& name);
+  virtual process::Future<bool> set(const Entry& entry, const UUID& uuid);
+  virtual process::Future<bool> expunge(const Entry& entry);
   virtual process::Future<std::vector<std::string> > names();
 
-protected:
-  // More State implementation.
-  virtual process::Future<Option<Entry> > fetch(const std::string& name);
-  virtual process::Future<bool> swap(const Entry& entry, const UUID& uuid);
-
 private:
-  ZooKeeperStateProcess* process;
+  ZooKeeperStorageProcess* process;
 };
 
 
-class ZooKeeperStateProcess : public process::Process<ZooKeeperStateProcess>
+class ZooKeeperStorageProcess : public process::Process<ZooKeeperStorageProcess>
 {
 public:
-  ZooKeeperStateProcess(
+  ZooKeeperStorageProcess(
       const std::string& servers,
       const Duration& timeout,
       const std::string& znode,
       const Option<zookeeper::Authentication>& auth);
-  virtual ~ZooKeeperStateProcess();
+  virtual ~ZooKeeperStorageProcess();
 
   virtual void initialize();
 
-  // State implementation.
+  // Storage implementation.
+  process::Future<Option<Entry> > get(const std::string& name);
+  process::Future<bool> set(const Entry& entry, const UUID& uuid);
+  virtual process::Future<bool> expunge(const Entry& entry);
   process::Future<std::vector<std::string> > names();
-  process::Future<Option<Entry> > fetch(const std::string& name);
-  process::Future<bool> swap(const Entry& entry, const UUID& uuid);
 
   // ZooKeeper events.
   void connected(bool reconnect);
@@ -86,8 +83,9 @@ public:
 private:
   // Helpers for getting the names, fetching, and swapping.
   Result<std::vector<std::string> > doNames();
-  Result<Option<Entry> > doFetch(const std::string& name);
-  Result<bool> doSwap(const Entry& entry, const UUID& uuid);
+  Result<Option<Entry> > doGet(const std::string& name);
+  Result<bool> doSet(const Entry& entry, const UUID& uuid);
+  Result<bool> doExpunge(const Entry& entry);
 
   const std::string servers;
   const Duration timeout;
@@ -111,49 +109,56 @@ private:
     process::Promise<std::vector<std::string> > promise;
   };
 
-  struct Fetch
+  struct Get
   {
-    Fetch(const std::string& _name)
+    Get(const std::string& _name)
       : name(_name) {}
     std::string name;
     process::Promise<Option<Entry> > promise;
   };
 
-  struct Swap
+  struct Set
   {
-    Swap(const Entry& _entry, const UUID& _uuid)
+    Set(const Entry& _entry, const UUID& _uuid)
       : entry(_entry), uuid(_uuid) {}
     Entry entry;
     UUID uuid;
     process::Promise<bool> promise;
   };
 
+  struct Expunge
+  {
+    Expunge(const Entry& _entry)
+      : entry(_entry) {}
+    Entry entry;
+    process::Promise<bool> promise;
+  };
+
   // TODO(benh): Make pending a single queue of "operations" that can
   // be "invoked" (C++11 lambdas would help).
   struct {
     std::queue<Names*> names;
-    std::queue<Fetch*> fetches;
-    std::queue<Swap*> swaps;
+    std::queue<Get*> gets;
+    std::queue<Set*> sets;
+    std::queue<Expunge*> expunges;
   } pending;
 
   Option<std::string> error;
 };
 
 
-template <typename Serializer>
-ZooKeeperState<Serializer>::ZooKeeperState(
+inline ZooKeeperStorage::ZooKeeperStorage(
     const std::string& servers,
     const Duration& timeout,
     const std::string& znode,
     const Option<zookeeper::Authentication>& auth)
 {
-  process = new ZooKeeperStateProcess(servers, timeout, znode, auth);
+  process = new ZooKeeperStorageProcess(servers, timeout, znode, auth);
   process::spawn(process);
 }
 
 
-template <typename Serializer>
-ZooKeeperState<Serializer>::~ZooKeeperState()
+inline ZooKeeperStorage::~ZooKeeperStorage()
 {
   process::terminate(process);
   process::wait(process);
@@ -161,27 +166,31 @@ ZooKeeperState<Serializer>::~ZooKeeperState()
 }
 
 
-template <typename Serializer>
-process::Future<std::vector<std::string> > ZooKeeperState<Serializer>::names()
+inline process::Future<Option<Entry> > ZooKeeperStorage::get(
+    const std::string& name)
 {
-  return process::dispatch(process, &ZooKeeperStateProcess::names);
+  return process::dispatch(process, &ZooKeeperStorageProcess::get, name);
 }
 
 
-template <typename Serializer>
-process::Future<Option<Entry> > ZooKeeperState<Serializer>::fetch(
-    const std::string& name)
+inline process::Future<bool> ZooKeeperStorage::set(
+    const Entry& entry,
+    const UUID& uuid)
 {
-  return process::dispatch(process, &ZooKeeperStateProcess::fetch, name);
+  return process::dispatch(process, &ZooKeeperStorageProcess::set, entry, uuid);
 }
 
 
-template <typename Serializer>
-process::Future<bool> ZooKeeperState<Serializer>::swap(
-    const Entry& entry,
-    const UUID& uuid)
+inline process::Future<bool> ZooKeeperStorage::expunge(
+    const Entry& entry)
+{
+  return process::dispatch(process, &ZooKeeperStorageProcess::expunge, entry);
+}
+
+
+inline process::Future<std::vector<std::string> > ZooKeeperStorage::names()
 {
-  return process::dispatch(process, &ZooKeeperStateProcess::swap, entry, uuid);
+  return process::dispatch(process, &ZooKeeperStorageProcess::names);
 }
 
 } // namespace state {


[13/28] git commit: Cleaned up the output from running and automagically disabling the CgroupsNoHierarchyTest.

Posted by be...@apache.org.
Cleaned up the output from running and automagically disabling the
CgroupsNoHierarchyTest.

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


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

Branch: refs/heads/master
Commit: 7995751b66c7c09e31dcdc8b9444777718b4b2c4
Parents: 6b1b820
Author: Benjamin Hindman <be...@twitter.com>
Authored: Thu May 9 23:34:48 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:40 2013 -0700

----------------------------------------------------------------------
 src/tests/cgroups_tests.cpp |   19 ++++++++-----------
 src/tests/environment.cpp   |    7 ++++---
 2 files changed, 12 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/7995751b/src/tests/cgroups_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/cgroups_tests.cpp b/src/tests/cgroups_tests.cpp
index f062fe6..f6b23c4 100644
--- a/src/tests/cgroups_tests.cpp
+++ b/src/tests/cgroups_tests.cpp
@@ -84,17 +84,14 @@ public:
 
     Try<std::set<std::string> > hierarchies = cgroups::hierarchies();
     ASSERT_SOME(hierarchies);
-    if (!hierarchies.get().empty()) {
-      std::cerr
-        << "-------------------------------------------------------------\n"
-        << "We cannot run any cgroups tests that require mounting\n"
-        << "hierarchies because you have the following hierarchies mounted:\n"
-        << strings::trim(stringify(hierarchies.get()), " {},") << "\n"
-        << "You can either unmount those hierarchies, or disable\n"
-        << "this test case (i.e., --gtest_filter=-CgroupsNoHierarchyTest.*).\n"
-        << "-------------------------------------------------------------"
-        << std::endl;
-    }
+    ASSERT_TRUE(hierarchies.get().empty())
+      << "-------------------------------------------------------------\n"
+      << "We cannot run any cgroups tests that require mounting\n"
+      << "hierarchies because you have the following hierarchies mounted:\n"
+      << strings::trim(stringify(hierarchies.get()), " {},") << "\n"
+      << "You can either unmount those hierarchies, or disable\n"
+      << "this test case (i.e., --gtest_filter=-CgroupsNoHierarchyTest.*).\n"
+      << "-------------------------------------------------------------";
   }
 };
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/7995751b/src/tests/environment.cpp
----------------------------------------------------------------------
diff --git a/src/tests/environment.cpp b/src/tests/environment.cpp
index 2a22acd..d8bb5fd 100644
--- a/src/tests/environment.cpp
+++ b/src/tests/environment.cpp
@@ -35,6 +35,8 @@
 #include "linux/cgroups.hpp"
 #endif
 
+#include "logging/logging.hpp"
+
 #include "tests/environment.hpp"
 #include "tests/flags.hpp"
 
@@ -83,15 +85,14 @@ static bool enable(const ::testing::TestInfo& test)
 #ifdef __linux__
     if (strings::contains(name, "NOHIERARCHY_")) {
       Try<std::set<std::string> > hierarchies = cgroups::hierarchies();
-      CHECK(hierarchies.isSome());
+      CHECK_SOME(hierarchies);
       if (!hierarchies.get().empty()) {
         std::cerr
           << "-------------------------------------------------------------\n"
           << "We cannot run any cgroups tests that require mounting\n"
           << "hierarchies because you have the following hierarchies mounted:\n"
           << strings::trim(stringify(hierarchies.get()), " {},") << "\n"
-          << "You can either unmount those hierarchies, or disable\n"
-          << "this test case (i.e., --gtest_filter=-CgroupsNoHierarchyTest.*).\n"
+          << "We'll disable the CgroupsNoHierarchyTest test fixture for now.\n"
           << "-------------------------------------------------------------"
           << std::endl;
 


[18/28] git commit: More spring cleaning, this time in the slave recovery tets.

Posted by be...@apache.org.
More spring cleaning, this time in the slave recovery tets.

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


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

Branch: refs/heads/master
Commit: a1e25cb703d1d6d206292d7aef926254f1377f34
Parents: bfa2255
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sat May 11 19:38:15 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:41 2013 -0700

----------------------------------------------------------------------
 src/tests/slave_recovery_tests.cpp |  166 +++++++++++++++----------------
 1 files changed, 82 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/a1e25cb7/src/tests/slave_recovery_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_recovery_tests.cpp b/src/tests/slave_recovery_tests.cpp
index 65f50ed..0315c52 100644
--- a/src/tests/slave_recovery_tests.cpp
+++ b/src/tests/slave_recovery_tests.cpp
@@ -155,12 +155,15 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
   Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
-  // Message expectations.
-  Future<Message> registerFramework =
-    FUTURE_MESSAGE(Eq(RegisterFrameworkMessage().GetTypeName()), _, _);
-
-  // Scheduler expectations.
   MockScheduler sched;
+
+  // Enable checkpointing for the framework.
+  FrameworkInfo frameworkInfo;
+  frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
+  frameworkInfo.set_checkpoint(true);
+
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
+
   FrameworkID frameworkId;
   EXPECT_CALL(sched, registered(_, _, _))
     .WillOnce(SaveArg<1>(&frameworkId));
@@ -170,18 +173,14 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
     .WillOnce(FutureArg<1>(&offers))
     .WillRepeatedly(Return());      // Ignore subsequent offers.
 
-  // Enable checkpointing for the framework.
-  FrameworkInfo frameworkInfo;
-  frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
-  frameworkInfo.set_checkpoint(true);
-
-  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
+  Future<Message> registerFrameworkMessage =
+    FUTURE_MESSAGE(Eq(RegisterFrameworkMessage().GetTypeName()), _, _);
 
   driver.start();
 
   // Capture the framework pid.
-  AWAIT_READY(registerFramework);
-  UPID frameworkPid = registerFramework.get().from;
+  AWAIT_READY(registerFrameworkMessage);
+  UPID frameworkPid = registerFrameworkMessage.get().from;
 
   AWAIT_READY(offers);
   EXPECT_NE(0u, offers.get().size());
@@ -330,16 +329,8 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
 
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers))
-    .WillRepeatedly(Return());      // Ignore subsequent offers.
-
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
@@ -347,6 +338,13 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return());      // Ignore subsequent offers.
+
   driver.start();
 
   AWAIT_READY(offers);
@@ -414,14 +412,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers))
-    .WillRepeatedly(Return());      // Ignore subsequent offers.
 
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -430,6 +421,13 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return());      // Ignore subsequent offers.
+
   driver.start();
 
   AWAIT_READY(offers);
@@ -506,14 +504,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers))
-    .WillRepeatedly(Return());      // Ignore subsequent offers.
 
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -522,6 +513,13 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return());      // Ignore subsequent offers.
+
   driver.start();
 
   AWAIT_READY(offers);
@@ -599,14 +597,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers))
-    .WillRepeatedly(Return());      // Ignore subsequent offers.
 
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -615,6 +606,13 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return());      // Ignore subsequent offers.
+
   driver.start();
 
   AWAIT_READY(offers);
@@ -698,14 +696,7 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers))
-    .WillRepeatedly(Return());      // Ignore subsequent offers.
 
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -714,6 +705,13 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return());      // Ignore subsequent offers.
+
   driver.start();
 
   AWAIT_READY(offers);
@@ -780,14 +778,7 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
   Try<PID<Slave> > slave = this->StartSlave(&isolator);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers))
-    .WillRepeatedly(Return());      // Ignore subsequent offers.
 
   // Disable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -796,6 +787,13 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return());      // Ignore subsequent offers.
+
   driver.start();
 
   AWAIT_READY(offers);
@@ -845,8 +843,15 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
   Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
+
+  // Disable checkpointing for the framework.
+  FrameworkInfo frameworkInfo;
+  frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
+  frameworkInfo.set_checkpoint(false);
+
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
+
   FrameworkID frameworkId;
   EXPECT_CALL(sched, registered(_, _, _))
     .WillOnce(SaveArg<1>(&frameworkId));
@@ -856,13 +861,6 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
     .WillOnce(FutureArg<1>(&offers))
     .WillRepeatedly(Return());      // Ignore subsequent offers.
 
-  // Disable checkpointing for the framework.
-  FrameworkInfo frameworkInfo;
-  frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
-  frameworkInfo.set_checkpoint(false);
-
-  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
-
   driver.start();
 
   AWAIT_READY(offers);
@@ -928,13 +926,7 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers1;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers1));
 
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -943,6 +935,12 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers1;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers1));
+
   driver.start();
 
   AWAIT_READY(offers1);
@@ -1039,14 +1037,7 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers))
-    .WillRepeatedly(Return()); // Ignore subsequent offers.
 
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -1055,6 +1046,13 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
   driver.start();
 
   AWAIT_READY(offers);
@@ -1161,14 +1159,7 @@ TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
   Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
   ASSERT_SOME(slave);
 
-  // Scheduler expectations.
   MockScheduler sched;
-  EXPECT_CALL(sched, registered(_, _, _));
-
-  Future<vector<Offer> > offers1;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers1))
-    .WillOnce(Return());       // Ignore the offer when slave is shutting down.
 
   // Enable checkpointing for the framework.
   FrameworkInfo frameworkInfo;
@@ -1177,6 +1168,13 @@ TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
 
   MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  Future<vector<Offer> > offers1;
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(FutureArg<1>(&offers1))
+    .WillOnce(Return());       // Ignore the offer when slave is shutting down.
+
   driver.start();
 
   AWAIT_READY(offers1);


[26/28] git commit: Fixed bug where we didn't stop all MesosExecutorDrivers when using the TestingIsolator (potentially causing a segfault when a driver attempts to use a MockExecutor that had been deallocated).

Posted by be...@apache.org.
Fixed bug where we didn't stop all MesosExecutorDrivers when using the
TestingIsolator (potentially causing a segfault when a driver attempts
to use a MockExecutor that had been deallocated).

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


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

Branch: refs/heads/master
Commit: bc9cb875536dd2ee349dfc8b917322d77a865a04
Parents: 6958e6d
Author: Benjamin Hindman <be...@twitter.com>
Authored: Tue May 21 23:35:11 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 09:28:38 2013 -0700

----------------------------------------------------------------------
 src/tests/allocator_tests.cpp             |   38 ++-------
 src/tests/allocator_zookeeper_tests.cpp   |  116 +++++++++---------------
 src/tests/fault_tolerance_tests.cpp       |   51 ++++-------
 src/tests/gc_tests.cpp                    |   20 ++---
 src/tests/isolator.hpp                    |   10 ++-
 src/tests/master_tests.cpp                |   42 ++-------
 src/tests/resource_offers_tests.cpp       |    5 +-
 src/tests/status_update_manager_tests.cpp |   21 +----
 8 files changed, 105 insertions(+), 198 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_tests.cpp b/src/tests/allocator_tests.cpp
index 8b868bc..52e2b03 100644
--- a/src/tests/allocator_tests.cpp
+++ b/src/tests/allocator_tests.cpp
@@ -666,15 +666,12 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
     .Times(AtMost(1));
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver2.stop();
   driver2.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
@@ -796,25 +793,20 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
   EXPECT_CALL(sched2, resourceOffers(_, OfferEq(2, 768)))
     .WillOnce(FutureSatisfy(&resourceOffers));
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver1.stop();
   driver1.join();
 
   AWAIT_READY(resourceOffers);
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver2.stop();
   driver2.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
@@ -881,9 +873,8 @@ TYPED_TEST(AllocatorTest, SlaveLost)
     .WillOnce(DoAll(InvokeSlaveRemoved(&this->allocator),
                     FutureSatisfy(&slaveRemoved)));
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   EXPECT_CALL(sched, slaveLost(_, _));
 
@@ -891,10 +882,6 @@ TYPED_TEST(AllocatorTest, SlaveLost)
 
   AWAIT_READY(slaveRemoved);
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
-  MockExecutor exec2(DEFAULT_EXECUTOR_ID);
-
   slave::Flags flags2 = this->CreateSlaveFlags();
   flags2.resources = Option<string>("cpus:3;mem:256");
 
@@ -907,7 +894,7 @@ TYPED_TEST(AllocatorTest, SlaveLost)
   EXPECT_CALL(sched, resourceOffers(_, OfferEq(3, 256)))
     .WillOnce(FutureSatisfy(&resourceOffers));
 
-  Try<PID<Slave> > slave2 = this->StartSlave(&exec2, flags2);
+  Try<PID<Slave> > slave2 = this->StartSlave(flags2);
   ASSERT_SOME(slave2);
 
   AWAIT_READY(resourceOffers);
@@ -922,14 +909,9 @@ TYPED_TEST(AllocatorTest, SlaveLost)
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
     .Times(AtMost(1));
 
-  EXPECT_CALL(exec2, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
-
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
@@ -1025,15 +1007,12 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
     .Times(AtMost(1));
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(2));
 
@@ -1135,15 +1114,12 @@ TYPED_TEST(AllocatorTest, TaskFinished)
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
     .Times(AtMost(1));
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/allocator_zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_zookeeper_tests.cpp b/src/tests/allocator_zookeeper_tests.cpp
index 31f4dc6..1034d72 100644
--- a/src/tests/allocator_zookeeper_tests.cpp
+++ b/src/tests/allocator_zookeeper_tests.cpp
@@ -121,47 +121,28 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
   MesosSchedulerDriver driver(
       &sched, DEFAULT_FRAMEWORK_INFO, stringify(this->url.get()));
 
-  Future<Nothing> registered;
-  EXPECT_CALL(sched, registered(&driver, _, _))
-    .WillOnce(FutureSatisfy(&registered));
+  EXPECT_CALL(sched, registered(&driver, _, _));
 
-  Future<vector<Offer> > resourceOffers1;
-  EXPECT_CALL(sched, resourceOffers(&driver, _))
-    .WillOnce(DoAll(LaunchTasks(1, 1, 500),
-                    FutureArg<1>(&resourceOffers1)))
+  // The framework should be offered all of the resources on the slave
+  // since it is the only framework running.
+  EXPECT_CALL(sched, resourceOffers(&driver, OfferEq(2, 1024)))
+    .WillOnce(LaunchTasks(1, 1, 500))
     .WillRepeatedly(DeclineOffers());
 
-  Future<TaskStatus> statusUpdate;
-  EXPECT_CALL(sched, statusUpdate(&driver, _))
-    .WillOnce(FutureArg<1>(&statusUpdate));
-
-  EXPECT_CALL(sched, disconnected(_))
-    .WillRepeatedly(DoDefault());
-
   EXPECT_CALL(exec, registered(_, _, _, _));
 
   EXPECT_CALL(exec, launchTask(_, _))
     .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
 
-  EXPECT_CALL(exec, disconnected(_))
-    .WillRepeatedly(DoDefault());
-
-  EXPECT_CALL(exec, shutdown(_))
-    .WillRepeatedly(DoDefault());
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
 
   driver.start();
 
-  AWAIT_READY(registered);
+  AWAIT_READY(status);
 
-  AWAIT_READY(resourceOffers1);
-
-  // The framework will be offered all of the resources on the slave,
-  // since it is the only framework running.
-  EXPECT_THAT(resourceOffers1.get(), OfferEq(2, 1024));
-
-  AWAIT_READY(statusUpdate);
-
-  EXPECT_EQ(TASK_RUNNING, statusUpdate.get().state());
+  EXPECT_EQ(TASK_RUNNING, status.get().state());
 
   // Stop the failing master from telling the slave to shut down when
   // it is killed.
@@ -172,6 +153,16 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
   // framework has reregistered.
   DROP_PROTOBUFS(ReregisterSlaveMessage(), _, _);
 
+  // Shutting down the masters will cause the scheduler to get
+  // disconnected.
+  EXPECT_CALL(sched, disconnected(_));
+
+  // Shutting down the masters will also cause the slave to shutdown
+  // frameworks that are not checkpointing, thus causing the executor
+  // to get shutdown.
+  EXPECT_CALL(exec, shutdown(_))
+    .Times(AtMost(1));
+
   this->ShutdownMasters();
 
   AWAIT_READY(shutdownMessage);
@@ -213,20 +204,15 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
   EXPECT_CALL(allocator2, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(allocator2, frameworkDeactivated(_));
+  EXPECT_CALL(allocator2, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(allocator2, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
-
-  EXPECT_CALL(exec, shutdown(_))
     .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(frameworkRemoved);
-
   EXPECT_CALL(allocator2, slaveRemoved(_))
     .Times(AtMost(1));
 
@@ -257,47 +243,28 @@ TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
   MesosSchedulerDriver driver(
       &sched, DEFAULT_FRAMEWORK_INFO, stringify(this->url.get()));
 
-  Future<Nothing> registered;
-  EXPECT_CALL(sched, registered(&driver, _, _))
-    .WillOnce(FutureSatisfy(&registered));
+  EXPECT_CALL(sched, registered(&driver, _, _));
 
-  Future<vector<Offer> > resourceOffers1;
-  EXPECT_CALL(sched, resourceOffers(&driver, _))
-    .WillOnce(DoAll(LaunchTasks(1, 1, 500),
-                    FutureArg<1>(&resourceOffers1)))
+  // The framework should be offered all of the resources on the slave
+  // since it is the only framework running.
+  EXPECT_CALL(sched, resourceOffers(&driver, OfferEq(2, 1024)))
+    .WillOnce(LaunchTasks(1, 1, 500))
     .WillRepeatedly(DeclineOffers());
 
-  Future<TaskStatus> statusUpdate;
-  EXPECT_CALL(sched, statusUpdate(&driver, _))
-    .WillOnce(FutureArg<1>(&statusUpdate));
-
-  EXPECT_CALL(sched, disconnected(_))
-    .WillRepeatedly(DoDefault());
-
   EXPECT_CALL(exec, registered(_, _, _, _));
 
   EXPECT_CALL(exec, launchTask(_, _))
     .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
 
-  EXPECT_CALL(exec, disconnected(_))
-    .WillRepeatedly(DoDefault());
-
-  EXPECT_CALL(exec, shutdown(_))
-    .WillRepeatedly(DoDefault());
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
 
   driver.start();
 
-  AWAIT_READY(registered);
+  AWAIT_READY(status);
 
-  AWAIT_READY(resourceOffers1);
-
-  // The framework will be offered all of the resources on the slave,
-  // since it is the only framework running.
-  EXPECT_THAT(resourceOffers1.get(), OfferEq(2, 1024));
-
-  AWAIT_READY(statusUpdate);
-
-  EXPECT_EQ(TASK_RUNNING, statusUpdate.get().state());
+  EXPECT_EQ(TASK_RUNNING, status.get().state());
 
   // Stop the failing master from telling the slave to shut down when
   // it is killed.
@@ -308,6 +275,16 @@ TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
   // slave has reregistered.
   DROP_PROTOBUFS(ReregisterFrameworkMessage(), _, _);
 
+  // Shutting down the masters will cause the scheduler to get
+  // disconnected.
+  EXPECT_CALL(sched, disconnected(_));
+
+  // Shutting down the masters will also cause the slave to shutdown
+  // frameworks that are not checkpointing, thus causing the executor
+  // to get shutdown.
+  EXPECT_CALL(exec, shutdown(_))
+    .Times(AtMost(1));
+
   this->ShutdownMasters();
 
   AWAIT_READY(shutdownMessage);
@@ -349,20 +326,15 @@ TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
   EXPECT_CALL(allocator2, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(allocator2, frameworkDeactivated(_));
+  EXPECT_CALL(allocator2, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(allocator2, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
-
-  EXPECT_CALL(exec, shutdown(_))
     .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(frameworkRemoved);
-
   EXPECT_CALL(allocator2, slaveRemoved(_))
     .Times(AtMost(1));
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/fault_tolerance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/fault_tolerance_tests.cpp b/src/tests/fault_tolerance_tests.cpp
index 287453d..c8fad7c 100644
--- a/src/tests/fault_tolerance_tests.cpp
+++ b/src/tests/fault_tolerance_tests.cpp
@@ -274,7 +274,7 @@ TEST_F(FaultToleranceTest, PartitionedSlaveReregistration)
   // Drop the first shutdown message from the master (simulated
   // partition), allow the second shutdown message to pass when
   // the slave re-registers.
-  Future<ShutdownMessage> shutdownSlave =
+  Future<ShutdownMessage> shutdownMessage =
     DROP_PROTOBUF(ShutdownMessage(), _, slave.get());
 
   Future<TaskStatus> lostStatus;
@@ -309,7 +309,7 @@ TEST_F(FaultToleranceTest, PartitionedSlaveReregistration)
   EXPECT_EQ(TASK_LOST, lostStatus.get().state());
 
   // Wait for the master to attempt to shut down the slave.
-  AWAIT_READY(shutdownSlave);
+  AWAIT_READY(shutdownMessage);
 
   // The master will notify the framework that the slave was lost.
   AWAIT_READY(slaveLost);
@@ -319,11 +319,11 @@ TEST_F(FaultToleranceTest, PartitionedSlaveReregistration)
   // normally occur during a network partition.
   process::post(slave.get(), NoMasterDetectedMessage());
 
-  Future<Nothing> shutdownExecutor;
+  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdownExecutor));
+    .WillOnce(FutureSatisfy(&shutdown));
 
-  shutdownSlave = FUTURE_PROTOBUF(ShutdownMessage(), _, slave.get());
+  shutdownMessage = FUTURE_PROTOBUF(ShutdownMessage(), _, slave.get());
 
   // Have the slave re-register with the master.
   NewMasterDetectedMessage newMasterDetectedMessage;
@@ -332,8 +332,8 @@ TEST_F(FaultToleranceTest, PartitionedSlaveReregistration)
 
   // Upon re-registration, the master will shutdown the slave.
   // The slave will then shut down the executor.
-  AWAIT_READY(shutdownSlave);
-  AWAIT_READY(shutdownExecutor);
+  AWAIT_READY(shutdownMessage);
+  AWAIT_READY(shutdown);
 
   Clock::resume();
 
@@ -392,7 +392,7 @@ TEST_F(FaultToleranceTest, PartitionedSlaveStatusUpdates)
   // Drop the first shutdown message from the master (simulated
   // partition), allow the second shutdown message to pass when
   // the slave sends an update.
-  Future<ShutdownMessage> shutdownSlave =
+  Future<ShutdownMessage> shutdownMessage =
     DROP_PROTOBUF(ShutdownMessage(), _, slave.get());
 
   EXPECT_CALL(sched, offerRescinded(&driver, _))
@@ -422,12 +422,12 @@ TEST_F(FaultToleranceTest, PartitionedSlaveStatusUpdates)
   Clock::settle();
 
   // Wait for the master to attempt to shut down the slave.
-  AWAIT_READY(shutdownSlave);
+  AWAIT_READY(shutdownMessage);
 
   // The master will notify the framework that the slave was lost.
   AWAIT_READY(slaveLost);
 
-  shutdownSlave = FUTURE_PROTOBUF(ShutdownMessage(), _, slave.get());
+  shutdownMessage = FUTURE_PROTOBUF(ShutdownMessage(), _, slave.get());
 
   // At this point, the slave still thinks it's registered, so we
   // simulate a status update coming from the slave.
@@ -445,7 +445,7 @@ TEST_F(FaultToleranceTest, PartitionedSlaveStatusUpdates)
   process::post(master.get(), statusUpdate);
 
   // The master should shutdown the slave upon receiving the update.
-  AWAIT_READY(shutdownSlave);
+  AWAIT_READY(shutdownMessage);
 
   Clock::resume();
 
@@ -519,6 +519,7 @@ TEST_F(FaultToleranceTest, PartitionedSlaveExitedExecutor)
 
   // Set up the expectations for launching the task.
   EXPECT_CALL(exec, registered(_, _, _, _));
+
   EXPECT_CALL(exec, launchTask(_, _))
     .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
 
@@ -532,7 +533,7 @@ TEST_F(FaultToleranceTest, PartitionedSlaveExitedExecutor)
   // Drop the first shutdown message from the master (simulated
   // partition) and allow the second shutdown message to pass when
   // triggered by the ExitedExecutorMessage.
-  Future<ShutdownMessage> shutdownSlave =
+  Future<ShutdownMessage> shutdownMessage =
     DROP_PROTOBUF(ShutdownMessage(), _, slave.get());
 
   Future<TaskStatus> lostStatus;
@@ -567,12 +568,12 @@ TEST_F(FaultToleranceTest, PartitionedSlaveExitedExecutor)
   EXPECT_EQ(TASK_LOST, lostStatus.get().state());
 
   // Wait for the master to attempt to shut down the slave.
-  AWAIT_READY(shutdownSlave);
+  AWAIT_READY(shutdownMessage);
 
   // The master will notify the framework that the slave was lost.
   AWAIT_READY(slaveLost);
 
-  shutdownSlave = FUTURE_PROTOBUF(ShutdownMessage(), _, slave.get());
+  shutdownMessage = FUTURE_PROTOBUF(ShutdownMessage(), _, slave.get());
 
   // Induce an ExitedExecutorMessage from the slave.
   dispatch(isolator,
@@ -581,7 +582,7 @@ TEST_F(FaultToleranceTest, PartitionedSlaveExitedExecutor)
            DEFAULT_EXECUTOR_INFO.executor_id());
 
   // Upon receiving the message, the master will shutdown the slave.
-  AWAIT_READY(shutdownSlave);
+  AWAIT_READY(shutdownMessage);
 
   Clock::resume();
 
@@ -964,9 +965,8 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
 
   AWAIT_READY(statusUpdate);
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver1.stop();
   driver2.stop();
@@ -974,8 +974,6 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
   driver1.join();
   driver2.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 
   Clock::resume();
@@ -1052,15 +1050,12 @@ TEST_F(FaultToleranceTest, ForwardStatusUpdateUnknownExecutor)
   EXPECT_EQ(taskId, status.get().task_id());
   EXPECT_EQ(TASK_RUNNING, status.get().state());
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 }
 
@@ -1144,9 +1139,8 @@ TEST_F(FaultToleranceTest, SchedulerFailoverFrameworkMessage)
 
   AWAIT_READY(frameworkMessage);
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver1.stop();
   driver2.stop();
@@ -1154,8 +1148,6 @@ TEST_F(FaultToleranceTest, SchedulerFailoverFrameworkMessage)
   driver1.join();
   driver2.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 }
 
@@ -1212,15 +1204,12 @@ TEST_F(FaultToleranceTest, SchedulerExit)
   AWAIT_READY(status);
   EXPECT_EQ(TASK_RUNNING, status.get().state());
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown);
-
   Shutdown();
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/gc_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/gc_tests.cpp b/src/tests/gc_tests.cpp
index 43c3e5d..1745800 100644
--- a/src/tests/gc_tests.cpp
+++ b/src/tests/gc_tests.cpp
@@ -313,9 +313,8 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
 
   Clock::pause();
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   EXPECT_CALL(sched, statusUpdate(_, _))
     .Times(AtMost(1)); // Ignore TASK_LOST from killed executor.
@@ -326,8 +325,6 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
 
   Stop(slave.get());
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   AWAIT_READY(slaveLost);
 
   Future<Nothing> schedule =
@@ -727,21 +724,22 @@ TEST_F(GarbageCollectorIntegrationTest, Unschedule)
   Future<Nothing> unscheduleFrameworkWork =
     FUTURE_DISPATCH(_, &GarbageCollectorProcess::unschedule);
 
-  // Launch the next run of the executor on the receipt of next offer.
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(LaunchTasks(1, cpus, mem));
+  // We ask the isolator to kill the exector below.
+  EXPECT_CALL(exec, shutdown(_))
+    .Times(AtMost(1));
 
   EXPECT_CALL(sched, statusUpdate(_, _))
-    .WillRepeatedly(Return());            // Ignore subsequent updates.
+    .Times(AtMost(2)); // Once for a TASK_LOST then once for TASK_RUNNING.
+
+  // We use the killed executor/tasks resources to run another task.
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillOnce(LaunchTasks(1, cpus, mem));
 
   EXPECT_CALL(exec, registered(_, _, _, _));
 
   EXPECT_CALL(exec, launchTask(_, _))
     .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
 
-  EXPECT_CALL(exec, shutdown(_))
-    .WillRepeatedly(Return());
-
   Clock::pause();
 
   // Kill the first executor.

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/isolator.hpp
----------------------------------------------------------------------
diff --git a/src/tests/isolator.hpp b/src/tests/isolator.hpp
index ebfc485..fe6b38d 100644
--- a/src/tests/isolator.hpp
+++ b/src/tests/isolator.hpp
@@ -67,7 +67,15 @@ public:
     setup();
   }
 
-  virtual ~TestingIsolator() {}
+  virtual ~TestingIsolator()
+  {
+    foreachvalue (MesosExecutorDriver* driver, drivers) {
+      driver->stop();
+      driver->join();
+      delete driver;
+    }
+    drivers.clear();
+  }
 
   virtual void initialize(
       const slave::Flags& flags,

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/master_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_tests.cpp b/src/tests/master_tests.cpp
index 1d26eeb..5ac4d5f 100644
--- a/src/tests/master_tests.cpp
+++ b/src/tests/master_tests.cpp
@@ -134,15 +134,12 @@ TEST_F(MasterTest, TaskRunning)
 
   AWAIT_READY(resourcesChanged);
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
@@ -209,15 +206,12 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
 
   AWAIT_READY(resourcesChanged);
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
@@ -287,15 +281,12 @@ TEST_F(MasterTest, KillTask)
   AWAIT_READY(status);
   EXPECT_EQ(TASK_KILLED, status.get().state());
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // To ensure can deallocate MockExecutor.
-
   Shutdown();
 }
 
@@ -357,15 +348,12 @@ TEST_F(MasterTest, StatusUpdateAck)
   // Ensure the slave gets a status update ACK.
   AWAIT_READY(acknowledgement);
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 }
 
@@ -465,6 +453,9 @@ TEST_F(MasterTest, RecoverResources)
   EXPECT_CALL(sched, resourceOffers(&driver, _))
     .WillOnce(FutureArg<1>(&offers));
 
+  EXPECT_CALL(exec, shutdown(_))
+    .Times(AtMost(1));
+
   // Now kill the executor, scheduler should get an offer it's resources.
   // TODO(benh): WTF? Why aren't we dispatching?
   isolator.killExecutor(offer.framework_id(), executorInfo.executor_id());
@@ -482,11 +473,6 @@ TEST_F(MasterTest, RecoverResources)
   driver.stop();
   driver.join();
 
-  // Terminating the slave might cause the mock executor to get a
-  // shutdown since the executor driver "links" the slave.
-  EXPECT_CALL(exec, shutdown(_))
-    .Times(AtMost(1));
-
   Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
@@ -562,15 +548,12 @@ TEST_F(MasterTest, FrameworkMessage)
   AWAIT_READY(schedData);
   EXPECT_EQ("world", schedData.get());
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   schedDriver.stop();
   schedDriver.join();
 
-  AWAIT_READY(shutdown); // To ensure can deallocate MockExecutor.
-
   Shutdown();
 }
 
@@ -673,20 +656,15 @@ TEST_F(MasterTest, MultipleExecutors)
   AWAIT_READY(status2);
   EXPECT_EQ(TASK_RUNNING, status2.get().state());
 
-  Future<Nothing> shutdown1;
   EXPECT_CALL(exec1, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown1));
+    .Times(AtMost(1));
 
-  Future<Nothing> shutdown2;
   EXPECT_CALL(exec2, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown2));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown1); // To ensure can deallocate MockExecutor.
-  AWAIT_READY(shutdown2); // To ensure can deallocate MockExecutor.
-
   Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/resource_offers_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/resource_offers_tests.cpp b/src/tests/resource_offers_tests.cpp
index e030d3d..b066403 100644
--- a/src/tests/resource_offers_tests.cpp
+++ b/src/tests/resource_offers_tests.cpp
@@ -573,14 +573,11 @@ TEST_F(MultipleExecutorsTest, TasksExecutorInfoDiffers)
             " with same ExecutorID is not compatible)",
             status.get().message());
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // To ensure can deallocate MockExecutor.
-
   Shutdown();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bc9cb875/src/tests/status_update_manager_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/status_update_manager_tests.cpp b/src/tests/status_update_manager_tests.cpp
index 892a3f1..61ccfcc 100644
--- a/src/tests/status_update_manager_tests.cpp
+++ b/src/tests/status_update_manager_tests.cpp
@@ -64,6 +64,7 @@ using std::string;
 using std::vector;
 
 using testing::_;
+using testing::AtMost;
 using testing::Return;
 using testing::SaveArg;
 
@@ -176,15 +177,12 @@ TEST_F(StatusUpdateManagerTest, CheckpointStatusUpdate)
 
   close(fd.get());
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillRepeatedly(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 }
 
@@ -249,15 +247,12 @@ TEST_F(StatusUpdateManagerTest, RetryStatusUpdate)
 
   Clock::resume();
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillRepeatedly(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 }
 
@@ -369,15 +364,12 @@ TEST_F(StatusUpdateManagerTest, IgnoreDuplicateStatusUpdateAck)
 
   Clock::resume();
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillRepeatedly(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 }
 
@@ -464,14 +456,11 @@ TEST_F(StatusUpdateManagerTest, IgnoreUnexpectedStatusUpdateAck)
   // it is 'false'.
   AWAIT_READY(unexpectedAck);
 
-  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillRepeatedly(FutureSatisfy(&shutdown));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
-
   Shutdown();
 }


[06/28] git commit: Made tests flags inherit from logging.

Posted by be...@apache.org.
Made tests flags inherit from logging.

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


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

Branch: refs/heads/master
Commit: 6f6ca8767fe054fda167135711aeb0801ae50218
Parents: 0ebf393
Author: Benjamin Hindman <be...@twitter.com>
Authored: Fri Apr 26 17:17:42 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/Makefile.am     |    1 +
 src/tests/flags.cpp |   30 ++++++++++++++++++++++++++++++
 src/tests/flags.hpp |    5 ++++-
 src/tests/utils.cpp |    4 ----
 src/tests/utils.hpp |    4 ----
 5 files changed, 35 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6f6ca876/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 22346f3..5ed3423 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -769,6 +769,7 @@ check_PROGRAMS += mesos-tests
 
 mesos_tests_SOURCES = tests/main.cpp tests/utils.cpp			\
 	              tests/environment.cpp				\
+	              tests/flags.cpp					\
 	              tests/master_tests.cpp tests/state_tests.cpp	\
 	              tests/paths_tests.cpp				\
 	              tests/reaper_tests.cpp				\

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6f6ca876/src/tests/flags.cpp
----------------------------------------------------------------------
diff --git a/src/tests/flags.cpp b/src/tests/flags.cpp
new file mode 100644
index 0000000..98b780f
--- /dev/null
+++ b/src/tests/flags.cpp
@@ -0,0 +1,30 @@
+/**
+ * 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 "tests/flags.hpp"
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+// Storage for the flags.
+Flags flags;
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6f6ca876/src/tests/flags.hpp
----------------------------------------------------------------------
diff --git a/src/tests/flags.hpp b/src/tests/flags.hpp
index 9a4ebd6..6ba5eca 100644
--- a/src/tests/flags.hpp
+++ b/src/tests/flags.hpp
@@ -31,7 +31,7 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
-class Flags : public virtual flags::FlagsBase
+class Flags : public logging::Flags
 {
 public:
   Flags()
@@ -67,6 +67,9 @@ public:
   std::string build_dir;
 };
 
+// Global flags for running the tests.
+extern Flags flags;
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6f6ca876/src/tests/utils.cpp
----------------------------------------------------------------------
diff --git a/src/tests/utils.cpp b/src/tests/utils.cpp
index 9d1d5ad..0bb1536 100644
--- a/src/tests/utils.cpp
+++ b/src/tests/utils.cpp
@@ -35,10 +35,6 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
-// Storage for our flags.
-flags::Flags<logging::Flags, Flags> flags;
-
-
 Try<string> mkdtemp()
 {
   const ::testing::TestInfo* const testInfo =

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6f6ca876/src/tests/utils.hpp
----------------------------------------------------------------------
diff --git a/src/tests/utils.hpp b/src/tests/utils.hpp
index ca3ecd7..2e47734 100644
--- a/src/tests/utils.hpp
+++ b/src/tests/utils.hpp
@@ -79,10 +79,6 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
-// Flags used to run the tests.
-extern flags::Flags<logging::Flags, Flags> flags;
-
-
 #ifdef __linux__
 // Cgroups hierarchy used by the cgroups related tests.
 const static std::string TEST_CGROUPS_HIERARCHY = "/tmp/mesos_test_cgroup";


[02/28] git commit: Removed unnecessary use of Option.

Posted by be...@apache.org.
Removed unnecessary use of Option.

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


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

Branch: refs/heads/master
Commit: 39ce99efa04f94b3cc514f445d69a53922bf1186
Parents: f5be413
Author: Benjamin Hindman <be...@twitter.com>
Authored: Thu Apr 25 18:32:37 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/tests/allocator_zookeeper_tests.cpp |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/39ce99ef/src/tests/allocator_zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_zookeeper_tests.cpp b/src/tests/allocator_zookeeper_tests.cpp
index 39b4627..bb7f84d 100644
--- a/src/tests/allocator_zookeeper_tests.cpp
+++ b/src/tests/allocator_zookeeper_tests.cpp
@@ -100,7 +100,7 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
   Try<zookeeper::URL> url = zookeeper::URL::parse(zk);
   ASSERT_SOME(url);
 
-  Cluster cluster(Option<zookeeper::URL>(url.get()));
+  Cluster cluster(url.get());
 
   Try<PID<Master> > master = cluster.masters.start(&this->allocator1);
   ASSERT_SOME(master);
@@ -237,7 +237,7 @@ TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
   Try<zookeeper::URL> url = zookeeper::URL::parse(zk);
   ASSERT_SOME(url);
 
-  Cluster cluster(Option<zookeeper::URL>(url.get()));
+  Cluster cluster(url.get());
 
   Try<PID<Master> > master = cluster.masters.start(&this->allocator1);
   ASSERT_SOME(master);


[12/28] git commit: Refactored MesosTest/MesosClusterTest into a generic fixture for launching in-memory Mesos clusters and updated all tests appropriately.

Posted by be...@apache.org.
Refactored MesosTest/MesosClusterTest into a generic fixture for
launching in-memory Mesos clusters and updated all tests
appropriately.

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


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

Branch: refs/heads/master
Commit: 6b1b82085a6049944cb3342a415829fe3d0e9320
Parents: b553a07
Author: Benjamin Hindman <be...@twitter.com>
Authored: Wed Apr 24 22:06:48 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:35 2013 -0700

----------------------------------------------------------------------
 src/Makefile.am                               |    2 +
 src/master/hierarchical_allocator_process.hpp |    2 +-
 src/tests/allocator_tests.cpp                 |  166 +++---
 src/tests/allocator_zookeeper_tests.cpp       |  151 +++--
 src/tests/cgroups_tests.cpp                   |    5 +-
 src/tests/cluster.hpp                         |  247 ++------
 src/tests/configurator_tests.cpp              |   12 +-
 src/tests/exception_tests.cpp                 |   16 +-
 src/tests/fault_tolerance_tests.cpp           |  301 +++------
 src/tests/files_tests.cpp                     |    2 +
 src/tests/flags_tests.cpp                     |    3 +-
 src/tests/gc_tests.cpp                        |   88 ++-
 src/tests/group_tests.cpp                     |    3 +-
 src/tests/isolator.hpp                        |    9 +
 src/tests/isolator_tests.cpp                  |   62 +-
 src/tests/log_tests.cpp                       |    5 +-
 src/tests/logging_tests.cpp                   |    5 +-
 src/tests/main.cpp                            |    3 +-
 src/tests/master_detector_tests.cpp           |   17 +-
 src/tests/master_tests.cpp                    |  120 ++--
 src/tests/mesos.cpp                           |  240 +++++++
 src/tests/mesos.hpp                           |  676 ++++++++++++++++++
 src/tests/monitor_tests.cpp                   |    7 +-
 src/tests/paths_tests.cpp                     |    2 -
 src/tests/protobuf_io_tests.cpp               |    3 +-
 src/tests/reaper_tests.cpp                    |   15 +-
 src/tests/resource_offers_tests.cpp           |   24 +-
 src/tests/script.cpp                          |    4 +-
 src/tests/slave_recovery_tests.cpp            |  335 ++++++----
 src/tests/state_tests.cpp                     |    3 +-
 src/tests/status_update_manager_tests.cpp     |   52 +-
 src/tests/utils.cpp                           |    1 +
 src/tests/utils.hpp                           |  727 +-------------------
 src/tests/zookeeper.cpp                       |    2 +-
 src/tests/zookeeper.hpp                       |   10 +-
 src/tests/zookeeper_tests.cpp                 |    3 +-
 src/zookeeper/authentication.hpp              |   19 +-
 src/zookeeper/url.hpp                         |    9 +
 38 files changed, 1719 insertions(+), 1632 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index bc0c5c6..0f7794e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -233,6 +233,7 @@ libmesos_no_third_party_la_SOURCES += common/attributes.hpp		\
 	tests/zookeeper.hpp tests/flags.hpp tests/utils.hpp		\
 	tests/cluster.hpp						\
 	tests/isolator.hpp						\
+	tests/mesos.hpp							\
 	tests/zookeeper_test_server.hpp zookeeper/authentication.hpp	\
 	zookeeper/group.hpp zookeeper/watcher.hpp			\
 	zookeeper/zookeeper.hpp zookeeper/url.hpp
@@ -780,6 +781,7 @@ check_PROGRAMS += mesos-tests
 mesos_tests_SOURCES = tests/main.cpp tests/utils.cpp			\
 	              tests/environment.cpp				\
 	              tests/flags.cpp					\
+	              tests/mesos.cpp					\
 	              tests/master_tests.cpp tests/state_tests.cpp	\
 	              tests/paths_tests.cpp				\
 	              tests/reaper_tests.cpp				\

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/master/hierarchical_allocator_process.hpp
----------------------------------------------------------------------
diff --git a/src/master/hierarchical_allocator_process.hpp b/src/master/hierarchical_allocator_process.hpp
index f4afb71..ebd97e4 100644
--- a/src/master/hierarchical_allocator_process.hpp
+++ b/src/master/hierarchical_allocator_process.hpp
@@ -30,6 +30,7 @@
 #include "common/resources.hpp"
 
 #include "master/allocator.hpp"
+#include "master/drf_sorter.hpp"
 #include "master/master.hpp"
 #include "master/sorter.hpp"
 
@@ -38,7 +39,6 @@ namespace internal {
 namespace master {
 
 // Forward declarations.
-class DRFSorter;
 class Filter;
 
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_tests.cpp b/src/tests/allocator_tests.cpp
index 540c05a..5a0de33 100644
--- a/src/tests/allocator_tests.cpp
+++ b/src/tests/allocator_tests.cpp
@@ -34,8 +34,8 @@
 #include "master/hierarchical_allocator_process.hpp"
 #include "master/master.hpp"
 
-#include "tests/cluster.hpp"
-#include "tests/utils.hpp"
+#include "tests/isolator.hpp"
+#include "tests/mesos.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;
@@ -66,7 +66,7 @@ using testing::Return;
 using testing::SaveArg;
 
 
-class DRFAllocatorTest : public MesosClusterTest {};
+class DRFAllocatorTest : public MesosTest {};
 
 
 // Checks that the DRF allocator implements the DRF algorithm
@@ -82,16 +82,15 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
 
   EXPECT_CALL(allocator, initialize(_, _));
 
-  Try<PID<Master> > master = cluster.masters.start(&allocator);
+  Try<PID<Master> > master = StartMaster(&allocator);
   ASSERT_SOME(master);
 
-  TestingIsolator isolator1;
-  slave::Flags flags1 = cluster.slaves.flags;
+  slave::Flags flags1 = CreateSlaveFlags();
   flags1.resources = Option<string>("cpus:2;mem:1024;disk:0");
 
   EXPECT_CALL(allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave1 = cluster.slaves.start(flags1, &isolator1);
+  Try<PID<Slave> > slave1 = StartSlave(flags1);
   ASSERT_SOME(slave1);
   // Total cluster resources now cpus=2, mem=1024.
 
@@ -135,8 +134,7 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
 
   AWAIT_READY(frameworkAdded2);
 
-  TestingIsolator isolator2;
-  slave::Flags flags2 = cluster.slaves.flags;
+  slave::Flags flags2 = CreateSlaveFlags();
   flags2.resources = Option<string>("cpus:1;mem:512;disk:0");
 
   EXPECT_CALL(allocator, slaveAdded(_, _, _));
@@ -145,7 +143,7 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
   EXPECT_CALL(sched2, resourceOffers(_, _))
     .WillOnce(FutureArg<1>(&offers2));
 
-  Try<PID<Slave> > slave2 = cluster.slaves.start(flags2, &isolator2);
+  Try<PID<Slave> > slave2 = StartSlave(flags2);
   ASSERT_SOME(slave2);
   // Total cluster resources now cpus=3, mem=1536.
   // framework1 share = 0.66
@@ -159,8 +157,7 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
   // framework1 share =  0.66
   // framework2 share = 0.33
 
-  TestingIsolator isolator3;
-  slave::Flags flags3 = cluster.slaves.flags;
+  slave::Flags flags3 = CreateSlaveFlags();
   flags3.resources = Option<string>("cpus:3;mem:2048;disk:0");
 
   EXPECT_CALL(allocator, slaveAdded(_, _, _));
@@ -169,7 +166,7 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
   EXPECT_CALL(sched2, resourceOffers(_, _))
     .WillOnce(FutureArg<1>(&offers3));
 
-  Try<PID<Slave> > slave3 = cluster.slaves.start(flags3, &isolator3);
+  Try<PID<Slave> > slave3 = StartSlave(flags3);
   ASSERT_SOME(slave3);
   // Total cluster resources now cpus=6, mem=3584.
   // framework1 share = 0.33
@@ -200,8 +197,7 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
 
   AWAIT_READY(frameworkAdded3);
 
-  TestingIsolator isolator4;
-  slave::Flags flags4 = cluster.slaves.flags;
+  slave::Flags flags4 = CreateSlaveFlags();
   flags4.resources = Option<string>("cpus:4;mem:4096;disk:0");
 
   EXPECT_CALL(allocator, slaveAdded(_, _, _));
@@ -210,7 +206,7 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
   EXPECT_CALL(sched3, resourceOffers(_, _))
     .WillOnce(FutureArg<1>(&offers4));
 
-  Try<PID<Slave> > slave4 = cluster.slaves.start(flags4, &isolator4);
+  Try<PID<Slave> > slave4 = StartSlave(flags4);
   ASSERT_SOME(slave4);
   // Total cluster resources now cpus=10, mem=7680.
   // framework1 share = 0.2
@@ -240,17 +236,17 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
   driver2.stop();
   driver3.stop();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 template <typename T>
-class AllocatorTest : public MesosClusterTest
+class AllocatorTest : public MesosTest
 {
 protected:
   virtual void SetUp()
   {
-    MesosClusterTest::SetUp();
+    MesosTest::SetUp();
     a = new Allocator(&allocator);
   }
 
@@ -258,7 +254,7 @@ protected:
   virtual void TearDown()
   {
     delete a;
-    MesosClusterTest::TearDown();
+    MesosTest::TearDown();
   }
 
   MockAllocatorProcess<T> allocator;
@@ -277,17 +273,15 @@ TYPED_TEST(AllocatorTest, MockAllocator)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags = this->cluster.slaves.flags;
+  slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:2;mem:1024;disk:0");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = this->StartSlave(flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -327,11 +321,11 @@ TYPED_TEST(AllocatorTest, MockAllocator)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .WillOnce(FutureSatisfy(&slaveRemoved));
 
-  this->cluster.slaves.shutdown();
+  this->ShutdownSlaves();
 
   AWAIT_READY(slaveRemoved);
 
-  this->cluster.masters.shutdown();
+  this->ShutdownMasters();
 }
 
 
@@ -342,17 +336,17 @@ TYPED_TEST(AllocatorTest, ResourcesUnused)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags1 = this->cluster.slaves.flags;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  slave::Flags flags1 = this->CreateSlaveFlags();
   flags1.resources = Option<string>("cpus:2;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave1 = this->cluster.slaves.start(flags1, &isolator);
+  Try<PID<Slave> > slave1 = this->StartSlave(&exec, flags1);
   ASSERT_SOME(slave1);
 
   MockScheduler sched1;
@@ -431,7 +425,7 @@ TYPED_TEST(AllocatorTest, ResourcesUnused)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -442,16 +436,15 @@ TYPED_TEST(AllocatorTest, OutOfOrderDispatch)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator);
   ASSERT_SOME(master);
 
-  TestingIsolator isolator;
-  slave::Flags flags1 = this->cluster.slaves.flags;
+  slave::Flags flags1 = this->CreateSlaveFlags();
   flags1.resources = Option<string>("cpus:2;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave1 = this->cluster.slaves.start(flags1, &isolator);
+  Try<PID<Slave> > slave1 = this->StartSlave(flags1);
   ASSERT_SOME(slave1);
 
   FrameworkInfo frameworkInfo1;
@@ -553,7 +546,7 @@ TYPED_TEST(AllocatorTest, OutOfOrderDispatch)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -564,17 +557,18 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags = this->cluster.slaves.flags;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
+
+  slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:3;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo1;
@@ -680,7 +674,7 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -690,12 +684,12 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  master::Flags masterFlags = this->cluster.masters.flags;
+  master::Flags masterFlags = this->CreateMasterFlags();
   masterFlags.allocation_interval = Duration::parse("50ms").get();
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator, masterFlags);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
   EXPECT_CALL(exec, registered(_, _, _, _))
     .Times(2);
 
@@ -707,8 +701,9 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
   EXPECT_CALL(exec, shutdown(_))
     .Times(AtMost(2));
 
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags = this->cluster.slaves.flags;
+  TestingIsolator isolator(&exec);
+
+  slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:3;mem:1024");
 
   EXPECT_CALL(isolator, resourcesChanged(_, _, _))
@@ -716,7 +711,7 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched1;
@@ -809,7 +804,7 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -821,17 +816,18 @@ TYPED_TEST(AllocatorTest, SlaveLost)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags1 = this->cluster.slaves.flags;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
+
+  slave::Flags flags1 = this->CreateSlaveFlags();
   flags1.resources = Option<string>("cpus:2;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave1 = this->cluster.slaves.start(flags1, &isolator);
+  Try<PID<Slave> > slave1 = this->StartSlave(&isolator, flags1);
   ASSERT_SOME(slave1);
 
   MockScheduler sched1;
@@ -887,15 +883,15 @@ TYPED_TEST(AllocatorTest, SlaveLost)
 
   EXPECT_CALL(sched1, slaveLost(_, _));
 
-  this->cluster.slaves.shutdown();
+  this->ShutdownSlaves();
 
   AWAIT_READY(slaveRemoved1);
 
   AWAIT_READY(shutdownCall);
 
-  MockExecutor exec2;
-  TestingIsolator isolator2(DEFAULT_EXECUTOR_ID, &exec2);
-  slave::Flags flags2 = this->cluster.slaves.flags;
+  MockExecutor exec2(DEFAULT_EXECUTOR_ID);
+
+  slave::Flags flags2 = this->CreateSlaveFlags();
   flags2.resources = Option<string>("cpus:3;mem:256");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
@@ -907,7 +903,7 @@ TYPED_TEST(AllocatorTest, SlaveLost)
   EXPECT_CALL(sched1, resourceOffers(_, OfferEq(3, 256)))
     .WillOnce(FutureArg<1>(&resourceOffers2));
 
-  Try<PID<Slave> > slave2 = this->cluster.slaves.start(flags2, &isolator2);
+  Try<PID<Slave> > slave2 = this->StartSlave(&exec2, flags2);
   ASSERT_SOME(slave2);
 
   AWAIT_READY(resourceOffers2);
@@ -935,7 +931,7 @@ TYPED_TEST(AllocatorTest, SlaveLost)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -946,19 +942,20 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  master::Flags masterFlags = this->cluster.masters.flags;
+  master::Flags masterFlags = this->CreateMasterFlags();
   masterFlags.allocation_interval = Duration::parse("50ms").get();
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator, masterFlags);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags1 = this->cluster.slaves.flags;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
+
+  slave::Flags flags1 = this->CreateSlaveFlags();
   flags1.resources = Option<string>("cpus:3;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave1 = this->cluster.slaves.start(flags1, &isolator);
+  Try<PID<Slave> > slave1 = this->StartSlave(&isolator, flags1);
   ASSERT_SOME(slave1);
 
   MockScheduler sched1;
@@ -1004,7 +1001,7 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
 
   AWAIT_READY(launchTask);
 
-  slave::Flags flags2 = this->cluster.slaves.flags;
+  slave::Flags flags2 = this->CreateSlaveFlags();
   flags2.resources = Option<string>("cpus:4;mem:2048");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
@@ -1016,7 +1013,7 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
   EXPECT_CALL(sched1, resourceOffers(_, OfferEq(5, 2560)))
     .WillOnce(FutureSatisfy(&resourceOffers2));
 
-  Try<PID<Slave> > slave2 = this->cluster.slaves.start(flags2, &isolator);
+  Try<PID<Slave> > slave2 = this->StartSlave(flags2);
   ASSERT_SOME(slave2);
 
   AWAIT_READY(resourceOffers2);
@@ -1042,7 +1039,7 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(2));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -1052,19 +1049,20 @@ TYPED_TEST(AllocatorTest, TaskFinished)
 {
   EXPECT_CALL(this->allocator, initialize(_, _));
 
-  master::Flags masterFlags = this->cluster.masters.flags;
+  master::Flags masterFlags = this->CreateMasterFlags();
   masterFlags.allocation_interval = Duration::parse("50ms").get();
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator, masterFlags);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags = this->cluster.slaves.flags;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
+
+  slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:3;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched1;
@@ -1156,7 +1154,7 @@ TYPED_TEST(AllocatorTest, TaskFinished)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -1170,7 +1168,7 @@ TYPED_TEST(AllocatorTest, WhitelistSlave)
   string path = "whitelist.txt";
   ASSERT_SOME(os::write(path, hosts)) << "Error writing whitelist";
 
-  master::Flags masterFlags = this->cluster.masters.flags;
+  master::Flags masterFlags = this->CreateMasterFlags();
   masterFlags.whitelist = "file://" + path; // TODO(benh): Put in /tmp.
 
   EXPECT_CALL(this->allocator, initialize(_, _));
@@ -1180,17 +1178,15 @@ TYPED_TEST(AllocatorTest, WhitelistSlave)
     .WillOnce(DoAll(InvokeUpdateWhitelist(&this->allocator),
                     FutureSatisfy(&updateWhitelist1)));
 
-  Try<PID<Master> > master = this->cluster.masters.start(&this->allocator, masterFlags);
+  Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags = this->cluster.slaves.flags;
+  slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:2;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = this->StartSlave(flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -1256,7 +1252,7 @@ TYPED_TEST(AllocatorTest, WhitelistSlave)
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
-  this->cluster.shutdown();
+  this->Shutdown();
 
   os::rm(path);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/allocator_zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_zookeeper_tests.cpp b/src/tests/allocator_zookeeper_tests.cpp
index d03a564..31f4dc6 100644
--- a/src/tests/allocator_zookeeper_tests.cpp
+++ b/src/tests/allocator_zookeeper_tests.cpp
@@ -22,16 +22,15 @@
 #include <process/gmock.hpp>
 #include <process/message.hpp>
 
-#include "detector/detector.hpp"
+#include <stout/option.hpp>
+#include <stout/try.hpp>
 
 #include "master/allocator.hpp"
 #include "master/master.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/mesos.hpp"
 #include "tests/zookeeper.hpp"
 
-#include "zookeeper/url.hpp"
-
 using namespace mesos;
 using namespace mesos::internal;
 using namespace mesos::internal::tests;
@@ -45,7 +44,6 @@ using mesos::internal::slave::Slave;
 using process::Future;
 using process::PID;
 
-using std::map;
 using std::string;
 using std::vector;
 
@@ -53,20 +51,49 @@ using testing::_;
 using testing::AtMost;
 using testing::DoAll;
 using testing::DoDefault;
-using testing::Eq;
-using testing::Return;
-using testing::SaveArg;
 
 
 template <typename T = AllocatorProcess>
-class AllocatorZooKeeperTest : public ZooKeeperTest
+class AllocatorZooKeeperTest : public MesosTest
 {
+public:
+  static void SetUpTestCase()
+  {
+    // Make sure the JVM is created.
+    ZooKeeperTest::SetUpTestCase();
+
+    // Launch the ZooKeeper test server.
+    server = new ZooKeeperTestServer();
+    server->startNetwork();
+
+    Try<zookeeper::URL> parse = zookeeper::URL::parse(
+        "zk://" + server->connectString() + "/znode");
+    ASSERT_SOME(parse);
+
+    url = parse.get();
+  }
+
+  static void TearDownTestCase()
+  {
+    delete server;
+    server = NULL;
+  }
+
 protected:
-  T allocator1;
-  MockAllocatorProcess<T> allocator2;
+  AllocatorZooKeeperTest() : MesosTest(url) {}
+
+  static ZooKeeperTestServer* server;
+  static Option<zookeeper::URL> url;
 };
 
 
+template <typename T>
+ZooKeeperTestServer* AllocatorZooKeeperTest<T>::server = NULL;
+
+template <typename T>
+Option<zookeeper::URL> AllocatorZooKeeperTest<T>::url;
+
+
 // Runs TYPED_TEST(AllocatorZooKeeperTest, ...) on all AllocatorTypes.
 TYPED_TEST_CASE(AllocatorZooKeeperTest, AllocatorTypes);
 
@@ -77,25 +104,22 @@ TYPED_TEST_CASE(AllocatorZooKeeperTest, AllocatorTypes);
 // accounted for correctly.
 TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
 {
-  string zk = "zk://" + this->server->connectString() + "/znode";
-  Try<zookeeper::URL> url = zookeeper::URL::parse(zk);
-  ASSERT_SOME(url);
+  TypeParam allocator1;
 
-  Cluster cluster(url.get());
-
-  Try<PID<Master> > master = cluster.masters.start(&this->allocator1);
+  Try<PID<Master> > master = this->StartMaster(&allocator1);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags = cluster.slaves.flags;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:2;mem:1024");
 
-  Try<PID<Slave> > slave = cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = this->StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, zk);
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, stringify(this->url.get()));
 
   Future<Nothing> registered;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -141,32 +165,34 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
 
   // Stop the failing master from telling the slave to shut down when
   // it is killed.
-  Future<process::Message> shutdownMsg =
-    DROP_MESSAGE(Eq(ShutdownMessage().GetTypeName()), _, _);
+  Future<ShutdownMessage> shutdownMessage =
+    DROP_PROTOBUF(ShutdownMessage(), _, _);
 
   // Stop the slave from reregistering with the new master until the
   // framework has reregistered.
-  DROP_MESSAGES(Eq(ReregisterSlaveMessage().GetTypeName()), _, _);
+  DROP_PROTOBUFS(ReregisterSlaveMessage(), _, _);
 
-  cluster.masters.shutdown();
+  this->ShutdownMasters();
 
-  AWAIT_READY(shutdownMsg);
+  AWAIT_READY(shutdownMessage);
 
-  EXPECT_CALL(this->allocator2, initialize(_, _));
+  MockAllocatorProcess<TypeParam> allocator2;
 
-  Try<PID<Master> > master2 = cluster.masters.start(&this->allocator2);
+  EXPECT_CALL(allocator2, initialize(_, _));
+
+  Try<PID<Master> > master2 = this->StartMaster(&allocator2);
   ASSERT_SOME(master2);
 
   Future<Nothing> frameworkAdded;
-  EXPECT_CALL(this->allocator2, frameworkAdded(_, _, _))
-    .WillOnce(DoAll(InvokeFrameworkAdded(&this->allocator2),
+  EXPECT_CALL(allocator2, frameworkAdded(_, _, _))
+    .WillOnce(DoAll(InvokeFrameworkAdded(&allocator2),
                     FutureSatisfy(&frameworkAdded)));
 
   EXPECT_CALL(sched, reregistered(&driver, _));
 
   AWAIT_READY(frameworkAdded);
 
-  EXPECT_CALL(this->allocator2, slaveAdded(_, _, _));
+  EXPECT_CALL(allocator2, slaveAdded(_, _, _));
 
   Future<vector<Offer> > resourceOffers2;
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -184,13 +210,13 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
   EXPECT_THAT(resourceOffers2.get(), OfferEq(1, 524));
 
   // Shut everything down.
-  EXPECT_CALL(this->allocator2, resourcesRecovered(_, _, _))
+  EXPECT_CALL(allocator2, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator2, frameworkDeactivated(_));
+  EXPECT_CALL(allocator2, frameworkDeactivated(_));
 
   Future<Nothing> frameworkRemoved;
-  EXPECT_CALL(this->allocator2, frameworkRemoved(_))
+  EXPECT_CALL(allocator2, frameworkRemoved(_))
     .WillOnce(FutureSatisfy(&frameworkRemoved));
 
   EXPECT_CALL(exec, shutdown(_))
@@ -201,10 +227,10 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
 
   AWAIT_READY(frameworkRemoved);
 
-  EXPECT_CALL(this->allocator2, slaveRemoved(_))
+  EXPECT_CALL(allocator2, slaveRemoved(_))
     .Times(AtMost(1));
 
-  cluster.shutdown();
+  this->Shutdown();
 }
 
 
@@ -214,25 +240,22 @@ TYPED_TEST(AllocatorZooKeeperTest, FrameworkReregistersFirst)
 // accounted for correctly.
 TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
 {
-  string zk = "zk://" + this->server->connectString() + "/znode";
-  Try<zookeeper::URL> url = zookeeper::URL::parse(zk);
-  ASSERT_SOME(url);
-
-  Cluster cluster(url.get());
+  TypeParam allocator1;
 
-  Try<PID<Master> > master = cluster.masters.start(&this->allocator1);
+  Try<PID<Master> > master = this->StartMaster(&allocator1);
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-  slave::Flags flags = cluster.slaves.flags;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:2;mem:1024");
 
-  Try<PID<Slave> > slave = cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = this->StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO,zk);
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, stringify(this->url.get()));
 
   Future<Nothing> registered;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -278,32 +301,34 @@ TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
 
   // Stop the failing master from telling the slave to shut down when
   // it is killed.
-  Future<process::Message> shutdownMsg =
-    DROP_MESSAGE(Eq(ShutdownMessage().GetTypeName()), _, _);
+  Future<ShutdownMessage> shutdownMessage =
+    DROP_PROTOBUF(ShutdownMessage(), _, _);
 
   // Stop the framework from reregistering with the new master until the
   // slave has reregistered.
-  DROP_MESSAGES(Eq(ReregisterFrameworkMessage().GetTypeName()), _, _);
+  DROP_PROTOBUFS(ReregisterFrameworkMessage(), _, _);
+
+  this->ShutdownMasters();
 
-  cluster.masters.shutdown();
+  AWAIT_READY(shutdownMessage);
 
-  AWAIT_READY(shutdownMsg);
+  MockAllocatorProcess<TypeParam> allocator2;
 
-  EXPECT_CALL(this->allocator2, initialize(_, _));
+  EXPECT_CALL(allocator2, initialize(_, _));
 
-  Try<PID<Master> > master2 = cluster.masters.start(&this->allocator2);
+  Try<PID<Master> > master2 = this->StartMaster(&allocator2);
   ASSERT_SOME(master2);
 
   Future<Nothing> slaveAdded;
-  EXPECT_CALL(this->allocator2, slaveAdded(_, _, _))
-    .WillOnce(DoAll(InvokeSlaveAdded(&this->allocator2),
+  EXPECT_CALL(allocator2, slaveAdded(_, _, _))
+    .WillOnce(DoAll(InvokeSlaveAdded(&allocator2),
                     FutureSatisfy(&slaveAdded)));
 
   EXPECT_CALL(sched, reregistered(&driver, _));
 
   AWAIT_READY(slaveAdded);
 
-  EXPECT_CALL(this->allocator2, frameworkAdded(_, _, _));
+  EXPECT_CALL(allocator2, frameworkAdded(_, _, _));
 
   Future<vector<Offer> > resourceOffers2;
   EXPECT_CALL(sched, resourceOffers(&driver, _))
@@ -321,13 +346,13 @@ TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
   EXPECT_THAT(resourceOffers2.get(), OfferEq(1, 524));
 
   // Shut everything down.
-  EXPECT_CALL(this->allocator2, resourcesRecovered(_, _, _))
+  EXPECT_CALL(allocator2, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator2, frameworkDeactivated(_));
+  EXPECT_CALL(allocator2, frameworkDeactivated(_));
 
   Future<Nothing> frameworkRemoved;
-  EXPECT_CALL(this->allocator2, frameworkRemoved(_))
+  EXPECT_CALL(allocator2, frameworkRemoved(_))
     .WillOnce(FutureSatisfy(&frameworkRemoved));
 
   EXPECT_CALL(exec, shutdown(_))
@@ -338,8 +363,8 @@ TYPED_TEST(AllocatorZooKeeperTest, SlaveReregistersFirst)
 
   AWAIT_READY(frameworkRemoved);
 
-  EXPECT_CALL(this->allocator2, slaveRemoved(_))
+  EXPECT_CALL(allocator2, slaveRemoved(_))
     .Times(AtMost(1));
 
-  cluster.shutdown();
+  this->Shutdown();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/cgroups_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/cgroups_tests.cpp b/src/tests/cgroups_tests.cpp
index db33738..f062fe6 100644
--- a/src/tests/cgroups_tests.cpp
+++ b/src/tests/cgroups_tests.cpp
@@ -35,6 +35,9 @@
 
 #include <gmock/gmock.h>
 
+#include <process/gtest.hpp>
+
+#include <stout/gtest.hpp>
 #include <stout/hashmap.hpp>
 #include <stout/option.hpp>
 #include <stout/os.hpp>
@@ -44,7 +47,7 @@
 
 #include "linux/cgroups.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/mesos.hpp" // For TEST_CGROUPS_(HIERARCHY|ROOT).
 
 using namespace mesos::internal::tests;
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/cluster.hpp
----------------------------------------------------------------------
diff --git a/src/tests/cluster.hpp b/src/tests/cluster.hpp
index 682b7d6..25cd554 100644
--- a/src/tests/cluster.hpp
+++ b/src/tests/cluster.hpp
@@ -43,10 +43,9 @@
 
 #include "slave/flags.hpp"
 #include "slave/isolator.hpp"
+#include "slave/process_isolator.hpp"
 #include "slave/slave.hpp"
 
-#include "tests/isolator.hpp" // For TestingIsolator.
-
 #include "zookeeper/url.hpp"
 
 namespace mesos {
@@ -56,7 +55,6 @@ namespace tests {
 class Cluster
 {
 public:
-  // TODO(benh): Take flags and make const in Masters and Slaves.
   Cluster(const Option<zookeeper::URL>& url = None())
     : masters(this, url),
       slaves(this, &masters) {}
@@ -70,23 +68,17 @@ public:
 
     void shutdown();
 
-    // Start and manage a new master.
-    Try<process::PID<master::Master> > start();
-
     // Start and manage a new master using the specified flags.
-    Try<process::PID<master::Master> > start(const master::Flags& flags);
-
-    // Start and manage a new master injecting the specified allocator
-    // process. The allocator process is expected to outlive the
-    // launched master (i.e., until it is stopped via Masters::stop).
     Try<process::PID<master::Master> > start(
-        master::AllocatorProcess* allocatorProcess);
+        const master::Flags& flags = master::Flags());
 
-    // Start and manage a new master using the specified flags
-    // and injecting the allocator process as above.
+    // Start and manage a new master injecting the specified allocator
+    // process and using the specified flags. The allocator process is
+    // expected to outlive the launched master (i.e., until it is
+    // stopped via Masters::stop).
     Try<process::PID<master::Master> > start(
         master::AllocatorProcess* allocatorProcess,
-        const master::Flags& flags);
+        const master::Flags& flags = master::Flags());
 
     // Stops and cleans up a master at the specified PID.
     Try<Nothing> stop(const process::PID<master::Master>& pid);
@@ -94,10 +86,7 @@ public:
     // Returns a new master detector for this instance of masters.
     Owned<MasterDetector> detector(
         const process::PID<slave::Slave>& pid,
-        bool quiet);
-
-    // "Default" flags used for creating masters.
-    master::Flags flags;
+        const slave::Flags& flags);
 
   private:
     // Not copyable, not assignable.
@@ -107,6 +96,7 @@ public:
     Cluster* cluster; // Enclosing class.
     Option<zookeeper::URL> url;
 
+    // Encapsulates a single master's dependencies.
     struct Master
     {
       Master()
@@ -134,42 +124,24 @@ public:
     // Stop and clean up all slaves.
     void shutdown();
 
-    // Start and manage a new slave.
-    Try<process::PID<slave::Slave> > start();
-
-    // Start and manage a new slave using the specified flags.
-    Try<process::PID<slave::Slave> > start(const slave::Flags& flags);
-
-    // Start and manage a new slave with a testing isolator that uses
-    // the specified executor for the specified ID. The executor is
-    // expected to outlive the launched slave (i.e., until it is
-    // stopped via Slaves::stop).
+    // Start and manage a new slave with a process isolator using the
+    // specified flags.
     Try<process::PID<slave::Slave> > start(
-        const ExecutorID& executorId,
-        Executor* executor);
-
-    // Start and manage a new slave using the specified flags with a
-    // testing isolator that uses the specified executor for the
-    // specified ID. The executor is expected to outlive the launched
-    // slave (i.e., until it is stopped via Slaves::stop).
-    Try<process::PID<slave::Slave> > start(
-        const slave::Flags& flags,
-        const ExecutorID& executorId,
-        Executor* executor);
+        const slave::Flags& flags = slave::Flags());
 
     // Start and manage a new slave injecting the specified isolator.
     // The isolator is expected to outlive the launched slave (i.e.,
     // until it is stopped via Slaves::stop).
-    Try<process::PID<slave::Slave> > start(slave::Isolator* isolator);
     Try<process::PID<slave::Slave> > start(
-        const slave::Flags& flags,
-        slave::Isolator* isolator);
+        slave::Isolator* isolator,
+        const slave::Flags& flags = slave::Flags());
 
-    // Stops and cleans up a slave at the specified PID.
-    Try<Nothing> stop(const process::PID<slave::Slave>& pid);
-
-    // "Default" flags used for creating slaves.
-    slave::Flags flags;
+    // Stops and cleans up a slave at the specified PID. If 'shutdown'
+    // is true than the slave is sent a shutdown message instead of
+    // being terminated.
+    Try<Nothing> stop(
+        const process::PID<slave::Slave>& pid,
+        bool shutdown = false);
 
   private:
     // Not copyable, not assignable.
@@ -179,15 +151,16 @@ public:
     Cluster* cluster; // Enclosing class.
     Masters* masters; // Used to create MasterDetector instances.
 
+    // Encapsulates a single slave's dependencies.
     struct Slave
     {
       Slave()
-        : slave(NULL),
-          isolator(NULL),
+        : isolator(NULL),
+          slave(NULL),
           detector(NULL) {}
 
-      slave::Slave* slave;
       slave::Isolator* isolator;
+      slave::Slave* slave;
       Owned<MasterDetector> detector;
     };
 
@@ -238,32 +211,6 @@ inline void Cluster::Masters::shutdown()
 }
 
 
-inline Try<process::PID<master::Master> > Cluster::Masters::start()
-{
-  // Disallow multiple masters when not using ZooKeeper.
-  if (!masters.empty() && url.isNone()) {
-    return Error("Can not start multiple masters when not using ZooKeeper");
-  }
-
-  Master master;
-  master.allocatorProcess = new master::HierarchicalDRFAllocatorProcess();
-  master.allocator = new master::Allocator(master.allocatorProcess);
-  master.master = new master::Master(master.allocator, &cluster->files, flags);
-
-  process::PID<master::Master> pid = process::spawn(master.master);
-
-  if (url.isSome()) {
-    master.detector = new ZooKeeperMasterDetector(url.get(), pid, true, true);
-  } else {
-    master.detector = new BasicMasterDetector(pid);
-  }
-
-  masters[pid] = master;
-
-  return pid;
-}
-
-
 inline Try<process::PID<master::Master> > Cluster::Masters::start(
     const master::Flags& flags)
 {
@@ -273,6 +220,7 @@ inline Try<process::PID<master::Master> > Cluster::Masters::start(
   }
 
   Master master;
+
   master.allocatorProcess = new master::HierarchicalDRFAllocatorProcess();
   master.allocator = new master::Allocator(master.allocatorProcess);
   master.master = new master::Master(master.allocator, &cluster->files, flags);
@@ -292,13 +240,6 @@ inline Try<process::PID<master::Master> > Cluster::Masters::start(
 
 
 inline Try<process::PID<master::Master> > Cluster::Masters::start(
-    master::AllocatorProcess* allocatorProcess)
-{
-  return Cluster::Masters::start(allocatorProcess, flags);
-}
-
-
-inline Try<process::PID<master::Master> > Cluster::Masters::start(
   master::AllocatorProcess* allocatorProcess,
   const master::Flags& flags)
 {
@@ -339,11 +280,8 @@ inline Try<Nothing> Cluster::Masters::stop(
   process::wait(master.master);
   delete master.master;
 
-  delete master.allocator; // Terminates and waits for the allocator process.
-
-  if (master.allocatorProcess != NULL) {
-    delete master.allocatorProcess;
-  }
+  delete master.allocator; // Terminates and waits for allocator process.
+  delete master.allocatorProcess; // May be NULL.
 
   delete master.detector;
 
@@ -355,10 +293,10 @@ inline Try<Nothing> Cluster::Masters::stop(
 
 inline Owned<MasterDetector> Cluster::Masters::detector(
     const process::PID<slave::Slave>& pid,
-    bool quiet)
+    const slave::Flags& flags)
 {
   if (url.isSome()) {
-    return new ZooKeeperMasterDetector(url.get(), pid, false, quiet);
+    return new ZooKeeperMasterDetector(url.get(), pid, false, flags.quiet);
   }
 
   CHECK(masters.size() == 1);
@@ -387,52 +325,22 @@ inline void Cluster::Slaves::shutdown()
 }
 
 
-inline Try<process::PID<slave::Slave> > Cluster::Slaves::start()
-{
-  // TODO(benh): Check that we dont have another slave already running
-  // with flags that conflict (e.g., work_dir).
-
-  Slave slave;
-
-  slave.isolator = new TestingIsolator();
-
-  process::spawn(slave.isolator);
-
-  // TODO(benh): Create a work directory for each slave.
-
-  slave.slave = new slave::Slave(flags, true, slave.isolator, &cluster->files);
-
-  process::PID<slave::Slave> pid = process::spawn(slave.slave);
-
-  // Get a detector for the master(s).
-  slave.detector = masters->detector(pid, flags.quiet);
-
-  slaves[pid] = slave;
-
-  return pid;
-}
-
-
 inline Try<process::PID<slave::Slave> > Cluster::Slaves::start(
     const slave::Flags& flags)
 {
-  // TODO(benh): Check that we dont have another slave already running
-  // with flags that conflict (e.g., work_dir).
+  // TODO(benh): Create a work directory if using the default.
 
   Slave slave;
 
-  slave.isolator = new TestingIsolator();
-
+  // Create a new process isolator for this slave.
+  slave.isolator = new slave::ProcessIsolator();
   process::spawn(slave.isolator);
 
-  // TODO(benh): Create a work directory for each slave.
-
   slave.slave = new slave::Slave(flags, true, slave.isolator, &cluster->files);
-
   process::PID<slave::Slave> pid = process::spawn(slave.slave);
 
   // Get a detector for the master(s).
-  slave.detector = masters->detector(pid, flags.quiet);
+  slave.detector = masters->detector(pid, flags);
 
   slaves[pid] = slave;
 
@@ -441,82 +349,18 @@ inline Try<process::PID<slave::Slave> > Cluster::Slaves::start(
 
 
 inline Try<process::PID<slave::Slave> > Cluster::Slaves::start(
-    const ExecutorID& executorId,
-    Executor* executor)
-{
-  return start(flags, executorId, executor);
-}
-
-
-inline Try<process::PID<slave::Slave> > Cluster::Slaves::start(
-    const slave::Flags& flags,
-    const ExecutorID& executorId,
-    Executor* executor)
-{
-  // TODO(benh): Check that we dont have another slave already running
-  // with flags that conflict (e.g., work_dir).
-
-  Slave slave;
-
-  slave.isolator = new TestingIsolator(executorId, executor);
-
-  process::spawn(slave.isolator);
-
-  // TODO(benh): Create a work directory for each slave.
-
-  slave.slave = new slave::Slave(flags, true, slave.isolator, &cluster->files);
-
-  process::PID<slave::Slave> pid = process::spawn(slave.slave);
-
-  // Get a detector for the master(s).
-  slave.detector = masters->detector(pid, flags.quiet);
-
-  slaves[pid] = slave;
-
-  return pid;
-}
-
-
-inline Try<process::PID<slave::Slave> > Cluster::Slaves::start(
-    slave::Isolator* isolator)
-{
-  // TODO(benh): Check that we dont have another slave already running
-  // with flags that conflict (e.g., work_dir).
-
-  Slave slave;
-
-  // TODO(benh): Create a work directory for each slave.
-
-  slave.slave = new slave::Slave(flags, true, isolator, &cluster->files);
-
-  process::PID<slave::Slave> pid = process::spawn(slave.slave);
-
-  // Get a detector for the master(s).
-  slave.detector = masters->detector(pid, flags.quiet);
-
-  slaves[pid] = slave;
-
-  return pid;
-}
-
-
-inline Try<process::PID<slave::Slave> > Cluster::Slaves::start(
-    const slave::Flags& flags,
-    slave::Isolator* isolator)
+    slave::Isolator* isolator,
+    const slave::Flags& flags)
 {
-  // TODO(benh): Check that we dont have another slave already running
-  // with flags that conflict (e.g., work_dir).
+  // TODO(benh): Create a work directory if using the default.
 
   Slave slave;
 
-  // TODO(benh): Create a work directory for each slave.
-
   slave.slave = new slave::Slave(flags, true, isolator, &cluster->files);
-
   process::PID<slave::Slave> pid = process::spawn(slave.slave);
 
   // Get a detector for the master(s).
-  slave.detector = masters->detector(pid, flags.quiet);
+  slave.detector = masters->detector(pid, flags);
 
   slaves[pid] = slave;
 
@@ -525,7 +369,8 @@ inline Try<process::PID<slave::Slave> > Cluster::Slaves::start(
 
 
 inline Try<Nothing> Cluster::Slaves::stop(
-    const process::PID<slave::Slave>& pid)
+    const process::PID<slave::Slave>& pid,
+    bool shutdown)
 {
   if (slaves.count(pid) == 0) {
     return Error("No slave found to stop");
@@ -533,17 +378,15 @@ inline Try<Nothing> Cluster::Slaves::stop(
 
   Slave slave = slaves[pid];
 
-  process::terminate(slave.slave);
+  if (shutdown) {
+    process::dispatch(slave.slave, &slave::Slave::shutdown);
+  } else {
+    process::terminate(slave.slave);
+  }
   process::wait(slave.slave);
   delete slave.slave;
 
-  if (slave.isolator != NULL) {
-    // TODO(benh): Terminate and wait for the isolator once the slave
-    // is no longer doing so.
-    // process::terminate(slave.isolator);
-    // process::wait(slave.isolator);
-    delete slave.isolator;
-  }
+  delete slave.isolator; // May be NULL.
 
   slaves.erase(pid);
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/configurator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/configurator_tests.cpp b/src/tests/configurator_tests.cpp
index e8ba936..b82f5c2 100644
--- a/src/tests/configurator_tests.cpp
+++ b/src/tests/configurator_tests.cpp
@@ -18,17 +18,13 @@
 
 #include <gtest/gtest.h>
 
-#include <fstream>
-
-#include <boost/lexical_cast.hpp>
+#include <stout/gtest.hpp>
+#include <stout/os.hpp>
 
 #include "configurator/configurator.hpp"
 
 #include "tests/utils.hpp"
 
-using boost::lexical_cast;
-
-using std::ofstream;
 using std::string;
 
 using namespace mesos;
@@ -36,9 +32,7 @@ using namespace mesos::internal;
 using namespace mesos::internal::tests;
 
 
-class ConfiguratorTest : public TemporaryDirectoryTest
-{
-};
+class ConfiguratorTest : public TemporaryDirectoryTest {};
 
 
 TEST_F(ConfiguratorTest, Environment)

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/exception_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/exception_tests.cpp b/src/tests/exception_tests.cpp
index 911e786..60bb690 100644
--- a/src/tests/exception_tests.cpp
+++ b/src/tests/exception_tests.cpp
@@ -22,17 +22,14 @@
 #include <mesos/scheduler.hpp>
 
 #include <process/gmock.hpp>
-
-#include "detector/detector.hpp"
+#include <process/pid.hpp>
+#include <process/process.hpp>
 
 #include "local/local.hpp"
 
 #include "master/master.hpp"
 
-#include "slave/process_isolator.hpp"
-#include "slave/slave.hpp"
-
-#include "tests/utils.hpp"
+#include "tests/mesos.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;
@@ -40,8 +37,6 @@ using namespace mesos::internal::tests;
 
 using mesos::internal::master::Master;
 
-using mesos::internal::slave::Slave;
-
 using process::Future;
 using process::PID;
 
@@ -50,14 +45,9 @@ using std::map;
 using std::vector;
 
 using testing::_;
-using testing::AnyOf;
 using testing::AtMost;
-using testing::DoAll;
-using testing::ElementsAre;
 using testing::Eq;
-using testing::Not;
 using testing::Return;
-using testing::SaveArg;
 
 
 TEST(ExceptionTest, DeactivateFrameworkOnAbort)

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/fault_tolerance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/fault_tolerance_tests.cpp b/src/tests/fault_tolerance_tests.cpp
index bcfe5db..e41a044 100644
--- a/src/tests/fault_tolerance_tests.cpp
+++ b/src/tests/fault_tolerance_tests.cpp
@@ -38,26 +38,21 @@
 
 #include "common/protobuf_utils.hpp"
 
-#include "detector/detector.hpp"
-
 #include "local/local.hpp"
 
-#include "master/allocator.hpp"
-#include "master/hierarchical_allocator_process.hpp"
 #include "master/master.hpp"
 
 #include "slave/isolator.hpp"
 #include "slave/slave.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/isolator.hpp"
+#include "tests/mesos.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;
 using namespace mesos::internal::protobuf;
 using namespace mesos::internal::tests;
 
-using mesos::internal::master::Allocator;
-using mesos::internal::master::HierarchicalDRFAllocatorProcess;
 using mesos::internal::master::Master;
 
 using mesos::internal::slave::Isolator;
@@ -92,21 +87,14 @@ class FaultToleranceTest : public MesosTest {};
 // its offer(s) is rescinded.
 TEST_F(FaultToleranceTest, SlaveLost)
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  TestingIsolator isolator;
-
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _));
 
@@ -128,7 +116,7 @@ TEST_F(FaultToleranceTest, SlaveLost)
   EXPECT_CALL(sched, slaveLost(&driver, offers.get()[0].slave_id()))
     .WillOnce(FutureSatisfy(&slaveLost));
 
-  process::terminate(slave);
+  ShutdownSlaves();
 
   AWAIT_READY(offerRescinded);
   AWAIT_READY(slaveLost);
@@ -136,10 +124,7 @@ TEST_F(FaultToleranceTest, SlaveLost)
   driver.stop();
   driver.join();
 
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 }
 
 
@@ -206,9 +191,6 @@ TEST_F(FaultToleranceTest, PartitionedSlave)
 }
 
 
-// TODO(bmahler): Remove this when all the tests are refactored.
-class FaultToleranceClusterTest : public MesosClusterTest {};
-
 // The purpose of this test is to ensure that when slaves are removed
 // from the master, and then attempt to re-register, we deny the
 // re-registration by sending a ShutdownMessage to the slave.
@@ -218,9 +200,9 @@ class FaultToleranceClusterTest : public MesosClusterTest {};
 // re-register with its running tasks. We've already notified
 // frameworks that these tasks were LOST, so we have to have the slave
 // slave shut down.
-TEST_F(FaultToleranceClusterTest, PartitionedSlaveReregistration)
+TEST_F(FaultToleranceTest, PartitionedSlaveReregistration)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   // Allow the master to PING the slave, but drop all PONG messages
@@ -230,8 +212,9 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveReregistration)
   Future<Message> ping = FUTURE_MESSAGE(Eq("PING"), _, _);
   DROP_MESSAGES(Eq("PONG"), _, _);
 
-  MockExecutor exec;
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  Try<PID<Slave> > slave = StartSlave(&exec);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -355,7 +338,7 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveReregistration)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
@@ -367,9 +350,9 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveReregistration)
 // the slave may attempt to send updates if it was unaware that the
 // master deactivated it. We've already notified frameworks that these
 // tasks were LOST, so we have to have the slave shut down.
-TEST_F(FaultToleranceClusterTest, PartitionedSlaveStatusUpdates)
+TEST_F(FaultToleranceTest, PartitionedSlaveStatusUpdates)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   // Allow the master to PING the slave, but drop all PONG messages
@@ -382,8 +365,9 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveStatusUpdates)
   Future<SlaveRegisteredMessage> slaveRegisteredMessage =
     FUTURE_PROTOBUF(SlaveRegisteredMessage(), _, _);
 
-  MockExecutor exec;
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  Try<PID<Slave> > slave = StartSlave(&exec);
   ASSERT_SOME(slave);
 
   AWAIT_READY(slaveRegisteredMessage);
@@ -466,7 +450,7 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveStatusUpdates)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
@@ -479,9 +463,9 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveStatusUpdates)
 // it was unaware that the master deactivated it. We've already
 // notified frameworks that the tasks under the executors were LOST,
 // so we have to have the slave shut down.
-TEST_F(FaultToleranceClusterTest, PartitionedSlaveExitedExecutor)
+TEST_F(FaultToleranceTest, PartitionedSlaveExitedExecutor)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   // Allow the master to PING the slave, but drop all PONG messages
@@ -491,10 +475,10 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveExitedExecutor)
   Future<Message> ping = FUTURE_MESSAGE(Eq("PING"), _, _);
   DROP_MESSAGES(Eq("PONG"), _, _);
 
-  MockExecutor exec;
-  TestingIsolator* isolator = new TestingIsolator(DEFAULT_EXECUTOR_ID, &exec);
-  process::spawn(isolator);
-  Try<PID<Slave> > slave = cluster.slaves.start(isolator);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
+
+  Try<PID<Slave> > slave = StartSlave(&isolator);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -602,21 +586,15 @@ TEST_F(FaultToleranceClusterTest, PartitionedSlaveExitedExecutor)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
-
-  // TODO(benh): Terminate and wait for the isolator once the slave
-  // is no longer doing so.
-  // process::terminate(isolator);
-  // process::wait(isolator);
-  delete isolator;
+  Shutdown();
 }
 
 
 // This test ensures that a framework connecting with a
 // failed over master gets a re-registered callback.
-TEST_F(FaultToleranceClusterTest, MasterFailover)
+TEST_F(FaultToleranceTest, MasterFailover)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   MockScheduler sched;
@@ -632,10 +610,12 @@ TEST_F(FaultToleranceClusterTest, MasterFailover)
   AWAIT_READY(frameworkRegisteredMessage);
 
   // Simulate failed over master by restarting the master.
-  ASSERT_SOME(cluster.masters.stop(master.get()));
-  master = cluster.masters.start();
+  Stop(master.get());
+  master = StartMaster();
   ASSERT_SOME(master);
 
+  EXPECT_CALL(sched, disconnected(&driver));
+
   Future<Nothing> reregistered;
   EXPECT_CALL(sched, reregistered(&driver, _))
     .WillOnce(FutureSatisfy(&reregistered));
@@ -652,7 +632,7 @@ TEST_F(FaultToleranceClusterTest, MasterFailover)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
@@ -818,21 +798,14 @@ TEST_F(FaultToleranceTest, FrameworkReregister)
 
 TEST_F(FaultToleranceTest, TaskLost)
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  TestingIsolator isolator;
-
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _));
 
@@ -882,11 +855,7 @@ TEST_F(FaultToleranceTest, TaskLost)
   driver.stop();
   driver.join();
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 }
 
 
@@ -896,23 +865,17 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
 {
   Clock::pause();
 
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
 
   // Launch the first (i.e., failing) scheduler.
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
 
   FrameworkID frameworkId;
   EXPECT_CALL(sched1, registered(&driver1, _, _))
@@ -948,7 +911,7 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
   // Drop the first status update message
   // between master and the scheduler.
   Future<StatusUpdateMessage> statusUpdateMessage =
-    DROP_PROTOBUF(StatusUpdateMessage(), _, Not(AnyOf(Eq(master), Eq(slave))));
+    DROP_PROTOBUF(StatusUpdateMessage(), _, Not(AnyOf(Eq(master.get()), Eq(slave.get()))));
 
   driver1.launchTasks(offers.get()[0].id(), tasks);
 
@@ -964,7 +927,7 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
   framework2 = DEFAULT_FRAMEWORK_INFO;
   framework2.mutable_id()->MergeFrom(frameworkId);
 
-  MesosSchedulerDriver driver2(&sched2, framework2, master);
+  MesosSchedulerDriver driver2(&sched2, framework2, master.get());
 
   Future<Nothing> registered2;
   EXPECT_CALL(sched2, registered(&driver2, frameworkId, _))
@@ -999,11 +962,7 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 
   Clock::resume();
 }
@@ -1011,22 +970,16 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
 
 TEST_F(FaultToleranceTest, ForwardStatusUpdateUnknownExecutor)
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   FrameworkID frameworkId;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -1078,7 +1031,7 @@ TEST_F(FaultToleranceTest, ForwardStatusUpdateUnknownExecutor)
   StatusUpdate statusUpdate2 = createStatusUpdate(
       frameworkId, offer.slave_id(), taskId, TASK_RUNNING, "Dummy update");
 
-  process::dispatch(slave, &Slave::statusUpdate, statusUpdate2);
+  process::dispatch(slave.get(), &Slave::statusUpdate, statusUpdate2);
 
   // Ensure that the scheduler receives task2's update.
   AWAIT_READY(status);
@@ -1094,32 +1047,22 @@ TEST_F(FaultToleranceTest, ForwardStatusUpdateUnknownExecutor)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 }
 
 
 TEST_F(FaultToleranceTest, SchedulerFailoverFrameworkMessage)
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  MockExecutor exec;
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
 
   FrameworkID frameworkId;
   EXPECT_CALL(sched1, registered(&driver1, _, _))
@@ -1167,7 +1110,7 @@ TEST_F(FaultToleranceTest, SchedulerFailoverFrameworkMessage)
   framework2 = DEFAULT_FRAMEWORK_INFO;
   framework2.mutable_id()->MergeFrom(frameworkId);
 
-  MesosSchedulerDriver driver2(&sched2, framework2, master);
+  MesosSchedulerDriver driver2(&sched2, framework2, master.get());
 
   Future<Nothing> registered;
   EXPECT_CALL(sched2, registered(&driver2, frameworkId, _))
@@ -1199,34 +1142,23 @@ TEST_F(FaultToleranceTest, SchedulerFailoverFrameworkMessage)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 }
 
 
 // This test checks that a scheduler exit shuts down the executor.
 TEST_F(FaultToleranceTest, SchedulerExit)
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  MockExecutor exec;
-
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _));
 
@@ -1275,11 +1207,7 @@ TEST_F(FaultToleranceTest, SchedulerExit)
 
   AWAIT_READY(shutdown);
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 }
 
 
@@ -1287,25 +1215,18 @@ TEST_F(FaultToleranceTest, SlaveReliableRegistration)
 {
   Clock::pause();
 
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  TestingIsolator isolator;
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
   // Drop the first slave registered message, allow subsequent messages.
   Future<SlaveRegisteredMessage> slaveRegisteredMessage =
     DROP_PROTOBUF(SlaveRegisteredMessage(), _, _);
 
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
-
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _));
 
@@ -1325,11 +1246,7 @@ TEST_F(FaultToleranceTest, SlaveReliableRegistration)
   driver.stop();
   driver.join();
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 
   Clock::resume();
 }
@@ -1337,21 +1254,14 @@ TEST_F(FaultToleranceTest, SlaveReliableRegistration)
 
 TEST_F(FaultToleranceTest, SlaveReregisterOnZKExpiration)
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  TestingIsolator isolator;
-
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _));
 
@@ -1371,44 +1281,32 @@ TEST_F(FaultToleranceTest, SlaveReregisterOnZKExpiration)
   // expiration) at the slave.
 
   NewMasterDetectedMessage message;
-  message.set_pid(master);
+  message.set_pid(master.get());
 
-  process::post(slave, message);
+  process::post(slave.get(), message);
 
   AWAIT_READY(slaveReregisteredMessage);
 
   driver.stop();
   driver.join();
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 }
 
 
 // This test verifies that the master sends TASK_LOST updates
 // for tasks in the master absent from the re-registered slave.
 // We do this by dropping RunTaskMessage from master to the slave.
-// TODO(vinod): Use 'Cluster' abstraction.
 TEST_F(FaultToleranceTest, ConsolidateTasksOnSlaveReregistration)
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
-
-  TestingIsolator isolator;
-
-  Slave s(slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  BasicMasterDetector detector(master, slave, true);
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _));
 
@@ -1435,14 +1333,15 @@ TEST_F(FaultToleranceTest, ConsolidateTasksOnSlaveReregistration)
 
   // We now launch a task and drop the corresponding RunTaskMessage on
   // the slave, to ensure that only the master knows about this task.
-  Future<RunTaskMessage> runTaskMessage = DROP_PROTOBUF(RunTaskMessage(), _, _);
+  Future<RunTaskMessage> runTaskMessage =
+    DROP_PROTOBUF(RunTaskMessage(), _, _);
 
   driver.launchTasks(offers.get()[0].id(), tasks);
 
   AWAIT_READY(runTaskMessage);
 
   Future<SlaveReregisteredMessage> slaveReregisteredMessage =
-      FUTURE_PROTOBUF(SlaveReregisteredMessage(), _, _);
+    FUTURE_PROTOBUF(SlaveReregisteredMessage(), _, _);
 
   Future<TaskStatus> status;
   EXPECT_CALL(sched, statusUpdate(&driver, _))
@@ -1452,9 +1351,9 @@ TEST_F(FaultToleranceTest, ConsolidateTasksOnSlaveReregistration)
   // expiration) at the slave to force re-registration.
 
   NewMasterDetectedMessage message;
-  message.set_pid(master);
+  message.set_pid(master.get());
 
-  process::post(slave, message);
+  process::post(slave.get(), message);
 
   AWAIT_READY(slaveReregisteredMessage);
 
@@ -1466,9 +1365,5 @@ TEST_F(FaultToleranceTest, ConsolidateTasksOnSlaveReregistration)
   driver.stop();
   driver.join();
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  Shutdown();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/files_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/files_tests.cpp b/src/tests/files_tests.cpp
index 5679ecd..a696aa2 100644
--- a/src/tests/files_tests.cpp
+++ b/src/tests/files_tests.cpp
@@ -21,10 +21,12 @@
 #include <gmock/gmock.h>
 
 #include <process/future.hpp>
+#include <process/gtest.hpp>
 #include <process/http.hpp>
 #include <process/pid.hpp>
 #include <process/process.hpp>
 
+#include <stout/gtest.hpp>
 #include <stout/json.hpp>
 #include <stout/os.hpp>
 #include <stout/stringify.hpp>

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/flags_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/flags_tests.cpp b/src/tests/flags_tests.cpp
index e07dbcc..d52d4db 100644
--- a/src/tests/flags_tests.cpp
+++ b/src/tests/flags_tests.cpp
@@ -23,6 +23,7 @@
 #include <string>
 
 #include <stout/duration.hpp>
+#include <stout/gtest.hpp>
 #include <stout/none.hpp>
 #include <stout/option.hpp>
 
@@ -31,8 +32,6 @@
 
 #include "flags/flags.hpp"
 
-#include "tests/utils.hpp"
-
 using namespace flags;
 
 class TestFlags : public virtual FlagsBase

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/gc_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/gc_tests.cpp b/src/tests/gc_tests.cpp
index 949678c..43c3e5d 100644
--- a/src/tests/gc_tests.cpp
+++ b/src/tests/gc_tests.cpp
@@ -55,6 +55,8 @@
 #include "slave/paths.hpp"
 #include "slave/slave.hpp"
 
+#include "tests/isolator.hpp"
+#include "tests/mesos.hpp"
 #include "tests/utils.hpp"
 
 using namespace mesos;
@@ -248,20 +250,24 @@ TEST_F(GarbageCollectorTest, Prune)
 }
 
 
-class GarbageCollectorIntegrationTest : public MesosClusterTest {};
+class GarbageCollectorIntegrationTest : public MesosTest {};
 
 
 TEST_F(GarbageCollectorIntegrationTest, Restart)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   Future<SlaveRegisteredMessage> slaveRegisteredMessage =
     FUTURE_PROTOBUF(SlaveRegisteredMessage(), _, _);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  // Need to create our own flags because we want to reuse them when
+  // we (re)start the slave below.
+  slave::Flags flags = CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   AWAIT_READY(slaveRegisteredMessage);
@@ -272,7 +278,7 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
   EXPECT_CALL(sched, registered(_, _, _))
     .Times(1);
 
-  Resources resources = Resources::parse(cluster.slaves.flags.resources.get());
+  Resources resources = Resources::parse(flags.resources.get());
   double cpus = resources.get("cpus", Value::Scalar()).value();
   double mem = resources.get("mem", Value::Scalar()).value();
 
@@ -300,7 +306,7 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
   // until the task is launched. We get the slave ID from the
   // SlaveRegisteredMessage.
   const std::string& slaveDir = slave::paths::getSlavePath(
-      cluster.slaves.flags.work_dir,
+      flags.work_dir,
       slaveRegisteredMessage.get().slave_id());
 
   ASSERT_TRUE(os::exists(slaveDir));
@@ -318,7 +324,7 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
   EXPECT_CALL(sched, slaveLost(_, _))
     .WillOnce(FutureSatisfy(&slaveLost));
 
-  cluster.slaves.stop(slave.get());
+  Stop(slave.get());
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
@@ -327,14 +333,14 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
   Future<Nothing> schedule =
     FUTURE_DISPATCH(_, &GarbageCollectorProcess::schedule);
 
-  slave = cluster.slaves.start();
+  slave = StartSlave(flags);
   ASSERT_SOME(slave);
 
   AWAIT_READY(schedule);
 
   Clock::settle(); // Wait for GarbageCollectorProcess::schedule to complete.
 
-  Clock::advance(cluster.slaves.flags.gc_delay);
+  Clock::advance(flags.gc_delay);
 
   Clock::settle();
 
@@ -346,21 +352,23 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 TEST_F(GarbageCollectorIntegrationTest, ExitedFramework)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   Future<SlaveRegisteredMessage> slaveRegisteredMessage =
     FUTURE_PROTOBUF(SlaveRegisteredMessage(), _, _);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  slave::Flags flags = CreateSlaveFlags();
 
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Slave> > slave = StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   AWAIT_READY(slaveRegisteredMessage);
@@ -374,7 +382,7 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedFramework)
   EXPECT_CALL(sched, registered(_, _, _))
     .WillOnce(SaveArg<1>(&frameworkId));
 
-  Resources resources = Resources::parse(cluster.slaves.flags.resources.get());
+  Resources resources = Resources::parse(flags.resources.get());
   double cpus = resources.get("cpus", Value::Scalar()).value();
   double mem = resources.get("mem", Value::Scalar()).value();
 
@@ -418,7 +426,7 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedFramework)
     FUTURE_DISPATCH(_, &GarbageCollectorProcess::schedule);
 
   // Advance clock to kill executor via isolator.
-  Clock::advance(cluster.slaves.flags.executor_shutdown_grace_period);
+  Clock::advance(flags.executor_shutdown_grace_period);
 
   Clock::settle();
 
@@ -426,13 +434,13 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedFramework)
 
   Clock::settle(); // Wait for GarbageCollectorProcess::schedule to complete.
 
-  Clock::advance(cluster.slaves.flags.gc_delay);
+  Clock::advance(flags.gc_delay);
 
   Clock::settle();
 
   // Framework's directory should be gc'ed by now.
   const string& frameworkDir = slave::paths::getFrameworkPath(
-      cluster.slaves.flags.work_dir, slaveId, frameworkId);
+      flags.work_dir, slaveId, frameworkId);
 
   ASSERT_FALSE(os::exists(frameworkDir));
 
@@ -443,20 +451,22 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedFramework)
 
   Clock::resume();
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
 TEST_F(GarbageCollectorIntegrationTest, ExitedExecutor)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  TestingIsolator isolator(&exec);
 
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  slave::Flags flags = CreateSlaveFlags();
 
-  Try<PID<Slave> > slave = cluster.slaves.start(&isolator);
+  Try<PID<Slave> > slave = StartSlave(&isolator);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -466,7 +476,7 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedExecutor)
   EXPECT_CALL(sched, registered(_, _, _))
     .WillOnce(FutureArg<1>(&frameworkId));
 
-  Resources resources = Resources::parse(cluster.slaves.flags.resources.get());
+  Resources resources = Resources::parse(flags.resources.get());
   double cpus = resources.get("cpus", Value::Scalar()).value();
   double mem = resources.get("mem", Value::Scalar()).value();
 
@@ -518,7 +528,7 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedExecutor)
 
   Clock::settle(); // Wait for GarbageCollectorProcess::schedule to complete.
 
-  Clock::advance(cluster.slaves.flags.gc_delay);
+  Clock::advance(flags.gc_delay);
 
   Clock::settle();
 
@@ -533,20 +543,22 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedExecutor)
   driver.stop();
   driver.join();
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
 TEST_F(GarbageCollectorIntegrationTest, DiskUsage)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  TestingIsolator isolator(&exec);
 
-  Try<PID<Slave> > slave = cluster.slaves.start(&isolator);
+  slave::Flags flags = CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -556,7 +568,7 @@ TEST_F(GarbageCollectorIntegrationTest, DiskUsage)
   EXPECT_CALL(sched, registered(_, _, _))
     .WillOnce(FutureArg<1>(&frameworkId));
 
-  Resources resources = Resources::parse(cluster.slaves.flags.resources.get());
+  Resources resources = Resources::parse(flags.resources.get());
   double cpus = resources.get("cpus", Value::Scalar()).value();
   double mem = resources.get("mem", Value::Scalar()).value();
 
@@ -632,7 +644,7 @@ TEST_F(GarbageCollectorIntegrationTest, DiskUsage)
   driver.stop();
   driver.join();
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
@@ -641,17 +653,19 @@ TEST_F(GarbageCollectorIntegrationTest, DiskUsage)
 // created by an old executor (with the same id).
 TEST_F(GarbageCollectorIntegrationTest, Unschedule)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   Future<SlaveRegisteredMessage> slaveRegistered =
     FUTURE_PROTOBUF(SlaveRegisteredMessage(), _, _);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  TestingIsolator isolator(&exec);
 
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  slave::Flags flags = CreateSlaveFlags();
 
-  Try<PID<Slave> > slave = cluster.slaves.start(&isolator);
+  Try<PID<Slave> > slave = StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
   AWAIT_READY(slaveRegistered);
@@ -663,7 +677,7 @@ TEST_F(GarbageCollectorIntegrationTest, Unschedule)
   EXPECT_CALL(sched, registered(_, _, _))
     .WillOnce(FutureArg<1>(&frameworkId));
 
-  Resources resources = Resources::parse(cluster.slaves.flags.resources.get());
+  Resources resources = Resources::parse(flags.resources.get());
   double cpus = resources.get("cpus", Value::Scalar()).value();
   double mem = resources.get("mem", Value::Scalar()).value();
 
@@ -755,5 +769,5 @@ TEST_F(GarbageCollectorIntegrationTest, Unschedule)
   driver.stop();
   driver.join();
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/group_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/group_tests.cpp b/src/tests/group_tests.cpp
index d32b74f..c7f789c 100644
--- a/src/tests/group_tests.cpp
+++ b/src/tests/group_tests.cpp
@@ -23,10 +23,11 @@
 #include <string>
 
 #include <process/future.hpp>
+#include <process/gtest.hpp>
 
+#include <stout/gtest.hpp>
 #include <stout/option.hpp>
 
-#include "tests/utils.hpp"
 #include "tests/zookeeper.hpp"
 
 #include "zookeeper/authentication.hpp"

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/isolator.hpp
----------------------------------------------------------------------
diff --git a/src/tests/isolator.hpp b/src/tests/isolator.hpp
index 17dc7b3..ebfc485 100644
--- a/src/tests/isolator.hpp
+++ b/src/tests/isolator.hpp
@@ -26,6 +26,7 @@
 #include <process/future.hpp>
 #include <process/pid.hpp>
 
+#include <stout/os.hpp>
 #include <stout/try.hpp>
 #include <stout/uuid.hpp>
 
@@ -34,6 +35,8 @@
 
 #include "slave/isolator.hpp"
 
+#include "tests/mesos.hpp" // For MockExecutor.
+
 namespace mesos {
 namespace internal {
 namespace tests {
@@ -58,6 +61,12 @@ public:
     setup();
   }
 
+  TestingIsolator(MockExecutor* executor)
+  {
+    executors[executor->id] = executor;
+    setup();
+  }
+
   virtual ~TestingIsolator() {}
 
   virtual void initialize(

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/isolator_tests.cpp b/src/tests/isolator_tests.cpp
index 4715fb7..aae8b2f 100644
--- a/src/tests/isolator_tests.cpp
+++ b/src/tests/isolator_tests.cpp
@@ -32,9 +32,6 @@
 
 #include "detector/detector.hpp"
 
-#include "master/allocator.hpp"
-#include "master/flags.hpp"
-#include "master/hierarchical_allocator_process.hpp"
 #include "master/master.hpp"
 
 #include "slave/flags.hpp"
@@ -44,7 +41,7 @@
 #include "slave/process_isolator.hpp"
 #include "slave/slave.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/mesos.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;
@@ -52,8 +49,6 @@ using namespace mesos::internal::tests;
 
 using namespace process;
 
-using mesos::internal::master::Allocator;
-using mesos::internal::master::HierarchicalDRFAllocatorProcess;
 using mesos::internal::master::Master;
 
 #ifdef __linux__
@@ -80,6 +75,7 @@ typedef ::testing::Types<ProcessIsolator> IsolatorTypes;
 
 TYPED_TEST_CASE(IsolatorTest, IsolatorTypes);
 
+
 // TODO(bmahler): This test is disabled on OSX, until proc::children
 // is implemented for OSX.
 #ifdef __APPLE__
@@ -88,20 +84,18 @@ TYPED_TEST(IsolatorTest, DISABLED_Usage)
 TYPED_TEST(IsolatorTest, Usage)
 #endif
 {
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator a(&allocator);
-  Files files;
-  Master m(&a, &files);
-  PID<Master> master = process::spawn(&m);
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
 
   TypeParam isolator;
-  Slave s(this->slaveFlags, true, &isolator, &files);
-  PID<Slave> slave = process::spawn(&s);
 
-  BasicMasterDetector detector(master, slave, true);
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   Future<FrameworkID> frameworkId;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -112,11 +106,6 @@ TYPED_TEST(IsolatorTest, Usage)
     .WillOnce(FutureArg<1>(&offers))
     .WillRepeatedly(Return()); // Ignore subsequent offers.
 
-  Future<TaskStatus> status1, status2;
-  EXPECT_CALL(sched, statusUpdate(&driver, _))
-    .WillOnce(FutureArg<1>(&status1))
-    .WillOnce(FutureArg<1>(&status2));
-
   driver.start();
 
   AWAIT_READY(frameworkId);
@@ -130,7 +119,7 @@ TYPED_TEST(IsolatorTest, Usage)
   task.mutable_slave_id()->MergeFrom(offers.get()[0].slave_id());
   task.mutable_resources()->MergeFrom(offers.get()[0].resources());
 
-  const std::string& file = path::join(this->slaveFlags.work_dir, "ready");
+  const std::string& file = path::join(flags.work_dir, "ready");
 
   // This task induces user/system load in a child process by
   // running top in a child process for ten seconds.
@@ -148,11 +137,15 @@ TYPED_TEST(IsolatorTest, Usage)
   vector<TaskInfo> tasks;
   tasks.push_back(task);
 
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
+
   driver.launchTasks(offers.get()[0].id(), tasks);
 
-  AWAIT_READY(status1);
+  AWAIT_READY(status);
 
-  EXPECT_EQ(TASK_RUNNING, status1.get().state());
+  EXPECT_EQ(TASK_RUNNING, status.get().state());
 
   // Wait for the task to begin inducing cpu time.
   while (!os::exists(file));
@@ -167,8 +160,12 @@ TYPED_TEST(IsolatorTest, Usage)
   ResourceStatistics statistics;
   Duration waited = Duration::zero();
   do {
-    const Future<ResourceStatistics>& usage =
-      isolator.usage(frameworkId.get(), executorId);
+    Future<ResourceStatistics> usage =
+      process::dispatch(
+          (Isolator*) &isolator, // TODO(benh): Fix after reaper changes.
+          &Isolator::usage,
+          frameworkId.get(),
+          executorId);
 
     AWAIT_READY(usage);
 
@@ -182,27 +179,26 @@ TYPED_TEST(IsolatorTest, Usage)
     }
 
     os::sleep(Milliseconds(100));
-    waited = waited + Milliseconds(100);
+    waited += Milliseconds(100);
   } while (waited < Seconds(10));
 
   EXPECT_GE(statistics.memory_rss(), 1024u);
   EXPECT_GE(statistics.cpu_user_time(), 0.125);
   EXPECT_GE(statistics.cpu_system_time(), 0.125);
 
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
+
   driver.killTask(task.task_id());
 
-  AWAIT_READY(status2);
+  AWAIT_READY(status);
 
   // TODO(bmahler): The command executor is buggy in that it does not
   // send TASK_KILLED for a non-zero exit code due to a kill.
-  EXPECT_EQ(TASK_FAILED, status2.get().state());
+  EXPECT_EQ(TASK_FAILED, status.get().state());
 
   driver.stop();
   driver.join();
 
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
+  this->Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/log_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/log_tests.cpp b/src/tests/log_tests.cpp
index 208e83e..dbd12b8 100644
--- a/src/tests/log_tests.cpp
+++ b/src/tests/log_tests.cpp
@@ -24,10 +24,12 @@
 #include <process/clock.hpp>
 #include <process/future.hpp>
 #include <process/gmock.hpp>
+#include <process/gtest.hpp>
 #include <process/pid.hpp>
 #include <process/protobuf.hpp>
 #include <process/timeout.hpp>
 
+#include <stout/gtest.hpp>
 #include <stout/option.hpp>
 #include <stout/os.hpp>
 
@@ -39,12 +41,9 @@
 
 #include "messages/messages.hpp"
 
-#include "tests/utils.hpp"
-
 using namespace mesos;
 using namespace mesos::internal;
 using namespace mesos::internal::log;
-using namespace mesos::internal::tests;
 
 using process::Clock;
 using process::Future;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/logging_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/logging_tests.cpp b/src/tests/logging_tests.cpp
index 57eae79..58e9b33 100644
--- a/src/tests/logging_tests.cpp
+++ b/src/tests/logging_tests.cpp
@@ -19,15 +19,14 @@
 #include <gmock/gmock.h>
 
 #include <process/future.hpp>
+#include <process/gtest.hpp>
 #include <process/http.hpp>
 #include <process/pid.hpp>
+#include <process/process.hpp>
 
 #include "logging/logging.hpp"
 
-#include "tests/utils.hpp"
-
 using namespace mesos::internal;
-using namespace mesos::internal::tests;
 
 using process::http::BadRequest;
 using process::http::OK;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/main.cpp
----------------------------------------------------------------------
diff --git a/src/tests/main.cpp b/src/tests/main.cpp
index b06c0d1..868bdd5 100644
--- a/src/tests/main.cpp
+++ b/src/tests/main.cpp
@@ -29,9 +29,10 @@
 
 #include "logging/logging.hpp"
 
+#include "messages/messages.hpp" // For GOOGLE_PROTOBUF_VERIFY_VERSION.
+
 #include "tests/environment.hpp"
 #include "tests/flags.hpp"
-#include "tests/utils.hpp"
 
 using namespace mesos::internal;
 using namespace mesos::internal::tests;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/master_detector_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_detector_tests.cpp b/src/tests/master_detector_tests.cpp
index c9d6d20..57f4e3e 100644
--- a/src/tests/master_detector_tests.cpp
+++ b/src/tests/master_detector_tests.cpp
@@ -48,7 +48,8 @@
 
 #include "slave/slave.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/isolator.hpp"
+#include "tests/mesos.hpp"
 #ifdef MESOS_HAS_JAVA
 #include "tests/zookeeper.hpp"
 #endif
@@ -75,16 +76,20 @@ using testing::AtMost;
 using testing::Return;
 
 
-class MasterDetectorTest : public MesosClusterTest {};
+class MasterDetectorTest : public MesosTest {};
 
 
 TEST_F(MasterDetectorTest, File)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
+  Files files;
   TestingIsolator isolator;
-  Slave s(cluster.slaves.flags, true, &isolator, &cluster.files);
+
+  slave::Flags flags = CreateSlaveFlags();
+
+  Slave s(flags, true, &isolator, &files);
   PID<Slave> slave = process::spawn(&s);
 
   // Write "master" to a file and use the "file://" mechanism to
@@ -92,7 +97,7 @@ TEST_F(MasterDetectorTest, File)
   // detector for the master first.
   BasicMasterDetector detector1(master.get(), vector<UPID>(), true);
 
-  const string& path = path::join(cluster.slaves.flags.work_dir, "master");
+  const string& path = path::join(flags.work_dir, "master");
   ASSERT_SOME(os::write(path, stringify(master.get())));
 
   Try<MasterDetector*> detector =
@@ -119,7 +124,7 @@ TEST_F(MasterDetectorTest, File)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 
   process::terminate(slave);
   process::wait(slave);


[17/28] git commit: Removed unnecessary TestingIsolators.

Posted by be...@apache.org.
Removed unnecessary TestingIsolators.

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


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

Branch: refs/heads/master
Commit: fd981ce6eb5a3fc86a263b9b38a8b7280a4b89b5
Parents: bb18d3b
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sat May 11 10:18:30 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:41 2013 -0700

----------------------------------------------------------------------
 src/tests/allocator_tests.cpp |   32 +++++---------------------------
 1 files changed, 5 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/fd981ce6/src/tests/allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_tests.cpp b/src/tests/allocator_tests.cpp
index 7ee71de..e8f833d 100644
--- a/src/tests/allocator_tests.cpp
+++ b/src/tests/allocator_tests.cpp
@@ -34,7 +34,6 @@
 #include "master/hierarchical_allocator_process.hpp"
 #include "master/master.hpp"
 
-#include "tests/isolator.hpp"
 #include "tests/mesos.hpp"
 
 using namespace mesos;
@@ -561,14 +560,13 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
   ASSERT_SOME(master);
 
   MockExecutor exec(DEFAULT_EXECUTOR_ID);
-  TestingIsolator isolator(&exec);
 
   slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:3;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
+  Try<PID<Slave> > slave = this->StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo1;
@@ -596,9 +594,6 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
                     FutureArg<1>(&offers1)))
     .WillRepeatedly(DeclineOffers());
 
-  EXPECT_CALL(isolator, resourcesChanged(_, _, _))
-    .WillRepeatedly(DoDefault());
-
   EXPECT_CALL(exec, registered(_, _, _, _));
 
   Future<Nothing> launchTask;
@@ -701,17 +696,12 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
   EXPECT_CALL(exec, shutdown(_))
     .Times(AtMost(2));
 
-  TestingIsolator isolator(&exec);
-
   slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:3;mem:1024");
 
-  EXPECT_CALL(isolator, resourcesChanged(_, _, _))
-    .WillRepeatedly(DoDefault());
-
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
+  Try<PID<Slave> > slave = this->StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched1;
@@ -820,14 +810,13 @@ TYPED_TEST(AllocatorTest, SlaveLost)
   ASSERT_SOME(master);
 
   MockExecutor exec(DEFAULT_EXECUTOR_ID);
-  TestingIsolator isolator(&exec);
 
   slave::Flags flags1 = this->CreateSlaveFlags();
   flags1.resources = Option<string>("cpus:2;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave1 = this->StartSlave(&isolator, flags1);
+  Try<PID<Slave> > slave1 = this->StartSlave(&exec, flags1);
   ASSERT_SOME(slave1);
 
   MockScheduler sched1;
@@ -855,9 +844,6 @@ TYPED_TEST(AllocatorTest, SlaveLost)
     .WillOnce(DoAll(SendStatusUpdateFromTask(TASK_RUNNING),
                     FutureSatisfy(&launchTask)));
 
-  EXPECT_CALL(isolator, resourcesChanged(_, _, _))
-    .WillRepeatedly(DoDefault());
-
   driver1.start();
 
   AWAIT_READY(resourceOffers1);
@@ -948,14 +934,13 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
   ASSERT_SOME(master);
 
   MockExecutor exec(DEFAULT_EXECUTOR_ID);
-  TestingIsolator isolator(&exec);
 
   slave::Flags flags1 = this->CreateSlaveFlags();
   flags1.resources = Option<string>("cpus:3;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave1 = this->StartSlave(&isolator, flags1);
+  Try<PID<Slave> > slave1 = this->StartSlave(&exec, flags1);
   ASSERT_SOME(slave1);
 
   MockScheduler sched1;
@@ -992,9 +977,6 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
     .WillOnce(DoAll(SendStatusUpdateFromTask(TASK_RUNNING),
                     FutureSatisfy(&launchTask)));
 
-  EXPECT_CALL(isolator, resourcesChanged(_, _, _))
-    .WillRepeatedly(DoDefault());
-
   driver1.start();
 
   AWAIT_READY(resourceOffers1);
@@ -1055,14 +1037,13 @@ TYPED_TEST(AllocatorTest, TaskFinished)
   ASSERT_SOME(master);
 
   MockExecutor exec(DEFAULT_EXECUTOR_ID);
-  TestingIsolator isolator(&exec);
 
   slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:3;mem:1024");
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
+  Try<PID<Slave> > slave = this->StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched1;
@@ -1107,9 +1088,6 @@ TYPED_TEST(AllocatorTest, TaskFinished)
                     FutureSatisfy(&launchTask)))
     .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
 
-  EXPECT_CALL(isolator, resourcesChanged(_, _, _))
-    .WillRepeatedly(DoDefault());
-
   driver1.start();
 
   AWAIT_READY(resourceOffers1);


[07/28] git commit: Refactored zookeeper_tests.cpp into master_detector_tests.cpp and group_tests.cpp.

Posted by be...@apache.org.
Refactored zookeeper_tests.cpp into master_detector_tests.cpp and
group_tests.cpp.

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


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

Branch: refs/heads/master
Commit: 0ebf3933b597c1a4cb65cca505cd01fb415517da
Parents: 39ce99e
Author: Benjamin Hindman <be...@twitter.com>
Authored: Thu Apr 25 19:22:22 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/Makefile.am                     |    1 +
 src/tests/group_tests.cpp           |  295 +++++++++++
 src/tests/master_detector_tests.cpp |  510 +++++++++++++++++++
 src/tests/zookeeper_test.hpp        |   31 ++
 src/tests/zookeeper_tests.cpp       |  796 ------------------------------
 5 files changed, 837 insertions(+), 796 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/0ebf3933/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 343a7c5..22346f3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -775,6 +775,7 @@ mesos_tests_SOURCES = tests/main.cpp tests/utils.cpp			\
 	              tests/slave_recovery_tests.cpp			\
 	              tests/status_update_manager_tests.cpp		\
 	              tests/gc_tests.cpp				\
+	              tests/group_tests.cpp				\
 	              tests/resource_offers_tests.cpp			\
 	              tests/fault_tolerance_tests.cpp			\
 	              tests/files_tests.cpp tests/flags_tests.cpp	\

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/0ebf3933/src/tests/group_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/group_tests.cpp b/src/tests/group_tests.cpp
new file mode 100644
index 0000000..3e442cd
--- /dev/null
+++ b/src/tests/group_tests.cpp
@@ -0,0 +1,295 @@
+/**
+ * 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 <zookeeper.h>
+
+#include <gmock/gmock.h>
+
+#include <string>
+
+#include <process/future.hpp>
+
+#include <stout/option.hpp>
+
+#include "tests/utils.hpp"
+#include "tests/zookeeper_test.hpp"
+
+#include "zookeeper/authentication.hpp"
+#include "zookeeper/group.hpp"
+
+using namespace mesos::internal;
+using namespace mesos::internal::tests;
+
+using zookeeper::Group;
+
+using process::Future;
+
+
+class GroupTest : public ZooKeeperTest {};
+
+
+TEST_F(GroupTest, Group)
+{
+  Group group(server->connectString(), NO_TIMEOUT, "/test/");
+
+  Future<Group::Membership> membership = group.join("hello world");
+
+  AWAIT_READY(membership);
+
+  Future<std::set<Group::Membership> > memberships = group.watch();
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(1u, memberships.get().size());
+  EXPECT_EQ(1u, memberships.get().count(membership.get()));
+
+  Future<std::string> data = group.data(membership.get());
+
+  AWAIT_EXPECT_EQ("hello world", data);
+
+  Future<bool> cancellation = group.cancel(membership.get());
+
+  AWAIT_EXPECT_EQ(true, cancellation);
+
+  memberships = group.watch(memberships.get());
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(0u, memberships.get().size());
+
+  ASSERT_TRUE(membership.get().cancelled().isReady());
+  ASSERT_TRUE(membership.get().cancelled().get());
+}
+
+
+TEST_F(GroupTest, GroupJoinWithDisconnect)
+{
+  Group group(server->connectString(), NO_TIMEOUT, "/test/");
+
+  server->shutdownNetwork();
+
+  Future<Group::Membership> membership = group.join("hello world");
+
+  EXPECT_TRUE(membership.isPending());
+
+  server->startNetwork();
+
+  AWAIT_READY(membership);
+
+  Future<std::set<Group::Membership> > memberships = group.watch();
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(1u, memberships.get().size());
+  EXPECT_EQ(1u, memberships.get().count(membership.get()));
+}
+
+
+TEST_F(GroupTest, GroupDataWithDisconnect)
+{
+  Group group(server->connectString(), NO_TIMEOUT, "/test/");
+
+  Future<Group::Membership> membership = group.join("hello world");
+
+  AWAIT_READY(membership);
+
+  Future<std::set<Group::Membership> > memberships = group.watch();
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(1u, memberships.get().size());
+  EXPECT_EQ(1u, memberships.get().count(membership.get()));
+
+  server->shutdownNetwork();
+
+  Future<std::string> data = group.data(membership.get());
+
+  EXPECT_TRUE(data.isPending());
+
+  server->startNetwork();
+
+  AWAIT_EXPECT_EQ("hello world", data);
+}
+
+
+TEST_F(GroupTest, GroupCancelWithDisconnect)
+{
+  Group group(server->connectString(), NO_TIMEOUT, "/test/");
+
+  Future<Group::Membership> membership = group.join("hello world");
+
+  AWAIT_READY(membership);
+
+  Future<std::set<Group::Membership> > memberships = group.watch();
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(1u, memberships.get().size());
+  EXPECT_EQ(1u, memberships.get().count(membership.get()));
+
+  Future<std::string> data = group.data(membership.get());
+
+  AWAIT_EXPECT_EQ("hello world", data);
+
+  server->shutdownNetwork();
+
+  Future<bool> cancellation = group.cancel(membership.get());
+
+  EXPECT_TRUE(cancellation.isPending());
+
+  server->startNetwork();
+
+  AWAIT_EXPECT_EQ(true, cancellation);
+
+  memberships = group.watch(memberships.get());
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(0u, memberships.get().size());
+
+  ASSERT_TRUE(membership.get().cancelled().isReady());
+  ASSERT_TRUE(membership.get().cancelled().get());
+}
+
+
+TEST_F(GroupTest, GroupWatchWithSessionExpiration)
+{
+  Group group(server->connectString(), NO_TIMEOUT, "/test/");
+
+  Future<Group::Membership> membership = group.join("hello world");
+
+  AWAIT_READY(membership);
+
+  Future<std::set<Group::Membership> > memberships = group.watch();
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(1u, memberships.get().size());
+  EXPECT_EQ(1u, memberships.get().count(membership.get()));
+
+  Future<Option<int64_t> > session = group.session();
+
+  AWAIT_READY(session);
+  ASSERT_SOME(session.get());
+
+  memberships = group.watch(memberships.get());
+
+  server->expireSession(session.get().get());
+
+  AWAIT_READY(memberships);
+  EXPECT_EQ(0u, memberships.get().size());
+
+  ASSERT_TRUE(membership.get().cancelled().isReady());
+  ASSERT_FALSE(membership.get().cancelled().get());
+}
+
+
+TEST_F(GroupTest, MultipleGroups)
+{
+  Group group1(server->connectString(), NO_TIMEOUT, "/test/");
+  Group group2(server->connectString(), NO_TIMEOUT, "/test/");
+
+  Future<Group::Membership> membership1 = group1.join("group 1");
+
+  AWAIT_READY(membership1);
+
+  Future<Group::Membership> membership2 = group2.join("group 2");
+
+  AWAIT_READY(membership2);
+
+  Future<std::set<Group::Membership> > memberships1 = group1.watch();
+
+  AWAIT_READY(memberships1);
+  EXPECT_EQ(2u, memberships1.get().size());
+  EXPECT_EQ(1u, memberships1.get().count(membership1.get()));
+  EXPECT_EQ(1u, memberships1.get().count(membership2.get()));
+
+  Future<std::set<Group::Membership> > memberships2 = group2.watch();
+
+  AWAIT_READY(memberships2);
+  EXPECT_EQ(2u, memberships2.get().size());
+  EXPECT_EQ(1u, memberships2.get().count(membership1.get()));
+  EXPECT_EQ(1u, memberships2.get().count(membership2.get()));
+
+  Future<bool> cancelled;
+
+  // Now watch the membership owned by group1 from group2.
+  foreach (const Group::Membership& membership, memberships2.get()) {
+    if (membership == membership1.get()) {
+      cancelled = membership.cancelled();
+      break;
+    }
+  }
+
+  Future<Option<int64_t> > session1 = group1.session();
+
+  AWAIT_READY(session1);
+  ASSERT_SOME(session1.get());
+
+  server->expireSession(session1.get().get());
+
+  AWAIT_ASSERT_EQ(false, cancelled);
+}
+
+
+TEST_F(GroupTest, GroupPathWithRestrictivePerms)
+{
+  ZooKeeperTest::TestWatcher watcher;
+
+  ZooKeeper authenticatedZk(server->connectString(), NO_TIMEOUT, &watcher);
+  watcher.awaitSessionEvent(ZOO_CONNECTED_STATE);
+
+  authenticatedZk.authenticate("digest", "creator:creator");
+
+  authenticatedZk.create(
+      "/read-only",
+      "42",
+      zookeeper::EVERYONE_READ_CREATOR_ALL,
+      0,
+      NULL);
+
+  ASSERT_ZK_GET("42", &authenticatedZk, "/read-only");
+
+  authenticatedZk.create(
+      "/read-only/writable",
+      "37",
+      ZOO_OPEN_ACL_UNSAFE,
+      0,
+      NULL);
+
+  ASSERT_ZK_GET("37", &authenticatedZk, "/read-only/writable");
+
+  zookeeper::Authentication auth("digest", "non-creator:non-creator");
+
+  Group failedGroup1(
+      server->connectString(),
+      NO_TIMEOUT,
+      "/read-only/",
+      auth);
+
+  AWAIT_FAILED(failedGroup1.join("fail"));
+
+  Group failedGroup2(
+      server->connectString(),
+      NO_TIMEOUT,
+      "/read-only/new",
+      auth);
+
+  AWAIT_FAILED(failedGroup2.join("fail"));
+
+  Group successGroup(
+      server->connectString(),
+      NO_TIMEOUT,
+      "/read-only/writable/",
+      auth);
+
+  AWAIT_READY(successGroup.join("succeed"));
+}

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/0ebf3933/src/tests/master_detector_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_detector_tests.cpp b/src/tests/master_detector_tests.cpp
index 3a7b3b4..1739823 100644
--- a/src/tests/master_detector_tests.cpp
+++ b/src/tests/master_detector_tests.cpp
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+#include <zookeeper.h>
+
 #include <gmock/gmock.h>
 
 #include <fstream>
@@ -26,9 +28,14 @@
 #include <mesos/executor.hpp>
 #include <mesos/scheduler.hpp>
 
+#include <process/clock.hpp>
+#include <process/future.hpp>
 #include <process/pid.hpp>
+#include <process/protobuf.hpp>
 
+#include <stout/duration.hpp>
 #include <stout/gtest.hpp>
+#include <stout/nothing.hpp>
 #include <stout/os.hpp>
 #include <stout/path.hpp>
 #include <stout/try.hpp>
@@ -37,9 +44,14 @@
 
 #include "master/master.hpp"
 
+#include "messages/messages.hpp"
+
 #include "slave/slave.hpp"
 
 #include "tests/utils.hpp"
+#ifdef MESOS_HAS_JAVA
+#include "tests/zookeeper_test.hpp"
+#endif
 
 using namespace mesos;
 using namespace mesos::internal;
@@ -49,6 +61,7 @@ using mesos::internal::master::Master;
 
 using mesos::internal::slave::Slave;
 
+using process::Clock;
 using process::Future;
 using process::PID;
 using process::UPID;
@@ -58,6 +71,8 @@ using std::string;
 using std::vector;
 
 using testing::_;
+using testing::AtMost;
+using testing::Return;
 
 
 class MasterDetectorTest : public MesosClusterTest {};
@@ -109,3 +124,498 @@ TEST_F(MasterDetectorTest, File)
   process::terminate(slave);
   process::wait(slave);
 }
+
+
+class MockMasterDetectorListenerProcess
+  : public ProtobufProcess<MockMasterDetectorListenerProcess>
+{
+public:
+  MockMasterDetectorListenerProcess() {}
+  virtual ~MockMasterDetectorListenerProcess() {}
+
+  MOCK_METHOD1(newMasterDetected, void(const process::UPID&));
+  MOCK_METHOD0(noMasterDetected, void(void));
+
+protected:
+  virtual void initialize()
+  {
+    install<NewMasterDetectedMessage>(
+        &MockMasterDetectorListenerProcess::newMasterDetected,
+        &NewMasterDetectedMessage::pid);
+
+    install<NoMasterDetectedMessage>(
+        &MockMasterDetectorListenerProcess::noMasterDetected);
+  }
+};
+
+
+#ifdef MESOS_HAS_JAVA
+class ZooKeeperMasterDetectorTest : public ZooKeeperTest {};
+
+
+TEST_F(ZooKeeperMasterDetectorTest, MasterDetector)
+{
+  MockMasterDetectorListenerProcess mock;
+  process::spawn(mock);
+
+  Future<Nothing> newMasterDetected;
+  EXPECT_CALL(mock, newMasterDetected(mock.self()))
+    .WillOnce(FutureSatisfy(&newMasterDetected));
+
+  std::string master = "zk://" + server->connectString() + "/mesos";
+
+  Try<MasterDetector*> detector =
+    MasterDetector::create(master, mock.self(), true, true);
+
+  ASSERT_SOME(detector);
+
+  AWAIT_READY(newMasterDetected);
+
+  MasterDetector::destroy(detector.get());
+
+  process::terminate(mock);
+  process::wait(mock);
+}
+
+
+TEST_F(ZooKeeperMasterDetectorTest, MasterDetectors)
+{
+  MockMasterDetectorListenerProcess mock1;
+  process::spawn(mock1);
+
+  Future<Nothing> newMasterDetected1;
+  EXPECT_CALL(mock1, newMasterDetected(mock1.self()))
+    .WillOnce(FutureSatisfy(&newMasterDetected1));
+
+  std::string master = "zk://" + server->connectString() + "/mesos";
+
+  Try<MasterDetector*> detector1 =
+    MasterDetector::create(master, mock1.self(), true, true);
+
+  ASSERT_SOME(detector1);
+
+  AWAIT_READY(newMasterDetected1);
+
+  MockMasterDetectorListenerProcess mock2;
+  process::spawn(mock2);
+
+  Future<Nothing> newMasterDetected2;
+  EXPECT_CALL(mock2, newMasterDetected(mock1.self())) // N.B. mock1
+    .WillOnce(FutureSatisfy(&newMasterDetected2));
+
+  Try<MasterDetector*> detector2 =
+    MasterDetector::create(master, mock2.self(), true, true);
+
+  ASSERT_SOME(detector2);
+
+  AWAIT_READY(newMasterDetected2);
+
+  // Destroying detector1 (below) might cause another election so we
+  // need to set up expectations appropriately.
+  EXPECT_CALL(mock2, newMasterDetected(_))
+    .WillRepeatedly(Return());
+
+  MasterDetector::destroy(detector1.get());
+
+  process::terminate(mock1);
+  process::wait(mock1);
+
+  MasterDetector::destroy(detector2.get());
+
+  process::terminate(mock2);
+  process::wait(mock2);
+}
+
+
+TEST_F(ZooKeeperMasterDetectorTest, MasterDetectorShutdownNetwork)
+{
+  Clock::pause();
+
+  MockMasterDetectorListenerProcess mock;
+  process::spawn(mock);
+
+  Future<Nothing> newMasterDetected1;
+  EXPECT_CALL(mock, newMasterDetected(mock.self()))
+    .WillOnce(FutureSatisfy(&newMasterDetected1));
+
+  std::string master = "zk://" + server->connectString() + "/mesos";
+
+  Try<MasterDetector*> detector =
+    MasterDetector::create(master, mock.self(), true, true);
+
+  ASSERT_SOME(detector);
+
+  AWAIT_READY(newMasterDetected1);
+
+  Future<Nothing> noMasterDetected;
+  EXPECT_CALL(mock, noMasterDetected())
+    .WillOnce(FutureSatisfy(&noMasterDetected));
+
+  server->shutdownNetwork();
+
+  Clock::advance(Seconds(10)); // TODO(benh): Get session timeout from detector.
+
+  AWAIT_READY(noMasterDetected);
+
+  Future<Nothing> newMasterDetected2;
+  EXPECT_CALL(mock, newMasterDetected(mock.self()))
+    .WillOnce(FutureSatisfy(&newMasterDetected2));
+
+  server->startNetwork();
+
+  AWAIT_READY(newMasterDetected2);
+
+  MasterDetector::destroy(detector.get());
+
+  process::terminate(mock);
+  process::wait(mock);
+
+  Clock::resume();
+}
+
+
+// Tests that a detector sends a NoMasterDetectedMessage when we
+// reach our ZooKeeper session timeout. This is to enforce that we
+// manually expire the session when we don't get reconnected within
+// the ZOOKEEPER_SESSION_TIMEOUT.
+TEST_F(ZooKeeperTest, MasterDetectorTimedoutSession)
+{
+  Try<zookeeper::URL> url =
+    zookeeper::URL::parse("zk://" + server->connectString() + "/mesos");
+  ASSERT_SOME(url);
+
+  // First we bring up three master detector listeners:
+  //   1. A leading contender.
+  //   2. A non-leading contender.
+  //   3. A non-contender.
+
+  // 1. Simulate a leading contender.
+  MockMasterDetectorListenerProcess leader;
+
+  Future<Nothing> newMasterDetected;
+  EXPECT_CALL(leader, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected));
+
+  process::spawn(leader);
+
+  ZooKeeperMasterDetector leaderDetector(
+      url.get(), leader.self(), true, true);
+
+  AWAIT_READY(newMasterDetected);
+
+  // 2. Simulate a non-leading contender.
+  MockMasterDetectorListenerProcess follower;
+
+  EXPECT_CALL(follower, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected));
+
+  process::spawn(follower);
+
+  ZooKeeperMasterDetector followerDetector(
+      url.get(), follower.self(), true, true);
+
+  AWAIT_READY(newMasterDetected);
+
+  // 3. Simulate a non-contender.
+  MockMasterDetectorListenerProcess nonContender;
+
+  EXPECT_CALL(nonContender, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected));
+
+  process::spawn(nonContender);
+
+  ZooKeeperMasterDetector nonContenderDetector(
+      url.get(), nonContender.self(), false, true);
+
+  AWAIT_READY(newMasterDetected);
+
+  // Now we want to induce lost connections on each of the
+  // master detectors.
+  // Induce a reconnection on the leader.
+  Future<Nothing> leaderReconnecting = FUTURE_DISPATCH(
+      leaderDetector.process->self(),
+      &ZooKeeperMasterDetectorProcess::reconnecting);
+
+  dispatch(leaderDetector.process,
+           &ZooKeeperMasterDetectorProcess::reconnecting);
+
+  AWAIT_READY(leaderReconnecting);
+
+  // Induce a reconnection on the follower.
+  Future<Nothing> followerReconnecting = FUTURE_DISPATCH(
+      followerDetector.process->self(),
+      &ZooKeeperMasterDetectorProcess::reconnecting);
+
+  dispatch(followerDetector.process,
+           &ZooKeeperMasterDetectorProcess::reconnecting);
+
+  AWAIT_READY(followerReconnecting);
+
+  // Induce a reconnection on the non-contender.
+  Future<Nothing> nonContenderReconnecting = FUTURE_DISPATCH(
+      nonContenderDetector.process->self(),
+      &ZooKeeperMasterDetectorProcess::reconnecting);
+
+  dispatch(nonContenderDetector.process,
+           &ZooKeeperMasterDetectorProcess::reconnecting);
+
+  AWAIT_READY(nonContenderReconnecting);
+
+  // Now induce the reconnection timeout.
+  Future<Nothing> leaderNoMasterDetected;
+  EXPECT_CALL(leader, noMasterDetected())
+    .WillOnce(FutureSatisfy(&leaderNoMasterDetected));
+
+  Future<Nothing> followerNoMasterDetected;
+  EXPECT_CALL(follower, noMasterDetected())
+    .WillOnce(FutureSatisfy(&followerNoMasterDetected));
+
+  Future<Nothing> nonContenderNoMasterDetected;
+  EXPECT_CALL(nonContender, noMasterDetected())
+    .WillOnce(FutureSatisfy(&nonContenderNoMasterDetected));
+
+  Clock::pause();
+  Clock::advance(ZOOKEEPER_SESSION_TIMEOUT);
+  Clock::settle();
+
+  AWAIT_READY(leaderNoMasterDetected);
+  AWAIT_READY(followerNoMasterDetected);
+  AWAIT_READY(nonContenderNoMasterDetected);
+
+  process::terminate(leader);
+  process::wait(leader);
+
+  process::terminate(follower);
+  process::wait(follower);
+
+  process::terminate(nonContender);
+  process::wait(nonContender);
+}
+
+
+// Tests whether a leading master correctly detects a new master when
+// its ZooKeeper session is expired.
+TEST_F(ZooKeeperMasterDetectorTest, MasterDetectorExpireMasterZKSession)
+{
+  // Simulate a leading master.
+  MockMasterDetectorListenerProcess leader;
+
+  Future<Nothing> newMasterDetected1, newMasterDetected2;
+  EXPECT_CALL(leader, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected1))
+    .WillOnce(FutureSatisfy(&newMasterDetected2));
+
+  EXPECT_CALL(leader, noMasterDetected())
+    .Times(0);
+
+  process::spawn(leader);
+
+  std::string znode = "zk://" + server->connectString() + "/mesos";
+
+  Try<zookeeper::URL> url = zookeeper::URL::parse(znode);
+  ASSERT_SOME(url);
+
+  // Leader's detector.
+  ZooKeeperMasterDetector leaderDetector(
+      url.get(), leader.self(), true, true);
+
+  AWAIT_READY(newMasterDetected1);
+
+  // Simulate a following master.
+  MockMasterDetectorListenerProcess follower;
+
+  Future<Nothing> newMasterDetected3;
+  EXPECT_CALL(follower, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected3))
+    .WillRepeatedly(Return());
+
+  EXPECT_CALL(follower, noMasterDetected())
+    .Times(0);
+
+  process::spawn(follower);
+
+  // Follower's detector.
+  ZooKeeperMasterDetector followerDetector(
+      url.get(),
+      follower.self(),
+      true,
+      true);
+
+  AWAIT_READY(newMasterDetected3);
+
+  // Now expire the leader's zk session.
+  Future<int64_t> session = leaderDetector.session();
+  AWAIT_READY(session);
+
+  server->expireSession(session.get());
+
+  // Wait for session expiration and ensure we receive a
+  // NewMasterDetected message.
+  AWAIT_READY(newMasterDetected2);
+
+  process::terminate(follower);
+  process::wait(follower);
+
+  process::terminate(leader);
+  process::wait(leader);
+}
+
+
+// Tests whether a slave correctly DOES NOT disconnect from the master
+// when its ZooKeeper session is expired, but the master still stays
+// the leader when the slave re-connects with the ZooKeeper.
+TEST_F(ZooKeeperMasterDetectorTest, MasterDetectorExpireSlaveZKSession)
+{
+  // Simulate a leading master.
+  MockMasterDetectorListenerProcess master;
+
+  Future<Nothing> newMasterDetected1;
+  EXPECT_CALL(master, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected1));
+
+  EXPECT_CALL(master, noMasterDetected())
+    .Times(0);
+
+  process::spawn(master);
+
+  std::string znode = "zk://" + server->connectString() + "/mesos";
+
+  Try<zookeeper::URL> url = zookeeper::URL::parse(znode);
+  ASSERT_SOME(url);
+
+  // Leading master's detector.
+  ZooKeeperMasterDetector masterDetector(
+      url.get(), master.self(), true, true);
+
+  AWAIT_READY(newMasterDetected1);
+
+  // Simulate a slave.
+  MockMasterDetectorListenerProcess slave;
+
+  Future<Nothing> newMasterDetected2, newMasterDetected3;
+  EXPECT_CALL(slave, newMasterDetected(_))
+    .Times(1)
+    .WillOnce(FutureSatisfy(&newMasterDetected2));
+
+  EXPECT_CALL(slave, noMasterDetected())
+    .Times(0);
+
+  process::spawn(slave);
+
+  // Slave's master detector.
+  ZooKeeperMasterDetector slaveDetector(
+      url.get(), slave.self(), false, true);
+
+  AWAIT_READY(newMasterDetected2);
+
+  // Now expire the slave's zk session.
+  Future<int64_t> session = slaveDetector.session();
+  AWAIT_READY(session);
+
+  server->expireSession(session.get());
+
+  // Wait for enough time to ensure no NewMasterDetected message is sent.
+  os::sleep(Seconds(4)); // ZooKeeper needs extra time for session expiration.
+
+  process::terminate(slave);
+  process::wait(slave);
+
+  process::terminate(master);
+  process::wait(master);
+}
+
+
+// Tests whether a slave correctly detects the new master when its
+// ZooKeeper session is expired and a new master is elected before the
+// slave reconnects with ZooKeeper.
+TEST_F(ZooKeeperMasterDetectorTest, MasterDetectorExpireSlaveZKSessionNewMaster)
+{
+  // Simulate a leading master.
+  MockMasterDetectorListenerProcess master1;
+
+  Future<Nothing> newMasterDetected1;
+  EXPECT_CALL(master1, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected1))
+    .WillRepeatedly(Return());
+
+  EXPECT_CALL(master1, noMasterDetected())
+    .Times(0);
+
+  process::spawn(master1);
+
+  std::string znode = "zk://" + server->connectString() + "/mesos";
+
+  Try<zookeeper::URL> url = zookeeper::URL::parse(znode);
+  ASSERT_SOME(url);
+
+  // Leading master's detector.
+  ZooKeeperMasterDetector masterDetector1(
+      url.get(), master1.self(), true, true);
+
+  AWAIT_READY(newMasterDetected1);
+
+  // Simulate a non-leading master.
+  MockMasterDetectorListenerProcess master2;
+
+  Future<Nothing> newMasterDetected2;
+  EXPECT_CALL(master2, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected2))
+    .WillRepeatedly(Return());
+
+  EXPECT_CALL(master2, noMasterDetected())
+    .Times(0);
+
+  process::spawn(master2);
+
+  // Non-leading master's detector.
+  ZooKeeperMasterDetector masterDetector2(
+      url.get(), master2.self(), true, true);
+
+  AWAIT_READY(newMasterDetected2);
+
+  // Simulate a slave.
+  MockMasterDetectorListenerProcess slave;
+
+  Future<Nothing> newMasterDetected3, newMasterDetected4;
+  EXPECT_CALL(slave, newMasterDetected(_))
+    .WillOnce(FutureSatisfy(&newMasterDetected3))
+    .WillOnce(FutureSatisfy(&newMasterDetected4));
+
+  EXPECT_CALL(slave, noMasterDetected())
+    .Times(AtMost(1));
+
+  process::spawn(slave);
+
+  // Slave's master detector.
+  ZooKeeperMasterDetector slaveDetector(
+      url.get(), slave.self(), false, true);
+
+  AWAIT_READY(newMasterDetected3);
+
+  // Now expire the slave's and leading master's zk sessions.
+  // NOTE: Here we assume that slave stays disconnected from the ZK when the
+  // leading master loses its session.
+  Future<int64_t> slaveSession = slaveDetector.session();
+  AWAIT_READY(slaveSession);
+
+  server->expireSession(slaveSession.get());
+
+  Future<int64_t> masterSession = masterDetector1.session();
+  AWAIT_READY(masterSession);
+
+  server->expireSession(masterSession.get());
+
+  // Wait for session expiration and ensure we receive a
+  // NewMasterDetected message.
+  AWAIT_READY(newMasterDetected4);
+
+  process::terminate(slave);
+  process::wait(slave);
+
+  process::terminate(master2);
+  process::wait(master2);
+
+  process::terminate(master1);
+  process::wait(master1);
+}
+#endif // MESOS_HAS_JAVA

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/0ebf3933/src/tests/zookeeper_test.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test.hpp b/src/tests/zookeeper_test.hpp
index b5215b0..61a3d25 100644
--- a/src/tests/zookeeper_test.hpp
+++ b/src/tests/zookeeper_test.hpp
@@ -38,6 +38,37 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
+// Helper for invoking ZooKeeper::get(path, ...) in order to check the
+// data stored at a specified znode path.
+inline ::testing::AssertionResult AssertZKGet(
+    const char* expectedExpr,
+    const char* zkExpr,
+    const char* pathExpr,
+    const std::string& expected,
+    ZooKeeper* zk,
+    const std::string& path)
+{
+  std::string result;
+  int code = zk->get(path, false, &result, NULL);
+  if (code == ZOK) {
+    if (expected == result) {
+      return ::testing::AssertionSuccess();
+    } else {
+      return ::testing::AssertionFailure()
+        << "Expected data at znode '" << pathExpr << "' "
+        << "to be '" << expected << "', but actually '" << result << "'";
+    }
+  } else {
+    return ::testing::AssertionFailure()
+      << "(" << zkExpr << ").get(" << pathExpr << ", ...): "
+      << zk->message(code);
+  }
+}
+
+#define ASSERT_ZK_GET(expected, zk, path)                               \
+  ASSERT_PRED_FORMAT3(mesos::internal::tests::AssertZKGet, expected, zk, path)
+
+
 // A fixture for tests that need to interact with a ZooKeeper server
 // ensemble. Tests can access the in process ZooKeeperTestServer via
 // the variable 'server'. This test fixture ensures the server is

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/0ebf3933/src/tests/zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_tests.cpp b/src/tests/zookeeper_tests.cpp
index e9180bf..5193d03 100644
--- a/src/tests/zookeeper_tests.cpp
+++ b/src/tests/zookeeper_tests.cpp
@@ -22,68 +22,14 @@
 
 #include <string>
 
-#include <process/clock.hpp>
-#include <process/process.hpp>
-#include <process/protobuf.hpp>
-
-#include <stout/duration.hpp>
-#include <stout/os.hpp>
 #include <stout/strings.hpp>
-#include <stout/nothing.hpp>
-#include <stout/try.hpp>
-
-#include "detector/detector.hpp"
-
-#include "messages/messages.hpp"
 
 #include "tests/utils.hpp"
 #include "tests/zookeeper_test.hpp"
 
-#include "zookeeper/authentication.hpp"
-#include "zookeeper/group.hpp"
-#include "zookeeper/url.hpp"
-
 using namespace mesos::internal;
 using namespace mesos::internal::tests;
 
-using process::Clock;
-using process::Future;
-
-using testing::_;
-using testing::AtMost;
-using testing::Return;
-
-
-// Helper for invoking ZooKeeper::get(path, ...) in order to check the
-// data stored at a specified znode path.
-::testing::AssertionResult AssertZKGet(
-    const char* expectedExpr,
-    const char* zkExpr,
-    const char* pathExpr,
-    const std::string& expected,
-    ZooKeeper* zk,
-    const std::string& path)
-{
-  std::string result;
-  int code = zk->get(path, false, &result, NULL);
-  if (code == ZOK) {
-    if (expected == result) {
-      return ::testing::AssertionSuccess();
-    } else {
-      return ::testing::AssertionFailure()
-        << "Expected data at znode '" << pathExpr << "' "
-        << "to be '" << expected << "', but actually '" << result << "'";
-    }
-  } else {
-    return ::testing::AssertionFailure()
-      << "(" << zkExpr << ").get(" << pathExpr << ", ...): "
-      << zk->message(code);
-  }
-}
-
-#define ASSERT_ZK_GET(expected, zk, path)               \
-  ASSERT_PRED_FORMAT3(AssertZKGet, expected, zk, path)
-
 
 TEST_F(ZooKeeperTest, Auth)
 {
@@ -158,745 +104,3 @@ TEST_F(ZooKeeperTest, Create)
                                    true));
   EXPECT_TRUE(strings::startsWith(result, "/foo/bar/baz/0"));
 }
-
-
-class MockMasterDetectorListenerProcess
-  : public ProtobufProcess<MockMasterDetectorListenerProcess>
-{
-public:
-  MockMasterDetectorListenerProcess() {}
-  virtual ~MockMasterDetectorListenerProcess() {}
-
-  MOCK_METHOD1(newMasterDetected, void(const process::UPID&));
-  MOCK_METHOD0(noMasterDetected, void(void));
-
-protected:
-  virtual void initialize()
-  {
-    install<NewMasterDetectedMessage>(
-        &MockMasterDetectorListenerProcess::newMasterDetected,
-        &NewMasterDetectedMessage::pid);
-
-    install<NoMasterDetectedMessage>(
-        &MockMasterDetectorListenerProcess::noMasterDetected);
-  }
-};
-
-
-TEST_F(ZooKeeperTest, MasterDetector)
-{
-  MockMasterDetectorListenerProcess mock;
-  process::spawn(mock);
-
-  Future<Nothing> newMasterDetected;
-  EXPECT_CALL(mock, newMasterDetected(mock.self()))
-    .WillOnce(FutureSatisfy(&newMasterDetected));
-
-  std::string master = "zk://" + server->connectString() + "/mesos";
-
-  Try<MasterDetector*> detector =
-    MasterDetector::create(master, mock.self(), true, true);
-
-  ASSERT_SOME(detector);
-
-  AWAIT_READY(newMasterDetected);
-
-  MasterDetector::destroy(detector.get());
-
-  process::terminate(mock);
-  process::wait(mock);
-}
-
-
-TEST_F(ZooKeeperTest, MasterDetectors)
-{
-  MockMasterDetectorListenerProcess mock1;
-  process::spawn(mock1);
-
-  Future<Nothing> newMasterDetected1;
-  EXPECT_CALL(mock1, newMasterDetected(mock1.self()))
-    .WillOnce(FutureSatisfy(&newMasterDetected1));
-
-  std::string master = "zk://" + server->connectString() + "/mesos";
-
-  Try<MasterDetector*> detector1 =
-    MasterDetector::create(master, mock1.self(), true, true);
-
-  ASSERT_SOME(detector1);
-
-  AWAIT_READY(newMasterDetected1);
-
-  MockMasterDetectorListenerProcess mock2;
-  process::spawn(mock2);
-
-  Future<Nothing> newMasterDetected2;
-  EXPECT_CALL(mock2, newMasterDetected(mock1.self())) // N.B. mock1
-    .WillOnce(FutureSatisfy(&newMasterDetected2));
-
-  Try<MasterDetector*> detector2 =
-    MasterDetector::create(master, mock2.self(), true, true);
-
-  ASSERT_SOME(detector2);
-
-  AWAIT_READY(newMasterDetected2);
-
-  // Destroying detector1 (below) might cause another election so we
-  // need to set up expectations appropriately.
-  EXPECT_CALL(mock2, newMasterDetected(_))
-    .WillRepeatedly(Return());
-
-  MasterDetector::destroy(detector1.get());
-
-  process::terminate(mock1);
-  process::wait(mock1);
-
-  MasterDetector::destroy(detector2.get());
-
-  process::terminate(mock2);
-  process::wait(mock2);
-}
-
-
-TEST_F(ZooKeeperTest, MasterDetectorShutdownNetwork)
-{
-  Clock::pause();
-
-  MockMasterDetectorListenerProcess mock;
-  process::spawn(mock);
-
-  Future<Nothing> newMasterDetected1;
-  EXPECT_CALL(mock, newMasterDetected(mock.self()))
-    .WillOnce(FutureSatisfy(&newMasterDetected1));
-
-  std::string master = "zk://" + server->connectString() + "/mesos";
-
-  Try<MasterDetector*> detector =
-    MasterDetector::create(master, mock.self(), true, true);
-
-  ASSERT_SOME(detector);
-
-  AWAIT_READY(newMasterDetected1);
-
-  Future<Nothing> noMasterDetected;
-  EXPECT_CALL(mock, noMasterDetected())
-    .WillOnce(FutureSatisfy(&noMasterDetected));
-
-  server->shutdownNetwork();
-
-  Clock::advance(Seconds(10)); // TODO(benh): Get session timeout from detector.
-
-  AWAIT_READY(noMasterDetected);
-
-  Future<Nothing> newMasterDetected2;
-  EXPECT_CALL(mock, newMasterDetected(mock.self()))
-    .WillOnce(FutureSatisfy(&newMasterDetected2));
-
-  server->startNetwork();
-
-  AWAIT_READY(newMasterDetected2);
-
-  MasterDetector::destroy(detector.get());
-
-  process::terminate(mock);
-  process::wait(mock);
-
-  Clock::resume();
-}
-
-
-// Tests that a detector sends a NoMasterDetectedMessage when we
-// reach our ZooKeeper session timeout. This is to enforce that we
-// manually expire the session when we don't get reconnected within
-// the ZOOKEEPER_SESSION_TIMEOUT.
-TEST_F(ZooKeeperTest, MasterDetectorTimedoutSession)
-{
-  Try<zookeeper::URL> url =
-    zookeeper::URL::parse("zk://" + server->connectString() + "/mesos");
-  ASSERT_SOME(url);
-
-  // First we bring up three master detector listeners:
-  //   1. A leading contender.
-  //   2. A non-leading contender.
-  //   3. A non-contender.
-
-  // 1. Simulate a leading contender.
-  MockMasterDetectorListenerProcess leader;
-
-  Future<Nothing> newMasterDetected;
-  EXPECT_CALL(leader, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected));
-
-  process::spawn(leader);
-
-  ZooKeeperMasterDetector leaderDetector(
-      url.get(), leader.self(), true, true);
-
-  AWAIT_READY(newMasterDetected);
-
-  // 2. Simulate a non-leading contender.
-  MockMasterDetectorListenerProcess follower;
-
-  EXPECT_CALL(follower, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected));
-
-  process::spawn(follower);
-
-  ZooKeeperMasterDetector followerDetector(
-      url.get(), follower.self(), true, true);
-
-  AWAIT_READY(newMasterDetected);
-
-  // 3. Simulate a non-contender.
-  MockMasterDetectorListenerProcess nonContender;
-
-  EXPECT_CALL(nonContender, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected));
-
-  process::spawn(nonContender);
-
-  ZooKeeperMasterDetector nonContenderDetector(
-      url.get(), nonContender.self(), false, true);
-
-  AWAIT_READY(newMasterDetected);
-
-  // Now we want to induce lost connections on each of the
-  // master detectors.
-  // Induce a reconnection on the leader.
-  Future<Nothing> leaderReconnecting = FUTURE_DISPATCH(
-      leaderDetector.process->self(),
-      &ZooKeeperMasterDetectorProcess::reconnecting);
-
-  dispatch(leaderDetector.process,
-           &ZooKeeperMasterDetectorProcess::reconnecting);
-
-  AWAIT_READY(leaderReconnecting);
-
-  // Induce a reconnection on the follower.
-  Future<Nothing> followerReconnecting = FUTURE_DISPATCH(
-      followerDetector.process->self(),
-      &ZooKeeperMasterDetectorProcess::reconnecting);
-
-  dispatch(followerDetector.process,
-           &ZooKeeperMasterDetectorProcess::reconnecting);
-
-  AWAIT_READY(followerReconnecting);
-
-  // Induce a reconnection on the non-contender.
-  Future<Nothing> nonContenderReconnecting = FUTURE_DISPATCH(
-      nonContenderDetector.process->self(),
-      &ZooKeeperMasterDetectorProcess::reconnecting);
-
-  dispatch(nonContenderDetector.process,
-           &ZooKeeperMasterDetectorProcess::reconnecting);
-
-  AWAIT_READY(nonContenderReconnecting);
-
-  // Now induce the reconnection timeout.
-  Future<Nothing> leaderNoMasterDetected;
-  EXPECT_CALL(leader, noMasterDetected())
-    .WillOnce(FutureSatisfy(&leaderNoMasterDetected));
-
-  Future<Nothing> followerNoMasterDetected;
-  EXPECT_CALL(follower, noMasterDetected())
-    .WillOnce(FutureSatisfy(&followerNoMasterDetected));
-
-  Future<Nothing> nonContenderNoMasterDetected;
-  EXPECT_CALL(nonContender, noMasterDetected())
-    .WillOnce(FutureSatisfy(&nonContenderNoMasterDetected));
-
-  Clock::pause();
-  Clock::advance(ZOOKEEPER_SESSION_TIMEOUT);
-  Clock::settle();
-
-  AWAIT_READY(leaderNoMasterDetected);
-  AWAIT_READY(followerNoMasterDetected);
-  AWAIT_READY(nonContenderNoMasterDetected);
-
-  process::terminate(leader);
-  process::wait(leader);
-
-  process::terminate(follower);
-  process::wait(follower);
-
-  process::terminate(nonContender);
-  process::wait(nonContender);
-}
-
-
-// Tests whether a leading master correctly detects a new master when its
-// ZooKeeper session is expired.
-TEST_F(ZooKeeperTest, MasterDetectorExpireMasterZKSession)
-{
-  // Simulate a leading master.
-  MockMasterDetectorListenerProcess leader;
-
-  Future<Nothing> newMasterDetected1, newMasterDetected2;
-  EXPECT_CALL(leader, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected1))
-    .WillOnce(FutureSatisfy(&newMasterDetected2));
-
-  EXPECT_CALL(leader, noMasterDetected())
-    .Times(0);
-
-  process::spawn(leader);
-
-  std::string znode = "zk://" + server->connectString() + "/mesos";
-
-  Try<zookeeper::URL> url = zookeeper::URL::parse(znode);
-  ASSERT_SOME(url);
-
-  // Leader's detector.
-  ZooKeeperMasterDetector leaderDetector(url.get(), leader.self(), true, true);
-
-  AWAIT_READY(newMasterDetected1);
-
-  // Simulate a following master.
-  MockMasterDetectorListenerProcess follower;
-
-  Future<Nothing> newMasterDetected3;
-  EXPECT_CALL(follower, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected3))
-    .WillRepeatedly(Return());
-
-  EXPECT_CALL(follower, noMasterDetected())
-    .Times(0);
-
-  process::spawn(follower);
-
-  // Follower's detector.
-  ZooKeeperMasterDetector followerDetector(
-      url.get(),
-      follower.self(),
-      true,
-      true);
-
-  AWAIT_READY(newMasterDetected3);
-
-  // Now expire the leader's zk session.
-  process::Future<int64_t> session = leaderDetector.session();
-  AWAIT_READY(session);
-
-  server->expireSession(session.get());
-
-  // Wait for session expiration and ensure we receive a
-  // NewMasterDetected message.
-  AWAIT_READY(newMasterDetected2);
-
-  process::terminate(follower);
-  process::wait(follower);
-
-  process::terminate(leader);
-  process::wait(leader);
-}
-
-
-// Tests whether a slave correctly DOES NOT disconnect from the master
-// when its ZooKeeper session is expired, but the master still stays the leader
-// when the slave re-connects with the ZooKeeper.
-TEST_F(ZooKeeperTest, MasterDetectorExpireSlaveZKSession)
-{
-  // Simulate a leading master.
-  MockMasterDetectorListenerProcess master;
-
-  Future<Nothing> newMasterDetected1;
-  EXPECT_CALL(master, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected1));
-
-  EXPECT_CALL(master, noMasterDetected())
-    .Times(0);
-
-  process::spawn(master);
-
-  std::string znode = "zk://" + server->connectString() + "/mesos";
-
-  Try<zookeeper::URL> url = zookeeper::URL::parse(znode);
-  ASSERT_SOME(url);
-
-  // Leading master's detector.
-  ZooKeeperMasterDetector masterDetector(url.get(), master.self(), true, true);
-
-  AWAIT_READY(newMasterDetected1);
-
-  // Simulate a slave.
-  MockMasterDetectorListenerProcess slave;
-
-  Future<Nothing> newMasterDetected2, newMasterDetected3;
-  EXPECT_CALL(slave, newMasterDetected(_))
-    .Times(1)
-    .WillOnce(FutureSatisfy(&newMasterDetected2));
-
-  EXPECT_CALL(slave, noMasterDetected())
-    .Times(0);
-
-  process::spawn(slave);
-
-  // Slave's master detector.
-  ZooKeeperMasterDetector slaveDetector(url.get(), slave.self(), false, true);
-
-  AWAIT_READY(newMasterDetected2);
-
-  // Now expire the slave's zk session.
-  process::Future<int64_t> session = slaveDetector.session();
-  AWAIT_READY(session);
-
-  server->expireSession(session.get());
-
-  // Wait for enough time to ensure no NewMasterDetected message is sent.
-  os::sleep(Seconds(4)); // ZooKeeper needs extra time for session expiration.
-
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master);
-  process::wait(master);
-}
-
-
-// Tests whether a slave correctly detects the new master
-// when its ZooKeeper session is expired and a new master is elected before the
-// slave reconnects with ZooKeeper.
-TEST_F(ZooKeeperTest, MasterDetectorExpireSlaveZKSessionNewMaster)
-{
-  // Simulate a leading master.
-  MockMasterDetectorListenerProcess master1;
-
-  Future<Nothing> newMasterDetected1;
-  EXPECT_CALL(master1, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected1))
-    .WillRepeatedly(Return());
-
-  EXPECT_CALL(master1, noMasterDetected())
-    .Times(0);
-
-  process::spawn(master1);
-
-  std::string znode = "zk://" + server->connectString() + "/mesos";
-
-  Try<zookeeper::URL> url = zookeeper::URL::parse(znode);
-  ASSERT_SOME(url);
-
-  // Leading master's detector.
-  ZooKeeperMasterDetector masterDetector1(
-      url.get(), master1.self(), true, true);
-
-  AWAIT_READY(newMasterDetected1);
-
-  // Simulate a non-leading master.
-  MockMasterDetectorListenerProcess master2;
-
-  Future<Nothing> newMasterDetected2;
-  EXPECT_CALL(master2, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected2))
-    .WillRepeatedly(Return());
-
-  EXPECT_CALL(master2, noMasterDetected())
-    .Times(0);
-
-  process::spawn(master2);
-
-  // Non-leading master's detector.
-  ZooKeeperMasterDetector masterDetector2(
-      url.get(), master2.self(), true, true);
-
-  AWAIT_READY(newMasterDetected2);
-
-  // Simulate a slave.
-  MockMasterDetectorListenerProcess slave;
-
-  Future<Nothing> newMasterDetected3, newMasterDetected4;
-  EXPECT_CALL(slave, newMasterDetected(_))
-    .WillOnce(FutureSatisfy(&newMasterDetected3))
-    .WillOnce(FutureSatisfy(&newMasterDetected4));
-
-  EXPECT_CALL(slave, noMasterDetected())
-    .Times(AtMost(1));
-
-  process::spawn(slave);
-
-  // Slave's master detector.
-  ZooKeeperMasterDetector slaveDetector(url.get(), slave.self(), false, true);
-
-  AWAIT_READY(newMasterDetected3);
-
-  // Now expire the slave's and leading master's zk sessions.
-  // NOTE: Here we assume that slave stays disconnected from the ZK when the
-  // leading master loses its session.
-  process::Future<int64_t> slaveSession = slaveDetector.session();
-  AWAIT_READY(slaveSession);
-
-  server->expireSession(slaveSession.get());
-
-  process::Future<int64_t> masterSession = masterDetector1.session();
-  AWAIT_READY(masterSession);
-
-  server->expireSession(masterSession.get());
-
-  // Wait for session expiration and ensure we receive a
-  // NewMasterDetected message.
-  AWAIT_READY(newMasterDetected4);
-
-  process::terminate(slave);
-  process::wait(slave);
-
-  process::terminate(master2);
-  process::wait(master2);
-
-  process::terminate(master1);
-  process::wait(master1);
-}
-
-
-TEST_F(ZooKeeperTest, Group)
-{
-  zookeeper::Group group(server->connectString(), NO_TIMEOUT, "/test/");
-
-  process::Future<zookeeper::Group::Membership> membership =
-    group.join("hello world");
-
-  AWAIT_READY(membership);
-
-  process::Future<std::set<zookeeper::Group::Membership> > memberships =
-    group.watch();
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(1u, memberships.get().size());
-  EXPECT_EQ(1u, memberships.get().count(membership.get()));
-
-  process::Future<std::string> data = group.data(membership.get());
-
-  AWAIT_EXPECT_EQ("hello world", data);
-
-  process::Future<bool> cancellation = group.cancel(membership.get());
-
-  AWAIT_EXPECT_EQ(true, cancellation);
-
-  memberships = group.watch(memberships.get());
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(0u, memberships.get().size());
-
-  ASSERT_TRUE(membership.get().cancelled().isReady());
-  ASSERT_TRUE(membership.get().cancelled().get());
-}
-
-
-TEST_F(ZooKeeperTest, GroupJoinWithDisconnect)
-{
-  zookeeper::Group group(server->connectString(), NO_TIMEOUT, "/test/");
-
-  server->shutdownNetwork();
-
-  process::Future<zookeeper::Group::Membership> membership =
-    group.join("hello world");
-
-  EXPECT_TRUE(membership.isPending());
-
-  server->startNetwork();
-
-  AWAIT_READY(membership);
-
-  process::Future<std::set<zookeeper::Group::Membership> > memberships =
-    group.watch();
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(1u, memberships.get().size());
-  EXPECT_EQ(1u, memberships.get().count(membership.get()));
-}
-
-
-TEST_F(ZooKeeperTest, GroupDataWithDisconnect)
-{
-  zookeeper::Group group(server->connectString(), NO_TIMEOUT, "/test/");
-
-  process::Future<zookeeper::Group::Membership> membership =
-    group.join("hello world");
-
-  AWAIT_READY(membership);
-
-  process::Future<std::set<zookeeper::Group::Membership> > memberships =
-    group.watch();
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(1u, memberships.get().size());
-  EXPECT_EQ(1u, memberships.get().count(membership.get()));
-
-  server->shutdownNetwork();
-
-  process::Future<std::string> data = group.data(membership.get());
-
-  EXPECT_TRUE(data.isPending());
-
-  server->startNetwork();
-
-  AWAIT_EXPECT_EQ("hello world", data);
-}
-
-
-TEST_F(ZooKeeperTest, GroupCancelWithDisconnect)
-{
-  zookeeper::Group group(server->connectString(), NO_TIMEOUT, "/test/");
-
-  process::Future<zookeeper::Group::Membership> membership =
-    group.join("hello world");
-
-  AWAIT_READY(membership);
-
-  process::Future<std::set<zookeeper::Group::Membership> > memberships =
-    group.watch();
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(1u, memberships.get().size());
-  EXPECT_EQ(1u, memberships.get().count(membership.get()));
-
-  process::Future<std::string> data = group.data(membership.get());
-
-  AWAIT_EXPECT_EQ("hello world", data);
-
-  server->shutdownNetwork();
-
-  process::Future<bool> cancellation = group.cancel(membership.get());
-
-  EXPECT_TRUE(cancellation.isPending());
-
-  server->startNetwork();
-
-  AWAIT_EXPECT_EQ(true, cancellation);
-
-  memberships = group.watch(memberships.get());
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(0u, memberships.get().size());
-
-  ASSERT_TRUE(membership.get().cancelled().isReady());
-  ASSERT_TRUE(membership.get().cancelled().get());
-}
-
-
-TEST_F(ZooKeeperTest, GroupWatchWithSessionExpiration)
-{
-  zookeeper::Group group(server->connectString(), NO_TIMEOUT, "/test/");
-
-  process::Future<zookeeper::Group::Membership> membership =
-    group.join("hello world");
-
-  AWAIT_READY(membership);
-
-  process::Future<std::set<zookeeper::Group::Membership> > memberships =
-    group.watch();
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(1u, memberships.get().size());
-  EXPECT_EQ(1u, memberships.get().count(membership.get()));
-
-  process::Future<Option<int64_t> > session = group.session();
-
-  AWAIT_READY(session);
-  ASSERT_SOME(session.get());
-
-  memberships = group.watch(memberships.get());
-
-  server->expireSession(session.get().get());
-
-  AWAIT_READY(memberships);
-  EXPECT_EQ(0u, memberships.get().size());
-
-  ASSERT_TRUE(membership.get().cancelled().isReady());
-  ASSERT_FALSE(membership.get().cancelled().get());
-}
-
-
-TEST_F(ZooKeeperTest, MultipleGroups)
-{
-  zookeeper::Group group1(server->connectString(), NO_TIMEOUT, "/test/");
-  zookeeper::Group group2(server->connectString(), NO_TIMEOUT, "/test/");
-
-  process::Future<zookeeper::Group::Membership> membership1 =
-    group1.join("group 1");
-
-  AWAIT_READY(membership1);
-
-  process::Future<zookeeper::Group::Membership> membership2 =
-    group2.join("group 2");
-
-  AWAIT_READY(membership2);
-
-  process::Future<std::set<zookeeper::Group::Membership> > memberships1 =
-    group1.watch();
-
-  AWAIT_READY(memberships1);
-  EXPECT_EQ(2u, memberships1.get().size());
-  EXPECT_EQ(1u, memberships1.get().count(membership1.get()));
-  EXPECT_EQ(1u, memberships1.get().count(membership2.get()));
-
-  process::Future<std::set<zookeeper::Group::Membership> > memberships2 =
-    group2.watch();
-
-  AWAIT_READY(memberships2);
-  EXPECT_EQ(2u, memberships2.get().size());
-  EXPECT_EQ(1u, memberships2.get().count(membership1.get()));
-  EXPECT_EQ(1u, memberships2.get().count(membership2.get()));
-
-  process::Future<bool> cancelled;
-
-  // Now watch the membership owned by group1 from group2.
-  foreach (const zookeeper::Group::Membership& membership, memberships2.get()) {
-    if (membership == membership1.get()) {
-      cancelled = membership.cancelled();
-      break;
-    }
-  }
-
-  process::Future<Option<int64_t> > session1 = group1.session();
-
-  AWAIT_READY(session1);
-  ASSERT_SOME(session1.get());
-
-  server->expireSession(session1.get().get());
-
-  AWAIT_ASSERT_EQ(false, cancelled);
-}
-
-
-TEST_F(ZooKeeperTest, GroupPathWithRestrictivePerms)
-{
-  ZooKeeperTest::TestWatcher watcher;
-
-  ZooKeeper authenticatedZk(server->connectString(), NO_TIMEOUT, &watcher);
-  watcher.awaitSessionEvent(ZOO_CONNECTED_STATE);
-  authenticatedZk.authenticate("digest", "creator:creator");
-  authenticatedZk.create("/read-only",
-                         "42",
-                         zookeeper::EVERYONE_READ_CREATOR_ALL,
-                         0,
-                         NULL);
-  ASSERT_ZK_GET("42", &authenticatedZk, "/read-only");
-  authenticatedZk.create("/read-only/writable",
-                         "37",
-                         ZOO_OPEN_ACL_UNSAFE,
-                         0,
-                         NULL);
-  ASSERT_ZK_GET("37", &authenticatedZk, "/read-only/writable");
-
-  zookeeper::Authentication auth("digest", "non-creator:non-creator");
-
-  zookeeper::Group failedGroup1(server->connectString(), NO_TIMEOUT,
-                                "/read-only/", auth);
-  process::Future<zookeeper::Group::Membership> failedMembership1 =
-    failedGroup1.join("fail");
-
-  AWAIT_FAILED(failedMembership1);
-
-  zookeeper::Group failedGroup2(server->connectString(), NO_TIMEOUT,
-                                "/read-only/new", auth);
-  process::Future<zookeeper::Group::Membership> failedMembership2 =
-    failedGroup2.join("fail");
-
-  AWAIT_FAILED(failedMembership2);
-
-  zookeeper::Group successGroup(server->connectString(), NO_TIMEOUT,
-                                "/read-only/writable/", auth);
-  process::Future<zookeeper::Group::Membership> successMembership =
-    successGroup.join("succeed");
-
-  AWAIT_READY(successMembership);
-}


[05/28] git commit: Minor cleanup in stout/exit.hpp.

Posted by be...@apache.org.
Minor cleanup in stout/exit.hpp.

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


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

Branch: refs/heads/master
Commit: 07c44ce216d96ecdc1a639ec489d30590308e9af
Parents: 65e2fba
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sat May 4 12:09:42 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 .../third_party/stout/include/stout/exit.hpp       |   17 ++++++++-------
 1 files changed, 9 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/07c44ce2/third_party/libprocess/third_party/stout/include/stout/exit.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/third_party/stout/include/stout/exit.hpp b/third_party/libprocess/third_party/stout/include/stout/exit.hpp
index c588ac0..e8da726 100644
--- a/third_party/libprocess/third_party/stout/include/stout/exit.hpp
+++ b/third_party/libprocess/third_party/stout/include/stout/exit.hpp
@@ -3,34 +3,35 @@
 
 #include <stdlib.h>
 
+#include <iostream> // For std::cerr.
 #include <ostream>
 #include <sstream>
 #include <string>
 
-// Exit takes an exit code and provides a stream for output prior to
+// Exit takes an exit status and provides a stream for output prior to
 // exiting. This is like glog's LOG(FATAL) or CHECK, except that it
-// does _not_ print a stack trace because we don't want to freak out
-// the user.
+// does _not_ print a stack trace.
 //
 // Ex: EXIT(1) << "Cgroups are not present in this system.";
-#define EXIT __Exit().stream
+#define EXIT(status) __Exit(status).stream()
 
 struct __Exit
 {
+  __Exit(int _status) : status(_status) {}
+
   ~__Exit()
   {
     std::cerr << out.str() << std::endl;
-    exit(exitCode);
+    exit(status);
   }
 
-  std::ostream& stream(int exitCode)
+  std::ostream& stream()
   {
-    this->exitCode = exitCode;
     return out;
   }
 
   std::ostringstream out;
-  int exitCode;
+  const int status;
 };
 
 #endif // __STOUT_EXIT_HPP__


[21/28] Refactored base 'State' implementation to be serialization agnostic and use a 'Storage' instance. Changed the LevelDB and ZooKeeper implementations to implement 'Storage' instead of 'State'. Provided a protobuf specific implementation on top of '

Posted by be...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/33f4ff4b/src/tests/state_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/state_tests.cpp b/src/tests/state_tests.cpp
index 2e75673..ca12499 100644
--- a/src/tests/state_tests.cpp
+++ b/src/tests/state_tests.cpp
@@ -31,14 +31,15 @@
 #include <stout/gtest.hpp>
 #include <stout/option.hpp>
 #include <stout/os.hpp>
+#include <stout/try.hpp>
 
 #include "common/type_utils.hpp"
 
-#include "messages/messages.hpp"
+#include "master/registry.hpp"
 
 #include "state/leveldb.hpp"
-#include "state/serializer.hpp"
-#include "state/state.hpp"
+#include "state/protobuf.hpp"
+#include "state/storage.hpp"
 #include "state/zookeeper.hpp"
 
 #ifdef MESOS_HAS_JAVA
@@ -47,166 +48,272 @@
 
 using namespace mesos;
 using namespace mesos::internal;
-using namespace mesos::internal::state;
+using namespace mesos::internal::tests;
 
 using namespace process;
 
+using mesos::internal::registry::Registry;
+using mesos::internal::registry::Slave;
 
-void GetSetGet(State<ProtobufSerializer>* state)
-{
-  Future<Variable<Slaves> > variable = state->get<Slaves>("slaves");
-  AWAIT_READY(variable);
+using state::LevelDBStorage;
+using state::Storage;
+#ifdef MESOS_HAS_JAVA
+using state::ZooKeeperStorage;
+#endif
 
-  Variable<Slaves> slaves1 = variable.get();
-  EXPECT_TRUE(slaves1->infos().size() == 0);
+using state::protobuf::State;
+using state::protobuf::Variable;
 
-  SlaveInfo info;
-  info.set_hostname("localhost");
-  info.set_webui_hostname("localhost");
 
-  slaves1->add_infos()->MergeFrom(info);
+void FetchAndStoreAndFetch(State* state)
+{
+  Future<Variable<Registry> > future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
 
-  Future<Option<Variable<Slaves> > > result = state->set(slaves1);
+  Variable<Registry> variable = future1.get();
 
-  result.await();
+  Registry registry1 = variable.get();
+  EXPECT_TRUE(registry1.slaves().size() == 0);
 
-  ASSERT_TRUE(result.isReady());
-  ASSERT_SOME(result.get());
+  Slave* slave = registry1.add_slaves();
+  slave->mutable_info()->set_hostname("localhost");
+  slave->mutable_info()->set_webui_hostname("localhost");
 
-  variable = state->get<Slaves>("slaves");
+  variable = variable.mutate(registry1);
 
-  variable.await();
+  Future<Option<Variable<Registry> > > future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
 
-  ASSERT_TRUE(variable.isReady());
+  future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
 
-  Variable<Slaves> slaves2 = variable.get();
+  variable = future1.get();
 
-  ASSERT_TRUE(slaves2->infos().size() == 1);
-  EXPECT_EQ("localhost", slaves2->infos(0).hostname());
-  EXPECT_EQ("localhost", slaves2->infos(0).webui_hostname());
+  Registry registry2 = variable.get();
+  ASSERT_TRUE(registry2.slaves().size() == 1);
+  EXPECT_EQ("localhost", registry2.slaves(0).info().hostname());
+  EXPECT_EQ("localhost", registry2.slaves(0).info().webui_hostname());
 }
 
 
-void GetSetSetGet(State<ProtobufSerializer>* state)
+void FetchAndStoreAndStoreAndFetch(State* state)
 {
-  Future<Variable<Slaves> > variable = state->get<Slaves>("slaves");
-  AWAIT_READY(variable);
+  Future<Variable<Registry> > future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
+
+  Variable<Registry> variable = future1.get();
+
+  Registry registry1 = variable.get();
+  EXPECT_TRUE(registry1.slaves().size() == 0);
+
+  Slave* slave = registry1.add_slaves();
+  slave->mutable_info()->set_hostname("localhost");
+  slave->mutable_info()->set_webui_hostname("localhost");
+
+  variable = variable.mutate(registry1);
 
-  Variable<Slaves> slaves1 = variable.get();
-  EXPECT_TRUE(slaves1->infos().size() == 0);
+  Future<Option<Variable<Registry> > > future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
 
-  SlaveInfo info;
-  info.set_hostname("localhost");
-  info.set_webui_hostname("localhost");
+  variable = future2.get().get();
 
-  slaves1->add_infos()->MergeFrom(info);
+  future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
 
-  Future<Option<Variable<Slaves> > > result = state->set(slaves1);
+  future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
 
-  result.await();
+  variable = future1.get();
 
-  ASSERT_TRUE(result.isReady());
-  ASSERT_SOME(result.get());
+  Registry registry2 = variable.get();
+  ASSERT_TRUE(registry2.slaves().size() == 1);
+  EXPECT_EQ("localhost", registry2.slaves(0).info().hostname());
+  EXPECT_EQ("localhost", registry2.slaves(0).info().webui_hostname());
+}
+
+
+void FetchAndStoreAndStoreFailAndFetch(State* state)
+{
+  Future<Variable<Registry> > future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
 
-  slaves1 = result.get().get();
+  Variable<Registry> variable1 = future1.get();
 
-  result = state->set(slaves1);
+  Registry registry1 = variable1.get();
+  EXPECT_TRUE(registry1.slaves().size() == 0);
 
-  result.await();
+  Slave* slave1 = registry1.add_slaves();
+  slave1->mutable_info()->set_hostname("localhost1");
+  slave1->mutable_info()->set_webui_hostname("localhost1");
 
-  ASSERT_TRUE(result.isReady());
-  ASSERT_SOME(result.get());
+  Variable<Registry> variable2 = variable1.mutate(registry1);
 
-  variable = state->get<Slaves>("slaves");
+  Future<Option<Variable<Registry> > > future2 = state->store(variable2);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
 
-  variable.await();
+  Registry registry2 = variable1.get();
+  EXPECT_TRUE(registry2.slaves().size() == 0);
 
-  ASSERT_TRUE(variable.isReady());
+  Slave* slave2 = registry2.add_slaves();
+  slave2->mutable_info()->set_hostname("localhost2");
+  slave2->mutable_info()->set_webui_hostname("localhost2");
 
-  Variable<Slaves> slaves2 = variable.get();
+  variable2 = variable1.mutate(registry2);
 
-  ASSERT_TRUE(slaves2->infos().size() == 1);
-  EXPECT_EQ("localhost", slaves2->infos(0).hostname());
-  EXPECT_EQ("localhost", slaves2->infos(0).webui_hostname());
+  future2 = state->store(variable2);
+  AWAIT_READY(future2);
+  EXPECT_TRUE(future2.get().isNone());
+
+  future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
+
+  variable1 = future1.get();
+
+  registry1 = variable1.get();
+  ASSERT_TRUE(registry1.slaves().size() == 1);
+  EXPECT_EQ("localhost1", registry1.slaves(0).info().hostname());
+  EXPECT_EQ("localhost1", registry1.slaves(0).info().webui_hostname());
 }
 
 
-void GetGetSetSetGet(State<ProtobufSerializer>* state)
+void FetchAndStoreAndExpungeAndFetch(State* state)
 {
-  Future<Variable<Slaves> > variable = state->get<Slaves>("slaves");
-  AWAIT_READY(variable);
+  Future<Variable<Registry> > future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
 
-  Variable<Slaves> slaves1 = variable.get();
-  EXPECT_TRUE(slaves1->infos().size() == 0);
+  Variable<Registry> variable = future1.get();
 
-  variable = state->get<Slaves>("slaves");
-  AWAIT_READY(variable);
+  Registry registry1 = variable.get();
+  EXPECT_TRUE(registry1.slaves().size() == 0);
 
-  Variable<Slaves> slaves2 = variable.get();
-  EXPECT_TRUE(slaves2->infos().size() == 0);
+  Slave* slave = registry1.add_slaves();
+  slave->mutable_info()->set_hostname("localhost");
+  slave->mutable_info()->set_webui_hostname("localhost");
 
-  SlaveInfo info2;
-  info2.set_hostname("localhost2");
-  info2.set_webui_hostname("localhost2");
+  variable = variable.mutate(registry1);
 
-  slaves2->add_infos()->MergeFrom(info2);
+  Future<Option<Variable<Registry> > > future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
 
-  Future<Option<Variable<Slaves> > > result = state->set(slaves2);
+  variable = future2.get().get();
 
-  result.await();
+  Future<bool> future3 = state->expunge(variable);
+  AWAIT_READY(future3);
+  ASSERT_TRUE(future3.get());
 
-  ASSERT_TRUE(result.isReady());
-  ASSERT_SOME(result.get());
+  future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
 
-  SlaveInfo info1;
-  info1.set_hostname("localhost1");
-  info1.set_webui_hostname("localhost1");
+  variable = future1.get();
 
-  slaves1->add_infos()->MergeFrom(info1);
+  Registry registry2 = variable.get();
+  ASSERT_EQ(0, registry2.slaves().size());
+}
 
-  result = state->set(slaves1);
-  AWAIT_READY(result);
-  EXPECT_TRUE(result.get().isNone());
 
-  variable = state->get<Slaves>("slaves");
-  AWAIT_READY(variable);
+void FetchAndStoreAndExpungeAndExpunge(State* state)
+{
+  Future<Variable<Registry> > future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
+
+  Variable<Registry> variable = future1.get();
+
+  Registry registry1 = variable.get();
+  EXPECT_TRUE(registry1.slaves().size() == 0);
+
+  Slave* slave = registry1.add_slaves();
+  slave->mutable_info()->set_hostname("localhost");
+  slave->mutable_info()->set_webui_hostname("localhost");
 
-  slaves1 = variable.get();
+  variable = variable.mutate(registry1);
 
-  ASSERT_TRUE(slaves1->infos().size() == 1);
-  EXPECT_EQ("localhost2", slaves1->infos(0).hostname());
-  EXPECT_EQ("localhost2", slaves1->infos(0).webui_hostname());
+  Future<Option<Variable<Registry> > > future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
+
+  variable = future2.get().get();
+
+  Future<bool> future3 = state->expunge(variable);
+  AWAIT_READY(future3);
+  ASSERT_TRUE(future3.get());
+
+  future3 = state->expunge(variable);
+  AWAIT_READY(future3);
+  ASSERT_FALSE(future3.get());
 }
 
 
-void Names(State<ProtobufSerializer>* state)
+void FetchAndStoreAndExpungeAndStoreAndFetch(State* state)
 {
-  Future<Variable<Slaves> > variable = state->get<Slaves>("slaves");
-  AWAIT_READY(variable);
+  Future<Variable<Registry> > future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
 
-  Variable<Slaves> slaves1 = variable.get();
-  EXPECT_TRUE(slaves1->infos().size() == 0);
+  Variable<Registry> variable = future1.get();
 
-  SlaveInfo info;
-  info.set_hostname("localhost");
-  info.set_webui_hostname("localhost");
+  Registry registry1 = variable.get();
+  EXPECT_TRUE(registry1.slaves().size() == 0);
 
-  slaves1->add_infos()->MergeFrom(info);
+  Slave* slave = registry1.add_slaves();
+  slave->mutable_info()->set_hostname("localhost");
+  slave->mutable_info()->set_webui_hostname("localhost");
 
-  Future<Option<Variable<Slaves> > > result = state->set(slaves1);
+  variable = variable.mutate(registry1);
 
-  result.await();
+  Future<Option<Variable<Registry> > > future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
 
-  ASSERT_TRUE(result.isReady());
-  EXPECT_SOME(result.get());
+  variable = future2.get().get();
 
-  Future<std::vector<std::string> > names = state->names();
+  Future<bool> future3 = state->expunge(variable);
+  AWAIT_READY(future3);
+  ASSERT_TRUE(future3.get());
+
+  future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
+
+  future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
+
+  variable = future1.get();
+
+  Registry registry2 = variable.get();
+  ASSERT_TRUE(registry2.slaves().size() == 1);
+  EXPECT_EQ("localhost", registry2.slaves(0).info().hostname());
+  EXPECT_EQ("localhost", registry2.slaves(0).info().webui_hostname());
+}
+
+
+void Names(State* state)
+{
+  Future<Variable<Registry> > future1 = state->fetch<Registry>("registry");
+  AWAIT_READY(future1);
+
+  Variable<Registry> variable = future1.get();
+
+  Registry registry1 = variable.get();
+  EXPECT_TRUE(registry1.slaves().size() == 0);
+
+  Slave* slave = registry1.add_slaves();
+  slave->mutable_info()->set_hostname("localhost");
+  slave->mutable_info()->set_webui_hostname("localhost");
 
-  names.await();
+  variable = variable.mutate(registry1);
 
-  ASSERT_TRUE(names.isReady());
+  Future<Option<Variable<Registry> > > future2 = state->store(variable);
+  AWAIT_READY(future2);
+  ASSERT_SOME(future2.get());
+
+  Future<std::vector<std::string> > names = state->names();
+  AWAIT_READY(names);
   ASSERT_TRUE(names.get().size() == 1);
-  EXPECT_EQ("slaves", names.get()[0]);
+  EXPECT_EQ("registry", names.get()[0]);
 }
 
 
@@ -214,43 +321,66 @@ class LevelDBStateTest : public ::testing::Test
 {
 public:
   LevelDBStateTest()
-    : state(NULL), path(os::getcwd() + "/.state") {}
+    : storage(NULL),
+      state(NULL),
+      path(os::getcwd() + "/.state") {}
 
 protected:
   virtual void SetUp()
   {
     os::rmdir(path);
-    state = new LevelDBState<ProtobufSerializer>(path);
+    storage = new state::LevelDBStorage(path);
+    state = new State(storage);
   }
 
   virtual void TearDown()
   {
     delete state;
+    delete storage;
     os::rmdir(path);
   }
 
-  State<ProtobufSerializer>* state;
+  state::Storage* storage;
+  State* state;
 
 private:
   const std::string path;
 };
 
 
-TEST_F(LevelDBStateTest, GetSetGet)
+TEST_F(LevelDBStateTest, FetchAndStoreAndFetch)
+{
+  FetchAndStoreAndFetch(state);
+}
+
+
+TEST_F(LevelDBStateTest, FetchAndStoreAndStoreAndFetch)
+{
+  FetchAndStoreAndStoreAndFetch(state);
+}
+
+
+TEST_F(LevelDBStateTest, FetchAndStoreAndStoreFailAndFetch)
 {
-  GetSetGet(state);
+  FetchAndStoreAndStoreFailAndFetch(state);
 }
 
 
-TEST_F(LevelDBStateTest, GetSetSetGet)
+TEST_F(LevelDBStateTest, FetchAndStoreAndExpungeAndFetch)
 {
-  GetSetSetGet(state);
+  FetchAndStoreAndExpungeAndFetch(state);
 }
 
 
-TEST_F(LevelDBStateTest, GetGetSetSetGet)
+TEST_F(LevelDBStateTest, FetchAndStoreAndExpungeAndExpunge)
 {
-  GetGetSetSetGet(state);
+  FetchAndStoreAndExpungeAndExpunge(state);
+}
+
+
+TEST_F(LevelDBStateTest, FetchAndStoreAndExpungeAndStoreAndFetch)
+{
+  FetchAndStoreAndExpungeAndStoreAndFetch(state);
 }
 
 
@@ -265,45 +395,68 @@ class ZooKeeperStateTest : public tests::ZooKeeperTest
 {
 public:
   ZooKeeperStateTest()
-    : state(NULL) {}
+    : storage(NULL),
+      state(NULL) {}
 
 protected:
   virtual void SetUp()
   {
     ZooKeeperTest::SetUp();
-    state = new ZooKeeperState<ProtobufSerializer>(
+    storage = new state::ZooKeeperStorage(
         server->connectString(),
         NO_TIMEOUT,
         "/state/");
+    state = new State(storage);
   }
 
   virtual void TearDown()
   {
     delete state;
+    delete storage;
     ZooKeeperTest::TearDown();
   }
 
-  State<ProtobufSerializer>* state;
+  state::Storage* storage;
+  State* state;
 };
 
 
-TEST_F(ZooKeeperStateTest, GetSetGet)
+TEST_F(ZooKeeperStateTest, FetchAndStoreAndFetch)
+{
+  FetchAndStoreAndFetch(state);
+}
+
+
+TEST_F(ZooKeeperStateTest, FetchAndStoreAndStoreAndFetch)
 {
-  GetSetGet(state);
+  FetchAndStoreAndStoreAndFetch(state);
 }
 
 
-TEST_F(ZooKeeperStateTest, GetSetSetGet)
+TEST_F(ZooKeeperStateTest, FetchAndStoreAndStoreFailAndFetch)
 {
-  GetSetSetGet(state);
+  FetchAndStoreAndStoreFailAndFetch(state);
 }
 
 
-TEST_F(ZooKeeperStateTest, GetGetSetSetGet)
+TEST_F(ZooKeeperStateTest, FetchAndStoreAndExpungeAndFetch)
 {
-  GetGetSetSetGet(state);
+  FetchAndStoreAndExpungeAndFetch(state);
 }
 
+
+TEST_F(ZooKeeperStateTest, FetchAndStoreAndExpungeAndExpunge)
+{
+  FetchAndStoreAndExpungeAndExpunge(state);
+}
+
+
+TEST_F(ZooKeeperStateTest, FetchAndStoreAndExpungeAndStoreAndFetch)
+{
+  FetchAndStoreAndExpungeAndStoreAndFetch(state);
+}
+
+
 TEST_F(ZooKeeperStateTest, Names)
 {
   Names(state);


[27/28] git commit: Added some helpers for failing a collection of futures.

Posted by be...@apache.org.
Added some helpers for failing a collection of futures.

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


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

Branch: refs/heads/master
Commit: 50d93fc78e42770f0a90725df751c5d9592bc40e
Parents: 023e431
Author: Benjamin Hindman <be...@twitter.com>
Authored: Mon Jan 14 15:55:33 2013 -0800
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 09:28:38 2013 -0700

----------------------------------------------------------------------
 third_party/libprocess/include/process/future.hpp |   22 ++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/50d93fc7/third_party/libprocess/include/process/future.hpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/include/process/future.hpp b/third_party/libprocess/include/process/future.hpp
index b458997..daf4b92 100644
--- a/third_party/libprocess/include/process/future.hpp
+++ b/third_party/libprocess/include/process/future.hpp
@@ -450,6 +450,28 @@ void discard(const std::list<Future<T> >& futures)
 }
 
 
+template <class T>
+void fail(const std::vector<Promise<T>*>& promises, const std::string& message)
+{
+  typename std::vector<Promise<T>*>::const_iterator iterator;
+  for (iterator = promises.begin(); iterator != promises.end(); ++iterator) {
+    Promise<T>* promise = *iterator;
+    promise->fail(message);
+  }
+}
+
+
+template <class T>
+void fail(const std::list<Promise<T>*>& promises, const std::string& message)
+{
+  typename std::list<Promise<T>*>::const_iterator iterator;
+  for (iterator = promises.begin(); iterator != promises.end(); ++iterator) {
+    Promise<T>* promise = *iterator;
+    promise->fail(message);
+  }
+}
+
+
 template <typename T>
 Future<T> Future<T>::failed(const std::string& message)
 {


[25/28] git commit: Updated MonitorTest.WatchUnwatch to be deterministic.

Posted by be...@apache.org.
Updated MonitorTest.WatchUnwatch to be deterministic.

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


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

Branch: refs/heads/master
Commit: 4392c6e3b7b3dfabfc11a73f930063ad9fe92bc8
Parents: bc9cb87
Author: Benjamin Hindman <be...@twitter.com>
Authored: Thu May 23 13:44:30 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 09:28:38 2013 -0700

----------------------------------------------------------------------
 src/tests/monitor_tests.cpp |   34 ++++++++++++++++++++++++----------
 1 files changed, 24 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/4392c6e3/src/tests/monitor_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/monitor_tests.cpp b/src/tests/monitor_tests.cpp
index 5681af2..53920a0 100644
--- a/src/tests/monitor_tests.cpp
+++ b/src/tests/monitor_tests.cpp
@@ -29,6 +29,8 @@
 #include <process/pid.hpp>
 #include <process/process.hpp>
 
+#include <stout/nothing.hpp>
+
 #include "slave/constants.hpp"
 #include "slave/monitor.hpp"
 
@@ -49,6 +51,7 @@ using process::http::Response;
 using std::string;
 
 using testing::_;
+using testing::DoAll;
 using testing::Return;
 
 
@@ -79,14 +82,17 @@ TEST(MonitorTest, WatchUnwatch)
 
   process::spawn(isolator);
 
+  Future<Nothing> usage;
   EXPECT_CALL(isolator, usage(frameworkId, executorId))
-    .WillRepeatedly(Return(statistics));
+    .WillOnce(DoAll(FutureSatisfy(&usage),
+                    Return(statistics)));
 
   slave::ResourceMonitor monitor(&isolator);
 
-  // Monitor the executor.
-  Future<Nothing> watch =
-    FUTURE_DISPATCH(_, &slave::ResourceMonitorProcess::watch);
+  // We pause the clock first in order to make sure that we can
+  // advance time below to force the 'delay' in
+  // ResourceMonitorProcess::watch to execute.
+  process::Clock::pause();
 
   monitor.watch(
       frameworkId,
@@ -94,12 +100,18 @@ TEST(MonitorTest, WatchUnwatch)
       executorInfo,
       slave::RESOURCE_MONITORING_INTERVAL);
 
-  AWAIT_READY(watch);
+  // Now wait for ResouorceMonitorProcess::watch to finish so we can
+  // advance time to cause collection to begin.
+  process::Clock::settle();
 
-  process::Clock::pause();
   process::Clock::advance(slave::RESOURCE_MONITORING_INTERVAL);
   process::Clock::settle();
 
+  AWAIT_READY(usage);
+
+  // Wait until the isolator has finished returning the statistics.
+  process::Clock::settle();
+
   process::UPID upid("monitor", process::ip(), process::port());
 
   Future<Response> response = process::http::get(upid, "usage.json");
@@ -130,12 +142,14 @@ TEST(MonitorTest, WatchUnwatch)
       response);
 
   // Ensure the monitor stops polling the isolator.
-  Future<Nothing> unwatch =
-    FUTURE_DISPATCH(_, &slave::ResourceMonitorProcess::unwatch);
-
   monitor.unwatch(frameworkId, executorId);
 
-  AWAIT_READY(unwatch);
+  // Wait until ResourceMonitorProcess::unwatch has completed.
+  process::Clock::settle();
+
+  // This time, Isolator::usage should not get called.
+  EXPECT_CALL(isolator, usage(frameworkId, executorId))
+    .Times(0);
 
   process::Clock::advance(slave::RESOURCE_MONITORING_INTERVAL);
   process::Clock::settle();


[28/28] git commit: Fixed output bug with CHECK_SOME.

Posted by be...@apache.org.
Fixed output bug with CHECK_SOME.

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


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

Branch: refs/heads/master
Commit: 023e431e8944a2bd9293b49ebefe47eede9baae0
Parents: 7b36ed5
Author: Benjamin Hindman <be...@twitter.com>
Authored: Mon Jan 14 15:47:43 2013 -0800
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 09:28:38 2013 -0700

----------------------------------------------------------------------
 src/logging/check_some.hpp |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/023e431e/src/logging/check_some.hpp
----------------------------------------------------------------------
diff --git a/src/logging/check_some.hpp b/src/logging/check_some.hpp
index 8c8e136..cbfd78b 100644
--- a/src/logging/check_some.hpp
+++ b/src/logging/check_some.hpp
@@ -83,12 +83,12 @@ struct _CheckSome
       expression(_expression),
       error(_error)
   {
-    out << "CHECK_SOME(" << expression << ") failed: ";
+    out << "CHECK_SOME(" << expression << "): ";
   }
 
   ~_CheckSome()
   {
-    out << ": " << error;
+    out << error;
     google::LogMessageFatal(file.c_str(), line).stream() << out.str();
   }
 


[24/28] git commit: Added a 'port' field to SlaveInfo and updated default master and slave ports.

Posted by be...@apache.org.
Added a 'port' field to SlaveInfo and updated default master and slave
ports.

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


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

Branch: refs/heads/master
Commit: 7b36ed5007d6db9e895a4d703d6064991416db2f
Parents: 33f4ff4
Author: Benjamin Hindman <be...@twitter.com>
Authored: Wed Nov 28 18:57:45 2012 -0800
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 09:28:38 2013 -0700

----------------------------------------------------------------------
 include/mesos/mesos.proto |    4 ++--
 src/master/main.cpp       |   16 ++++++++++------
 src/slave/main.cpp        |   18 ++++++++++--------
 src/slave/slave.cpp       |    1 +
 4 files changed, 23 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/7b36ed50/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index 1c242d6..ece6559 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -156,7 +156,7 @@ message ExecutorInfo {
 message MasterInfo {
   required string id = 1;
   required uint32 ip = 2;
-  required uint32 port = 3;
+  required uint32 port = 3 [default = 5050];
 }
 
 
@@ -172,7 +172,7 @@ message MasterInfo {
  */
 message SlaveInfo {
   required string hostname = 1;
-  // TODO(benh,andyk): Send bound ports, not just hostname.
+  optional int32 port = 8 [default = 5051];
   required string webui_hostname = 2;             // Deprecated!
   optional int32 webui_port = 4 [default = 8081]; // Deprecated!
   repeated Resource resources = 3;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/7b36ed50/src/master/main.cpp
----------------------------------------------------------------------
diff --git a/src/master/main.cpp b/src/master/main.cpp
index 19b6524..06c265a 100644
--- a/src/master/main.cpp
+++ b/src/master/main.cpp
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+#include <mesos/mesos.hpp>
+
 #include <stout/os.hpp>
 #include <stout/stringify.hpp>
 #include <stout/try.hpp>
@@ -40,6 +42,8 @@
 using namespace mesos::internal;
 using namespace mesos::internal::master;
 
+using mesos::MasterInfo;
+
 using std::cerr;
 using std::endl;
 using std::string;
@@ -62,13 +66,13 @@ int main(int argc, char** argv)
 
   // The following flags are executable specific (e.g., since we only
   // have one instance of libprocess per execution, we only want to
-  // advertise the port and ip option once, here).
-  uint16_t port;
-  flags.add(&port, "port", "Port to listen on", 5050);
-
+  // advertise the IP and port option once, here).
   Option<string> ip;
   flags.add(&ip, "ip", "IP address to listen on");
 
+  uint16_t port;
+  flags.add(&port, "port", "Port to listen on", MasterInfo().port());
+
   string zk;
   flags.add(&zk,
             "zk",
@@ -103,12 +107,12 @@ int main(int argc, char** argv)
   }
 
   // Initialize libprocess.
-  os::setenv("LIBPROCESS_PORT", stringify(port));
-
   if (ip.isSome()) {
     os::setenv("LIBPROCESS_IP", ip.get());
   }
 
+  os::setenv("LIBPROCESS_PORT", stringify(port));
+
   process::initialize("master");
 
   logging::initialize(argv[0], flags, true); // Catch signals.

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/7b36ed50/src/slave/main.cpp
----------------------------------------------------------------------
diff --git a/src/slave/main.cpp b/src/slave/main.cpp
index da286a2..97c818a 100644
--- a/src/slave/main.cpp
+++ b/src/slave/main.cpp
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+#include <mesos/mesos.hpp>
+
 #include <stout/os.hpp>
 #include <stout/stringify.hpp>
 #include <stout/try.hpp>
@@ -37,6 +39,8 @@
 using namespace mesos::internal;
 using namespace mesos::internal::slave;
 
+using mesos::SlaveInfo;
+
 using std::cerr;
 using std::endl;
 using std::string;
@@ -59,13 +63,13 @@ int main(int argc, char** argv)
 
   // The following flags are executable specific (e.g., since we only
   // have one instance of libprocess per execution, we only want to
-  // advertise the port and ip option once, here).
-  Option<uint16_t> port;
-  flags.add(&port, "port", "Port to listen on");
-
+  // advertise the IP and port option once, here).
   Option<string> ip;
   flags.add(&ip, "ip", "IP address to listen on");
 
+  uint16_t port;
+  flags.add(&port, "port", "Port to listen on", SlaveInfo().port());
+
   string isolation;
   flags.add(&isolation,
             "isolation",
@@ -109,14 +113,12 @@ int main(int argc, char** argv)
   }
 
   // Initialize libprocess.
-  if (port.isSome()) {
-    os::setenv("LIBPROCESS_PORT", stringify(port.get()));
-  }
-
   if (ip.isSome()) {
     os::setenv("LIBPROCESS_IP", ip.get());
   }
 
+  os::setenv("LIBPROCESS_PORT", stringify(port));
+
   process::initialize();
 
   logging::initialize(argv[0], flags, true); // Catch signals.

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/7b36ed50/src/slave/slave.cpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp
index b451d90..25c91d9 100644
--- a/src/slave/slave.cpp
+++ b/src/slave/slave.cpp
@@ -235,6 +235,7 @@ void Slave::initialize()
 
   // Initialize slave info.
   info.set_hostname(hostname);
+  info.set_port(self().port);
   info.set_webui_hostname(webui_hostname); // Deprecated!
   info.mutable_resources()->MergeFrom(resources);
   info.mutable_attributes()->MergeFrom(attributes);


[08/28] git commit: Moved 'tests::mkdtemp' to Environment.

Posted by be...@apache.org.
Moved 'tests::mkdtemp' to Environment.

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


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

Branch: refs/heads/master
Commit: 65e2fba73b10368cf5b5e13f273cad0cb8aef223
Parents: 6f6ca87
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sun Apr 28 18:53:58 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/tests/environment.cpp |   57 +++++++++++++++++++++++++++++++++++++++-
 src/tests/environment.hpp |   24 ++++++++++++++++-
 src/tests/main.cpp        |    7 ++++-
 src/tests/script.cpp      |    3 +-
 src/tests/utils.cpp       |   30 +-------------------
 src/tests/utils.hpp       |   11 ++-----
 6 files changed, 92 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/65e2fba7/src/tests/environment.cpp
----------------------------------------------------------------------
diff --git a/src/tests/environment.cpp b/src/tests/environment.cpp
index 15ef205..2a22acd 100644
--- a/src/tests/environment.cpp
+++ b/src/tests/environment.cpp
@@ -24,6 +24,7 @@
 #include <process/gmock.hpp>
 #include <process/gtest.hpp>
 
+#include <stout/error.hpp>
 #include <stout/exit.hpp>
 #include <stout/os.hpp>
 #include <stout/strings.hpp>
@@ -35,6 +36,7 @@
 #endif
 
 #include "tests/environment.hpp"
+#include "tests/flags.hpp"
 
 using std::list;
 using std::string;
@@ -43,6 +45,10 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
+// Storage for the global environment instance.
+Environment* environment;
+
+
 // Returns true if we should enable the provided test. Similar to how
 // tests can be disabled using the 'DISABLED_' prefix on a test case
 // name or test name, we use:
@@ -169,6 +175,18 @@ Environment::Environment()
 }
 
 
+Environment::~Environment()
+{
+  foreach (const string& directory, directories) {
+    Try<Nothing> rmdir = os::rmdir(directory);
+    if (rmdir.isError()) {
+      LOG(ERROR) << "Failed to remove '" << directory
+                 << "': " << rmdir.error();
+    }
+  }
+}
+
+
 void Environment::SetUp()
 {
   // Clear any MESOS_ environment variables so they don't affect our tests.
@@ -177,10 +195,47 @@ void Environment::SetUp()
   if (!GTEST_IS_THREADSAFE) {
     EXIT(1) << "Testing environment is not thread safe, bailing!";
   }
+
+  // For locating killtree.sh.
+  os::setenv("MESOS_SOURCE_DIR", tests::flags.source_dir);
 }
 
 
-void Environment::TearDown() {}
+void Environment::TearDown()
+{
+  os::unsetenv("MESOS_SOURCE_DIR");
+}
+
+
+Try<string> Environment::mkdtemp()
+{
+  const ::testing::TestInfo* const testInfo =
+    ::testing::UnitTest::GetInstance()->current_test_info();
+
+  if (testInfo == NULL) {
+    return Error("Failed to determine the current test information");
+  }
+
+  // We replace any slashes present in the test names (e.g. TYPED_TEST),
+  // to make sure the temporary directory resides under '/tmp/'.
+  const string& testCase =
+    strings::replace(testInfo->test_case_name(), "/", "_");
+
+  string testName = strings::replace(testInfo->name(), "/", "_");
+
+  // Adjust the test name to remove any 'DISABLED_' prefix (to make
+  // things easier to read). While this might seem alarming, if we are
+  // "running" a disabled test it must be the case that the test was
+  // explicitly enabled (e.g., via 'gtest_filter').
+  if (strings::startsWith(testName, "DISABLED_")) {
+    testName = strings::remove(testName, "DISABLED_", strings::PREFIX);
+  }
+
+  const string& path =
+    path::join("/tmp", strings::join("_", testCase, testName, "XXXXXX"));
+
+  return os::mkdtemp(path);
+}
 
 } // namespace tests {
 } // namespace internal {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/65e2fba7/src/tests/environment.hpp
----------------------------------------------------------------------
diff --git a/src/tests/environment.hpp b/src/tests/environment.hpp
index 61aa84d..691291f 100644
--- a/src/tests/environment.hpp
+++ b/src/tests/environment.hpp
@@ -21,18 +21,40 @@
 
 #include <gtest/gtest.h>
 
+#include <list>
+#include <string>
+
+#include <stout/try.hpp>
+
 namespace mesos {
 namespace internal {
 namespace tests {
 
-// Used to set up our particular test environment.
+// Used to set up and manage the test environment.
 class Environment : public ::testing::Environment {
 public:
   Environment();
+  virtual ~Environment();
+
   virtual void SetUp();
   virtual void TearDown();
+
+  // Helper to create a temporary directory based on the current test
+  // case name and test name (derived from TestInfo via
+  // ::testing::UnitTest::GetInstance()->current_test_info()). Note
+  // that the directory will automagically get removed when the
+  // environment instance gets destructed.
+  Try<std::string> mkdtemp();
+
+private:
+  // Temporary directories that we created and need to remove.
+  std::list<std::string> directories;
 };
 
+
+// Global environment instance.
+extern Environment* environment;
+
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/65e2fba7/src/tests/main.cpp
----------------------------------------------------------------------
diff --git a/src/tests/main.cpp b/src/tests/main.cpp
index e32ec0c..b06c0d1 100644
--- a/src/tests/main.cpp
+++ b/src/tests/main.cpp
@@ -30,6 +30,7 @@
 #include "logging/logging.hpp"
 
 #include "tests/environment.hpp"
+#include "tests/flags.hpp"
 #include "tests/utils.hpp"
 
 using namespace mesos::internal;
@@ -98,7 +99,11 @@ int main(int argc, char** argv)
   std::cout << "Source directory: " << flags.source_dir << std::endl;
   std::cout << "Build directory: " << flags.build_dir << std::endl;
 
-  testing::AddGlobalTestEnvironment(new Environment());
+  // Instantiate our environment. Note that it will be managed by
+  // gtest after we add it via testing::AddGlobalTestEnvironment.
+  environment = new Environment();
+
+  testing::AddGlobalTestEnvironment(environment);
 
   return RUN_ALL_TESTS();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/65e2fba7/src/tests/script.cpp
----------------------------------------------------------------------
diff --git a/src/tests/script.cpp b/src/tests/script.cpp
index d7f103e..e2b4efa 100644
--- a/src/tests/script.cpp
+++ b/src/tests/script.cpp
@@ -28,6 +28,7 @@
 #include <stout/path.hpp>
 #include <stout/strings.hpp>
 
+#include "tests/environment.hpp"
 #include "tests/script.hpp"
 #include "tests/utils.hpp"
 
@@ -40,7 +41,7 @@ namespace tests {
 void execute(const string& script)
 {
   // Create a temporary directory for the test.
-  Try<string> directory = mkdtemp();
+  Try<string> directory = environment->mkdtemp();
 
   CHECK_SOME(directory) << "Failed to create temporary directory";
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/65e2fba7/src/tests/utils.cpp
----------------------------------------------------------------------
diff --git a/src/tests/utils.cpp b/src/tests/utils.cpp
index 0bb1536..9a83053 100644
--- a/src/tests/utils.cpp
+++ b/src/tests/utils.cpp
@@ -26,6 +26,7 @@
 #include <stout/path.hpp>
 #include <stout/strings.hpp>
 
+#include "tests/environment.hpp"
 #include "tests/flags.hpp"
 #include "tests/utils.hpp"
 
@@ -35,40 +36,13 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
-Try<string> mkdtemp()
-{
-  const ::testing::TestInfo* const testInfo =
-    ::testing::UnitTest::GetInstance()->current_test_info();
-
-  // We replace any slashes present in the test names (e.g. TYPED_TEST),
-  // to make sure the temporary directory resides under '/tmp/'.
-  const string& testCase =
-    strings::replace(testInfo->test_case_name(), "/", "_");
-
-  string testName = strings::replace(testInfo->name(), "/", "_");
-
-  // Adjust the test name to remove any 'DISABLED_' prefix (to make
-  // things easier to read). While this might seem alarming, if we are
-  // "running" a disabled test it must be the case that the test was
-  // explicitly enabled (e.g., via 'gtest_filter').
-  if (strings::startsWith(testName, "DISABLED_")) {
-    testName = strings::remove(testName, "DISABLED_", strings::PREFIX);
-  }
-
-  const string& path =
-    path::join("/tmp", strings::join("_", testCase, testName, "XXXXXX"));
-
-  return os::mkdtemp(path);
-}
-
-
 void TemporaryDirectoryTest::SetUp()
 {
   // Save the current working directory.
   cwd = os::getcwd();
 
   // Create a temporary directory for the test.
-  Try<string> directory = mkdtemp();
+  Try<string> directory = environment->mkdtemp();
 
   ASSERT_SOME(directory) << "Failed to mkdtemp";
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/65e2fba7/src/tests/utils.hpp
----------------------------------------------------------------------
diff --git a/src/tests/utils.hpp b/src/tests/utils.hpp
index 2e47734..60e4678 100644
--- a/src/tests/utils.hpp
+++ b/src/tests/utils.hpp
@@ -72,6 +72,7 @@
 #include "slave/state.hpp"
 
 #include "tests/cluster.hpp"
+#include "tests/environment.hpp"
 #include "tests/flags.hpp"
 #include "tests/isolator.hpp"
 
@@ -88,12 +89,6 @@ const static std::string TEST_CGROUPS_ROOT = "mesos_test";
 #endif
 
 
-// Helper to create a temporary directory based on the current test
-// case name and test name (derived from TestInfo via
-// ::testing::UnitTest::GetInstance()->current_test_info()).
-Try<std::string> mkdtemp();
-
-
 // Test fixture for creating a temporary directory for each test.
 class TemporaryDirectoryTest : public ::testing::Test
 {
@@ -118,7 +113,7 @@ protected:
   virtual void SetUp()
   {
     // Create a temporary directory for the test.
-    Try<std::string> directory = mkdtemp();
+    Try<std::string> directory = environment->mkdtemp();
 
     CHECK(directory.isSome())
       << "Failed to create temporary directory: " << directory.error();
@@ -154,7 +149,7 @@ protected:
   virtual void SetUp()
   {
     // Create a temporary directory for the test.
-    Try<std::string> directory = mkdtemp();
+    Try<std::string> directory = environment->mkdtemp();
 
     CHECK(directory.isSome())
       << "Failed to create temporary directory: " << directory.error();


[14/28] git commit: A little spring cleaning in the allocator tests.

Posted by be...@apache.org.
A little spring cleaning in the allocator tests.

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


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

Branch: refs/heads/master
Commit: bfa22550d1818d2add7a4f46a40eb9a0c4373003
Parents: fd981ce
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sat May 11 19:23:44 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:41 2013 -0700

----------------------------------------------------------------------
 src/tests/allocator_tests.cpp |  535 ++++++++++++++++++------------------
 1 files changed, 274 insertions(+), 261 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bfa22550/src/tests/allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_tests.cpp b/src/tests/allocator_tests.cpp
index e8f833d..8b868bc 100644
--- a/src/tests/allocator_tests.cpp
+++ b/src/tests/allocator_tests.cpp
@@ -50,18 +50,14 @@ using process::Clock;
 using process::Future;
 using process::PID;
 
-using std::map;
 using std::string;
 using std::vector;
 
 using testing::_;
 using testing::AtMost;
-using testing::ByRef;
 using testing::DoAll;
 using testing::DoDefault;
 using testing::Eq;
-using testing::InSequence;
-using testing::Return;
 using testing::SaveArg;
 
 
@@ -96,6 +92,7 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
   FrameworkInfo frameworkInfo1;
   frameworkInfo1.set_name("framework1");
   frameworkInfo1.set_user("user1");
+
   MockScheduler sched1;
   MesosSchedulerDriver driver1(&sched1, frameworkInfo1, master.get());
 
@@ -228,12 +225,17 @@ TEST_F(DRFAllocatorTest, DRFAllocatorProcess)
   EXPECT_CALL(allocator, frameworkRemoved(_))
     .Times(AtMost(3));
 
-  EXPECT_CALL(allocator, slaveRemoved(_))
-    .Times(AtMost(4));
-
   driver1.stop();
+  driver1.join();
+
   driver2.stop();
+  driver2.join();
+
   driver3.stop();
+  driver3.join();
+
+  EXPECT_CALL(allocator, slaveRemoved(_))
+    .Times(AtMost(4));
 
   Shutdown();
 }
@@ -290,41 +292,33 @@ TYPED_TEST(AllocatorTest, MockAllocator)
 
   EXPECT_CALL(sched, registered(_, _, _));
 
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers));
+  // The framework should be offered all of the resources on the slave
+  // since it is the only framework in the cluster.
+  Future<Nothing> resourceOffers;
+  EXPECT_CALL(sched, resourceOffers(_, OfferEq(2, 1024)))
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   driver.start();
 
-  AWAIT_READY(offers);
-
-  // The framework should be offered all of the resources on the slave
-  // since it is the only framework in the cluster.
-  EXPECT_THAT(offers.get(), OfferEq(2, 1024));
+  AWAIT_READY(resourceOffers);
 
   // Shut everything down.
-  EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _));
+  EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
+    .WillRepeatedly(DoDefault());
 
   EXPECT_CALL(this->allocator, frameworkDeactivated(_))
-    .WillRepeatedly(DoDefault());
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+    .Times(AtMost(1));
 
   driver.stop();
+  driver.join();
 
-  AWAIT_READY(frameworkRemoved);
-
-  Future<Nothing> slaveRemoved;
   EXPECT_CALL(this->allocator, slaveRemoved(_))
-    .WillOnce(FutureSatisfy(&slaveRemoved));
-
-  this->ShutdownSlaves();
-
-  AWAIT_READY(slaveRemoved);
+    .Times(AtMost(1));
 
-  this->ShutdownMasters();
+  this->Shutdown();
 }
 
 
@@ -353,19 +347,25 @@ TYPED_TEST(AllocatorTest, ResourcesUnused)
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
-  Future<Nothing> resourcesUnused;
-  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
-    .WillOnce(DoAll(InvokeResourcesUnused(&this->allocator),
-                    FutureSatisfy(&resourcesUnused)));
-
   EXPECT_CALL(sched1, registered(_, _, _));
 
+  // We decline offers that we aren't expecting so that the resources
+  // get aggregated. Note that we need to do this _first_ and
+  // _separate_ from the expectation below so that this expectation is
+  // checked last and matches all possible offers.
+  EXPECT_CALL(sched1, resourceOffers(_, _))
+    .WillRepeatedly(DeclineOffers());
+
   // The first offer will contain all of the slave's resources, since
   // this is the only framework running so far. Launch a task that
   // uses less than that to leave some resources unused.
   EXPECT_CALL(sched1, resourceOffers(_, OfferEq(2, 1024)))
-    .WillOnce(LaunchTasks(1, 1, 512))
-    .WillRepeatedly(DeclineOffers());
+    .WillOnce(LaunchTasks(1, 1, 512));
+
+  Future<Nothing> resourcesUnused;
+  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
+    .WillOnce(DoAll(InvokeResourcesUnused(&this->allocator),
+                    FutureSatisfy(&resourcesUnused)));
 
   EXPECT_CALL(exec, registered(_, _, _, _));
 
@@ -375,51 +375,55 @@ TYPED_TEST(AllocatorTest, ResourcesUnused)
 
   driver1.start();
 
+  AWAIT_READY(launchTask);
+
+  // We need to wait until the allocator knows about the unused
+  // resources to start the second framework so that we get the
+  // expected offer.
   AWAIT_READY(resourcesUnused);
 
-  AWAIT_READY(launchTask);
+  FrameworkInfo frameworkInfo2;
+  frameworkInfo2.set_user("user2");
+  frameworkInfo2.set_name("framework2");
 
-  FrameworkInfo info2;
-  info2.set_user("user2");
-  info2.set_name("framework2");
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, info2, master.get());
+  MesosSchedulerDriver driver2(&sched2, frameworkInfo2, master.get());
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
   EXPECT_CALL(sched2, registered(_, _, _));
 
-  Future<vector<Offer> > offers;
-  EXPECT_CALL(sched2, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers));
+  // We should expect that framework2 gets offered all of the
+  // resources on the slave not being used by the launched task.
+  Future<Nothing> resourceOffers;
+  EXPECT_CALL(sched2, resourceOffers(_, OfferEq(1, 512)))
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   driver2.start();
 
-  AWAIT_READY(offers);
-
-  // framework2 will be offered all of the resources on the slave not
-  // being used by the task that was launched.
-  EXPECT_THAT(offers.get(), OfferEq(1, 512));
+  AWAIT_READY(resourceOffers);
 
   // Shut everything down.
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
   EXPECT_CALL(this->allocator, frameworkDeactivated(_))
-    .Times(2);
+    .Times(AtMost(2));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(DoDefault())
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+    .Times(AtMost(2));
 
+  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .Times(AtMost(1));
+    .WillOnce(FutureSatisfy(&shutdown));
 
   driver1.stop();
+  driver1.join();
+
   driver2.stop();
+  driver2.join();
 
-  AWAIT_READY(frameworkRemoved);
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
@@ -449,28 +453,31 @@ TYPED_TEST(AllocatorTest, OutOfOrderDispatch)
   FrameworkInfo frameworkInfo1;
   frameworkInfo1.set_user("user1");
   frameworkInfo1.set_name("framework1");
+
   MockScheduler sched1;
   MesosSchedulerDriver driver1(&sched1, frameworkInfo1, master.get());
 
-  FrameworkID frameworkId1;
   EXPECT_CALL(this->allocator, frameworkAdded(_, Eq(frameworkInfo1), _))
-    .WillOnce(DoAll(InvokeFrameworkAdded(&this->allocator),
-                    SaveArg<0>(&frameworkId1)));
+    .WillOnce(InvokeFrameworkAdded(&this->allocator));
 
-  EXPECT_CALL(sched1, registered(_, _, _));
+  FrameworkID frameworkId1;
+  EXPECT_CALL(sched1, registered(_, _, _))
+    .WillOnce(SaveArg<1>(&frameworkId1));
 
-  Future<vector<Offer> > offers1;
-  EXPECT_CALL(sched1, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers1));
+  // All of the slave's resources should be offered to start.
+  Future<Nothing> resourceOffers;
+  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(2, 1024)))
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   driver1.start();
 
-  AWAIT_READY(offers1);
-
-  // framework1 will be offered all of the slave's resources, since
-  // it is the only framework running right now.
-  EXPECT_THAT(offers1.get(), OfferEq(2, 1024));
+  AWAIT_READY(resourceOffers);
 
+  // TODO(benh): I don't see why we want to "catch" (i.e., block) this
+  // resourcesRecovered call. It seems like we want this one to
+  // properly be executed and later we want to _inject_ a
+  // resourcesRecovered to simulate the code in Master::offer after a
+  // framework has terminated or is inactive.
   FrameworkID frameworkId;
   SlaveID slaveId;
   Resources savedResources;
@@ -502,46 +509,45 @@ TYPED_TEST(AllocatorTest, OutOfOrderDispatch)
   // that recovering resources from a removed framework works.
   this->a->resourcesRecovered(frameworkId, slaveId, savedResources);
 
+  // TODO(benh): Seems like we should wait for the above
+  // resourcesRecovered to be executed.
+
   FrameworkInfo frameworkInfo2;
   frameworkInfo2.set_user("user2");
   frameworkInfo2.set_name("framework2");
+
   MockScheduler sched2;
   MesosSchedulerDriver driver2(&sched2, frameworkInfo2, master.get());
 
-  FrameworkID frameworkId2;
   EXPECT_CALL(this->allocator, frameworkAdded(_, Eq(frameworkInfo2), _))
-    .WillOnce(DoAll(InvokeFrameworkAdded(&this->allocator),
-                    SaveArg<0>(&frameworkId2)));
+    .WillOnce(InvokeFrameworkAdded(&this->allocator));
 
-  EXPECT_CALL(sched2, registered(_, _, _));
+  FrameworkID frameworkId2;
+  EXPECT_CALL(sched2, registered(_, _, _))
+    .WillOnce(SaveArg<1>(&frameworkId2));
 
-  Future<vector<Offer> > offers2;
-  EXPECT_CALL(sched2, resourceOffers(_, _))
-    .WillOnce(FutureArg<1>(&offers2));
+  // All of the slave's resources should be offered since no other
+  // frameworks should be running.
+  EXPECT_CALL(sched2, resourceOffers(_, OfferEq(2, 1024)))
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   driver2.start();
 
-  AWAIT_READY(offers2);
-
-  // framework2 will be offered all of the slave's resources, since
-  // it is the only framework running right now.
-  EXPECT_THAT(offers2.get(), OfferEq(2, 1024));
+  AWAIT_READY(resourceOffers);
 
   // Shut everything down.
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  EXPECT_CALL(this->allocator, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved2;
   EXPECT_CALL(this->allocator, frameworkRemoved(Eq(frameworkId2)))
-    .WillOnce(FutureSatisfy(&frameworkRemoved2));
+    .Times(AtMost(1));
 
   driver2.stop();
   driver2.join();
 
-  AWAIT_READY(frameworkRemoved2);
-
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 
@@ -573,27 +579,33 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
   frameworkInfo1.set_name("framework1");
   frameworkInfo1.set_user("user1");
   frameworkInfo1.set_failover_timeout(.1);
+
   // Launch the first (i.e., failing) scheduler.
   MockScheduler sched1;
   MesosSchedulerDriver driver1(&sched1, frameworkInfo1, master.get());
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
-  // We don't filter the unused resources to make sure that
-  // they get offered to the framework as soon as it fails over.
-  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
-    .WillOnce(InvokeUnusedWithFilters(&this->allocator, 0));
-
   FrameworkID frameworkId;
   EXPECT_CALL(sched1, registered(&driver1, _, _))
     .WillOnce(SaveArg<1>(&frameworkId));
 
-  Future<vector<Offer> > offers1;
+  // We decline offers that we aren't expecting so that the resources
+  // get aggregated. Note that we need to do this _first_ and
+  // _separate_ from the expectation below so that this expectation is
+  // checked last and matches all possible offers.
   EXPECT_CALL(sched1, resourceOffers(_, _))
-    .WillOnce(DoAll(LaunchTasks(1, 1, 256),
-                    FutureArg<1>(&offers1)))
     .WillRepeatedly(DeclineOffers());
 
+  // Initially, all of slave1's resources are avaliable.
+  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(3, 1024)))
+    .WillOnce(LaunchTasks(1, 1, 256));
+
+  // We don't filter the unused resources to make sure that
+  // they get offered to the framework as soon as it fails over.
+  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
+    .WillOnce(InvokeUnusedWithFilters(&this->allocator, 0));
+
   EXPECT_CALL(exec, registered(_, _, _, _));
 
   Future<Nothing> launchTask;
@@ -602,11 +614,6 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
 
   driver1.start();
 
-  AWAIT_READY(offers1);
-
-  // Initially, all cluster resources are avaliable.
-  EXPECT_THAT(offers1.get(), OfferEq(3, 1024));
-
   // Ensures that the task has been completely launched
   // before we have the framework fail over.
   AWAIT_READY(launchTask);
@@ -614,7 +621,7 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
   // When we shut down the first framework, we don't want it to tell
   // the master it's shutting down so that the master will wait to see
   // if it fails over.
-  DROP_MESSAGES(Eq(UnregisterFrameworkMessage().GetTypeName()), _, _);
+  DROP_PROTOBUFS(UnregisterFrameworkMessage(), _, _);
 
   Future<Nothing> frameworkDeactivated;
   EXPECT_CALL(this->allocator, frameworkDeactivated(_))
@@ -625,13 +632,14 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
 
   AWAIT_READY(frameworkDeactivated);
 
-  FrameworkInfo framework2; // Bug in gcc 4.1.*, must assign on next line.
-  framework2 = DEFAULT_FRAMEWORK_INFO;
-  framework2.mutable_id()->MergeFrom(frameworkId);
+  FrameworkInfo frameworkInfo2; // Bug in gcc 4.1.*, must assign on next line.
+  frameworkInfo2 = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo2.mutable_id()->MergeFrom(frameworkId);
+
   // Now launch the second (i.e., failover) scheduler using the
   // framework id recorded from the first scheduler.
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, framework2, master.get());
+  MesosSchedulerDriver driver2(&sched2, frameworkInfo2, master.get());
 
   EXPECT_CALL(this->allocator, frameworkActivated(_, _));
 
@@ -640,31 +648,32 @@ TYPED_TEST(AllocatorTest, SchedulerFailover)
   // Even though the scheduler failed over, the 1 cpu, 512 mem
   // task that it launched earlier should still be running, so
   // only 2 cpus and 768 mem are available.
-  Future<Nothing> resourceOffers2;
+  Future<Nothing> resourceOffers;
   EXPECT_CALL(sched2, resourceOffers(_, OfferEq(2, 768)))
-    .WillOnce(FutureSatisfy(&resourceOffers2));
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   driver2.start();
 
-  AWAIT_READY(resourceOffers2);
+  AWAIT_READY(resourceOffers);
 
   // Shut everything down.
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  EXPECT_CALL(this->allocator, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+    .Times(AtMost(1));
 
+  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .Times(AtMost(1));
+    .WillOnce(FutureSatisfy(&shutdown));
 
   driver2.stop();
   driver2.join();
 
-  AWAIT_READY(frameworkRemoved);
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
@@ -684,17 +693,9 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
   Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 
+  // TODO(benh): We use this executor for two frameworks in this test
+  // which works but is brittle and harder to reason about.
   MockExecutor exec(DEFAULT_EXECUTOR_ID);
-  EXPECT_CALL(exec, registered(_, _, _, _))
-    .Times(2);
-
-  Future<Nothing> launchTask;
-  EXPECT_CALL(exec, launchTask(_, _))
-    .WillOnce(FutureSatisfy(&launchTask))
-    .WillOnce(DoDefault());
-
-  EXPECT_CALL(exec, shutdown(_))
-    .Times(AtMost(2));
 
   slave::Flags flags = this->CreateSlaveFlags();
   flags.resources = Option<string>("cpus:3;mem:1024");
@@ -709,87 +710,110 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
-  Future<Nothing> resourcesUnused;
-  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
-    .WillOnce(DoAll(InvokeResourcesUnused(&this->allocator),
-                    FutureSatisfy(&resourcesUnused)));
-
   EXPECT_CALL(sched1, registered(_, _, _));
 
+  // We decline offers that we aren't expecting so that the resources
+  // get aggregated. Note that we need to do this _first_ and
+  // _separate_ from the expectation below so that this expectation is
+  // checked last and matches all possible offers.
   EXPECT_CALL(sched1, resourceOffers(_, _))
     .WillRepeatedly(DeclineOffers());
 
-  // The first time the framework is offered resources,
-  // all of the cluster's resources should be avaliable.
-  Future<Nothing> resourcesOffers1;
+  // The first time the framework is offered resources, all of the
+  // cluster's resources should be avaliable.
   EXPECT_CALL(sched1, resourceOffers(_, OfferEq(3, 1024)))
-    .WillOnce(DoAll(LaunchTasks(1, 2, 512),
-                    FutureSatisfy(&resourcesOffers1)));
+    .WillOnce(LaunchTasks(1, 2, 512));
 
-  driver1.start();
+  // The framework does not use all the resources.
+  Future<Nothing> resourcesUnused;
+  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
+    .WillOnce(DoAll(InvokeResourcesUnused(&this->allocator),
+                    FutureSatisfy(&resourcesUnused)));
 
-  AWAIT_READY(resourcesOffers1);
+  EXPECT_CALL(exec, registered(_, _, _, _));
 
-  AWAIT_READY(resourcesUnused);
+  Future<Nothing> launchTask;
+  EXPECT_CALL(exec, launchTask(_, _))
+    .WillOnce(FutureSatisfy(&launchTask));
+
+  driver1.start();
 
   // Ensures that framework 1's task is completely launched
   // before we kill the framework to test if its resources
   // are recovered correctly.
   AWAIT_READY(launchTask);
 
+  // We need to wait until the allocator knows about the unused
+  // resources to start the second framework so that we get the
+  // expected offer.
+  AWAIT_READY(resourcesUnused);
+
   MockScheduler sched2;
   MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
-  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _));
-
   EXPECT_CALL(sched2, registered(_, _, _));
 
+  // We decline offers that we aren't expecting so that the resources
+  // get aggregated. Note that we need to do this _first_ and
+  // _separate_ from the expectation below so that this expectation is
+  // checked last and matches all possible offers.
   EXPECT_CALL(sched2, resourceOffers(_, _))
     .WillRepeatedly(DeclineOffers());
 
-  // The first time sched2 gets an offer, framework 1 has a
-  // task running with 2 cpus and 512 mem, leaving 1 cpu and 512 mem.
-  Future<Nothing> resourceOffers2;
+  // The first time sched2 gets an offer, framework 1 has a task
+  // running with 2 cpus and 512 mem, leaving 1 cpu and 512 mem.
   EXPECT_CALL(sched2, resourceOffers(_, OfferEq(1, 512)))
-    .WillOnce(DoAll(LaunchTasks(1, 1, 256),
-                    FutureSatisfy(&resourceOffers2)));
+    .WillOnce(LaunchTasks(1, 1, 256));
+
+  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _));
+
+  EXPECT_CALL(exec, registered(_, _, _, _));
+
+  EXPECT_CALL(exec, launchTask(_, _))
+    .WillOnce(FutureSatisfy(&launchTask));
 
   driver2.start();
 
-  AWAIT_READY(resourceOffers2);
+  AWAIT_READY(launchTask);
 
+  // Shut everything down but check that framework 2 gets the
+  // resources from framework 1 after it is shutdown.
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  EXPECT_CALL(this->allocator, frameworkDeactivated(_))
+    .Times(AtMost(2)); // Once for each framework.
 
-  EXPECT_CALL(this->allocator, frameworkRemoved(_));
+  EXPECT_CALL(this->allocator, frameworkRemoved(_))
+    .Times(AtMost(2)); // Once for each framework.
 
-  // After we kill framework 1, all of it's resources should
+  // After we stop framework 1, all of it's resources should
   // have been returned, but framework 2 should still have a
   // task with 1 cpu and 256 mem, leaving 2 cpus and 768 mem.
-  Future<Nothing> resourceOffers3;
+  Future<Nothing> resourceOffers;
   EXPECT_CALL(sched2, resourceOffers(_, OfferEq(2, 768)))
-    .WillOnce(FutureSatisfy(&resourceOffers3));
+    .WillOnce(FutureSatisfy(&resourceOffers));
+
+  Future<Nothing> shutdown;
+  EXPECT_CALL(exec, shutdown(_))
+    .WillOnce(FutureSatisfy(&shutdown));
 
   driver1.stop();
   driver1.join();
 
-  AWAIT_READY(resourceOffers3);
+  AWAIT_READY(resourceOffers);
 
-  // Shut everything down.
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  Future<Nothing> frameworkRemoved;
-  EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+  EXPECT_CALL(exec, shutdown(_))
+    .WillOnce(FutureSatisfy(&shutdown));
 
   driver2.stop();
   driver2.join();
 
-  AWAIT_READY(frameworkRemoved);
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
@@ -819,23 +843,18 @@ TYPED_TEST(AllocatorTest, SlaveLost)
   Try<PID<Slave> > slave1 = this->StartSlave(&exec, flags1);
   ASSERT_SOME(slave1);
 
-  MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
-  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _));
-
-  EXPECT_CALL(sched1, registered(_, _, _));
+  EXPECT_CALL(sched, registered(_, _, _));
 
-  EXPECT_CALL(sched1, statusUpdate(_, _))
-    .WillRepeatedly(DoDefault());
+  // Initially, all of slave1's resources are available.
+  EXPECT_CALL(sched, resourceOffers(_, OfferEq(2, 1024)))
+    .WillOnce(LaunchTasks(1, 2, 512));
 
-  Future<vector<Offer> > resourceOffers1;
-  // Initially, all of slave1's resources are avaliable.
-  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(2, 1024)))
-    .WillOnce(DoAll(LaunchTasks(1, 2, 512),
-                    FutureArg<1>(&resourceOffers1)));
+  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _));
 
   EXPECT_CALL(exec, registered(_, _, _, _));
 
@@ -844,11 +863,10 @@ TYPED_TEST(AllocatorTest, SlaveLost)
     .WillOnce(DoAll(SendStatusUpdateFromTask(TASK_RUNNING),
                     FutureSatisfy(&launchTask)));
 
-  driver1.start();
-
-  AWAIT_READY(resourceOffers1);
+  EXPECT_CALL(sched, statusUpdate(_, _))
+    .WillRepeatedly(DoDefault());
 
-  EXPECT_THAT(resourceOffers1.get(), OfferEq(2, 1024));
+  driver.start();
 
   // Ensures the task is completely launched before we
   // kill the slave, to test that the task's resources
@@ -858,22 +876,22 @@ TYPED_TEST(AllocatorTest, SlaveLost)
 
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _));
 
-  Future<Nothing> slaveRemoved1;
+  Future<Nothing> slaveRemoved;
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .WillOnce(DoAll(InvokeSlaveRemoved(&this->allocator),
-                    FutureSatisfy(&slaveRemoved1)));
+                    FutureSatisfy(&slaveRemoved)));
 
-  Future<Nothing> shutdownCall;
+  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .WillOnce(FutureSatisfy(&shutdownCall));
+    .WillOnce(FutureSatisfy(&shutdown));
 
-  EXPECT_CALL(sched1, slaveLost(_, _));
+  EXPECT_CALL(sched, slaveLost(_, _));
 
   this->ShutdownSlaves();
 
-  AWAIT_READY(slaveRemoved1);
+  AWAIT_READY(slaveRemoved);
 
-  AWAIT_READY(shutdownCall);
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
   MockExecutor exec2(DEFAULT_EXECUTOR_ID);
 
@@ -885,34 +903,32 @@ TYPED_TEST(AllocatorTest, SlaveLost)
   // Eventually after slave2 is launched, we should get
   // an offer that contains all of slave2's resources
   // and none of slave1's resources.
-  Future<vector<Offer> > resourceOffers2;
-  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(3, 256)))
-    .WillOnce(FutureArg<1>(&resourceOffers2));
+  Future<Nothing> resourceOffers;
+  EXPECT_CALL(sched, resourceOffers(_, OfferEq(3, 256)))
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   Try<PID<Slave> > slave2 = this->StartSlave(&exec2, flags2);
   ASSERT_SOME(slave2);
 
-  AWAIT_READY(resourceOffers2);
-
-  EXPECT_THAT(resourceOffers2.get(), OfferEq(3, 256));
+  AWAIT_READY(resourceOffers);
 
   // Shut everything down.
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  EXPECT_CALL(this->allocator, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+    .Times(AtMost(1));
 
   EXPECT_CALL(exec2, shutdown(_))
-    .Times(AtMost(1));
+    .WillOnce(FutureSatisfy(&shutdown));
 
-  driver1.stop();
-  driver1.join();
+  driver.stop();
+  driver.join();
 
-  AWAIT_READY(frameworkRemoved);
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
@@ -943,33 +959,32 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
   Try<PID<Slave> > slave1 = this->StartSlave(&exec, flags1);
   ASSERT_SOME(slave1);
 
-  MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
+  EXPECT_CALL(sched, registered(_, _, _));
+
+  // We decline offers that we aren't expecting so that the resources
+  // get aggregated. Note that we need to do this _first_ and
+  // _separate_ from the expectation below so that this expectation is
+  // checked last and matches all possible offers.
+  EXPECT_CALL(sched, resourceOffers(_, _))
+    .WillRepeatedly(DeclineOffers());
+
+  // Initially, all of slave1's resources are avaliable.
+  EXPECT_CALL(sched, resourceOffers(_, OfferEq(3, 1024)))
+    .WillOnce(LaunchTasks(1, 2, 512));
+
   // We filter the first time so that the unused resources
   // on slave1 from the task launch won't get reoffered
   // immediately and will get combined with slave2's
   // resources for a single offer.
   EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
-    .WillOnce(InvokeUnusedWithFilters(&this->allocator, .1))
+    .WillOnce(InvokeUnusedWithFilters(&this->allocator, 0.1))
     .WillRepeatedly(InvokeUnusedWithFilters(&this->allocator, 0));
 
-  EXPECT_CALL(sched1, registered(_, _, _));
-
-  EXPECT_CALL(sched1, statusUpdate(_, _))
-    .WillRepeatedly(DoDefault());
-
-  EXPECT_CALL(sched1, resourceOffers(_, _))
-    .WillRepeatedly(DeclineOffers());
-
-  // Initially, all of slave1's resources are avaliable.
-  Future<Nothing> resourceOffers1;
-  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(3, 1024)))
-    .WillOnce(DoAll(LaunchTasks(1, 2, 512),
-                    FutureSatisfy(&resourceOffers1)));
-
   EXPECT_CALL(exec, registered(_, _, _, _));
 
   Future<Nothing> launchTask;
@@ -977,9 +992,10 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
     .WillOnce(DoAll(SendStatusUpdateFromTask(TASK_RUNNING),
                     FutureSatisfy(&launchTask)));
 
-  driver1.start();
+  EXPECT_CALL(sched, statusUpdate(_, _))
+    .WillRepeatedly(DoDefault());
 
-  AWAIT_READY(resourceOffers1);
+  driver.start();
 
   AWAIT_READY(launchTask);
 
@@ -988,35 +1004,35 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
 
   EXPECT_CALL(this->allocator, slaveAdded(_, _, _));
 
-  // After slave2 launches, all of its resources are
-  // combined with the resources on slave1 that the
-  // task isn't using.
-  Future<Nothing> resourceOffers2;
-  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(5, 2560)))
-    .WillOnce(FutureSatisfy(&resourceOffers2));
+  // After slave2 launches, all of its resources are combined with the
+  // resources on slave1 that the task isn't using.
+  Future<Nothing> resourceOffers;
+  EXPECT_CALL(sched, resourceOffers(_, OfferEq(5, 2560)))
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   Try<PID<Slave> > slave2 = this->StartSlave(flags2);
   ASSERT_SOME(slave2);
 
-  AWAIT_READY(resourceOffers2);
+  AWAIT_READY(resourceOffers);
 
   // Shut everything down.
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  EXPECT_CALL(this->allocator, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+    .Times(AtMost(1));
 
+  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .Times(AtMost(1));
+    .WillOnce(FutureSatisfy(&shutdown));
 
-  driver1.stop();
-  driver1.join();
+  driver.stop();
+  driver.join();
 
-  AWAIT_READY(frameworkRemoved);
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(2));
@@ -1046,35 +1062,32 @@ TYPED_TEST(AllocatorTest, TaskFinished)
   Try<PID<Slave> > slave = this->StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
-  MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(this->allocator, frameworkAdded(_, _, _));
 
-  // We don't filter because we want to see the unused resources
-  // from the task launch get reoffered to us.
-  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
-    .WillRepeatedly(InvokeUnusedWithFilters(&this->allocator, 0));
-
-  EXPECT_CALL(sched1, registered(_, _, _));
-
-  EXPECT_CALL(sched1, statusUpdate(_, _))
-    .WillRepeatedly(DoDefault());
+  EXPECT_CALL(sched, registered(_, _, _));
 
-  EXPECT_CALL(sched1, resourceOffers(_, _))
+  // We decline offers that we aren't expecting so that the resources
+  // get aggregated. Note that we need to do this _first_ and
+  // _separate_ from the expectation below so that this expectation is
+  // checked last and matches all possible offers.
+  EXPECT_CALL(sched, resourceOffers(_, _))
     .WillRepeatedly(DeclineOffers());
 
   // Initially, all of the slave's resources.
-  Future<Nothing> resourceOffers1;
-  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(3, 1024)))
-    .WillOnce(DoAll(LaunchTasks(2, 1, 256),
-                    FutureSatisfy(&resourceOffers1)));
+  EXPECT_CALL(sched, resourceOffers(_, OfferEq(3, 1024)))
+    .WillOnce(LaunchTasks(2, 1, 256));
 
-  // After the tasks are launched.
-  Future<Nothing> resourceOffers2;
-  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(1, 512)))
-    .WillOnce(DoAll(DeclineOffers(),
-                    FutureSatisfy(&resourceOffers2)));
+  // Some resources will be unused and we need to make sure that we
+  // don't send the TASK_FINISHED status update below until after the
+  // allocator knows about the unused resources so that it can
+  // aggregate them with the resources from the finished task.
+  Future<Nothing> resourcesUnused;
+  EXPECT_CALL(this->allocator, resourcesUnused(_, _, _, _))
+    .WillRepeatedly(DoAll(InvokeResourcesUnused(&this->allocator),
+                          FutureSatisfy(&resourcesUnused)));
 
   EXPECT_CALL(exec, registered(_, _, _, _));
 
@@ -1088,13 +1101,14 @@ TYPED_TEST(AllocatorTest, TaskFinished)
                     FutureSatisfy(&launchTask)))
     .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
 
-  driver1.start();
+  EXPECT_CALL(sched, statusUpdate(_, _))
+    .WillRepeatedly(DoDefault());
 
-  AWAIT_READY(resourceOffers1);
+  driver.start();
 
   AWAIT_READY(launchTask);
 
-  AWAIT_READY(resourceOffers2);
+  AWAIT_READY(resourcesUnused);
 
   TaskStatus status;
   status.mutable_task_id()->MergeFrom(taskInfo.task_id());
@@ -1103,31 +1117,32 @@ TYPED_TEST(AllocatorTest, TaskFinished)
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _));
 
   // After the first task gets killed.
-  Future<Nothing> resourceOffers3;
-  EXPECT_CALL(sched1, resourceOffers(_, OfferEq(2, 768)))
-    .WillOnce(FutureSatisfy(&resourceOffers3));
+  Future<Nothing> resourceOffers;
+  EXPECT_CALL(sched, resourceOffers(_, OfferEq(2, 768)))
+    .WillOnce(FutureSatisfy(&resourceOffers));
 
   execDriver->sendStatusUpdate(status);
 
-  AWAIT_READY(resourceOffers3);
+  AWAIT_READY(resourceOffers);
 
   // Shut everything down.
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  EXPECT_CALL(this->allocator, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+    .Times(AtMost(1));
 
+  Future<Nothing> shutdown;
   EXPECT_CALL(exec, shutdown(_))
-    .Times(AtMost(1));
+    .WillOnce(FutureSatisfy(&shutdown));
 
-  driver1.stop();
-  driver1.join();
+  driver.stop();
+  driver.join();
 
-  AWAIT_READY(frameworkRemoved);
+  AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
@@ -1216,17 +1231,15 @@ TYPED_TEST(AllocatorTest, WhitelistSlave)
   EXPECT_CALL(this->allocator, resourcesRecovered(_, _, _))
     .WillRepeatedly(DoDefault());
 
-  EXPECT_CALL(this->allocator, frameworkDeactivated(_));
+  EXPECT_CALL(this->allocator, frameworkDeactivated(_))
+    .Times(AtMost(1));
 
-  Future<Nothing> frameworkRemoved;
   EXPECT_CALL(this->allocator, frameworkRemoved(_))
-    .WillOnce(FutureSatisfy(&frameworkRemoved));
+    .Times(AtMost(1));
 
   driver.stop();
   driver.join();
 
-  AWAIT_READY(frameworkRemoved);
-
   EXPECT_CALL(this->allocator, slaveRemoved(_))
     .Times(AtMost(1));
 


[16/28] git commit: Cleanups in configure.ac.

Posted by be...@apache.org.
Cleanups in configure.ac.

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


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

Branch: refs/heads/master
Commit: 1e35e9e3862c1586c4e2b3603b60faec1014fec4
Parents: 5e87116
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sun May 19 20:29:11 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:41 2013 -0700

----------------------------------------------------------------------
 third_party/libprocess/configure.ac |   23 +++++++++++------------
 1 files changed, 11 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/1e35e9e3/third_party/libprocess/configure.ac
----------------------------------------------------------------------
diff --git a/third_party/libprocess/configure.ac b/third_party/libprocess/configure.ac
index 329fa47..efa7783 100644
--- a/third_party/libprocess/configure.ac
+++ b/third_party/libprocess/configure.ac
@@ -69,6 +69,15 @@ AC_ARG_WITH([zlib],
                             will be far less responsive; not recommended]),
             [], [with_zlib=yes])
 
+# Do some OS specific setup.
+case "${target_os}" in
+  linux*)
+    LIBS="$LIBS -lrt" # For clock_gettime() in stout/stopwatch.hpp.
+    OS_NAME=linux # Used below for OS_LINUX.
+    ;;
+  *)
+    ;;
+esac
 
 # Checks for gcc toolchain (we rely on some atomic builtins for now).
 AC_PROG_CXX([g++])
@@ -101,18 +110,8 @@ fi
 
 AM_CONDITIONAL([HAS_GPERFTOOLS], [test "x$gperftools" = "xyes"])
 
-# Added for clock_gettime() call in stout/stopwatch.hpp.
-# We also only want to use stout/proc.hpp on linux.
-case "${target_os}" in
-  linux*)
-    LIBS="$LIBS -lrt"
-    OS_NAME=linux
-    ;;
-  *)
-    ;;
-esac
-
-# Used for conditionally including source files.
+# Used for conditionally building source files (e.g., only want to
+# build stout/tests/proc_tests.cpp on Linux).
 AM_CONDITIONAL([OS_LINUX], [test "x$OS_NAME" = "xlinux"])
 
 AC_OUTPUT


[23/28] git commit: Fixed synchronization bug when waiting for a process.

Posted by be...@apache.org.
Fixed synchronization bug when waiting for a process.

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


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

Branch: refs/heads/master
Commit: 6958e6d298bf211fe199a0560d601a5aea6f8590
Parents: 50d93fc
Author: Benjamin Hindman <be...@twitter.com>
Authored: Tue May 21 23:34:07 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 09:28:38 2013 -0700

----------------------------------------------------------------------
 third_party/libprocess/src/process.cpp |   19 ++++++++++++-------
 1 files changed, 12 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6958e6d2/third_party/libprocess/src/process.cpp
----------------------------------------------------------------------
diff --git a/third_party/libprocess/src/process.cpp b/third_party/libprocess/src/process.cpp
index 91b00f8..56f1ec5 100644
--- a/third_party/libprocess/src/process.cpp
+++ b/third_party/libprocess/src/process.cpp
@@ -2545,15 +2545,20 @@ void ProcessManager::cleanup(ProcessBase* process)
     // process until after we have used the process in
     // SocketManager::exited).
     socket_manager->exited(process);
-  }
 
-  // ***************************************************************
-  // At this point we can no longer dereference the process since it
-  // might already be deallocated (e.g., by the garbage collector).
-  // ***************************************************************
+    // ***************************************************************
+    // At this point we can no longer dereference the process since it
+    // might already be deallocated (e.g., by the garbage collector).
+    // ***************************************************************
 
-  if (gate != NULL) {
-    gate->open();
+    // Note that we need to open the gate while synchronized on
+    // processes because otherwise we might _open_ the gate before
+    // another thread _approaches_ the gate causing that thread to
+    // wait on _arrival_ to the gate forever (see
+    // ProcessManager::wait).
+    if (gate != NULL) {
+      gate->open();
+    }
   }
 }
 


[20/28] git commit: Removed unused local::launch overload.

Posted by be...@apache.org.
Removed unused local::launch overload.

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


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

Branch: refs/heads/master
Commit: 5e87116047fd16da5a6923b7ce3f558c76520644
Parents: 5690d20
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sun May 12 14:21:37 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:41 2013 -0700

----------------------------------------------------------------------
 src/local/local.cpp |   20 --------------------
 src/local/local.hpp |   17 +++--------------
 2 files changed, 3 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/5e871160/src/local/local.cpp
----------------------------------------------------------------------
diff --git a/src/local/local.cpp b/src/local/local.cpp
index f43ab2a..eb33e5d 100644
--- a/src/local/local.cpp
+++ b/src/local/local.cpp
@@ -73,26 +73,6 @@ static map<Isolator*, Slave*> slaves;
 static MasterDetector* detector = NULL;
 static Files* files = NULL;
 
-PID<Master> launch(
-    int numSlaves,
-    double cpus,
-    uint64_t mem,
-    uint64_t disk,
-    bool quiet,
-    Allocator* _allocator)
-{
-  Configuration configuration;
-  configuration.set("slaves", "*");
-  configuration.set("num_slaves", numSlaves);
-  configuration.set("quiet", quiet);
-
-  stringstream out;
-  out << "cpus:" << cpus << ";" << "mem:" << mem << ";" << "disk:" << disk;
-  configuration.set("resources", out.str());
-
-  return launch(configuration, _allocator);
-}
-
 
 PID<Master> launch(const Configuration& configuration, Allocator* _allocator)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/5e871160/src/local/local.hpp
----------------------------------------------------------------------
diff --git a/src/local/local.hpp b/src/local/local.hpp
index 2633d25..51324e2 100644
--- a/src/local/local.hpp
+++ b/src/local/local.hpp
@@ -36,21 +36,10 @@ class Configuration;
 
 namespace local {
 
-
-// Launch a local cluster with a given number of slaves and given numbers
-// of CPUs and memory per slave. Additionally one can also toggle whether
-// to initialize Google Logging and whether to log quietly.
-process::PID<master::Master> launch(int numSlaves,
-                                    double cpus,
-                                    uint64_t mem,
-                                    uint64_t disk,
-                                    bool quiet,
-                                    master::Allocator* _allocator = NULL);
-
-
 // Launch a local cluster with a given configuration.
-process::PID<master::Master> launch(const Configuration& configuration,
-                                    master::Allocator* _allocator = NULL);
+process::PID<master::Master> launch(
+    const Configuration& configuration,
+    master::Allocator* _allocator = NULL);
 
 
 void shutdown();


[10/28] Refactored MesosTest/MesosClusterTest into a generic fixture for launching in-memory Mesos clusters and updated all tests appropriately.

Posted by be...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/utils.hpp
----------------------------------------------------------------------
diff --git a/src/tests/utils.hpp b/src/tests/utils.hpp
index 60e4678..3b80933 100644
--- a/src/tests/utils.hpp
+++ b/src/tests/utils.hpp
@@ -19,76 +19,16 @@
 #ifndef __TESTS_UTILS_HPP__
 #define __TESTS_UTILS_HPP__
 
-#include <unistd.h> // For usleep.
+#include <gtest/gtest.h>
 
-#include <gmock/gmock.h>
-
-#include <fstream>
-#include <map>
 #include <string>
 
-#include <mesos/executor.hpp>
-#include <mesos/scheduler.hpp>
-
-#include <process/future.hpp>
-#include <process/gmock.hpp>
-#include <process/gtest.hpp>
-#include <process/http.hpp>
-#include <process/process.hpp>
-
-#include <stout/duration.hpp>
-#include <stout/gtest.hpp>
-#include <stout/lambda.hpp>
-#include <stout/nothing.hpp>
 #include <stout/option.hpp>
-#include <stout/os.hpp>
-#include <stout/path.hpp>
-#include <stout/stringify.hpp>
-#include <stout/try.hpp>
-#include <stout/uuid.hpp>
-
-#include "common/resources.hpp"
-#include "common/type_utils.hpp"
-
-#ifdef __linux__
-#include "linux/cgroups.hpp"
-#endif
-
-#include "logging/logging.hpp"
-
-#include "master/allocator.hpp"
-#include "master/drf_sorter.hpp"
-#include "master/hierarchical_allocator_process.hpp"
-#include "master/master.hpp"
-
-#include "messages/messages.hpp"
-
-#ifdef __linux__
-#include "slave/cgroups_isolator.hpp"
-#endif
-#include "slave/isolator.hpp"
-#include "slave/reaper.hpp"
-#include "slave/slave.hpp"
-#include "slave/state.hpp"
-
-#include "tests/cluster.hpp"
-#include "tests/environment.hpp"
-#include "tests/flags.hpp"
-#include "tests/isolator.hpp"
 
 namespace mesos {
 namespace internal {
 namespace tests {
 
-#ifdef __linux__
-// Cgroups hierarchy used by the cgroups related tests.
-const static std::string TEST_CGROUPS_HIERARCHY = "/tmp/mesos_test_cgroup";
-
-// Name of the root cgroup used by the cgroups related tests.
-const static std::string TEST_CGROUPS_ROOT = "mesos_test";
-#endif
-
-
 // Test fixture for creating a temporary directory for each test.
 class TemporaryDirectoryTest : public ::testing::Test
 {
@@ -101,671 +41,6 @@ private:
   Option<std::string> sandbox;
 };
 
-
-// Test fixture to setup mesos configuration for tests.
-// This fixture creates a new temporary working directory for each test and
-// deletes it when a test finishes. It also supports setting slave resources.
-// TODO(vinod): Make this fixture more generic to provide a basic set of
-// setup abstractions for tests.
-class MesosTest : public ::testing::Test
-{
-protected:
-  virtual void SetUp()
-  {
-    // Create a temporary directory for the test.
-    Try<std::string> directory = environment->mkdtemp();
-
-    CHECK(directory.isSome())
-      << "Failed to create temporary directory: " << directory.error();
-
-    slaveFlags.work_dir = directory.get();
-    slaveFlags.launcher_dir = path::join(tests::flags.build_dir, "src");
-
-    // For locating killtree.sh.
-    os::setenv("MESOS_SOURCE_DIR", tests::flags.source_dir);
-
-    setSlaveResources("cpus:2;mem:1024;disk:1024;ports:[31000-32000]");
-  }
-
-  virtual void TearDown()
-  {
-    os::rmdir(slaveFlags.work_dir);
-
-    os::unsetenv("MESOS_SOURCE_DIR");
-  }
-
-  void setSlaveResources(const std::string& resources)
-  {
-    slaveFlags.resources = Option<std::string>::some(resources);
-  }
-
-  slave::Flags slaveFlags;
-};
-
-
-class MesosClusterTest : public ::testing::Test
-{
-protected:
-  virtual void SetUp()
-  {
-    // Create a temporary directory for the test.
-    Try<std::string> directory = environment->mkdtemp();
-
-    CHECK(directory.isSome())
-      << "Failed to create temporary directory: " << directory.error();
-
-    cluster.slaves.flags.work_dir = directory.get();
-    cluster.slaves.flags.launcher_dir =
-      path::join(tests::flags.build_dir, "src");
-
-    // For locating killtree.sh.
-    os::setenv("MESOS_SOURCE_DIR", tests::flags.source_dir);
-
-    cluster.slaves.flags.resources =
-      Option<std::string>("cpus:2;mem:1024;disk:1024;ports:[31000-32000]");
-  }
-
-  virtual void TearDown()
-  {
-    os::rmdir(cluster.slaves.flags.work_dir);
-
-    os::unsetenv("MESOS_SOURCE_DIR");
-  }
-
-  Cluster cluster;
-};
-
-
-
-template <typename T>
-class IsolatorTest : public MesosTest
-{};
-
-
-#ifdef __linux__
-template <>
-class IsolatorTest<slave::CgroupsIsolator> : public MesosTest
-{
-public:
-  static void SetUpTestCase()
-  {
-    // Clean up the testing hierarchy, in case it wasn't cleaned up
-    // properly from previous tests.
-    AWAIT_READY(cgroups::cleanup(TEST_CGROUPS_HIERARCHY));
-  }
-
-  static void TearDownTestCase()
-  {
-    AWAIT_READY(cgroups::cleanup(TEST_CGROUPS_HIERARCHY));
-  }
-
-protected:
-  virtual void SetUp()
-  {
-    const std::string subsystems = "cpu,cpuacct,memory,freezer";
-    Result<std::string> hierarchy_ = cgroups::hierarchy(subsystems);
-    ASSERT_FALSE(hierarchy_.isError());
-    if (hierarchy_.isNone()) {
-      // Try to mount a hierarchy for testing.
-      ASSERT_SOME(cgroups::mount(TEST_CGROUPS_HIERARCHY, subsystems))
-        << "-------------------------------------------------------------\n"
-        << "We cannot run any cgroups tests that require\n"
-        << "a hierarchy with subsystems '" << subsystems << "'\n"
-        << "because we failed to find an existing hierarchy\n"
-        << "or create a new one. You can either remove all existing\n"
-        << "hierarchies, or disable this test case\n"
-        << "(i.e., --gtest_filter=-"
-        << ::testing::UnitTest::GetInstance()
-             ->current_test_info()
-             ->test_case_name() << ".*).\n"
-        << "-------------------------------------------------------------";
-
-      hierarchy = TEST_CGROUPS_HIERARCHY;
-    } else {
-      hierarchy = hierarchy_.get();
-    }
-
-    MesosTest::SetUp();
-
-    // Set slave's cgroup flags.
-    slaveFlags.cgroups_hierarchy = hierarchy;
-    slaveFlags.cgroups_root = TEST_CGROUPS_ROOT;
-  }
-
-  virtual void TearDown()
-  {
-    MesosTest::TearDown();
-
-    Try<bool> exists = cgroups::exists(hierarchy, TEST_CGROUPS_ROOT);
-    ASSERT_SOME(exists);
-    if (exists.get()) {
-     AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
-    }
-  }
-
-private:
-  std::string hierarchy;
-};
-#endif
-
-
-// Macros to get/create (default) ExecutorInfos and FrameworkInfos.
-#define DEFAULT_EXECUTOR_INFO                                           \
-      ({ ExecutorInfo executor;                                         \
-        executor.mutable_executor_id()->set_value("default");           \
-        executor.mutable_command()->set_value("exit 1");                \
-        executor; })
-
-
-#define CREATE_EXECUTOR_INFO(executorId, command)                       \
-      ({ ExecutorInfo executor;                                         \
-        executor.mutable_executor_id()->MergeFrom(executorId);          \
-        executor.mutable_command()->set_value(command);                 \
-        executor; })
-
-
-#define DEFAULT_FRAMEWORK_INFO                                          \
-     ({ FrameworkInfo framework;                                        \
-        framework.set_name("default");                                  \
-        framework; })
-
-
-#define DEFAULT_EXECUTOR_ID						\
-      DEFAULT_EXECUTOR_INFO.executor_id()
-
-
-inline TaskInfo createTask(
-    const Offer& offer,
-    const std::string& command,
-    const std::string& name = "test-task",
-    const std::string& id = UUID::random().toString())
-{
-  TaskInfo task;
-  task.set_name(name);
-  task.mutable_task_id()->set_value(id);
-  task.mutable_slave_id()->MergeFrom(offer.slave_id());
-  task.mutable_resources()->MergeFrom(offer.resources());
-  task.mutable_command()->set_value(command);
-
-  return task;
-}
-
-
-// Definition of a mock Scheduler to be used in tests with gmock.
-class MockScheduler : public Scheduler
-{
-public:
-  MOCK_METHOD3(registered, void(SchedulerDriver*,
-                                const FrameworkID&,
-                                const MasterInfo&));
-  MOCK_METHOD2(reregistered, void(SchedulerDriver*, const MasterInfo&));
-  MOCK_METHOD1(disconnected, void(SchedulerDriver*));
-  MOCK_METHOD2(resourceOffers, void(SchedulerDriver*,
-                                    const std::vector<Offer>&));
-  MOCK_METHOD2(offerRescinded, void(SchedulerDriver*, const OfferID&));
-  MOCK_METHOD2(statusUpdate, void(SchedulerDriver*, const TaskStatus&));
-  MOCK_METHOD4(frameworkMessage, void(SchedulerDriver*,
-                                      const ExecutorID&,
-                                      const SlaveID&,
-                                      const std::string&));
-  MOCK_METHOD2(slaveLost, void(SchedulerDriver*, const SlaveID&));
-  MOCK_METHOD4(executorLost, void(SchedulerDriver*,
-                                  const ExecutorID&,
-                                  const SlaveID&,
-                                  int));
-  MOCK_METHOD2(error, void(SchedulerDriver*, const std::string&));
-};
-
-// For use with a MockScheduler, for example:
-// EXPECT_CALL(sched, resourceOffers(_, _))
-//   .WillOnce(LaunchTasks(TASKS, CPUS, MEM));
-// Launches up to TASKS no-op tasks, if possible,
-// each with CPUS cpus and MEM memory.
-ACTION_P3(LaunchTasks, tasks, cpus, mem)
-{
-  SchedulerDriver* driver = arg0;
-  std::vector<Offer> offers = arg1;
-  int numTasks = tasks;
-
-  int launched = 0;
-  for (size_t i = 0; i < offers.size(); i++) {
-    const Offer& offer = offers[i];
-    double offeredCpus = 0;
-    double offeredMem = 0;
-
-    for (int j = 0; j < offer.resources_size(); j++) {
-      const Resource& resource = offer.resources(j);
-      if (resource.name() == "cpus" &&
-          resource.type() == Value::SCALAR) {
-        offeredCpus = resource.scalar().value();
-      } else if (resource.name() == "mem" &&
-                 resource.type() == Value::SCALAR) {
-        offeredMem = resource.scalar().value();
-      }
-    }
-
-    int nextTaskId = 0;
-    std::vector<TaskInfo> tasks;
-
-    while (offeredCpus >= cpus && offeredMem >= mem && launched < numTasks) {
-      TaskInfo task;
-      task.set_name("TestTask");
-      task.mutable_task_id()->set_value(stringify(nextTaskId++));
-      task.mutable_slave_id()->MergeFrom(offer.slave_id());
-
-      ExecutorInfo executor;
-      executor.mutable_executor_id()->set_value("default");
-      executor.mutable_command()->set_value(":");
-      task.mutable_executor()->MergeFrom(executor);
-
-      Resource* resource;
-      resource = task.add_resources();
-      resource->set_name("cpus");
-      resource->set_type(Value::SCALAR);
-      resource->mutable_scalar()->set_value(cpus);
-
-      resource = task.add_resources();
-      resource->set_name("mem");
-      resource->set_type(Value::SCALAR);
-      resource->mutable_scalar()->set_value(mem);
-
-      tasks.push_back(task);
-      launched++;
-      offeredCpus -= cpus;
-      offeredMem -= mem;
-    }
-
-    driver->launchTasks(offer.id(), tasks);
-  }
-}
-
-
-// Like LaunchTasks, but decline the entire offer and
-// don't launch any tasks.
-ACTION(DeclineOffers)
-{
-  SchedulerDriver* driver = arg0;
-  std::vector<Offer> offers = arg1;
-
-  for (size_t i = 0; i < offers.size(); i++) {
-    driver->declineOffer(offers[i].id());
-  }
-}
-
-
-// Definition of a mock Executor to be used in tests with gmock.
-class MockExecutor : public Executor
-{
-public:
-  MOCK_METHOD4(registered, void(ExecutorDriver*,
-                                const ExecutorInfo&,
-                                const FrameworkInfo&,
-                                const SlaveInfo&));
-  MOCK_METHOD2(reregistered, void(ExecutorDriver*, const SlaveInfo&));
-  MOCK_METHOD1(disconnected, void(ExecutorDriver*));
-  MOCK_METHOD2(launchTask, void(ExecutorDriver*, const TaskInfo&));
-  MOCK_METHOD2(killTask, void(ExecutorDriver*, const TaskID&));
-  MOCK_METHOD2(frameworkMessage, void(ExecutorDriver*, const std::string&));
-  MOCK_METHOD1(shutdown, void(ExecutorDriver*));
-  MOCK_METHOD2(error, void(ExecutorDriver*, const std::string&));
-};
-
-
-class MockProcessListener : public slave::ProcessExitedListener
-{
-public:
-  MOCK_METHOD2(processExited, void(pid_t, int));
-};
-
-
-template <typename T = master::AllocatorProcess>
-class MockAllocatorProcess : public master::AllocatorProcess
-{
-public:
-  MockAllocatorProcess()
-  {
-    // Spawn the underlying allocator process.
-    process::spawn(real);
-
-    using ::testing::_;
-
-    ON_CALL(*this, initialize(_, _))
-      .WillByDefault(InvokeInitialize(this));
-
-    ON_CALL(*this, frameworkAdded(_, _, _))
-      .WillByDefault(InvokeFrameworkAdded(this));
-
-    ON_CALL(*this, frameworkRemoved(_))
-      .WillByDefault(InvokeFrameworkRemoved(this));
-
-    ON_CALL(*this, frameworkActivated(_, _))
-      .WillByDefault(InvokeFrameworkActivated(this));
-
-    ON_CALL(*this, frameworkDeactivated(_))
-      .WillByDefault(InvokeFrameworkDeactivated(this));
-
-    ON_CALL(*this, slaveAdded(_, _, _))
-      .WillByDefault(InvokeSlaveAdded(this));
-
-    ON_CALL(*this, slaveRemoved(_))
-      .WillByDefault(InvokeSlaveRemoved(this));
-
-    ON_CALL(*this, updateWhitelist(_))
-      .WillByDefault(InvokeUpdateWhitelist(this));
-
-    ON_CALL(*this, resourcesRequested(_, _))
-      .WillByDefault(InvokeResourcesRequested(this));
-
-    ON_CALL(*this, resourcesUnused(_, _, _, _))
-      .WillByDefault(InvokeResourcesUnused(this));
-
-    ON_CALL(*this, resourcesRecovered(_, _, _))
-      .WillByDefault(InvokeResourcesRecovered(this));
-
-    ON_CALL(*this, offersRevived(_))
-      .WillByDefault(InvokeOffersRevived(this));
-  }
-
-  ~MockAllocatorProcess()
-  {
-    process::terminate(real);
-    process::wait(real);
-  }
-
-  MOCK_METHOD2(initialize, void(const master::Flags&,
-                                const process::PID<master::Master>&));
-  MOCK_METHOD3(frameworkAdded, void(const FrameworkID&,
-                                    const FrameworkInfo&,
-                                    const Resources&));
-  MOCK_METHOD1(frameworkRemoved, void(const FrameworkID&));
-  MOCK_METHOD2(frameworkActivated, void(const FrameworkID&,
-                                        const FrameworkInfo&));
-  MOCK_METHOD1(frameworkDeactivated, void(const FrameworkID&));
-  MOCK_METHOD3(slaveAdded, void(const SlaveID&,
-                                const SlaveInfo&,
-                                const hashmap<FrameworkID, Resources>&));
-  MOCK_METHOD1(slaveRemoved, void(const SlaveID&));
-  MOCK_METHOD1(updateWhitelist, void(const Option<hashset<std::string> >&));
-  MOCK_METHOD2(resourcesRequested, void(const FrameworkID&,
-                                        const std::vector<Request>&));
-  MOCK_METHOD4(resourcesUnused, void(const FrameworkID&,
-                                     const SlaveID&,
-                                     const Resources&,
-                                     const Option<Filters>& filters));
-  MOCK_METHOD3(resourcesRecovered, void(const FrameworkID&,
-                                        const SlaveID&,
-                                        const Resources&));
-  MOCK_METHOD1(offersRevived, void(const FrameworkID&));
-
-  T real;
-};
-
-
-typedef ::testing::Types<master::HierarchicalDRFAllocatorProcess>
-AllocatorTypes;
-
-
-// The following actions make up for the fact that DoDefault
-// cannot be used inside a DoAll, for example:
-// EXPECT_CALL(allocator, frameworkAdded(_, _, _))
-//   .WillOnce(DoAll(InvokeFrameworkAdded(&allocator),
-//                   FutureSatisfy(&frameworkAdded)));
-
-ACTION_P(InvokeInitialize, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::initialize,
-      arg0,
-      arg1);
-}
-
-
-ACTION_P(InvokeFrameworkAdded, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::frameworkAdded,
-      arg0,
-      arg1,
-      arg2);
-}
-
-
-ACTION_P(InvokeFrameworkRemoved, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::frameworkRemoved, arg0);
-}
-
-
-ACTION_P(InvokeFrameworkActivated, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::frameworkActivated,
-      arg0,
-      arg1);
-}
-
-
-ACTION_P(InvokeFrameworkDeactivated, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::frameworkDeactivated,
-      arg0);
-}
-
-
-ACTION_P(InvokeSlaveAdded, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::slaveAdded,
-      arg0,
-      arg1,
-      arg2);
-}
-
-
-ACTION_P(InvokeSlaveRemoved, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::slaveRemoved,
-      arg0);
-}
-
-
-ACTION_P(InvokeUpdateWhitelist, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::updateWhitelist,
-      arg0);
-}
-
-
-ACTION_P(InvokeResourcesRequested, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::resourcesRequested,
-      arg0,
-      arg1);
-}
-
-
-
-ACTION_P(InvokeResourcesUnused, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::resourcesUnused,
-      arg0,
-      arg1,
-      arg2,
-      arg3);
-}
-
-
-ACTION_P2(InvokeUnusedWithFilters, allocator, timeout)
-{
-  Filters filters;
-  filters.set_refuse_seconds(timeout);
-
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::resourcesUnused,
-      arg0,
-      arg1,
-      arg2,
-      filters);
-}
-
-
-ACTION_P(InvokeResourcesRecovered, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::resourcesRecovered,
-      arg0,
-      arg1,
-      arg2);
-}
-
-
-ACTION_P(InvokeOffersRevived, allocator)
-{
-  process::dispatch(
-      allocator->real,
-      &master::AllocatorProcess::offersRevived,
-      arg0);
-}
-
-
-class OfferEqMatcher
-  : public ::testing::MatcherInterface<const std::vector<Offer>& >
-{
-public:
-  OfferEqMatcher(int _cpus, int _mem)
-    : cpus(_cpus), mem(_mem) {}
-
-  virtual bool MatchAndExplain(const std::vector<Offer>& offers,
-			       ::testing::MatchResultListener* listener) const
-  {
-    double totalCpus = 0;
-    double totalMem = 0;
-
-    foreach (const Offer& offer, offers) {
-      foreach (const Resource& resource, offer.resources()) {
-	if (resource.name() == "cpus") {
-	  totalCpus += resource.scalar().value();
-	} else if (resource.name() == "mem") {
-	  totalMem += resource.scalar().value();
-	}
-      }
-    }
-
-    bool matches = totalCpus == cpus && totalMem == mem;
-
-    if (!matches) {
-      *listener << totalCpus << " cpus and " << totalMem << "mem";
-    }
-
-    return matches;
-  }
-
-  virtual void DescribeTo(::std::ostream* os) const
-  {
-    *os << "contains " << cpus << " cpus and " << mem << " mem";
-  }
-
-  virtual void DescribeNegationTo(::std::ostream* os) const
-  {
-    *os << "does not contain " << cpus << " cpus and "  << mem << " mem";
-  }
-
-private:
-  int cpus;
-  int mem;
-};
-
-
-inline const ::testing::Matcher<const std::vector<Offer>& > OfferEq(int cpus, int mem)
-{
-  return MakeMatcher(new OfferEqMatcher(cpus, mem));
-}
-
-
-// Definition of the SendStatusUpdateFromTask action to be used with gmock.
-ACTION_P(SendStatusUpdateFromTask, state)
-{
-  TaskStatus status;
-  status.mutable_task_id()->MergeFrom(arg1.task_id());
-  status.set_state(state);
-  arg0->sendStatusUpdate(status);
-}
-
-
-// Definition of the SendStatusUpdateFromTaskID action to be used with gmock.
-ACTION_P(SendStatusUpdateFromTaskID, state)
-{
-  TaskStatus status;
-  status.mutable_task_id()->MergeFrom(arg1);
-  status.set_state(state);
-  arg0->sendStatusUpdate(status);
-}
-
-
-#define FUTURE_PROTOBUF(message, from, to)              \
-  FutureProtobuf(message, from, to)
-
-
-#define DROP_PROTOBUF(message, from, to)              \
-  FutureProtobuf(message, from, to, true)
-
-
-#define DROP_PROTOBUFS(message, from, to)              \
-  DropProtobufs(message, from, to)
-
-
-// Forward declaration.
-template <typename T>
-T _FutureProtobuf(const process::Message& message);
-
-
-template <typename T, typename From, typename To>
-process::Future<T> FutureProtobuf(T t, From from, To to, bool drop = false)
-{
-  // Help debugging by adding some "type constraints".
-  { google::protobuf::Message* m = &t; (void) m; }
-
-  return process::FutureMessage(testing::Eq(t.GetTypeName()), from, to, drop)
-    .then(lambda::bind(&_FutureProtobuf<T>, lambda::_1));
-}
-
-
-template <typename T>
-T _FutureProtobuf(const process::Message& message)
-{
-  T t;
-  t.ParseFromString(message.body);
-  return t;
-}
-
-
-template <typename T, typename From, typename To>
-void DropProtobufs(T t, From from, To to)
-{
-  // Help debugging by adding some "type constraints".
-  { google::protobuf::Message* m = &t; (void) m; }
-
-  process::DropMessages(testing::Eq(t.GetTypeName()), from, to);
-}
-
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/zookeeper.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper.cpp b/src/tests/zookeeper.cpp
index 3d11209..237d54c 100644
--- a/src/tests/zookeeper.cpp
+++ b/src/tests/zookeeper.cpp
@@ -35,7 +35,7 @@
 
 #include "logging/logging.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/flags.hpp"
 #include "tests/zookeeper.hpp"
 #include "tests/zookeeper_test_server.hpp"
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/zookeeper.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper.hpp b/src/tests/zookeeper.hpp
index 17e0886..1bc38c2 100644
--- a/src/tests/zookeeper.hpp
+++ b/src/tests/zookeeper.hpp
@@ -29,7 +29,6 @@
 
 #include <stout/duration.hpp>
 
-#include "tests/utils.hpp"
 #include "tests/zookeeper_test_server.hpp"
 
 namespace mesos {
@@ -72,7 +71,7 @@ inline ::testing::AssertionResult AssertZKGet(
 // the variable 'server'. This test fixture ensures the server is
 // started before each test and shutdown after it so that each test is
 // presented with a ZooKeeper ensemble with no data or watches.
-class ZooKeeperTest : public MesosTest
+class ZooKeeperTest : public ::testing::Test
 {
 public:
   // A watcher that is useful to install in a ZooKeeper client for
@@ -116,17 +115,18 @@ public:
     pthread_cond_t cond;
   };
 
-  ZooKeeperTest() : server(new ZooKeeperTestServer()) {}
-  virtual ~ZooKeeperTest() { delete server; }
-
   static void SetUpTestCase();
 
 protected:
+  ZooKeeperTest() : server(new ZooKeeperTestServer()) {}
+  virtual ~ZooKeeperTest() { delete server; }
+
   virtual void SetUp();
 
   // A very long session timeout that simulates no timeout for test cases.
   static const Duration NO_TIMEOUT;
 
+  // TODO(benh): Share the same ZooKeeperTestServer across all tests?
   ZooKeeperTestServer* server;
 };
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_tests.cpp b/src/tests/zookeeper_tests.cpp
index 27a6048..77a5ab2 100644
--- a/src/tests/zookeeper_tests.cpp
+++ b/src/tests/zookeeper_tests.cpp
@@ -24,7 +24,8 @@
 
 #include <stout/strings.hpp>
 
-#include "tests/utils.hpp"
+#include "zookeeper/authentication.hpp"
+
 #include "tests/zookeeper.hpp"
 
 using namespace mesos::internal;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/zookeeper/authentication.hpp
----------------------------------------------------------------------
diff --git a/src/zookeeper/authentication.hpp b/src/zookeeper/authentication.hpp
index fb0e3ca..7b6b767 100644
--- a/src/zookeeper/authentication.hpp
+++ b/src/zookeeper/authentication.hpp
@@ -5,6 +5,8 @@
 
 #include <string>
 
+#include "logging/logging.hpp"
+
 namespace zookeeper {
 
 struct Authentication
@@ -13,7 +15,11 @@ struct Authentication
       const std::string& _scheme,
       const std::string& _credentials)
     : scheme(_scheme),
-      credentials(_credentials) {}
+      credentials(_credentials)
+  {
+    // TODO(benh): Fix output operator below once this changes.
+    CHECK_EQ(scheme, "digest") << "Unsupported authentication scheme";
+  }
 
   const std::string scheme;
   const std::string credentials;
@@ -28,6 +34,17 @@ extern const ACL_vector EVERYONE_READ_CREATOR_ALL;
 // we're the the only authenticated user to mutate our nodes.
 extern const ACL_vector EVERYONE_CREATE_AND_READ_CREATOR_ALL;
 
+
+inline std::ostream& operator << (
+    std::ostream& stream,
+    const Authentication& authentication)
+{
+  // TODO(benh): Fix this once we support more than just 'digest'.
+  CHECK_EQ(authentication.scheme, "digest");
+  return stream << authentication.credentials;
+}
+
+
 } // namespace zookeeper {
 
 #endif // __ZOOKEEPER_AUTHENTICATION_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/zookeeper/url.hpp
----------------------------------------------------------------------
diff --git a/src/zookeeper/url.hpp b/src/zookeeper/url.hpp
index b297a16..11f2bdd 100644
--- a/src/zookeeper/url.hpp
+++ b/src/zookeeper/url.hpp
@@ -108,6 +108,15 @@ inline Try<URL> URL::parse(const std::string& url)
   }
 }
 
+inline std::ostream& operator << (std::ostream& stream, const URL& url)
+{
+  stream << "zk://";
+  if (url.authentication.isSome()) {
+    stream << url.authentication.get() << "@";
+  }
+  return stream << url.servers << url.path;
+}
+
 } // namespace zookeeper {
 
 #endif // __ZOOKEEPER_URL_HPP__


[19/28] git commit: Replaced local::launch in tests with MesosTest.

Posted by be...@apache.org.
Replaced local::launch in tests with MesosTest.

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


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

Branch: refs/heads/master
Commit: 5690d207f99022948db4a69c5bf654798876de79
Parents: a1e25cb
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sun May 12 14:17:48 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:41 2013 -0700

----------------------------------------------------------------------
 src/tests/exception_tests.cpp       |   51 ++++++++++-----
 src/tests/fault_tolerance_tests.cpp |   50 +++++++++-----
 src/tests/resource_offers_tests.cpp |  105 +++++++++++++++++++-----------
 3 files changed, 134 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/5690d207/src/tests/exception_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/exception_tests.cpp b/src/tests/exception_tests.cpp
index 60bb690..3fc1ac3 100644
--- a/src/tests/exception_tests.cpp
+++ b/src/tests/exception_tests.cpp
@@ -25,10 +25,13 @@
 #include <process/pid.hpp>
 #include <process/process.hpp>
 
-#include "local/local.hpp"
+#include <stout/gtest.hpp>
+#include <stout/try.hpp>
 
 #include "master/master.hpp"
 
+#include "slave/slave.hpp"
+
 #include "tests/mesos.hpp"
 
 using namespace mesos;
@@ -37,6 +40,8 @@ using namespace mesos::internal::tests;
 
 using mesos::internal::master::Master;
 
+using mesos::internal::slave::Slave;
+
 using process::Future;
 using process::PID;
 
@@ -50,13 +55,19 @@ using testing::Eq;
 using testing::Return;
 
 
-TEST(ExceptionTest, DeactivateFrameworkOnAbort)
+class ExceptionTest : public MesosTest {};
+
+
+TEST_F(ExceptionTest, DeactivateFrameworkOnAbort)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte,1 * Gigabyte,  false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  MockScheduler sched;
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   Future<Nothing> registered;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -80,17 +91,21 @@ TEST(ExceptionTest, DeactivateFrameworkOnAbort)
   AWAIT_READY(deactivateFrameworkMessage);
 
   driver.stop();
-  local::shutdown();
+
+  Shutdown();
 }
 
 
-TEST(ExceptionTest, DisallowSchedulerActionsOnAbort)
+TEST_F(ExceptionTest, DisallowSchedulerActionsOnAbort)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  MockScheduler sched;
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   Future<Nothing> registered;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -111,17 +126,21 @@ TEST(ExceptionTest, DisallowSchedulerActionsOnAbort)
   ASSERT_EQ(DRIVER_ABORTED, driver.reviveOffers());
 
   driver.stop();
-  local::shutdown();
+
+  Shutdown();
 }
 
 
-TEST(ExceptionTest, DisallowSchedulerCallbacksOnAbort)
+TEST_F(ExceptionTest, DisallowSchedulerCallbacksOnAbort)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  MockScheduler sched;
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _))
     .Times(1);
@@ -176,5 +195,5 @@ TEST(ExceptionTest, DisallowSchedulerCallbacksOnAbort)
   //Ensures reception of RescindResourceOfferMessage.
   AWAIT_READY(unregisterMsg);
 
-  local::shutdown();
+  Shutdown();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/5690d207/src/tests/fault_tolerance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/fault_tolerance_tests.cpp b/src/tests/fault_tolerance_tests.cpp
index e41a044..287453d 100644
--- a/src/tests/fault_tolerance_tests.cpp
+++ b/src/tests/fault_tolerance_tests.cpp
@@ -38,8 +38,6 @@
 
 #include "common/protobuf_utils.hpp"
 
-#include "local/local.hpp"
-
 #include "master/master.hpp"
 
 #include "slave/isolator.hpp"
@@ -134,17 +132,21 @@ TEST_F(FaultToleranceTest, PartitionedSlave)
 {
   Clock::pause();
 
-  // Set these expectations up before we spawn the slave (in
-  // local::launch) so that we don't miss the first PING.
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  // Set these expectations up before we spawn the slave so that we
+  // don't miss the first PING.
   Future<Message> ping = FUTURE_MESSAGE(Eq("PING"), _, _);
 
   // Drop all the PONGs to simulate slave partition.
   DROP_MESSAGES(Eq("PONG"), _, _);
 
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _));
 
@@ -185,7 +187,7 @@ TEST_F(FaultToleranceTest, PartitionedSlave)
   driver.stop();
   driver.join();
 
-  local::shutdown();
+  Shutdown();
 
   Clock::resume();
 }
@@ -638,14 +640,18 @@ TEST_F(FaultToleranceTest, MasterFailover)
 
 TEST_F(FaultToleranceTest, SchedulerFailover)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   // Launch the first (i.e., failing) scheduler and wait until
   // registered gets called to launch the second (i.e., failover)
   // scheduler.
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
 
   Future<FrameworkID> frameworkId;
   EXPECT_CALL(sched1, registered(&driver1, _, _))
@@ -668,7 +674,7 @@ TEST_F(FaultToleranceTest, SchedulerFailover)
   framework2 = DEFAULT_FRAMEWORK_INFO;
   framework2.mutable_id()->MergeFrom(frameworkId.get());
 
-  MesosSchedulerDriver driver2(&sched2, framework2, master);
+  MesosSchedulerDriver driver2(&sched2, framework2, master.get());
 
   Future<Nothing> sched2Registered;
   EXPECT_CALL(sched2, registered(&driver2, frameworkId.get(), _))
@@ -700,7 +706,7 @@ TEST_F(FaultToleranceTest, SchedulerFailover)
   EXPECT_EQ(DRIVER_ABORTED, driver1.stop());
   EXPECT_EQ(DRIVER_STOPPED, driver1.join());
 
-  local::shutdown();
+  Shutdown();
 }
 
 
@@ -708,10 +714,14 @@ TEST_F(FaultToleranceTest, FrameworkReliableRegistration)
 {
   Clock::pause();
 
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   Future<Nothing> registered;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -739,7 +749,7 @@ TEST_F(FaultToleranceTest, FrameworkReliableRegistration)
   driver.stop();
   driver.join();
 
-  local::shutdown();
+  Shutdown();
 
   Clock::resume();
 }
@@ -747,10 +757,14 @@ TEST_F(FaultToleranceTest, FrameworkReliableRegistration)
 
 TEST_F(FaultToleranceTest, FrameworkReregister)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   Future<Nothing> registered;
   EXPECT_CALL(sched, registered(&driver, _, _))
@@ -781,7 +795,7 @@ TEST_F(FaultToleranceTest, FrameworkReregister)
   // Simulate a spurious newMasterDetected event (e.g., due to ZooKeeper
   // expiration) at the scheduler.
   NewMasterDetectedMessage newMasterDetectedMsg;
-  newMasterDetectedMsg.set_pid(master);
+  newMasterDetectedMsg.set_pid(master.get());
 
   process::post(message.get().to, newMasterDetectedMsg);
 
@@ -792,7 +806,7 @@ TEST_F(FaultToleranceTest, FrameworkReregister)
   driver.stop();
   driver.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/5690d207/src/tests/resource_offers_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/resource_offers_tests.cpp b/src/tests/resource_offers_tests.cpp
index 28ec4bc..e030d3d 100644
--- a/src/tests/resource_offers_tests.cpp
+++ b/src/tests/resource_offers_tests.cpp
@@ -23,8 +23,6 @@
 #include <mesos/executor.hpp>
 #include <mesos/scheduler.hpp>
 
-#include "local/local.hpp"
-
 #include "master/hierarchical_allocator_process.hpp"
 #include "master/master.hpp"
 
@@ -51,12 +49,24 @@ using testing::AtMost;
 using testing::Return;
 
 
-TEST(ResourceOffersTest, ResourceOfferWithMultipleSlaves)
+class ResourceOffersTest : public MesosTest {};
+
+
+TEST_F(ResourceOffersTest, ResourceOfferWithMultipleSlaves)
 {
-  PID<Master> master = local::launch(10, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  // Start 10 slaves.
+  for (int i = 0; i < 10; i++) {
+    slave::Flags flags = CreateSlaveFlags();
+    flags.resources = Option<std::string>("cpus:2;mem:1024");
+    Try<PID<Slave> > slave = StartSlave(flags);
+    ASSERT_SOME(slave);
+  }
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _))
     .Times(1);
@@ -79,16 +89,20 @@ TEST(ResourceOffersTest, ResourceOfferWithMultipleSlaves)
   driver.stop();
   driver.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 
-TEST(ResourceOffersTest, TaskUsesNoResources)
+TEST_F(ResourceOffersTest, TaskUsesNoResources)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _))
     .Times(1);
@@ -127,16 +141,20 @@ TEST(ResourceOffersTest, TaskUsesNoResources)
   driver.stop();
   driver.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 
-TEST(ResourceOffersTest, TaskUsesInvalidResources)
+TEST_F(ResourceOffersTest, TaskUsesInvalidResources)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _))
     .Times(1);
@@ -180,16 +198,20 @@ TEST(ResourceOffersTest, TaskUsesInvalidResources)
   driver.stop();
   driver.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 
-TEST(ResourceOffersTest, TaskUsesMoreResourcesThanOffered)
+TEST_F(ResourceOffersTest, TaskUsesMoreResourcesThanOffered)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched, registered(&driver, _, _))
     .Times(1);
@@ -234,17 +256,20 @@ TEST(ResourceOffersTest, TaskUsesMoreResourcesThanOffered)
   driver.stop();
   driver.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 
-TEST(ResourceOffersTest, ResourcesGetReofferedAfterFrameworkStops)
+TEST_F(ResourceOffersTest, ResourcesGetReofferedAfterFrameworkStops)
 {
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
 
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched1, registered(&driver1, _, _))
     .Times(1);
@@ -262,7 +287,7 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterFrameworkStops)
   driver1.join();
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched2, registered(&driver2, _, _))
     .Times(1);
@@ -277,16 +302,20 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterFrameworkStops)
   driver2.stop();
   driver2.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 
-TEST(ResourceOffersTest, ResourcesGetReofferedWhenUnused)
+TEST_F(ResourceOffersTest, ResourcesGetReofferedWhenUnused)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched1, registered(&driver1, _, _))
     .Times(1);
@@ -304,7 +333,7 @@ TEST(ResourceOffersTest, ResourcesGetReofferedWhenUnused)
   driver1.launchTasks(offers.get()[0].id(), tasks);
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched2, registered(&driver2, _, _))
     .Times(1);
@@ -323,16 +352,20 @@ TEST(ResourceOffersTest, ResourcesGetReofferedWhenUnused)
   driver2.stop();
   driver2.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 
-TEST(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
+TEST_F(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
 {
-  PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
+  Try<PID<Master> > master = StartMaster();
+  ASSERT_SOME(master);
+
+  Try<PID<Slave> > slave = StartSlave();
+  ASSERT_SOME(slave);
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched1, registered(&driver1, _, _))
     .Times(1);
@@ -379,7 +412,7 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
   EXPECT_EQ("Task uses invalid resources", status.get().message());
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master);
+  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master.get());
 
   EXPECT_CALL(sched2, registered(&driver2, _, _))
     .Times(1);
@@ -398,7 +431,7 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
   driver2.stop();
   driver2.join();
 
-  local::shutdown();
+  Shutdown();
 }
 
 // TODO(benh): Add tests for checking correct slave IDs.
@@ -409,11 +442,7 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
 // unique task IDs and aggregate resource usage.
 
 
-// TODO(benh): Eliminate this class once we replace tests above to use
-// MesosTest/Cluster instead of local::launch.
-class ResourceOffersMesosTest : public MesosTest {};
-
-TEST_F(ResourceOffersMesosTest, Request)
+TEST_F(ResourceOffersTest, Request)
 {
   MockAllocatorProcess<HierarchicalDRFAllocatorProcess> allocator;
 


[03/28] git commit: Performed GTEST_IS_THREADSAFE check.

Posted by be...@apache.org.
Performed GTEST_IS_THREADSAFE check.

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


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

Branch: refs/heads/master
Commit: f5be4131d1aa4bd858eeedcbefffb842d7252252
Parents: 304835d
Author: Benjamin Hindman <be...@twitter.com>
Authored: Thu Apr 25 17:33:12 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/tests/environment.cpp                 |    5 ++++
 src/tests/exception_tests.cpp             |    6 -----
 src/tests/fault_tolerance_tests.cpp       |   26 ------------------------
 src/tests/gc_tests.cpp                    |   10 ---------
 src/tests/master_detector_tests.cpp       |    2 -
 src/tests/master_tests.cpp                |   24 ----------------------
 src/tests/reaper_tests.cpp                |    2 -
 src/tests/resource_offers_tests.cpp       |   17 ---------------
 src/tests/slave_recovery_tests.cpp        |    2 -
 src/tests/status_update_manager_tests.cpp |    8 -------
 10 files changed, 5 insertions(+), 97 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/environment.cpp
----------------------------------------------------------------------
diff --git a/src/tests/environment.cpp b/src/tests/environment.cpp
index c94c85f..15ef205 100644
--- a/src/tests/environment.cpp
+++ b/src/tests/environment.cpp
@@ -24,6 +24,7 @@
 #include <process/gmock.hpp>
 #include <process/gtest.hpp>
 
+#include <stout/exit.hpp>
 #include <stout/os.hpp>
 #include <stout/strings.hpp>
 
@@ -172,6 +173,10 @@ void Environment::SetUp()
 {
   // Clear any MESOS_ environment variables so they don't affect our tests.
   Configurator::clearMesosEnvironmentVars();
+
+  if (!GTEST_IS_THREADSAFE) {
+    EXIT(1) << "Testing environment is not thread safe, bailing!";
+  }
 }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/exception_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/exception_tests.cpp b/src/tests/exception_tests.cpp
index f405a61..911e786 100644
--- a/src/tests/exception_tests.cpp
+++ b/src/tests/exception_tests.cpp
@@ -62,8 +62,6 @@ using testing::SaveArg;
 
 TEST(ExceptionTest, DeactivateFrameworkOnAbort)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte,1 * Gigabyte,  false);
 
   MockScheduler sched;
@@ -98,8 +96,6 @@ TEST(ExceptionTest, DeactivateFrameworkOnAbort)
 
 TEST(ExceptionTest, DisallowSchedulerActionsOnAbort)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched;
@@ -131,8 +127,6 @@ TEST(ExceptionTest, DisallowSchedulerActionsOnAbort)
 
 TEST(ExceptionTest, DisallowSchedulerCallbacksOnAbort)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/fault_tolerance_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/fault_tolerance_tests.cpp b/src/tests/fault_tolerance_tests.cpp
index 2e9416e..bcfe5db 100644
--- a/src/tests/fault_tolerance_tests.cpp
+++ b/src/tests/fault_tolerance_tests.cpp
@@ -92,8 +92,6 @@ class FaultToleranceTest : public MesosTest {};
 // its offer(s) is rescinded.
 TEST_F(FaultToleranceTest, SlaveLost)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   HierarchicalDRFAllocatorProcess allocator;
   Allocator a(&allocator);
   Files files;
@@ -149,8 +147,6 @@ TEST_F(FaultToleranceTest, SlaveLost)
 // message for a partioned slave.
 TEST_F(FaultToleranceTest, PartitionedSlave)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Clock::pause();
 
   // Set these expectations up before we spawn the slave (in
@@ -662,8 +658,6 @@ TEST_F(FaultToleranceClusterTest, MasterFailover)
 
 TEST_F(FaultToleranceTest, SchedulerFailover)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   // Launch the first (i.e., failing) scheduler and wait until
@@ -732,8 +726,6 @@ TEST_F(FaultToleranceTest, SchedulerFailover)
 
 TEST_F(FaultToleranceTest, FrameworkReliableRegistration)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Clock::pause();
 
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
@@ -775,8 +767,6 @@ TEST_F(FaultToleranceTest, FrameworkReliableRegistration)
 
 TEST_F(FaultToleranceTest, FrameworkReregister)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched;
@@ -828,8 +818,6 @@ TEST_F(FaultToleranceTest, FrameworkReregister)
 
 TEST_F(FaultToleranceTest, TaskLost)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   HierarchicalDRFAllocatorProcess allocator;
   Allocator a(&allocator);
   Files files;
@@ -906,8 +894,6 @@ TEST_F(FaultToleranceTest, TaskLost)
 // retried status update.
 TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Clock::pause();
 
   HierarchicalDRFAllocatorProcess allocator;
@@ -1025,8 +1011,6 @@ TEST_F(FaultToleranceTest, SchedulerFailoverStatusUpdate)
 
 TEST_F(FaultToleranceTest, ForwardStatusUpdateUnknownExecutor)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   HierarchicalDRFAllocatorProcess allocator;
   Allocator a(&allocator);
   Files files;
@@ -1120,8 +1104,6 @@ TEST_F(FaultToleranceTest, ForwardStatusUpdateUnknownExecutor)
 
 TEST_F(FaultToleranceTest, SchedulerFailoverFrameworkMessage)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   HierarchicalDRFAllocatorProcess allocator;
   Allocator a(&allocator);
   Files files;
@@ -1228,8 +1210,6 @@ TEST_F(FaultToleranceTest, SchedulerFailoverFrameworkMessage)
 // This test checks that a scheduler exit shuts down the executor.
 TEST_F(FaultToleranceTest, SchedulerExit)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   HierarchicalDRFAllocatorProcess allocator;
   Allocator a(&allocator);
   Files files;
@@ -1305,8 +1285,6 @@ TEST_F(FaultToleranceTest, SchedulerExit)
 
 TEST_F(FaultToleranceTest, SlaveReliableRegistration)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Clock::pause();
 
   HierarchicalDRFAllocatorProcess allocator;
@@ -1359,8 +1337,6 @@ TEST_F(FaultToleranceTest, SlaveReliableRegistration)
 
 TEST_F(FaultToleranceTest, SlaveReregisterOnZKExpiration)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   HierarchicalDRFAllocatorProcess allocator;
   Allocator a(&allocator);
   Files files;
@@ -1418,8 +1394,6 @@ TEST_F(FaultToleranceTest, SlaveReregisterOnZKExpiration)
 // TODO(vinod): Use 'Cluster' abstraction.
 TEST_F(FaultToleranceTest, ConsolidateTasksOnSlaveReregistration)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   HierarchicalDRFAllocatorProcess allocator;
   Allocator a(&allocator);
   Files files;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/gc_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/gc_tests.cpp b/src/tests/gc_tests.cpp
index 97d2685..949678c 100644
--- a/src/tests/gc_tests.cpp
+++ b/src/tests/gc_tests.cpp
@@ -253,8 +253,6 @@ class GarbageCollectorIntegrationTest : public MesosClusterTest {};
 
 TEST_F(GarbageCollectorIntegrationTest, Restart)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -354,8 +352,6 @@ TEST_F(GarbageCollectorIntegrationTest, Restart)
 
 TEST_F(GarbageCollectorIntegrationTest, ExitedFramework)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -453,8 +449,6 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedFramework)
 
 TEST_F(GarbageCollectorIntegrationTest, ExitedExecutor)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -545,8 +539,6 @@ TEST_F(GarbageCollectorIntegrationTest, ExitedExecutor)
 
 TEST_F(GarbageCollectorIntegrationTest, DiskUsage)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -649,8 +641,6 @@ TEST_F(GarbageCollectorIntegrationTest, DiskUsage)
 // created by an old executor (with the same id).
 TEST_F(GarbageCollectorIntegrationTest, Unschedule)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/master_detector_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_detector_tests.cpp b/src/tests/master_detector_tests.cpp
index 521f027..3a7b3b4 100644
--- a/src/tests/master_detector_tests.cpp
+++ b/src/tests/master_detector_tests.cpp
@@ -65,8 +65,6 @@ class MasterDetectorTest : public MesosClusterTest {};
 
 TEST_F(MasterDetectorTest, File)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/master_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_tests.cpp b/src/tests/master_tests.cpp
index fe823f6..f99157e 100644
--- a/src/tests/master_tests.cpp
+++ b/src/tests/master_tests.cpp
@@ -77,8 +77,6 @@ class MasterTest : public MesosClusterTest {};
 
 TEST_F(MasterTest, TaskRunning)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -152,8 +150,6 @@ TEST_F(MasterTest, TaskRunning)
 
 TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -229,8 +225,6 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
 
 TEST_F(MasterTest, KillTask)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -309,8 +303,6 @@ TEST_F(MasterTest, KillTask)
 
 TEST_F(MasterTest, StatusUpdateAck)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -381,8 +373,6 @@ TEST_F(MasterTest, StatusUpdateAck)
 
 TEST_F(MasterTest, RecoverResources)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -504,8 +494,6 @@ TEST_F(MasterTest, RecoverResources)
 
 TEST_F(MasterTest, FrameworkMessage)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -590,8 +578,6 @@ TEST_F(MasterTest, FrameworkMessage)
 
 TEST_F(MasterTest, MultipleExecutors)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -708,8 +694,6 @@ TEST_F(MasterTest, MultipleExecutors)
 
 TEST_F(MasterTest, ShutdownUnregisteredExecutor)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -793,8 +777,6 @@ TEST_F(MasterTest, ShutdownUnregisteredExecutor)
 
 TEST_F(MasterTest, MasterInfo)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -826,8 +808,6 @@ TEST_F(MasterTest, MasterInfo)
 
 TEST_F(MasterTest, MasterInfoOnReElection)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -895,8 +875,6 @@ protected:
 
 TEST_F(WhitelistTest, WhitelistSlave)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   // Add some hosts to the white list.
   Try<string> hostname = os::hostname();
   ASSERT_SOME(hostname);
@@ -934,8 +912,6 @@ TEST_F(WhitelistTest, WhitelistSlave)
 
 TEST_F(MasterTest, MasterLost)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/reaper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/reaper_tests.cpp b/src/tests/reaper_tests.cpp
index 0809c1f..c1fc1c3 100644
--- a/src/tests/reaper_tests.cpp
+++ b/src/tests/reaper_tests.cpp
@@ -44,8 +44,6 @@ using testing::DoDefault;
 // This test checks that the Reaper can monitor a non-child process.
 TEST(ReaperTest, NonChildProcess)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   // Use pipes to determine the pid of the grand child process.
   int pipes[2];
   ASSERT_NE(-1, pipe(pipes));

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/resource_offers_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/resource_offers_tests.cpp b/src/tests/resource_offers_tests.cpp
index 5e53a89..0be5497 100644
--- a/src/tests/resource_offers_tests.cpp
+++ b/src/tests/resource_offers_tests.cpp
@@ -53,8 +53,6 @@ using testing::Return;
 
 TEST(ResourceOffersTest, ResourceOfferWithMultipleSlaves)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(10, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched;
@@ -87,8 +85,6 @@ TEST(ResourceOffersTest, ResourceOfferWithMultipleSlaves)
 
 TEST(ResourceOffersTest, TaskUsesNoResources)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched;
@@ -137,8 +133,6 @@ TEST(ResourceOffersTest, TaskUsesNoResources)
 
 TEST(ResourceOffersTest, TaskUsesInvalidResources)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched;
@@ -192,8 +186,6 @@ TEST(ResourceOffersTest, TaskUsesInvalidResources)
 
 TEST(ResourceOffersTest, TaskUsesMoreResourcesThanOffered)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched;
@@ -248,7 +240,6 @@ TEST(ResourceOffersTest, TaskUsesMoreResourcesThanOffered)
 
 TEST(ResourceOffersTest, ResourcesGetReofferedAfterFrameworkStops)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
 
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
@@ -292,8 +283,6 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterFrameworkStops)
 
 TEST(ResourceOffersTest, ResourcesGetReofferedWhenUnused)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched1;
@@ -340,8 +329,6 @@ TEST(ResourceOffersTest, ResourcesGetReofferedWhenUnused)
 
 TEST(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, 1 * Gigabyte, false);
 
   MockScheduler sched1;
@@ -424,8 +411,6 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
 
 TEST(ResourceOffersTest, Request)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Cluster cluster;
 
   MockAllocatorProcess<HierarchicalDRFAllocatorProcess> allocator;
@@ -484,8 +469,6 @@ class MultipleExecutorsTest : public MesosClusterTest {};
 
 TEST_F(MultipleExecutorsTest, TasksExecutorInfoDiffers)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/slave_recovery_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_recovery_tests.cpp b/src/tests/slave_recovery_tests.cpp
index d963ce1..fd6b9ac 100644
--- a/src/tests/slave_recovery_tests.cpp
+++ b/src/tests/slave_recovery_tests.cpp
@@ -132,8 +132,6 @@ public:
   {
     IsolatorTest<T>::SetUp();
 
-    ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
     a = new Allocator(&allocator);
     m = new Master(a, &files);
     master = process::spawn(m);

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/f5be4131/src/tests/status_update_manager_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/status_update_manager_tests.cpp b/src/tests/status_update_manager_tests.cpp
index e375898..042201a 100644
--- a/src/tests/status_update_manager_tests.cpp
+++ b/src/tests/status_update_manager_tests.cpp
@@ -90,8 +90,6 @@ class StatusUpdateManagerTest: public MesosClusterTest {};
 
 TEST_F(StatusUpdateManagerTest, CheckpointStatusUpdate)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -193,8 +191,6 @@ TEST_F(StatusUpdateManagerTest, CheckpointStatusUpdate)
 
 TEST_F(StatusUpdateManagerTest, RetryStatusUpdate)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -272,8 +268,6 @@ TEST_F(StatusUpdateManagerTest, RetryStatusUpdate)
 // duplicate ACK is for a retried update.
 TEST_F(StatusUpdateManagerTest, IgnoreDuplicateStatusUpdateAck)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 
@@ -394,8 +388,6 @@ TEST_F(StatusUpdateManagerTest, IgnoreDuplicateStatusUpdateAck)
 // for the original update and sending a random ACK to the slave.
 TEST_F(StatusUpdateManagerTest, IgnoreUnexpectedStatusUpdateAck)
 {
-  ASSERT_TRUE(GTEST_IS_THREADSAFE);
-
   Try<PID<Master> > master = cluster.masters.start();
   ASSERT_SOME(master);
 


[15/28] git commit: Used Milliseconds rather than Duration::parse.

Posted by be...@apache.org.
Used Milliseconds rather than Duration::parse.

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


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

Branch: refs/heads/master
Commit: bb18d3bcc8208bcfd0deb422323631765236c779
Parents: 7995751
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sat May 11 10:08:35 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Sun May 26 00:13:41 2013 -0700

----------------------------------------------------------------------
 src/tests/allocator_tests.cpp |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/bb18d3bc/src/tests/allocator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_tests.cpp b/src/tests/allocator_tests.cpp
index 5a0de33..7ee71de 100644
--- a/src/tests/allocator_tests.cpp
+++ b/src/tests/allocator_tests.cpp
@@ -685,7 +685,7 @@ TYPED_TEST(AllocatorTest, FrameworkExited)
   EXPECT_CALL(this->allocator, initialize(_, _));
 
   master::Flags masterFlags = this->CreateMasterFlags();
-  masterFlags.allocation_interval = Duration::parse("50ms").get();
+  masterFlags.allocation_interval = Milliseconds(50);
   Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 
@@ -943,7 +943,7 @@ TYPED_TEST(AllocatorTest, SlaveAdded)
   EXPECT_CALL(this->allocator, initialize(_, _));
 
   master::Flags masterFlags = this->CreateMasterFlags();
-  masterFlags.allocation_interval = Duration::parse("50ms").get();
+  masterFlags.allocation_interval = Milliseconds(50);
   Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 
@@ -1050,7 +1050,7 @@ TYPED_TEST(AllocatorTest, TaskFinished)
   EXPECT_CALL(this->allocator, initialize(_, _));
 
   master::Flags masterFlags = this->CreateMasterFlags();
-  masterFlags.allocation_interval = Duration::parse("50ms").get();
+  masterFlags.allocation_interval = Milliseconds(50);
   Try<PID<Master> > master = this->StartMaster(&this->allocator, masterFlags);
   ASSERT_SOME(master);
 


[11/28] Refactored MesosTest/MesosClusterTest into a generic fixture for launching in-memory Mesos clusters and updated all tests appropriately.

Posted by be...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/master_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_tests.cpp b/src/tests/master_tests.cpp
index f99157e..1d26eeb 100644
--- a/src/tests/master_tests.cpp
+++ b/src/tests/master_tests.cpp
@@ -44,8 +44,8 @@
 #include "slave/process_isolator.hpp"
 #include "slave/slave.hpp"
 
-#include "tests/cluster.hpp"
-#include "tests/utils.hpp"
+#include "tests/isolator.hpp"
+#include "tests/mesos.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;
@@ -72,19 +72,18 @@ using testing::Eq;
 using testing::Return;
 
 
-class MasterTest : public MesosClusterTest {};
+class MasterTest : public MesosTest {};
 
 
 TEST_F(MasterTest, TaskRunning)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
 
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
-
-  Try<PID<Slave> > slave = cluster.slaves.start(&isolator);
+  Try<PID<Slave> > slave = StartSlave(&isolator);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -144,22 +143,22 @@ TEST_F(MasterTest, TaskRunning)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
 TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
-
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
 
-  slave::Flags flags = cluster.slaves.flags;
+  slave::Flags flags = CreateSlaveFlags();
   flags.executor_shutdown_grace_period = Seconds(0);
-  Try<PID<Slave> > slave = cluster.slaves.start(flags, &isolator);
+
+  Try<PID<Slave> > slave = StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -219,18 +218,18 @@ TEST_F(MasterTest, ShutdownFrameworkWhileTaskRunning)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
 TEST_F(MasterTest, KillTask)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Slave> > slave = StartSlave(&exec);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -297,18 +296,18 @@ TEST_F(MasterTest, KillTask)
 
   AWAIT_READY(shutdown); // To ensure can deallocate MockExecutor.
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 TEST_F(MasterTest, StatusUpdateAck)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Slave> > slave = StartSlave(&exec);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -367,23 +366,23 @@ TEST_F(MasterTest, StatusUpdateAck)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 TEST_F(MasterTest, RecoverResources)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+  TestingIsolator isolator(&exec);
 
-  TestingIsolator isolator(DEFAULT_EXECUTOR_ID, &exec);
+  slave::Flags flags = CreateSlaveFlags();
+  flags.resources = Option<string>(
+      "cpus:2;mem:1024;disk:1024;ports:[1-10, 20-30]");
 
-  slave::Flags flags = cluster.slaves.flags;
-  flags.resources =
-    Option<string>("cpus:2;mem:1024;disk:1024;ports:[1-10, 20-30]");
-  Try<PID<Slave> > slave = cluster.slaves.start(flags, &isolator);
+  Try<PID<Slave> > slave = StartSlave(&isolator, flags);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -488,18 +487,18 @@ TEST_F(MasterTest, RecoverResources)
   EXPECT_CALL(exec, shutdown(_))
     .Times(AtMost(1));
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
 TEST_F(MasterTest, FrameworkMessage)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Slave> > slave = StartSlave(&exec);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -572,13 +571,13 @@ TEST_F(MasterTest, FrameworkMessage)
 
   AWAIT_READY(shutdown); // To ensure can deallocate MockExecutor.
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 TEST_F(MasterTest, MultipleExecutors)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   ExecutorID executorId1;
@@ -587,8 +586,8 @@ TEST_F(MasterTest, MultipleExecutors)
   ExecutorID executorId2;
   executorId2.set_value("executor-2");
 
-  MockExecutor exec1;
-  MockExecutor exec2;
+  MockExecutor exec1(executorId1);
+  MockExecutor exec2(executorId2);
 
   map<ExecutorID, Executor*> execs;
   execs[executorId1] = &exec1;
@@ -596,7 +595,7 @@ TEST_F(MasterTest, MultipleExecutors)
 
   TestingIsolator isolator(execs);
 
-  Try<PID<Slave> > slave = cluster.slaves.start(&isolator);
+  Try<PID<Slave> > slave = StartSlave(&isolator);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -688,18 +687,21 @@ TEST_F(MasterTest, MultipleExecutors)
   AWAIT_READY(shutdown1); // To ensure can deallocate MockExecutor.
   AWAIT_READY(shutdown2); // To ensure can deallocate MockExecutor.
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
 TEST_F(MasterTest, ShutdownUnregisteredExecutor)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
   ProcessIsolator isolator;
 
-  Try<PID<Slave> > slave = cluster.slaves.start(&isolator);
+  // Need flags for 'executor_registration_timeout'.
+  slave::Flags flags = CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = StartSlave(&isolator);
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -751,7 +753,7 @@ TEST_F(MasterTest, ShutdownUnregisteredExecutor)
   Future<Nothing> killExecutor =
     FUTURE_DISPATCH(_, &Isolator::killExecutor);
 
-  Clock::advance(cluster.slaves.flags.executor_registration_timeout);
+  Clock::advance(flags.executor_registration_timeout);
 
   AWAIT_READY(killExecutor);
 
@@ -771,16 +773,16 @@ TEST_F(MasterTest, ShutdownUnregisteredExecutor)
   driver.stop();
   driver.join();
 
-  cluster.shutdown(); // Must shutdown before 'isolator' gets deallocated.
+  Shutdown(); // Must shutdown before 'isolator' gets deallocated.
 }
 
 
 TEST_F(MasterTest, MasterInfo)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  Try<PID<Slave> > slave = cluster.slaves.start();
+  Try<PID<Slave> > slave = StartSlave();
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -802,16 +804,16 @@ TEST_F(MasterTest, MasterInfo)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 TEST_F(MasterTest, MasterInfoOnReElection)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  Try<PID<Slave> > slave = cluster.slaves.start();
+  Try<PID<Slave> > slave = StartSlave();
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -854,7 +856,7 @@ TEST_F(MasterTest, MasterInfoOnReElection)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
@@ -878,15 +880,17 @@ TEST_F(WhitelistTest, WhitelistSlave)
   // Add some hosts to the white list.
   Try<string> hostname = os::hostname();
   ASSERT_SOME(hostname);
+
   string hosts = hostname.get() + "\n" + "dummy-slave";
   ASSERT_SOME(os::write(path, hosts)) << "Error writing whitelist";
 
-  master::Flags flags = cluster.masters.flags;
+  master::Flags flags = CreateMasterFlags();
   flags.whitelist = "file://" + path;
-  Try<PID<Master> > master = cluster.masters.start(flags);
+
+  Try<PID<Master> > master = StartMaster(flags);
   ASSERT_SOME(master);
 
-  Try<PID<Slave> > slave = cluster.slaves.start();
+  Try<PID<Slave> > slave = StartSlave();
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -906,16 +910,16 @@ TEST_F(WhitelistTest, WhitelistSlave)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 TEST_F(MasterTest, MasterLost)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  Try<PID<Slave> > slave = cluster.slaves.start();
+  Try<PID<Slave> > slave = StartSlave();
   ASSERT_SOME(slave);
 
   MockScheduler sched;
@@ -946,5 +950,5 @@ TEST_F(MasterTest, MasterLost)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/mesos.cpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.cpp b/src/tests/mesos.cpp
new file mode 100644
index 0000000..4ddf032
--- /dev/null
+++ b/src/tests/mesos.cpp
@@ -0,0 +1,240 @@
+#include <stout/foreach.hpp>
+#include <stout/os.hpp>
+#include <stout/result.hpp>
+
+#ifdef __linux__
+#include "linux/cgroups.hpp"
+#endif
+
+#include "logging/logging.hpp"
+
+#include "tests/environment.hpp"
+#include "tests/flags.hpp"
+#include "tests/isolator.hpp"
+#include "tests/mesos.hpp"
+
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+MesosTest::MesosTest(const Option<zookeeper::URL>& url) : cluster(url) {}
+
+
+master::Flags MesosTest::CreateMasterFlags()
+{
+  return master::Flags();
+}
+
+
+slave::Flags MesosTest::CreateSlaveFlags()
+{
+  slave::Flags flags;
+
+  // Create a temporary work directory (removed by Environment).
+  Try<std::string> directory = environment->mkdtemp();
+  CHECK_SOME(directory) << "Failed to create temporary directory";
+
+  flags.work_dir = directory.get();
+
+  flags.launcher_dir = path::join(tests::flags.build_dir, "src");
+
+  flags.resources = Option<std::string>(
+      "cpus:2;mem:1024;disk:1024;ports:[31000-32000]");
+
+  return flags;
+}
+
+
+Try<process::PID<master::Master> > MesosTest::StartMaster(
+    const Option<master::Flags>& flags)
+{
+  return cluster.masters.start(
+      flags.isNone() ? CreateMasterFlags() : flags.get());
+}
+
+
+Try<process::PID<master::Master> > MesosTest::StartMaster(
+    master::AllocatorProcess* allocator,
+    const Option<master::Flags>& flags)
+{
+  return cluster.masters.start(
+      allocator, flags.isNone() ? CreateMasterFlags() : flags.get());
+}
+
+
+Try<process::PID<slave::Slave> > MesosTest::StartSlave(
+    const Option<slave::Flags>& flags)
+{
+  TestingIsolator* isolator = new TestingIsolator();
+
+  Try<process::PID<slave::Slave> > pid = StartSlave(isolator, flags);
+
+  if (pid.isError()) {
+    delete isolator;
+    return pid;
+  }
+
+  isolators[pid.get()] = isolator;
+
+  return pid;
+}
+
+
+Try<process::PID<slave::Slave> > MesosTest::StartSlave(
+    MockExecutor* executor,
+    const Option<slave::Flags>& flags)
+{
+  TestingIsolator* isolator = new TestingIsolator(executor);
+    
+  Try<process::PID<slave::Slave> > pid = StartSlave(isolator, flags);
+
+  if (pid.isError()) {
+    delete isolator;
+    return pid;
+  }
+
+  isolators[pid.get()] = isolator;
+
+  return pid;
+}
+
+
+Try<process::PID<slave::Slave> > MesosTest::StartSlave(
+    slave::Isolator* isolator,
+    const Option<slave::Flags>& flags)
+{
+  return cluster.slaves.start(
+      isolator, flags.isNone() ? CreateSlaveFlags() : flags.get());
+}
+
+
+void MesosTest::Stop(const process::PID<master::Master>& pid)
+{
+  cluster.masters.stop(pid);
+}
+
+
+void MesosTest::Stop(const process::PID<slave::Slave>& pid, bool shutdown)
+{
+  cluster.slaves.stop(pid, shutdown);
+  if (isolators.count(pid) > 0) {
+    TestingIsolator* isolator = isolators[pid];
+    isolators.erase(pid);
+    delete isolator;
+  }
+}
+
+
+void MesosTest::Shutdown()
+{
+  ShutdownMasters();
+  ShutdownSlaves();
+}
+
+
+void MesosTest::ShutdownMasters()
+{
+  cluster.masters.shutdown();
+}
+
+
+void MesosTest::ShutdownSlaves()
+{
+  cluster.slaves.shutdown();
+
+  foreachvalue (TestingIsolator* isolator, isolators) {
+    delete isolator;
+  }
+  isolators.clear();
+}
+
+
+void MesosTest::SetUp()
+{
+  // For locating killtree.sh.
+  os::setenv("MESOS_SOURCE_DIR", tests::flags.source_dir);
+}
+
+
+void MesosTest::TearDown()
+{
+  os::unsetenv("MESOS_SOURCE_DIR");
+
+  // TODO(benh): Fail the test if shutdown hasn't been called?
+  Shutdown();
+}
+
+
+#ifdef __linux__
+void IsolatorTest<slave::CgroupsIsolator>::SetUpTestCase()
+{
+  // Clean up the testing hierarchy, in case it wasn't cleaned up
+  // properly from previous tests.
+  AWAIT_READY(cgroups::cleanup(TEST_CGROUPS_HIERARCHY));
+}
+
+
+void IsolatorTest<slave::CgroupsIsolator>::TearDownTestCase()
+{
+  AWAIT_READY(cgroups::cleanup(TEST_CGROUPS_HIERARCHY));
+}
+
+
+slave::Flags IsolatorTest<slave::CgroupsIsolator>::CreateSlaveFlags()
+{
+  slave::Flags flags = MesosTest::CreateSlaveFlags();
+
+  flags.cgroups_hierarchy = hierarchy;
+
+  // TODO(benh): Create a different cgroups root for each slave.
+  flags.cgroups_root = TEST_CGROUPS_ROOT;
+
+  return flags;
+}
+
+
+void IsolatorTest<slave::CgroupsIsolator>::SetUp()
+{
+  MesosTest::SetUp();
+
+  const std::string subsystems = "cpu,cpuacct,memory,freezer";
+  Result<std::string> hierarchy_ = cgroups::hierarchy(subsystems);
+  ASSERT_FALSE(hierarchy_.isError());
+  if (hierarchy_.isNone()) {
+    // Try to mount a hierarchy for testing.
+    ASSERT_SOME(cgroups::mount(TEST_CGROUPS_HIERARCHY, subsystems))
+      << "-------------------------------------------------------------\n"
+      << "We cannot run any cgroups tests that require\n"
+      << "a hierarchy with subsystems '" << subsystems << "'\n"
+      << "because we failed to find an existing hierarchy\n"
+      << "or create a new one. You can either remove all existing\n"
+      << "hierarchies, or disable this test case\n"
+      << "(i.e., --gtest_filter=-"
+      << ::testing::UnitTest::GetInstance()
+           ->current_test_info()
+           ->test_case_name() << ".*).\n"
+      << "-------------------------------------------------------------";
+
+    hierarchy = TEST_CGROUPS_HIERARCHY;
+  } else {
+    hierarchy = hierarchy_.get();
+  }
+}
+
+
+void IsolatorTest<slave::CgroupsIsolator>::TearDown()
+{
+  MesosTest::TearDown();
+
+  Try<bool> exists = cgroups::exists(hierarchy, TEST_CGROUPS_ROOT);
+  ASSERT_SOME(exists);
+  if (exists.get()) {
+    AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
+  }
+}
+#endif // __linux__
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/mesos.hpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp
new file mode 100644
index 0000000..12298ae
--- /dev/null
+++ b/src/tests/mesos.hpp
@@ -0,0 +1,676 @@
+/**
+ * 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.
+ */
+
+#ifndef __TESTS_MESOS_HPP__
+#define __TESTS_MESOS_HPP__
+
+#include <map>
+#include <string>
+
+#include <mesos/executor.hpp>
+#include <mesos/scheduler.hpp>
+
+#include <process/future.hpp>
+#include <process/gmock.hpp>
+#include <process/gtest.hpp>
+#include <process/pid.hpp>
+#include <process/process.hpp>
+
+#include <stout/gtest.hpp>
+#include <stout/lambda.hpp>
+#include <stout/none.hpp>
+#include <stout/option.hpp>
+#include <stout/stringify.hpp>
+#include <stout/try.hpp>
+#include <stout/uuid.hpp>
+
+#include "messages/messages.hpp" // For google::protobuf::Message.
+
+#include "master/allocator.hpp"
+#include "master/hierarchical_allocator_process.hpp"
+#include "master/master.hpp"
+
+#ifdef __linux__
+#include "slave/cgroups_isolator.hpp"
+#endif
+#include "slave/isolator.hpp"
+#include "slave/slave.hpp"
+
+#include "tests/cluster.hpp"
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+// Forward declarations.
+class MockExecutor;
+class TestingIsolator;
+
+
+class MesosTest : public ::testing::Test
+{
+protected:
+  MesosTest(const Option<zookeeper::URL>& url = None());
+
+  virtual void SetUp();
+  virtual void TearDown();
+
+  // Returns the flags used to create masters.
+  virtual master::Flags CreateMasterFlags();
+
+  // Returns the flags used to create slaves.
+  virtual slave::Flags CreateSlaveFlags();
+
+  // Starts a master with the specified flags.
+  virtual Try<process::PID<master::Master> > StartMaster(
+      const Option<master::Flags>& flags = None());
+
+  // Starts a master with the specified allocator process and flags.
+  virtual Try<process::PID<master::Master> > StartMaster(
+      master::AllocatorProcess* allocator,
+      const Option<master::Flags>& flags = None());
+
+  // Starts a slave with the specified flags.
+  virtual Try<process::PID<slave::Slave> > StartSlave(
+      const Option<slave::Flags>& flags = None());
+
+  // Starts a slave with the specified mock executor and flags.
+  virtual Try<process::PID<slave::Slave> > StartSlave(
+      MockExecutor* executor,
+      const Option<slave::Flags>& flags = None());
+
+  // Starts a slave with the specified isolator and flags.
+  virtual Try<process::PID<slave::Slave> > StartSlave(
+      slave::Isolator* isolator,
+      const Option<slave::Flags>& flags = None());
+
+  // Stop the specified master.
+  virtual void Stop(
+      const process::PID<master::Master>& pid);
+
+  // Stop the specified slave.
+  virtual void Stop(
+      const process::PID<slave::Slave>& pid,
+      bool shutdown = false);
+
+  // Stop all masters and slaves.
+  virtual void Shutdown();
+
+  // Stop all masters.
+  virtual void ShutdownMasters();
+
+  // Stop all slaves.
+  virtual void ShutdownSlaves();
+
+  Cluster cluster;
+
+  // TestingIsolator(s) created during test that we need to cleanup.
+  std::map<process::PID<slave::Slave>, TestingIsolator*> isolators;
+};
+
+
+
+template <typename T>
+class IsolatorTest : public MesosTest {};
+
+
+#ifdef __linux__
+// Cgroups hierarchy used by the cgroups related tests.
+const static std::string TEST_CGROUPS_HIERARCHY = "/tmp/mesos_test_cgroup";
+
+// Name of the root cgroup used by the cgroups related tests.
+const static std::string TEST_CGROUPS_ROOT = "mesos_test";
+
+
+template <>
+class IsolatorTest<slave::CgroupsIsolator> : public MesosTest
+{
+public:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+
+protected:
+  virtual slave::Flags CreateSlaveFlags();
+  virtual void SetUp();
+  virtual void TearDown();
+
+private:
+  std::string hierarchy;
+};
+#endif // __linux__
+
+
+// Macros to get/create (default) ExecutorInfos and FrameworkInfos.
+#define DEFAULT_EXECUTOR_INFO                                           \
+      ({ ExecutorInfo executor;                                         \
+        executor.mutable_executor_id()->set_value("default");           \
+        executor.mutable_command()->set_value("exit 1");                \
+        executor; })
+
+
+#define CREATE_EXECUTOR_INFO(executorId, command)                       \
+      ({ ExecutorInfo executor;                                         \
+        executor.mutable_executor_id()->MergeFrom(executorId);          \
+        executor.mutable_command()->set_value(command);                 \
+        executor; })
+
+
+#define DEFAULT_FRAMEWORK_INFO                                          \
+     ({ FrameworkInfo framework;                                        \
+        framework.set_name("default");                                  \
+        framework; })
+
+
+#define DEFAULT_EXECUTOR_ID						\
+      DEFAULT_EXECUTOR_INFO.executor_id()
+
+
+inline TaskInfo createTask(
+    const Offer& offer,
+    const std::string& command,
+    const std::string& name = "test-task",
+    const std::string& id = UUID::random().toString())
+{
+  TaskInfo task;
+  task.set_name(name);
+  task.mutable_task_id()->set_value(id);
+  task.mutable_slave_id()->MergeFrom(offer.slave_id());
+  task.mutable_resources()->MergeFrom(offer.resources());
+  task.mutable_command()->set_value(command);
+
+  return task;
+}
+
+
+// Definition of a mock Scheduler to be used in tests with gmock.
+class MockScheduler : public Scheduler
+{
+public:
+  MOCK_METHOD3(registered, void(SchedulerDriver*,
+                                const FrameworkID&,
+                                const MasterInfo&));
+  MOCK_METHOD2(reregistered, void(SchedulerDriver*, const MasterInfo&));
+  MOCK_METHOD1(disconnected, void(SchedulerDriver*));
+  MOCK_METHOD2(resourceOffers, void(SchedulerDriver*,
+                                    const std::vector<Offer>&));
+  MOCK_METHOD2(offerRescinded, void(SchedulerDriver*, const OfferID&));
+  MOCK_METHOD2(statusUpdate, void(SchedulerDriver*, const TaskStatus&));
+  MOCK_METHOD4(frameworkMessage, void(SchedulerDriver*,
+                                      const ExecutorID&,
+                                      const SlaveID&,
+                                      const std::string&));
+  MOCK_METHOD2(slaveLost, void(SchedulerDriver*, const SlaveID&));
+  MOCK_METHOD4(executorLost, void(SchedulerDriver*,
+                                  const ExecutorID&,
+                                  const SlaveID&,
+                                  int));
+  MOCK_METHOD2(error, void(SchedulerDriver*, const std::string&));
+};
+
+// For use with a MockScheduler, for example:
+// EXPECT_CALL(sched, resourceOffers(_, _))
+//   .WillOnce(LaunchTasks(TASKS, CPUS, MEM));
+// Launches up to TASKS no-op tasks, if possible,
+// each with CPUS cpus and MEM memory.
+ACTION_P3(LaunchTasks, tasks, cpus, mem)
+{
+  SchedulerDriver* driver = arg0;
+  std::vector<Offer> offers = arg1;
+  int numTasks = tasks;
+
+  int launched = 0;
+  for (size_t i = 0; i < offers.size(); i++) {
+    const Offer& offer = offers[i];
+    double offeredCpus = 0;
+    double offeredMem = 0;
+
+    for (int j = 0; j < offer.resources_size(); j++) {
+      const Resource& resource = offer.resources(j);
+      if (resource.name() == "cpus" &&
+          resource.type() == Value::SCALAR) {
+        offeredCpus = resource.scalar().value();
+      } else if (resource.name() == "mem" &&
+                 resource.type() == Value::SCALAR) {
+        offeredMem = resource.scalar().value();
+      }
+    }
+
+    int nextTaskId = 0;
+    std::vector<TaskInfo> tasks;
+
+    while (offeredCpus >= cpus && offeredMem >= mem && launched < numTasks) {
+      TaskInfo task;
+      task.set_name("TestTask");
+      task.mutable_task_id()->set_value(stringify(nextTaskId++));
+      task.mutable_slave_id()->MergeFrom(offer.slave_id());
+
+      ExecutorInfo executor;
+      executor.mutable_executor_id()->set_value("default");
+      executor.mutable_command()->set_value(":");
+      task.mutable_executor()->MergeFrom(executor);
+
+      Resource* resource;
+      resource = task.add_resources();
+      resource->set_name("cpus");
+      resource->set_type(Value::SCALAR);
+      resource->mutable_scalar()->set_value(cpus);
+
+      resource = task.add_resources();
+      resource->set_name("mem");
+      resource->set_type(Value::SCALAR);
+      resource->mutable_scalar()->set_value(mem);
+
+      tasks.push_back(task);
+      launched++;
+      offeredCpus -= cpus;
+      offeredMem -= mem;
+    }
+
+    driver->launchTasks(offer.id(), tasks);
+  }
+}
+
+
+// Like LaunchTasks, but decline the entire offer and
+// don't launch any tasks.
+ACTION(DeclineOffers)
+{
+  SchedulerDriver* driver = arg0;
+  std::vector<Offer> offers = arg1;
+
+  for (size_t i = 0; i < offers.size(); i++) {
+    driver->declineOffer(offers[i].id());
+  }
+}
+
+
+// Definition of a mock Executor to be used in tests with gmock.
+class MockExecutor : public Executor
+{
+public:
+  MockExecutor(const ExecutorID& _id) : id(_id) {}
+
+  MOCK_METHOD4(registered, void(ExecutorDriver*,
+                                const ExecutorInfo&,
+                                const FrameworkInfo&,
+                                const SlaveInfo&));
+  MOCK_METHOD2(reregistered, void(ExecutorDriver*, const SlaveInfo&));
+  MOCK_METHOD1(disconnected, void(ExecutorDriver*));
+  MOCK_METHOD2(launchTask, void(ExecutorDriver*, const TaskInfo&));
+  MOCK_METHOD2(killTask, void(ExecutorDriver*, const TaskID&));
+  MOCK_METHOD2(frameworkMessage, void(ExecutorDriver*, const std::string&));
+  MOCK_METHOD1(shutdown, void(ExecutorDriver*));
+  MOCK_METHOD2(error, void(ExecutorDriver*, const std::string&));
+
+  const ExecutorID id;
+};
+
+
+template <typename T = master::AllocatorProcess>
+class MockAllocatorProcess : public master::AllocatorProcess
+{
+public:
+  MockAllocatorProcess()
+  {
+    // Spawn the underlying allocator process.
+    process::spawn(real);
+
+    using ::testing::_;
+
+    ON_CALL(*this, initialize(_, _))
+      .WillByDefault(InvokeInitialize(this));
+
+    ON_CALL(*this, frameworkAdded(_, _, _))
+      .WillByDefault(InvokeFrameworkAdded(this));
+
+    ON_CALL(*this, frameworkRemoved(_))
+      .WillByDefault(InvokeFrameworkRemoved(this));
+
+    ON_CALL(*this, frameworkActivated(_, _))
+      .WillByDefault(InvokeFrameworkActivated(this));
+
+    ON_CALL(*this, frameworkDeactivated(_))
+      .WillByDefault(InvokeFrameworkDeactivated(this));
+
+    ON_CALL(*this, slaveAdded(_, _, _))
+      .WillByDefault(InvokeSlaveAdded(this));
+
+    ON_CALL(*this, slaveRemoved(_))
+      .WillByDefault(InvokeSlaveRemoved(this));
+
+    ON_CALL(*this, updateWhitelist(_))
+      .WillByDefault(InvokeUpdateWhitelist(this));
+
+    ON_CALL(*this, resourcesRequested(_, _))
+      .WillByDefault(InvokeResourcesRequested(this));
+
+    ON_CALL(*this, resourcesUnused(_, _, _, _))
+      .WillByDefault(InvokeResourcesUnused(this));
+
+    ON_CALL(*this, resourcesRecovered(_, _, _))
+      .WillByDefault(InvokeResourcesRecovered(this));
+
+    ON_CALL(*this, offersRevived(_))
+      .WillByDefault(InvokeOffersRevived(this));
+  }
+
+  ~MockAllocatorProcess()
+  {
+    process::terminate(real);
+    process::wait(real);
+  }
+
+  MOCK_METHOD2(initialize, void(const master::Flags&,
+                                const process::PID<master::Master>&));
+  MOCK_METHOD3(frameworkAdded, void(const FrameworkID&,
+                                    const FrameworkInfo&,
+                                    const Resources&));
+  MOCK_METHOD1(frameworkRemoved, void(const FrameworkID&));
+  MOCK_METHOD2(frameworkActivated, void(const FrameworkID&,
+                                        const FrameworkInfo&));
+  MOCK_METHOD1(frameworkDeactivated, void(const FrameworkID&));
+  MOCK_METHOD3(slaveAdded, void(const SlaveID&,
+                                const SlaveInfo&,
+                                const hashmap<FrameworkID, Resources>&));
+  MOCK_METHOD1(slaveRemoved, void(const SlaveID&));
+  MOCK_METHOD1(updateWhitelist, void(const Option<hashset<std::string> >&));
+  MOCK_METHOD2(resourcesRequested, void(const FrameworkID&,
+                                        const std::vector<Request>&));
+  MOCK_METHOD4(resourcesUnused, void(const FrameworkID&,
+                                     const SlaveID&,
+                                     const Resources&,
+                                     const Option<Filters>& filters));
+  MOCK_METHOD3(resourcesRecovered, void(const FrameworkID&,
+                                        const SlaveID&,
+                                        const Resources&));
+  MOCK_METHOD1(offersRevived, void(const FrameworkID&));
+
+  T real;
+};
+
+
+typedef ::testing::Types<master::HierarchicalDRFAllocatorProcess>
+AllocatorTypes;
+
+
+// The following actions make up for the fact that DoDefault
+// cannot be used inside a DoAll, for example:
+// EXPECT_CALL(allocator, frameworkAdded(_, _, _))
+//   .WillOnce(DoAll(InvokeFrameworkAdded(&allocator),
+//                   FutureSatisfy(&frameworkAdded)));
+
+ACTION_P(InvokeInitialize, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::initialize,
+      arg0,
+      arg1);
+}
+
+
+ACTION_P(InvokeFrameworkAdded, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::frameworkAdded,
+      arg0,
+      arg1,
+      arg2);
+}
+
+
+ACTION_P(InvokeFrameworkRemoved, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::frameworkRemoved, arg0);
+}
+
+
+ACTION_P(InvokeFrameworkActivated, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::frameworkActivated,
+      arg0,
+      arg1);
+}
+
+
+ACTION_P(InvokeFrameworkDeactivated, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::frameworkDeactivated,
+      arg0);
+}
+
+
+ACTION_P(InvokeSlaveAdded, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::slaveAdded,
+      arg0,
+      arg1,
+      arg2);
+}
+
+
+ACTION_P(InvokeSlaveRemoved, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::slaveRemoved,
+      arg0);
+}
+
+
+ACTION_P(InvokeUpdateWhitelist, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::updateWhitelist,
+      arg0);
+}
+
+
+ACTION_P(InvokeResourcesRequested, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::resourcesRequested,
+      arg0,
+      arg1);
+}
+
+
+
+ACTION_P(InvokeResourcesUnused, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::resourcesUnused,
+      arg0,
+      arg1,
+      arg2,
+      arg3);
+}
+
+
+ACTION_P2(InvokeUnusedWithFilters, allocator, timeout)
+{
+  Filters filters;
+  filters.set_refuse_seconds(timeout);
+
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::resourcesUnused,
+      arg0,
+      arg1,
+      arg2,
+      filters);
+}
+
+
+ACTION_P(InvokeResourcesRecovered, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::resourcesRecovered,
+      arg0,
+      arg1,
+      arg2);
+}
+
+
+ACTION_P(InvokeOffersRevived, allocator)
+{
+  process::dispatch(
+      allocator->real,
+      &master::AllocatorProcess::offersRevived,
+      arg0);
+}
+
+
+class OfferEqMatcher
+  : public ::testing::MatcherInterface<const std::vector<Offer>& >
+{
+public:
+  OfferEqMatcher(int _cpus, int _mem)
+    : cpus(_cpus), mem(_mem) {}
+
+  virtual bool MatchAndExplain(const std::vector<Offer>& offers,
+			       ::testing::MatchResultListener* listener) const
+  {
+    double totalCpus = 0;
+    double totalMem = 0;
+
+    foreach (const Offer& offer, offers) {
+      foreach (const Resource& resource, offer.resources()) {
+	if (resource.name() == "cpus") {
+	  totalCpus += resource.scalar().value();
+	} else if (resource.name() == "mem") {
+	  totalMem += resource.scalar().value();
+	}
+      }
+    }
+
+    bool matches = totalCpus == cpus && totalMem == mem;
+
+    if (!matches) {
+      *listener << totalCpus << " cpus and " << totalMem << "mem";
+    }
+
+    return matches;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const
+  {
+    *os << "contains " << cpus << " cpus and " << mem << " mem";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const
+  {
+    *os << "does not contain " << cpus << " cpus and "  << mem << " mem";
+  }
+
+private:
+  int cpus;
+  int mem;
+};
+
+
+inline const ::testing::Matcher<const std::vector<Offer>& > OfferEq(int cpus, int mem)
+{
+  return MakeMatcher(new OfferEqMatcher(cpus, mem));
+}
+
+
+// Definition of the SendStatusUpdateFromTask action to be used with gmock.
+ACTION_P(SendStatusUpdateFromTask, state)
+{
+  TaskStatus status;
+  status.mutable_task_id()->MergeFrom(arg1.task_id());
+  status.set_state(state);
+  arg0->sendStatusUpdate(status);
+}
+
+
+// Definition of the SendStatusUpdateFromTaskID action to be used with gmock.
+ACTION_P(SendStatusUpdateFromTaskID, state)
+{
+  TaskStatus status;
+  status.mutable_task_id()->MergeFrom(arg1);
+  status.set_state(state);
+  arg0->sendStatusUpdate(status);
+}
+
+
+#define FUTURE_PROTOBUF(message, from, to)              \
+  FutureProtobuf(message, from, to)
+
+
+#define DROP_PROTOBUF(message, from, to)              \
+  FutureProtobuf(message, from, to, true)
+
+
+#define DROP_PROTOBUFS(message, from, to)              \
+  DropProtobufs(message, from, to)
+
+
+// Forward declaration.
+template <typename T>
+T _FutureProtobuf(const process::Message& message);
+
+
+template <typename T, typename From, typename To>
+process::Future<T> FutureProtobuf(T t, From from, To to, bool drop = false)
+{
+  // Help debugging by adding some "type constraints".
+  { google::protobuf::Message* m = &t; (void) m; }
+
+  return process::FutureMessage(testing::Eq(t.GetTypeName()), from, to, drop)
+    .then(lambda::bind(&_FutureProtobuf<T>, lambda::_1));
+}
+
+
+template <typename T>
+T _FutureProtobuf(const process::Message& message)
+{
+  T t;
+  t.ParseFromString(message.body);
+  return t;
+}
+
+
+template <typename T, typename From, typename To>
+void DropProtobufs(T t, From from, To to)
+{
+  // Help debugging by adding some "type constraints".
+  { google::protobuf::Message* m = &t; (void) m; }
+
+  process::DropMessages(testing::Eq(t.GetTypeName()), from, to);
+}
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __TESTS_MESOS_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/monitor_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/monitor_tests.cpp b/src/tests/monitor_tests.cpp
index 6a7be76..5681af2 100644
--- a/src/tests/monitor_tests.cpp
+++ b/src/tests/monitor_tests.cpp
@@ -20,22 +20,19 @@
 
 #include <gmock/gmock.h>
 
-#include <mesos/executor.hpp>
 #include <mesos/mesos.hpp>
 
 #include <process/clock.hpp>
 #include <process/future.hpp>
-#include <process/gmock.hpp>
+#include <process/gtest.hpp>
 #include <process/http.hpp>
 #include <process/pid.hpp>
 #include <process/process.hpp>
 
-#include <stout/duration.hpp>
-
 #include "slave/constants.hpp"
 #include "slave/monitor.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/isolator.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/paths_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/paths_tests.cpp b/src/tests/paths_tests.cpp
index 84ad9b3..655e9ce 100644
--- a/src/tests/paths_tests.cpp
+++ b/src/tests/paths_tests.cpp
@@ -29,8 +29,6 @@
 #include "slave/paths.hpp"
 #include "slave/state.hpp"
 
-#include "tests/utils.hpp"
-
 namespace mesos {
 namespace internal {
 namespace slave {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/protobuf_io_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/protobuf_io_tests.cpp b/src/tests/protobuf_io_tests.cpp
index b6478b3..5f80c04 100644
--- a/src/tests/protobuf_io_tests.cpp
+++ b/src/tests/protobuf_io_tests.cpp
@@ -20,6 +20,7 @@
 
 #include <gmock/gmock.h>
 
+#include <stout/gtest.hpp>
 #include <stout/none.hpp>
 #include <stout/os.hpp>
 #include <stout/protobuf.hpp>
@@ -29,8 +30,6 @@
 
 #include "messages/messages.hpp"
 
-#include "tests/utils.hpp"
-
 using namespace mesos;
 using namespace mesos::internal;
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/reaper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/reaper_tests.cpp b/src/tests/reaper_tests.cpp
index c1fc1c3..fbb6066 100644
--- a/src/tests/reaper_tests.cpp
+++ b/src/tests/reaper_tests.cpp
@@ -21,26 +21,31 @@
 
 #include <gtest/gtest.h>
 
+#include <process/clock.hpp>
 #include <process/dispatch.hpp>
 #include <process/gmock.hpp>
-
-#include <stout/exit.hpp>
+#include <process/gtest.hpp>
 
 #include "slave/reaper.hpp"
 
-#include "tests/utils.hpp"
-
 using namespace mesos;
 using namespace mesos::internal;
 using namespace mesos::internal::slave;
-using namespace mesos::internal::tests;
 
+using process::Clock;
 using process::Future;
 
 using testing::_;
 using testing::DoDefault;
 
 
+class MockProcessListener : public ProcessExitedListener
+{
+public:
+  MOCK_METHOD2(processExited, void(pid_t, int));
+};
+
+
 // This test checks that the Reaper can monitor a non-child process.
 TEST(ReaperTest, NonChildProcess)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/resource_offers_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/resource_offers_tests.cpp b/src/tests/resource_offers_tests.cpp
index 0be5497..28ec4bc 100644
--- a/src/tests/resource_offers_tests.cpp
+++ b/src/tests/resource_offers_tests.cpp
@@ -30,7 +30,7 @@
 
 #include "slave/slave.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/mesos.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;
@@ -409,16 +409,18 @@ TEST(ResourceOffersTest, ResourcesGetReofferedAfterTaskInfoError)
 // unique task IDs and aggregate resource usage.
 
 
-TEST(ResourceOffersTest, Request)
-{
-  Cluster cluster;
+// TODO(benh): Eliminate this class once we replace tests above to use
+// MesosTest/Cluster instead of local::launch.
+class ResourceOffersMesosTest : public MesosTest {};
 
+TEST_F(ResourceOffersMesosTest, Request)
+{
   MockAllocatorProcess<HierarchicalDRFAllocatorProcess> allocator;
 
   EXPECT_CALL(allocator, initialize(_, _))
     .Times(1);
 
-  Try<PID<Master> > master = cluster.masters.start(&allocator);
+  Try<PID<Master> > master = StartMaster(&allocator);
   ASSERT_SOME(master);
 
   MockScheduler sched;
@@ -460,21 +462,21 @@ TEST(ResourceOffersTest, Request)
   driver.stop();
   driver.join();
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
-class MultipleExecutorsTest : public MesosClusterTest {};
+class MultipleExecutorsTest : public MesosTest {};
 
 
 TEST_F(MultipleExecutorsTest, TasksExecutorInfoDiffers)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  Try<PID<Slave> > slave = cluster.slaves.start(DEFAULT_EXECUTOR_ID, &exec);
+  Try<PID<Slave> > slave = StartSlave(&exec);
   ASSERT_SOME(master);
 
   MockScheduler sched;
@@ -551,5 +553,5 @@ TEST_F(MultipleExecutorsTest, TasksExecutorInfoDiffers)
 
   AWAIT_READY(shutdown); // To ensure can deallocate MockExecutor.
 
-  cluster.shutdown();
+  Shutdown();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/script.cpp
----------------------------------------------------------------------
diff --git a/src/tests/script.cpp b/src/tests/script.cpp
index e2b4efa..74ce91a 100644
--- a/src/tests/script.cpp
+++ b/src/tests/script.cpp
@@ -28,9 +28,11 @@
 #include <stout/path.hpp>
 #include <stout/strings.hpp>
 
+#include "logging/logging.hpp"
+
 #include "tests/environment.hpp"
+#include "tests/flags.hpp"
 #include "tests/script.hpp"
-#include "tests/utils.hpp"
 
 using std::string;
 

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/slave_recovery_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/slave_recovery_tests.cpp b/src/tests/slave_recovery_tests.cpp
index fd6b9ac..65f50ed 100644
--- a/src/tests/slave_recovery_tests.cpp
+++ b/src/tests/slave_recovery_tests.cpp
@@ -44,8 +44,6 @@
 #include "linux/cgroups.hpp"
 #endif
 
-#include "master/allocator.hpp"
-#include "master/hierarchical_allocator_process.hpp"
 #include "master/master.hpp"
 
 #ifdef __linux__
@@ -59,6 +57,7 @@
 
 #include "messages/messages.hpp"
 
+#include "tests/mesos.hpp"
 #include "tests/utils.hpp"
 
 using namespace mesos;
@@ -69,8 +68,6 @@ using namespace mesos::internal::utils::process;
 
 using namespace process;
 
-using mesos::internal::master::Allocator;
-using mesos::internal::master::HierarchicalDRFAllocatorProcess;
 using mesos::internal::master::Master;
 
 #ifdef __linux__
@@ -83,7 +80,6 @@ using std::string;
 using std::vector;
 
 using testing::_;
-using testing::DoAll;
 using testing::Eq;
 using testing::Return;
 using testing::SaveArg;
@@ -123,80 +119,17 @@ template <typename T>
 class SlaveRecoveryTest : public IsolatorTest<T>
 {
 public:
-  static void SetUpTestCase()
+  virtual slave::Flags CreateSlaveFlags()
   {
-    IsolatorTest<T>::SetUpTestCase();
-  }
-
-  virtual void SetUp()
-  {
-    IsolatorTest<T>::SetUp();
+    slave::Flags flags = IsolatorTest<T>::CreateSlaveFlags();
 
-    a = new Allocator(&allocator);
-    m = new Master(a, &files);
-    master = process::spawn(m);
+    // Setup recovery slave flags.
+    flags.checkpoint = true;
+    flags.recover = "reconnect";
+    flags.safe = false;
 
-    // Reset recovery slaveFlags.
-    this->slaveFlags.checkpoint = true;
-    this->slaveFlags.recover = "reconnect";
-    this->slaveFlags.safe = false;
-
-    startSlave();
+    return flags;
   }
-
-  virtual void TearDown()
-  {
-    stopSlave(true);
-
-    process::terminate(master);
-    process::wait(master);
-    delete m;
-    delete a;
-
-    IsolatorTest<T>::TearDown();
-  }
-
-protected:
-  void startSlave()
-  {
-    isolator = new T();
-    s = new Slave(this->slaveFlags, true, isolator, &files);
-    slave = process::spawn(s);
-    detector = new BasicMasterDetector(master, slave, true);
-
-    running = true;
-  }
-
-  void stopSlave(bool shutdown = false)
-  {
-    if (!running) {
-      return;
-    }
-
-    delete detector;
-
-    if (shutdown) {
-      process::dispatch(slave, &Slave::shutdown);
-    } else {
-      process::terminate(slave);
-    }
-    process::wait(slave);
-    delete s;
-    delete isolator;
-
-    running = false;
-  }
-
-  HierarchicalDRFAllocatorProcess allocator;
-  Allocator *a;
-  Master* m;
-  Isolator* isolator;
-  Slave* s;
-  Files files;
-  BasicMasterDetector* detector;
-  PID<Master> master;
-  PID<Slave> slave;
-  bool running; // Is the slave running?
 };
 
 
@@ -206,13 +139,22 @@ typedef ::testing::Types<ProcessIsolator, CgroupsIsolator> IsolatorTypes;
 typedef ::testing::Types<ProcessIsolator> IsolatorTypes;
 #endif
 
-
 TYPED_TEST_CASE(SlaveRecoveryTest, IsolatorTypes);
 
 
 // Enable checkpointing on the slave and ensure recovery works.
 TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
+  ASSERT_SOME(slave);
+
   // Message expectations.
   Future<Message> registerFramework =
     FUTURE_MESSAGE(Eq(RegisterFrameworkMessage().GetTypeName()), _, _);
@@ -233,7 +175,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -259,7 +201,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
     FUTURE_MESSAGE(Eq(RegisterExecutorMessage().GetTypeName()), _, _);
 
   Future<StatusUpdateMessage> update =
-    FUTURE_PROTOBUF(StatusUpdateMessage(), Eq(this->master), _);
+    FUTURE_PROTOBUF(StatusUpdateMessage(), Eq(master.get()), _);
 
   Future<StatusUpdateAcknowledgementMessage> ack =
     FUTURE_PROTOBUF(StatusUpdateAcknowledgementMessage(), _, _);
@@ -284,8 +226,8 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
   AWAIT_READY(_ack);
 
   // Recover the state.
-  Result<state::SlaveState> recover =
-    state::recover(paths::getMetaRootDir(this->slaveFlags.work_dir), true);
+  Result<state::SlaveState> recover = state::recover(
+      paths::getMetaRootDir(flags.work_dir), true);
 
   ASSERT_SOME(recover);
 
@@ -369,6 +311,8 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -376,6 +320,16 @@ TYPED_TEST(SlaveRecoveryTest, RecoverSlaveState)
 // When the slave comes back up it resends the unacknowledged update.
 TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
 
@@ -391,7 +345,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -419,15 +373,18 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
   // Wait for the status update drop.
   AWAIT_READY(update);
 
-  this->stopSlave();
+  this->Stop(slave.get());
 
   Future<TaskStatus> status;
   EXPECT_CALL(sched, statusUpdate(_, _))
     .WillOnce(FutureArg<1>(&status))
     .WillRepeatedly(Return());       // Ignore subsequent updates.
 
-  // Restart the slave.
-  this->startSlave();
+  // Restart the slave (use same flags) with a new isolator.
+  TypeParam isolator2;
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   AWAIT_READY(status);
   ASSERT_EQ(TASK_RUNNING, status.get().state());
@@ -437,6 +394,8 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -445,6 +404,16 @@ TYPED_TEST(SlaveRecoveryTest, RecoverStatusUpdateManager)
 // sure the executor re-registers and the slave properly sends the update.
 TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -459,7 +428,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -479,7 +448,7 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
   // Stop the slave before the status update is received.
   AWAIT_READY(statusUpdate);
 
-  this->stopSlave();
+  this->Stop(slave.get());
 
   Future<Message> reregisterExecutorMessage =
     FUTURE_MESSAGE(Eq(ReregisterExecutorMessage().GetTypeName()), _, _);
@@ -489,8 +458,11 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
     .WillOnce(FutureArg<1>(&status))
     .WillRepeatedly(Return());       // Ignore subsequent updates.
 
-  // Restart the slave.
-  this->startSlave();
+  // Restart the slave (use same flags) with a new isolator.
+  TypeParam isolator2;
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   // Ensure the executor re-registers.
   AWAIT_READY(reregisterExecutorMessage);
@@ -514,6 +486,8 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -522,6 +496,16 @@ TYPED_TEST(SlaveRecoveryTest, ReconnectExecutor)
 // executor is killed and the task is transitioned to FAILED.
 TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -536,7 +520,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -557,7 +541,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
   AWAIT_READY(registerExecutor);
   UPID executorPid = registerExecutor.get().from;
 
-  this->stopSlave();
+  this->Stop(slave.get());
 
   Future<TaskStatus> status;
   EXPECT_CALL(sched, statusUpdate(_, _))
@@ -566,8 +550,11 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
 
   Future<Nothing> recover = FUTURE_DISPATCH(_, &Slave::_recover);
 
-  // Restart the slave.
-  this->startSlave();
+  // Restart the slave (use same flags) with a new isolator.
+  TypeParam isolator2;
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   Clock::pause();
 
@@ -591,6 +578,8 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -600,6 +589,16 @@ TYPED_TEST(SlaveRecoveryTest, RecoverUnregisteredExecutor)
 // sure the task is properly transitioned to FAILED.
 TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -614,7 +613,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -642,7 +641,7 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
   // Wait for the ACK to be checkpointed.
   AWAIT_READY(ack);
 
-  this->stopSlave();
+  this->Stop(slave.get());
 
   Future<TaskStatus> status;
   EXPECT_CALL(sched, statusUpdate(_, _))
@@ -653,8 +652,11 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
 
   Future<Nothing> recover = FUTURE_DISPATCH(_, &Slave::_recover);
 
-  // Restart the slave.
-  this->startSlave();
+  // Restart the slave (use same flags) with a new isolator.
+  TypeParam isolator2;
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   Clock::pause();
 
@@ -676,6 +678,8 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -684,6 +688,16 @@ TYPED_TEST(SlaveRecoveryTest, RecoverTerminatedExecutor)
 // executor, and transitions the task to FAILED.
 TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -698,7 +712,7 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -719,15 +733,19 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
   // Wait for the ACK to be checkpointed.
   AWAIT_READY(ack);
 
-  this->stopSlave();
+  this->Stop(slave.get());
 
   Future<TaskStatus> status;
   EXPECT_CALL(sched, statusUpdate(_, _))
     .WillOnce(FutureArg<1>(&status));
 
-  // Restart the slave in 'cleanup' recovery mode.
-  this->slaveFlags.recover = "cleanup";
-  this->startSlave();
+  // Restart the slave in 'cleanup' recovery mode with a new isolator.
+  TypeParam isolator2;
+
+  flags.recover = "cleanup";
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   Clock::pause();
 
@@ -745,6 +763,8 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -752,6 +772,14 @@ TYPED_TEST(SlaveRecoveryTest, CleanupExecutor)
 // properly removed, when a checkpointing slave is disconnected.
 TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator;
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -766,7 +794,7 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(false);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -790,7 +818,7 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
   EXPECT_CALL(sched, statusUpdate(_, _))
     .WillOnce(FutureArg<1>(&status));
 
-  this->stopSlave();
+  this->Stop(slave.get());
 
   // Scheduler should receive the TASK_LOST update.
   AWAIT_READY(status);
@@ -798,6 +826,8 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -805,6 +835,16 @@ TYPED_TEST(SlaveRecoveryTest, RemoveNonCheckpointingFramework)
 // framework that has disabled checkpointing.
 TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   FrameworkID frameworkId;
@@ -821,7 +861,7 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(false);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -844,11 +884,12 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
 
   Clock::pause();
 
-  Future<Nothing> updateFramework = FUTURE_DISPATCH(_, &Slave::updateFramework);
+  Future<Nothing> updateFramework =
+    FUTURE_DISPATCH(_, &Slave::updateFramework);
 
   // Simulate a 'UpdateFrameworkMessage' to ensure framework pid is
   // not being checkpointed.
-  process::dispatch(this->slave, &Slave::updateFramework, frameworkId, "");
+  process::dispatch(slave.get(), &Slave::updateFramework, frameworkId, "");
 
   AWAIT_READY(updateFramework);
 
@@ -856,7 +897,7 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
 
   // Ensure that the framework info is not being checkpointed.
   const string& path = paths::getFrameworkPath(
-      paths::getMetaRootDir(this->slaveFlags.work_dir),
+      paths::getMetaRootDir(flags.work_dir),
       task.slave_id(),
       frameworkId);
 
@@ -866,6 +907,8 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -875,6 +918,16 @@ TYPED_TEST(SlaveRecoveryTest, NonCheckpointingFramework)
 // (scheduler, master, executor).
 TYPED_TEST(SlaveRecoveryTest, KillTask)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -888,7 +941,7 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -909,15 +962,18 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
   // Wait for the ACK to be checkpointed.
   AWAIT_READY(ack);
 
-  // Restart the slave.
-  this->stopSlave();
+  this->Stop(slave.get());
 
   Future<Nothing> recover = FUTURE_DISPATCH(_, &Slave::_recover);
 
   Future<ReregisterSlaveMessage> reregisterSlave =
     FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
-  this->startSlave();
+  // Restart the slave (use same flags) with a new isolator.
+  TypeParam isolator2;
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   Clock::pause();
 
@@ -963,6 +1019,8 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -971,6 +1029,16 @@ TYPED_TEST(SlaveRecoveryTest, KillTask)
 // cannot recover the executor and hence schedules it for gc.
 TYPED_TEST(SlaveRecoveryTest, GCExecutor)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -985,7 +1053,7 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -1020,7 +1088,7 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
   // Wait for TASK_RUNNING update.
   AWAIT_READY(status);
 
-  this->stopSlave();
+  this->Stop(slave.get());
 
   // Now shut down the executor, when the slave is down.
   process::post(executorPid, ShutdownExecutorMessage());
@@ -1028,7 +1096,7 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
   // Remove the symlink "latest" in the executor directory
   // to simulate a non-recoverable executor.
   ASSERT_SOME(os::rm(paths::getExecutorLatestRunPath(
-      paths::getMetaRootDir(this->slaveFlags.work_dir),
+      paths::getMetaRootDir(flags.work_dir),
       slaveId,
       frameworkId,
       executorId)));
@@ -1038,8 +1106,11 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
   Future<ReregisterSlaveMessage> reregisterSlave =
     FUTURE_PROTOBUF(ReregisterSlaveMessage(), _, _);
 
-  // Restart the slave.
-  this->startSlave();
+  // Restart the slave (use same flags) with a new isolator.
+  TypeParam isolator2;
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   Clock::pause();
 
@@ -1053,16 +1124,16 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
 
   AWAIT_READY(reregisterSlave);
 
-  Clock::advance(this->slaveFlags.gc_delay);
+  Clock::advance(flags.gc_delay);
 
   Clock::settle();
 
   // Executor's work and meta directories should be gc'ed by now.
   ASSERT_FALSE(os::exists(paths::getExecutorPath(
-      this->slaveFlags.work_dir, slaveId, frameworkId, executorId)));
+      flags.work_dir, slaveId, frameworkId, executorId)));
 
   ASSERT_FALSE(os::exists(paths::getExecutorPath(
-      paths::getMetaRootDir(this->slaveFlags.work_dir),
+      paths::getMetaRootDir(flags.work_dir),
       slaveId,
       frameworkId,
       executorId)));
@@ -1071,6 +1142,8 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }
 
 
@@ -1078,6 +1151,16 @@ TYPED_TEST(SlaveRecoveryTest, GCExecutor)
 // register as a new slave.
 TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
 {
+  Try<PID<Master> > master = this->StartMaster();
+  ASSERT_SOME(master);
+
+  TypeParam isolator1;
+
+  slave::Flags flags = this->CreateSlaveFlags();
+
+  Try<PID<Slave> > slave = this->StartSlave(&isolator1, flags);
+  ASSERT_SOME(slave);
+
   // Scheduler expectations.
   MockScheduler sched;
   EXPECT_CALL(sched, registered(_, _, _));
@@ -1092,7 +1175,7 @@ TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
   frameworkInfo.CopyFrom(DEFAULT_FRAMEWORK_INFO);
   frameworkInfo.set_checkpoint(true);
 
-  MesosSchedulerDriver driver(&sched, frameworkInfo, this->master);
+  MesosSchedulerDriver driver(&sched, frameworkInfo, master.get());
 
   driver.start();
 
@@ -1139,16 +1222,18 @@ TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
 
   Clock::resume();
 
-  // Shut down the slave.
-  this->stopSlave(true);
+  this->Stop(slave.get(), true); // Send a "shut down".
 
   Future<vector<Offer> > offers2;
   EXPECT_CALL(sched, resourceOffers(_, _))
     .WillOnce(FutureArg<1>(&offers2))
     .WillRepeatedly(Return());        // Ignore subsequent offers.
 
-  // Now restart the slave.
-  this->startSlave();
+  // Now restart the slave (use same flags) with a new isolator.
+  TypeParam isolator2;
+
+  slave = this->StartSlave(&isolator2, flags);
+  ASSERT_SOME(slave);
 
   // Ensure that the slave registered with a new id.
   AWAIT_READY(offers2);
@@ -1161,4 +1246,6 @@ TYPED_TEST(SlaveRecoveryTest, ShutdownSlave)
 
   driver.stop();
   driver.join();
+
+  this->Shutdown(); // Shutdown before isolator(s) get deallocated.
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/state_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/state_tests.cpp b/src/tests/state_tests.cpp
index 9066025..2e75673 100644
--- a/src/tests/state_tests.cpp
+++ b/src/tests/state_tests.cpp
@@ -25,8 +25,10 @@
 #include <mesos/mesos.hpp>
 
 #include <process/future.hpp>
+#include <process/gtest.hpp>
 #include <process/protobuf.hpp>
 
+#include <stout/gtest.hpp>
 #include <stout/option.hpp>
 #include <stout/os.hpp>
 
@@ -39,7 +41,6 @@
 #include "state/state.hpp"
 #include "state/zookeeper.hpp"
 
-#include "tests/utils.hpp"
 #ifdef MESOS_HAS_JAVA
 #include "tests/zookeeper.hpp"
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/status_update_manager_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/status_update_manager_tests.cpp b/src/tests/status_update_manager_tests.cpp
index 042201a..892a3f1 100644
--- a/src/tests/status_update_manager_tests.cpp
+++ b/src/tests/status_update_manager_tests.cpp
@@ -44,7 +44,7 @@
 
 #include "messages/messages.hpp"
 
-#include "tests/utils.hpp"
+#include "tests/mesos.hpp"
 
 using namespace mesos;
 using namespace mesos::internal;
@@ -85,20 +85,20 @@ vector<TaskInfo> createTasks(const Offer& offer)
 }
 
 
-class StatusUpdateManagerTest: public MesosClusterTest {};
+class StatusUpdateManagerTest: public MesosTest {};
 
 
 TEST_F(StatusUpdateManagerTest, CheckpointStatusUpdate)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  slave::Flags flags = cluster.slaves.flags;
+  slave::Flags flags = CreateSlaveFlags();
   flags.checkpoint = true;
-  Try<PID<Slave> > slave = cluster.slaves.start(
-      flags, DEFAULT_EXECUTOR_ID, &exec);
+
+  Try<PID<Slave> > slave = StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo; // Bug in gcc 4.1.*, must assign on next line.
@@ -185,21 +185,21 @@ TEST_F(StatusUpdateManagerTest, CheckpointStatusUpdate)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
 TEST_F(StatusUpdateManagerTest, RetryStatusUpdate)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  slave::Flags flags = cluster.slaves.flags;
+  slave::Flags flags = CreateSlaveFlags();
   flags.checkpoint = true;
-  Try<PID<Slave> > slave = cluster.slaves.start(
-      flags, DEFAULT_EXECUTOR_ID, &exec);
+
+  Try<PID<Slave> > slave = StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo; // Bug in gcc 4.1.*, must assign on next line.
@@ -258,7 +258,7 @@ TEST_F(StatusUpdateManagerTest, RetryStatusUpdate)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
@@ -268,15 +268,15 @@ TEST_F(StatusUpdateManagerTest, RetryStatusUpdate)
 // duplicate ACK is for a retried update.
 TEST_F(StatusUpdateManagerTest, IgnoreDuplicateStatusUpdateAck)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  slave::Flags flags = cluster.slaves.flags;
+  slave::Flags flags = CreateSlaveFlags();
   flags.checkpoint = true;
-  Try<PID<Slave> > slave = cluster.slaves.start(
-      flags, DEFAULT_EXECUTOR_ID, &exec);
+
+  Try<PID<Slave> > slave = StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo; // Bug in gcc 4.1.*, must assign on next line.
@@ -378,7 +378,7 @@ TEST_F(StatusUpdateManagerTest, IgnoreDuplicateStatusUpdateAck)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  cluster.shutdown();
+  Shutdown();
 }
 
 
@@ -388,15 +388,15 @@ TEST_F(StatusUpdateManagerTest, IgnoreDuplicateStatusUpdateAck)
 // for the original update and sending a random ACK to the slave.
 TEST_F(StatusUpdateManagerTest, IgnoreUnexpectedStatusUpdateAck)
 {
-  Try<PID<Master> > master = cluster.masters.start();
+  Try<PID<Master> > master = StartMaster();
   ASSERT_SOME(master);
 
-  MockExecutor exec;
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
 
-  slave::Flags flags = cluster.slaves.flags;
+  slave::Flags flags = CreateSlaveFlags();
   flags.checkpoint = true;
-  Try<PID<Slave> > slave = cluster.slaves.start(
-      flags, DEFAULT_EXECUTOR_ID, &exec);
+
+  Try<PID<Slave> > slave = StartSlave(&exec, flags);
   ASSERT_SOME(slave);
 
   FrameworkInfo frameworkInfo; // Bug in gcc 4.1.*, must assign on next line.
@@ -473,5 +473,5 @@ TEST_F(StatusUpdateManagerTest, IgnoreUnexpectedStatusUpdateAck)
 
   AWAIT_READY(shutdown); // Ensures MockExecutor can be deallocated.
 
-  cluster.shutdown();
+  Shutdown();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/6b1b8208/src/tests/utils.cpp
----------------------------------------------------------------------
diff --git a/src/tests/utils.cpp b/src/tests/utils.cpp
index 9a83053..05ef305 100644
--- a/src/tests/utils.cpp
+++ b/src/tests/utils.cpp
@@ -22,6 +22,7 @@
 
 #include <gtest/gtest.h>
 
+#include <stout/gtest.hpp>
 #include <stout/os.hpp>
 #include <stout/path.hpp>
 #include <stout/strings.hpp>


[04/28] git commit: Removed unused variables in AllocatorZooKeeperTest.

Posted by be...@apache.org.
Removed unused variables in AllocatorZooKeeperTest.

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


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

Branch: refs/heads/master
Commit: 1d71e42b543c247a2e2bd060d9d5c90f136a8fd6
Parents: 233edea
Author: Benjamin Hindman <be...@twitter.com>
Authored: Sun May 5 16:23:43 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/tests/allocator_zookeeper_tests.cpp |   19 -------------------
 1 files changed, 0 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/1d71e42b/src/tests/allocator_zookeeper_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/allocator_zookeeper_tests.cpp b/src/tests/allocator_zookeeper_tests.cpp
index bb7f84d..962e876 100644
--- a/src/tests/allocator_zookeeper_tests.cpp
+++ b/src/tests/allocator_zookeeper_tests.cpp
@@ -61,28 +61,9 @@ using testing::SaveArg;
 template <typename T = AllocatorProcess>
 class AllocatorZooKeeperTest : public ZooKeeperTest
 {
-public:
-  virtual void SetUp()
-  {
-    ZooKeeperTest::SetUp();
-
-    a1 = new Allocator(&allocator1);
-    a2 = new Allocator(&allocator2);
-  }
-
-  virtual void TearDown()
-  {
-    ZooKeeperTest::TearDown();
-
-    delete a1;
-    delete a2;
-  }
-
 protected:
   T allocator1;
   MockAllocatorProcess<T> allocator2;
-  Allocator* a1;
-  Allocator* a2;
 };
 
 


[09/28] git commit: Improved library for using JVM/JNI and updated uses (in tests).

Posted by be...@apache.org.
Improved library for using JVM/JNI and updated uses (in tests).

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


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

Branch: refs/heads/master
Commit: 233edea23871302be582ddba340cfc6c7c68ef30
Parents: 07c44ce
Author: Benjamin Hindman <be...@twitter.com>
Authored: Thu May 2 09:29:32 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700

----------------------------------------------------------------------
 src/Makefile.am                     |   18 +-
 src/jvm/java/io.hpp                 |   36 ++
 src/jvm/java/lang.hpp               |   31 ++
 src/jvm/java/net.hpp                |   26 +
 src/jvm/jvm.cpp                     |  767 ++++++++++++++++++------------
 src/jvm/jvm.hpp                     |  367 ++++++++++-----
 src/jvm/org/apache/log4j.cpp        |   16 +
 src/jvm/org/apache/log4j.hpp        |   69 +++
 src/jvm/org/apache/zookeeper.hpp    |  168 +++++++
 src/tests/zookeeper_test.cpp        |   72 +--
 src/tests/zookeeper_test.hpp        |   12 +-
 src/tests/zookeeper_test_server.cpp |  201 ++------
 src/tests/zookeeper_test_server.hpp |   55 +--
 13 files changed, 1131 insertions(+), 707 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ed3423..fe31707 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -552,14 +552,24 @@ CLEANFILES += $(MESOS_SOURCES_JAR)
 # main libmesos.so.
 noinst_LTLIBRARIES += libjava.la
 
-libjava_la_SOURCES = java/jni/convert.cpp java/jni/construct.cpp	\
+libjava_la_SOURCES =							\
+	java/jni/convert.cpp						\
+	java/jni/convert.hpp						\
+	java/jni/construct.cpp						\
+	java/jni/construct.hpp						\
 	java/jni/org_apache_mesos_Log.cpp				\
 	java/jni/org_apache_mesos_MesosSchedulerDriver.cpp		\
 	java/jni/org_apache_mesos_MesosExecutorDriver.cpp		\
 	java/jni/org_apache_mesos_state_Variable.cpp			\
-	java/jni/org_apache_mesos_state_ZooKeeperState.cpp jvm/jvm.cpp
-
-libjava_la_SOURCES += java/jni/convert.hpp java/jni/construct.hpp jvm/jvm.hpp
+	java/jni/org_apache_mesos_state_ZooKeeperState.cpp		\
+	jvm/jvm.cpp							\
+	jvm/jvm.hpp							\
+	jvm/java/io.hpp							\
+	jvm/java/lang.hpp						\
+	jvm/java/net.hpp						\
+	jvm/org/apache/log4j.cpp					\
+	jvm/org/apache/log4j.hpp					\
+	jvm/org/apache/zookeeper.hpp
 
 libjava_la_CPPFLAGS = $(MESOS_CPPFLAGS)
 libjava_la_CPPFLAGS += $(JAVA_CPPFLAGS)

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/java/io.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/java/io.hpp b/src/jvm/java/io.hpp
new file mode 100644
index 0000000..fa0c60c
--- /dev/null
+++ b/src/jvm/java/io.hpp
@@ -0,0 +1,36 @@
+#ifndef __JAVA_IO_HPP__
+#define __JAVA_IO_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace java {
+namespace io {
+
+class File : public Jvm::Object
+{
+public:
+  File(const std::string& pathname)
+  {
+    static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+        Jvm::Class::named("java/io/File")
+        .constructor()
+        .parameter(Jvm::get()->stringClass));
+
+    object = Jvm::get()->invoke(constructor, Jvm::get()->string(pathname));
+  }
+
+  void deleteOnExit()
+  {
+    static Jvm::Method method = Jvm::get()->findMethod(
+        Jvm::Class::named("java/io/File")
+        .method("deleteOnExit")
+        .returns(Jvm::get()->voidClass));
+
+    Jvm::get()->invoke<void>(object, method);
+  }
+};
+
+} // namespace io {
+} // namespace java {
+
+#endif // __JAVA_IO_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/java/lang.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/java/lang.hpp b/src/jvm/java/lang.hpp
new file mode 100644
index 0000000..5eb365d
--- /dev/null
+++ b/src/jvm/java/lang.hpp
@@ -0,0 +1,31 @@
+#ifndef __JAVA_LANG_HPP__
+#define __JAVA_LANG_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace java {
+namespace lang {
+
+class Throwable : public Jvm::Object
+{
+public:
+  Throwable(const std::string& message)
+  {
+    static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+        Jvm::Class::named("java/lang/Throwable")
+        .constructor()
+        .parameter(Jvm::get()->stringClass));
+
+    object = Jvm::get()->invoke(constructor, Jvm::get()->string(message));
+  }
+
+private:
+  friend void Jvm::check(JNIEnv* env); // For constructing default instances.
+
+  Throwable() {}
+};
+
+} // namespace lang {
+} // namespace java {
+
+#endif // __JAVA_LANG_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/java/net.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/java/net.hpp b/src/jvm/java/net.hpp
new file mode 100644
index 0000000..7816251
--- /dev/null
+++ b/src/jvm/java/net.hpp
@@ -0,0 +1,26 @@
+#ifndef __JAVA_NET_HPP__
+#define __JAVA_NET_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace java {
+namespace net {
+
+class InetSocketAddress : public Jvm::Object // TODO(benh): Extends SocketAddress.
+{
+public:
+  InetSocketAddress(int port)
+  {
+    static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+        Jvm::Class::named("java/net/InetSocketAddress")
+        .constructor()
+        .parameter(Jvm::get()->intClass));
+
+    object = Jvm::get()->invoke(constructor, port);
+  }
+};
+
+} // namespace net {
+} // namespace java {
+
+#endif // __JAVA_NET_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/jvm.cpp
----------------------------------------------------------------------
diff --git a/src/jvm/jvm.cpp b/src/jvm/jvm.cpp
index a4fb791..d053f59 100644
--- a/src/jvm/jvm.cpp
+++ b/src/jvm/jvm.cpp
@@ -8,571 +8,714 @@
 #include <sstream>
 #include <vector>
 
-#include <stout/hashmap.hpp>
+#include <stout/exit.hpp>
 #include <stout/foreach.hpp>
 
 #include "jvm/jvm.hpp"
 
+#include "jvm/java/lang.hpp"
 
-namespace mesos {
-namespace internal {
 
-jmethodID Jvm::findMethod(const Jvm::JClass& clazz,
-                          const std::string& name,
-                          const Jvm::JClass& returnType,
-                          const std::vector<Jvm::JClass> argTypes,
-                          bool isStatic)
+// Static storage and initialization.
+Jvm* Jvm::instance = NULL;
+
+
+Try<Jvm*> Jvm::create(
+    const std::vector<std::string>& options,
+    JNI::Version version,
+    bool exceptions)
 {
-  std::ostringstream signature;
-  signature << "(";
-  std::vector<Jvm::JClass>::iterator args;
-  foreach (Jvm::JClass type, argTypes) {
-    signature << type.signature();
+  // TODO(benh): Make this thread-safe.
+  if (instance != NULL) {
+    return Error("Java Virtual Machine already created");
   }
-  signature << ")" << returnType.signature();
 
-  LOG(INFO) << "looking up" << (isStatic ? " static " : " ") << "method "
-            << name << signature.str();
-
-  jmethodID id = NULL;
-  if (isStatic) {
-    id = env->GetStaticMethodID(findClass(clazz),
-                                name.c_str(),
-                                signature.str().c_str());
-  } else {
-    id = env->GetMethodID(findClass(clazz),
-                          name.c_str(),
-                          signature.str().c_str());
+  JavaVMInitArgs vmArgs;
+  vmArgs.version = version;
+  vmArgs.ignoreUnrecognized = false;
+
+  JavaVMOption* opts = new JavaVMOption[options.size()];
+  for (size_t i = 0; i < options.size(); i++) {
+    opts[i].optionString = const_cast<char*>(options[i].c_str());
   }
+  vmArgs.nOptions = options.size();
+  vmArgs.options = opts;
 
-  // TODO(John Sirois): consider CHECK -> return Option if re-purposing this
-  // code outside of tests.
-  CHECK(id != NULL);
-  return id;
-}
+  JavaVM* jvm = NULL;
+  JNIEnv* env = NULL;
 
+  int result = JNI_CreateJavaVM(&jvm, JNIENV_CAST(&env), &vmArgs);
 
-Jvm::ConstructorFinder::ConstructorFinder(
-    const Jvm::JClass& _type)
-    : type(_type),
-      parameters() {}
+  if (result == JNI_ERR) {
+    return Error("Failed to create JVM!");
+  }
 
+  delete[] opts;
 
-Jvm::ConstructorFinder&
-Jvm::ConstructorFinder::parameter(const Jvm::JClass& type)
-{
-  parameters.push_back(type);
-  return *this;
+  return instance = new Jvm(jvm, version, exceptions);
 }
 
 
-Jvm::JConstructor Jvm::findConstructor(const ConstructorFinder& signature)
+bool Jvm::created()
 {
-  jmethodID id =
-      findMethod(signature.type,
-                 "<init>",
-                 voidClass,
-                 signature.parameters,
-                 false);
-  return Jvm::JConstructor(signature.type, id);
+  return instance != NULL;
 }
 
 
-Jvm::JConstructor::JConstructor(const JConstructor& other) : clazz(other.clazz),
-                                                             id(other.id) {}
+Jvm* Jvm::get()
+{
+  if (instance == NULL) {
+    create();
+  }
+  return CHECK_NOTNULL(instance);
+}
 
 
-Jvm::JConstructor::JConstructor(const JClass& _clazz,
-                                const jmethodID _id) : clazz(_clazz),
-                                                       id(_id) {}
+Jvm::ConstructorFinder::ConstructorFinder(const Jvm::Class& _clazz)
+  : clazz(_clazz), parameters() {}
 
 
-jobject Jvm::invoke(const JConstructor& ctor, ...)
+Jvm::ConstructorFinder& Jvm::ConstructorFinder::parameter(
+    const Jvm::Class& clazz)
 {
-  va_list args;
-  va_start(args, ctor);
-  jobject result = env->NewObjectV(findClass(ctor.clazz), ctor.id, args);
-  va_end(args);
-  CHECK(result != NULL);
-  return result;
+  parameters.push_back(clazz);
+  return *this;
 }
 
 
+Jvm::Constructor::Constructor(const Constructor& that)
+  : clazz(that.clazz), id(that.id) {}
+
+
+Jvm::Constructor::Constructor(const Class& _clazz, const jmethodID _id)
+  : clazz(_clazz), id(_id) {}
+
+
 Jvm::MethodFinder::MethodFinder(
-    const Jvm::JClass& _clazz,
+    const Jvm::Class& _clazz,
     const std::string& _name)
-    : clazz(_clazz),
-      name(_name),
-      parameters() {}
+  : clazz(_clazz),
+    name(_name),
+    parameters() {}
 
 
-Jvm::MethodFinder& Jvm::MethodFinder::parameter(const JClass& type)
+Jvm::MethodFinder& Jvm::MethodFinder::parameter(const Class& type)
 {
   parameters.push_back(type);
   return *this;
 }
 
 
-Jvm::MethodSignature Jvm::MethodFinder::returns(const JClass& returnType) const
+Jvm::MethodSignature Jvm::MethodFinder::returns(const Class& returnType) const
 {
   return Jvm::MethodSignature(clazz, name, returnType, parameters);
 }
 
 
-Jvm::JMethod Jvm::findMethod(const MethodSignature& signature)
-{
-  jmethodID id = findMethod(signature.clazz,
-                            signature.name,
-                            signature.returnType,
-                            signature.parameters,
-                            false);
-  return Jvm::JMethod(signature.clazz, id);
-}
-
-
-Jvm::JMethod Jvm::findStaticMethod(const MethodSignature& signature)
-{
-  jmethodID id = findMethod(signature.clazz,
-                            signature.name,
-                            signature.returnType,
-                            signature.parameters,
-                            true);
-  return Jvm::JMethod(signature.clazz, id);
-}
+Jvm::MethodSignature::MethodSignature(const MethodSignature& that)
+  : clazz(that.clazz),
+    name(that.name),
+    returnType(that.returnType),
+    parameters(that.parameters) {}
 
 
-Jvm::MethodSignature::MethodSignature(const MethodSignature& other) :
-    clazz(other.clazz),
-    name(other.name),
-    returnType(other.returnType),
-    parameters(other.parameters) {}
-
-
-Jvm::MethodSignature::MethodSignature(const JClass& _clazz,
-                                      const std::string& _name,
-                                      const JClass& _returnType,
-                                      const std::vector<JClass>& _parameters) :
-    clazz(_clazz),
+Jvm::MethodSignature::MethodSignature(
+    const Class& _clazz,
+    const std::string& _name,
+    const Class& _returnType,
+    const std::vector<Class>& _parameters)
+  : clazz(_clazz),
     name(_name),
     returnType(_returnType),
     parameters(_parameters) {}
 
 
-Jvm::JMethod::JMethod(const JMethod& other)
-    : clazz(other.clazz), id(other.id) {}
+Jvm::Method::Method(const Method& that)
+    : clazz(that.clazz), id(that.id) {}
 
 
-Jvm::JMethod::JMethod(const JClass& _clazz, const jmethodID _id)
+Jvm::Method::Method(const Class& _clazz, const jmethodID _id)
     : clazz(_clazz), id(_id) {}
 
 
-template <>
-jobject Jvm::invokeV<jobject>(const jobject receiver,
-                              const jmethodID id,
-                              va_list args)
+const Jvm::Class Jvm::Class::named(const std::string& name)
 {
-  jobject result = env->CallObjectMethodV(receiver, id, args);
-  CHECK(result != NULL);
-  return result;
+  return Jvm::Class(name, false /* NOT a native type. */);
 }
 
 
-template<>
-void Jvm::invokeV<void>(const jobject receiver,
-                        const jmethodID id,
-                        va_list args)
+Jvm::Class::Class(const Class& that)
+  : name(that.name), native(that.native) {}
+
+
+Jvm::Class::Class(const std::string& _name, bool _native)
+  : name(_name), native(_native) {}
+
+
+const Jvm::Class Jvm::Class::arrayOf() const
 {
-  env->CallVoidMethodV(receiver, id, args);
+  return Jvm::Class("[" + name, native);
 }
 
 
-template <>
-bool Jvm::invokeV<bool>(const jobject receiver,
-                        const jmethodID id,
-                        va_list args)
+Jvm::ConstructorFinder Jvm::Class::constructor() const
 {
-  return env->CallBooleanMethodV(receiver, id, args);
+  return Jvm::ConstructorFinder(*this);
 }
 
 
-template <>
-char Jvm::invokeV<char>(const jobject receiver,
-                        const jmethodID id,
-                        va_list args)
+Jvm::MethodFinder Jvm::Class::method(const std::string& name) const
 {
-  return env->CallCharMethodV(receiver, id, args);
+  return Jvm::MethodFinder(*this, name);
 }
 
 
-template <>
-short Jvm::invokeV<short>(const jobject receiver,
-                          const jmethodID id,
-                          va_list args)
+std::string Jvm::Class::signature() const
 {
-  return env->CallShortMethodV(receiver, id, args);
+  return native ? name : "L" + name + ";";
 }
 
 
-template <>
-int Jvm::invokeV<int>(const jobject receiver,
-                      const jmethodID id,
-                      va_list args)
+Jvm::Field::Field(const Field& that)
+  : clazz(that.clazz), id(that.id) {}
+
+
+Jvm::Field::Field(const Class& _clazz, const jfieldID _id)
+    : clazz(_clazz), id(_id) {}
+
+
+Jvm::Env::Env(bool daemon)
+  : env(NULL), detach(false)
 {
-  return env->CallIntMethodV(receiver, id, args);
-}
+  JavaVM* jvm = Jvm::get()->jvm;
 
+  // First check if we are already attached.
+  int result = jvm->GetEnv(JNIENV_CAST(&env), Jvm::get()->version);
 
-template <>
-long Jvm::invokeV<long>(const jobject receiver,
-                        const jmethodID id,
-                        va_list args)
+  // If we're not attached, attach now.
+  if (result == JNI_EDETACHED) {
+    if (daemon) {
+      jvm->AttachCurrentThreadAsDaemon(JNIENV_CAST(&env), NULL);
+    } else {
+      jvm->AttachCurrentThread(JNIENV_CAST(&env), NULL);
+    }
+    detach = true;
+  }
+}
+
+Jvm::Env::~Env()
 {
-  return env->CallLongMethodV(receiver, id, args);
+  if (detach) {
+    Jvm::get()->jvm->DetachCurrentThread();
+  }
 }
 
 
-template <>
-float Jvm::invokeV<float>(const jobject receiver,
-                          const jmethodID id,
-                          va_list args)
+jstring Jvm::string(const std::string& s)
 {
-  return env->CallFloatMethodV(receiver, id, args);
+  Env env;
+  return env->NewStringUTF(s.c_str());
 }
 
 
-template <>
-double Jvm::invokeV<double>(const jobject receiver,
-                            const jmethodID id,
-                            va_list args)
+Jvm::Constructor Jvm::findConstructor(const ConstructorFinder& finder)
 {
-  return env->CallDoubleMethodV(receiver, id, args);
+  jmethodID id = findMethod(
+      finder.clazz,
+      "<init>",
+      voidClass,
+      finder.parameters,
+      false);
+
+  return Jvm::Constructor(finder.clazz, id);
 }
 
 
-template <>
-void Jvm::invoke<void>(const jobject receiver, const JMethod& method, ...)
+Jvm::Method Jvm::findMethod(const MethodSignature& signature)
 {
-  va_list args;
-  va_start(args, method);
-  invokeV<void>(receiver, method.id, args);
-  va_end(args);
+  jmethodID id = findMethod(
+      signature.clazz,
+      signature.name,
+      signature.returnType,
+      signature.parameters,
+      false);
+
+  return Jvm::Method(signature.clazz, id);
 }
 
 
-template <>
-jobject Jvm::invokeStaticV<jobject>(const JClass& receiver,
-                                    const jmethodID id,
-                                    va_list args)
+Jvm::Method Jvm::findStaticMethod(const MethodSignature& signature)
 {
-  jobject result = env->CallStaticObjectMethodV(findClass(receiver), id, args);
-  CHECK(result != NULL);
-  return result;
+  jmethodID id = findMethod(
+      signature.clazz,
+      signature.name,
+      signature.returnType,
+      signature.parameters,
+      true);
+
+  return Jvm::Method(signature.clazz, id);
 }
 
 
-template<>
-void Jvm::invokeStaticV<void>(const JClass& receiver,
-                              const jmethodID id,
-                              va_list args)
+Jvm::Field Jvm::findStaticField(const Class& clazz, const std::string& name)
 {
-  env->CallStaticVoidMethodV(findClass(receiver), id, args);
+  Env env;
+
+  jfieldID id = env->GetStaticFieldID(
+      findClass(clazz),
+      name.c_str(),
+      clazz.signature().c_str());
+
+  check(env);
+
+  return Jvm::Field(clazz, id);
 }
 
 
-template <>
-bool Jvm::invokeStaticV<bool>(const JClass& receiver,
-                              const jmethodID id,
-                              va_list args)
+jobject Jvm::invoke(const Constructor& ctor, ...)
 {
-  return env->CallStaticBooleanMethodV(findClass(receiver), id, args);
+  Env env;
+  va_list args;
+  va_start(args, ctor);
+  jobject o = env->NewObjectV(findClass(ctor.clazz), ctor.id, args);
+  va_end(args);
+  check(env);
+  return o;
 }
 
 
 template <>
-char Jvm::invokeStaticV<char>(const JClass& receiver,
-                              const jmethodID id,
-                              va_list args)
+jobject Jvm::getStaticField<jobject>(const Field& field)
 {
-  return env->CallStaticCharMethodV(findClass(receiver), id, args);
+  Env env;
+  jobject o = env->GetStaticObjectField(findClass(field.clazz), field.id);
+  check(env);
+  return o;
 }
 
 
 template <>
-short Jvm::invokeStaticV<short>(const JClass& receiver,
-                                const jmethodID id,
-                                va_list args)
+bool Jvm::getStaticField<bool>(const Field& field)
 {
-  return env->CallStaticShortMethodV(findClass(receiver), id, args);
+  Env env;
+  bool b = env->GetStaticBooleanField(findClass(field.clazz), field.id);
+  check(env);
+  return b;
 }
 
 
 template <>
-int Jvm::invokeStaticV<int>(const JClass& receiver,
-                            const jmethodID id,
-                            va_list args)
+char Jvm::getStaticField<char>(const Field& field)
 {
-  return env->CallStaticIntMethodV(findClass(receiver), id, args);
+  Env env;
+  char c = env->GetStaticCharField(findClass(field.clazz), field.id);
+  check(env);
+  return c;
 }
 
 
 template <>
-long Jvm::invokeStaticV<long>(const JClass& receiver,
-                              const jmethodID id,
-                              va_list args)
+short Jvm::getStaticField<short>(const Field& field)
 {
-  return env->CallStaticLongMethodV(findClass(receiver), id, args);
+  Env env;
+  short s = env->GetStaticShortField(findClass(field.clazz), field.id);
+  check(env);
+  return s;
 }
 
 
 template <>
-float Jvm::invokeStaticV<float>(const JClass& receiver,
-                                const jmethodID id,
-                                va_list args)
+int Jvm::getStaticField<int>(const Field& field)
 {
-  return env->CallStaticFloatMethodV(findClass(receiver), id, args);
+  Env env;
+  int i = env->GetStaticIntField(findClass(field.clazz), field.id);
+  check(env);
+  return i;
 }
 
 
 template <>
-double Jvm::invokeStaticV<double>(const JClass& receiver,
-                                  const jmethodID id,
-                                  va_list args)
+long Jvm::getStaticField<long>(const Field& field)
 {
-  return env->CallStaticDoubleMethodV(findClass(receiver), id, args);
+  Env env;
+  long l = env->GetStaticLongField(findClass(field.clazz), field.id);
+  check(env);
+  return l;
 }
 
 
 template <>
-void Jvm::invokeStatic<void>(const JMethod& method, ...)
+float Jvm::getStaticField<float>(const Field& field)
 {
-  va_list args;
-  va_start(args, method);
-  invokeStaticV<void>(method.clazz, method.id, args);
-  va_end(args);
+  Env env;
+  float f = env->GetStaticFloatField(findClass(field.clazz), field.id);
+  check(env);
+  return f;
 }
 
 
-const Jvm::JClass Jvm::JClass::forName(const std::string& nativeName)
+template <>
+double Jvm::getStaticField<double>(const Field& field)
 {
-  return Jvm::JClass(nativeName, false /* not a native type */);
+  Env env;
+  double d = env->GetStaticDoubleField(findClass(field.clazz), field.id);
+  check(env);
+  return d;
 }
 
 
-Jvm::JClass::JClass(const JClass& other) : nativeName(other.nativeName),
-                                           isNative(other.isNative) {}
-
-
-Jvm::JClass::JClass(const std::string& _nativeName,
-                    bool _isNative) : nativeName(_nativeName),
-                                      isNative(_isNative) {}
+Jvm::Jvm(JavaVM* _jvm, JNI::Version _version, bool _exceptions)
+  : voidClass("V"),
+    booleanClass("Z"),
+    byteClass("B"),
+    charClass("C"),
+    shortClass("S"),
+    intClass("I"),
+    longClass("J"),
+    floatClass("F"),
+    doubleClass("D"),
+    stringClass(Class::named("java/lang/String")),
+    jvm(_jvm),
+    version(_version),
+    exceptions(_exceptions) {}
 
 
-const Jvm::JClass Jvm::JClass::arrayOf() const
+Jvm::~Jvm()
 {
-  return Jvm::JClass("[" + nativeName, isNative);
+  LOG(FATAL) << "Destroying the JVM is not supported";
 }
 
 
-Jvm::ConstructorFinder Jvm::JClass::constructor() const
+jobject Jvm::newGlobalRef(const jobject object)
 {
-  return Jvm::ConstructorFinder(*this);
+  Env env;
+  return env->NewGlobalRef(object);
 }
 
 
-Jvm::MethodFinder Jvm::JClass::method(const std::string& name) const
+void Jvm::deleteGlobalRef(const jobject object)
 {
-  return Jvm::MethodFinder(*this, name);
+  Env env;
+  if (object != NULL) {
+    env->DeleteGlobalRef(object);
+  }
 }
 
 
-std::string Jvm::JClass::signature() const
+jclass Jvm::findClass(const Class& clazz)
 {
-  return isNative ? nativeName : "L" + nativeName + ";";
+  Env env;
+
+  // TODO(John Sirois): Consider CHECK_NOTNULL -> return Option if
+  // re-purposing this code outside of tests.
+  return CHECK_NOTNULL(env->FindClass(clazz.name.c_str()));
 }
 
 
-Jvm::JField::JField(const JField& other) : clazz(other.clazz), id(other.id) {}
+jmethodID Jvm::findMethod(
+    const Jvm::Class& clazz,
+    const std::string& name,
+    const Jvm::Class& returnType,
+    const std::vector<Jvm::Class>& argTypes,
+    bool isStatic)
+{
+  Env env;
 
+  std::ostringstream signature;
+  signature << "(";
+  std::vector<Jvm::Class>::iterator args;
+  foreach (const Jvm::Class& type, argTypes) {
+    signature << type.signature();
+  }
+  signature << ")" << returnType.signature();
 
-Jvm::JField::JField(const JClass& _clazz, const jfieldID _id)
-    : clazz(_clazz), id(_id) {}
+  LOG(INFO) << "Looking up" << (isStatic ? " static " : " ")
+            << "method " << name << signature.str();
 
+  jmethodID id = isStatic
+    ? env->GetStaticMethodID(
+        findClass(clazz),
+        name.c_str(),
+        signature.str().c_str())
+    : env->GetMethodID(
+        findClass(clazz),
+        name.c_str(),
+        signature.str().c_str());
 
-Jvm::JField Jvm::findStaticField(const JClass& clazz, const std::string& name)
-{
-  jfieldID id =
-      env->GetStaticFieldID(findClass(clazz),
-                            name.c_str(),
-                            clazz.signature().c_str());
-  return Jvm::JField(clazz, id);
+  // TODO(John Sirois): Consider CHECK_NOTNULL -> return Option if
+  // re-purposing this code outside of tests.
+  return CHECK_NOTNULL(id);
 }
 
 
-template <>
-jobject Jvm::getStaticField<jobject>(const JField& field)
+template<>
+void Jvm::invokeV<void>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  jobject result = env->GetStaticObjectField(findClass(field.clazz), field.id);
-  CHECK(result != NULL);
-  return result;
+  Env env;
+  env->CallVoidMethodV(receiver, id, args);
+  check(env);
 }
 
 
 template <>
-bool Jvm::getStaticField<bool>(const JField& field)
+jobject Jvm::invokeV<jobject>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->GetStaticBooleanField(findClass(field.clazz), field.id);
+  Env env;
+  jobject o = env->CallObjectMethodV(receiver, id, args);
+  check(env);
+  return o;
 }
 
 
 template <>
-char Jvm::getStaticField<char>(const JField& field)
+bool Jvm::invokeV<bool>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->GetStaticCharField(findClass(field.clazz), field.id);
+  Env env;
+  bool b = env->CallBooleanMethodV(receiver, id, args);
+  check(env);
+  return b;
 }
 
 
 template <>
-short Jvm::getStaticField<short>(const JField& field)
+char Jvm::invokeV<char>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->GetStaticShortField(findClass(field.clazz), field.id);
+  Env env;
+  char c = env->CallCharMethodV(receiver, id, args);
+  check(env);
+  return c;
 }
 
 
 template <>
-int Jvm::getStaticField<int>(const JField& field)
+short Jvm::invokeV<short>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->GetStaticIntField(findClass(field.clazz), field.id);
+  Env env;
+  short s = env->CallShortMethodV(receiver, id, args);
+  check(env);
+  return s;
 }
 
 
 template <>
-long Jvm::getStaticField<long>(const JField& field)
+int Jvm::invokeV<int>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->GetStaticLongField(findClass(field.clazz), field.id);
+  Env env;
+  int i = env->CallIntMethodV(receiver, id, args);
+  check(env);
+  return i;
 }
 
 
 template <>
-float Jvm::getStaticField<float>(const JField& field)
+long Jvm::invokeV<long>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->GetStaticFloatField(findClass(field.clazz), field.id);
+  Env env;
+  long l = env->CallLongMethodV(receiver, id, args);
+  check(env);
+  return l;
 }
 
 
 template <>
-double Jvm::getStaticField<double>(const JField& field)
+float Jvm::invokeV<float>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->GetStaticDoubleField(findClass(field.clazz), field.id);
+  Env env;
+  float f = env->CallFloatMethodV(receiver, id, args);
+  check(env);
+  return f;
 }
 
 
-Jvm::Jvm(const std::vector<std::string>& options, JNIVersion jniVersion)
-  : voidClass("V"),
-    booleanClass("Z"),
-    byteClass("B"),
-    charClass("C"),
-    shortClass("S"),
-    intClass("I"),
-    longClass("J"),
-    floatClass("F"),
-    doubleClass("D"),
-    stringClass(JClass::forName("java/lang/String")),
-    jvm(NULL),
-    env(NULL)
+template <>
+double Jvm::invokeV<double>(
+    const jobject receiver,
+    const jmethodID id,
+    va_list args)
 {
-  JavaVMInitArgs vmArgs;
-  vmArgs.version = jniVersion;
-  vmArgs.ignoreUnrecognized = false;
-
-  JavaVMOption* opts = new JavaVMOption[options.size()];
-  for (size_t i = 0; i < options.size(); i++) {
-    opts[i].optionString = const_cast<char*>(options[i].c_str());
-  }
-  vmArgs.nOptions = options.size();
-  vmArgs.options = opts;
-
-  int result = JNI_CreateJavaVM(&jvm, JNIENV_CAST(&env), &vmArgs);
-  CHECK(result != JNI_ERR) << "Failed to create JVM!";
-
-  delete[] opts;
+  Env env;
+  double d = env->CallDoubleMethodV(receiver, id, args);
+  check(env);
+  return d;
 }
 
 
-Jvm::~Jvm()
+template<>
+void Jvm::invokeStaticV<void>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  CHECK(0 == jvm->DestroyJavaVM()) << "Failed to destroy JVM";
+  Env env;
+  env->CallStaticVoidMethodV(findClass(receiver), id, args);
+  check(env);
 }
 
 
-void Jvm::attachDaemon()
+template <>
+jobject Jvm::invokeStaticV<jobject>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  jvm->AttachCurrentThreadAsDaemon(JNIENV_CAST(&env), NULL);
+  Env env;
+  jobject o = env->CallStaticObjectMethodV(findClass(receiver), id, args);
+  check(env);
+  return o;
 }
 
 
-void Jvm::attach()
+template <>
+bool Jvm::invokeStaticV<bool>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  jvm->AttachCurrentThread(JNIENV_CAST(&env), NULL);
+  Env env;
+  bool b = env->CallStaticBooleanMethodV(findClass(receiver), id, args);
+  check(env);
+  return b;
 }
 
 
-void Jvm::detach()
+template <>
+char Jvm::invokeStaticV<char>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  jvm->DetachCurrentThread();
+  Env env;
+  char c = env->CallStaticCharMethodV(findClass(receiver), id, args);
+  check(env);
+  return c;
 }
 
 
-jclass Jvm::findClass(const JClass& clazz)
+template <>
+short Jvm::invokeStaticV<short>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  jclass cls = env->FindClass(clazz.nativeName.c_str());
-  // TODO(John Sirois): consider CHECK -> return Option if re-purposing this
-  // code outside of tests.
-  CHECK(cls != NULL);
-  return cls;
+  Env env;
+  short s = env->CallStaticShortMethodV(findClass(receiver), id, args);
+  check(env);
+  return s;
 }
 
 
-jobject Jvm::string(const std::string& str)
+template <>
+int Jvm::invokeStaticV<int>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->NewStringUTF(str.c_str());
+  Env env;
+  int i = env->CallStaticIntMethodV(findClass(receiver), id, args);
+  check(env);
+  return i;
 }
 
 
-jobject Jvm::newGlobalRef(const jobject object)
+template <>
+long Jvm::invokeStaticV<long>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  return env->NewGlobalRef(object);
+  Env env;
+  long l = env->CallStaticLongMethodV(findClass(receiver), id, args);
+  check(env);
+  return l;
 }
 
 
-void Jvm::deleteGlobalRef(const jobject object)
+template <>
+float Jvm::invokeStaticV<float>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
 {
-  env->DeleteGlobalRef(object);
+  Env env;
+  float f = env->CallStaticFloatMethodV(findClass(receiver), id, args);
+  check(env);
+  return f;
 }
 
 
-void Jvm::deleteGlobalRefSafe(const jobject object)
-{
-  if (object != NULL) {
-    deleteGlobalRef(object);
+template <>
+double Jvm::invokeStaticV<double>(
+    const Class& receiver,
+    const jmethodID id,
+    va_list args)
+{
+  Env env;
+  double d = env->CallStaticDoubleMethodV(findClass(receiver), id, args);
+  check(env);
+  return d;
+}
+
+
+void Jvm::check(JNIEnv* env)
+{
+  if (env->ExceptionCheck() == JNI_TRUE) {
+    if (!exceptions) {
+      env->ExceptionDescribe();
+      EXIT(1) << "Caught a JVM exception, not propagating";
+    } else {
+      java::lang::Throwable throwable;
+      Object* object = &throwable;
+      object->object = env->ExceptionOccurred();
+      env->ExceptionClear();
+      throw throwable;
+    }
   }
 }
 
-Jvm::Attach::Attach(Jvm* jvm, bool daemon) : _jvm(jvm)
+
+// N.B. Both Jvm::invoke<void> and Jvm::invokeStatic<void> template
+// instantiations need to be defined AFTER template instantions that
+// they use (i.e., Jvm::invokeV<void>, Jvm::invokeStaticV<void>).
+
+template <>
+void Jvm::invoke<void>(const jobject receiver, const Method& method, ...)
 {
-  if (daemon) {
-    _jvm->attachDaemon();
-  } else {
-    _jvm->attach();
-  }
+  va_list args;
+  va_start(args, method);
+  invokeV<void>(receiver, method.id, args);
+  va_end(args);
 }
 
 
-Jvm::Attach::~Attach()
+template <>
+void Jvm::invokeStatic<void>(const Method& method, ...)
 {
-  // TODO(John Sirois): this detaches too early under nested use, attach by a
-  // given thread should incr, this should decr and only detach on 0
-  _jvm->detach();
+  va_list args;
+  va_start(args, method);
+  invokeStaticV<void>(method.clazz, method.id, args);
+  va_end(args);
 }
-
-} // namespace internal
-} // namespace mesos

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/jvm.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/jvm.hpp b/src/jvm/jvm.hpp
index 6a31bd8..a3ea86a 100644
--- a/src/jvm/jvm.hpp
+++ b/src/jvm/jvm.hpp
@@ -3,10 +3,13 @@
 
 #include <jni.h>
 
-#include <glog/logging.h>
-
+#include <string>
 #include <vector>
 
+#include <stout/error.hpp>
+#include <stout/try.hpp>
+
+
 // Some compilers give us warnings about 'dereferencing type-punned
 // pointer will break strict-aliasing rules' when we cast our JNIEnv**
 // to void**. We use this function to do the magic for us.
@@ -16,118 +19,149 @@ inline void** JNIENV_CAST(JNIEnv** env)
 }
 
 
-namespace mesos {
-namespace internal {
+struct JNI
+{
+  enum Version
+  {
+    v_1_1 = JNI_VERSION_1_1,
+    v_1_2 = JNI_VERSION_1_2,
+    v_1_4 = JNI_VERSION_1_4,
+    v_1_6 = JNI_VERSION_1_6
+  };
+};
 
-// Facilitates embedding a jvm and calling into it.
-//
-// TODO(John Sirois): Fix variadic methods.  Possibly a way to do this with
-// typelists, type concatenation and unwinding builder inheritance.
-//
-// TODO(John Sirois): Support finding static methods.
+// Facilitates embedding a JVM and calling into it.
 class Jvm
 {
 public:
   // Forward declarations.
   class ConstructorFinder;
   class MethodFinder;
-  class JConstructor;
+  class Constructor;
   class MethodSignature;
-  class JMethod;
-
-  // An opaque class descriptor that can be used to find constructors, methods
-  // and fields.
-  class JClass
+  class Method;
+
+  // Starts a new embedded JVM with the given -D options. Each option
+  // supplied should be of the standard form: '-Dproperty=value'.
+  // Returns the singleton Jvm instance or an error if the JVM had
+  // already been created. Note that you can only create one JVM
+  // instance per process since destructing a JVM has issues, see:
+  // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4712793.  In
+  // addition, most JVM's use signals and couldn't possibly play
+  // nicely with one another.
+  // TODO(benh): Add a 'create' which just takes an already
+  // constructed JavaVM. This will be useful for when a JVM is calling
+  // into native code versus native code embedding a JVM.
+  // TODO(John Sirois): Consider elevating classpath as a top-level
+  // JVM configuration parameter since it will likely always need to
+  // be specified. Ditto for and non '-X' options.
+  static Try<Jvm*> create(
+      const std::vector<std::string>& options = std::vector<std::string>(),
+      JNI::Version version = JNI::v_1_6,
+      bool exceptions = false);
+
+  // Returns true if the JVM has already been created.
+  static bool created();
+
+  // Returns the singleton JVM instance, creating it with no options
+  // and a default version if necessary.
+  static Jvm* get();
+
+  // An opaque class descriptor that can be used to find constructors,
+  // methods and fields.
+  class Class
   {
   public:
-    // A factory for new java reference type class descriptors given the native
-    // name.  To obtain class descriptors for native types, use the fields in
-    // Jvm.
-    static const JClass forName(const std::string& nativeName);
+    // A factory for new Java reference type class descriptors given
+    // the fully-qualified class name (e.g., 'java/io/File'). To
+    // obtain class descriptors for native types (int, short, etc),
+    // use the fields in Jvm.
+    static const Class named(const std::string& name);
 
-    JClass(const JClass& other);
+    Class(const Class& that);
 
     // Returns the class of an array of the current class.
-    const JClass arrayOf() const;
+    const Class arrayOf() const;
 
-    // Creates a builder that can be used to locate a constructor of this
-    // class with Jvm::findConstructor.
+    // Creates a builder that can be used to locate a constructor of
+    // this class with Jvm::findConstructor.
     ConstructorFinder constructor() const;
 
-    // Creates a builder that can be used to locate an instance method of this
-    // class with Jvm::findMethod.
+    // Creates a builder that can be used to locate an instance method
+    // of this class with Jvm::findMethod.
     MethodFinder method(const std::string& name) const;
 
   private:
     friend class Jvm;
 
-    JClass(const std::string& nativeName,
-           bool isNative = true);
+    Class(const std::string& name, bool native = true);
 
     std::string signature() const;
 
-    std::string nativeName;
-    bool isNative;
+    std::string name;
+    bool native;
   };
 
 
-  // A builder that is used to specify a constructor by specifying its parameter
-  // list with zero or more calls to ConstructorFinder::parameter.
+  // A builder that is used to specify a constructor by specifying its
+  // parameter list with zero or more calls to
+  // ConstructorFinder::parameter.
   class ConstructorFinder
   {
   public:
     // Adds a parameter to the constructor parameter list.
-    ConstructorFinder& parameter(const JClass& type);
+    ConstructorFinder& parameter(const Class& clazz);
 
   private:
-    friend class JClass;
+    friend class Class;
     friend class Jvm;
 
-    ConstructorFinder(const JClass& type);
+    ConstructorFinder(const Class& clazz);
 
-    const JClass type;
-    std::vector<JClass> parameters;
+    const Class clazz;
+    std::vector<Class> parameters;
   };
 
 
-  // An opaque constructor descriptor that can be used to create new instances
-  // of a class using Jvm::invokeConstructor.
-  class JConstructor
+  // An opaque constructor descriptor that can be used to create new
+  // instances of a class using Jvm::invokeConstructor.
+  class Constructor
   {
   public:
-    JConstructor(const JConstructor& other);
+    Constructor(const Constructor& that);
 
   private:
     friend class Jvm;
 
-    JConstructor(const JClass& clazz, const jmethodID id);
+    Constructor(const Class& clazz, const jmethodID id);
 
-    const JClass clazz;
+    const Class clazz;
     const jmethodID id;
   };
 
 
-  // A builder that is used to specify an instance method by specifying its
-  // parameter list with zero or more calls to MethodFinder::parameter and a
-  // final call to MethodFinder::returns to get an opaque specification of the
-  // method for use with Jvm::findMethod.
+  // A builder that is used to specify an instance method by
+  // specifying its parameter list with zero or more calls to
+  // MethodFinder::parameter and a final call to MethodFinder::returns
+  // to get an opaque specification of the method for use with
+  // Jvm::findMethod.
   class MethodFinder
   {
   public:
     // Adds a parameter to the method parameter list.
-    MethodFinder& parameter(const JClass& type);
+    MethodFinder& parameter(const Class& type);
 
     // Terminates description of a method by specifying its return type.
-    MethodSignature returns(const JClass& type) const;
+    MethodSignature returns(const Class& type) const;
 
   private:
-    friend class JClass;
+    friend class Class;
 
-    MethodFinder(const JClass& clazz, const std::string& name);
+    MethodFinder(const Class& clazz, const std::string& name);
 
-    const JClass clazz;
+    const Class clazz;
     const std::string name;
-    std::vector<JClass> parameters;
+    std::vector<Class> parameters;
   };
 
 
@@ -135,153 +169,237 @@ public:
   class MethodSignature
   {
   public:
-    MethodSignature(const MethodSignature& other);
+    MethodSignature(const MethodSignature& that);
 
   private:
     friend class Jvm;
     friend class MethodFinder;
 
-    MethodSignature(const JClass& clazz,
+    MethodSignature(const Class& clazz,
                     const std::string& name,
-                    const JClass& returnType,
-                    const std::vector<JClass>& parameters);
+                    const Class& returnType,
+                    const std::vector<Class>& parameters);
 
-    const JClass clazz;
+    const Class clazz;
     const std::string name;
-    const JClass returnType;
-    std::vector<JClass> parameters;
+    const Class returnType;
+    std::vector<Class> parameters;
   };
 
 
   // An opaque method descriptor that can be used to invoke instance methods
   // using Jvm::invokeMethod.
-  class JMethod
+  class Method
   {
   public:
-    JMethod(const JMethod& other);
+    Method(const Method& that);
 
   private:
     friend class Jvm;
     friend class MethodSignature;
 
-    JMethod(const JClass& clazz, const jmethodID id);
+    Method(const Class& clazz, const jmethodID id);
 
-    const JClass clazz;
+    const Class clazz;
     const jmethodID id;
   };
 
 
   // An opaque field descriptor that can be used to access fields using
   // methods like Jvm::getStaticField.
-  class JField
+  class Field
   {
   public:
-    JField(const JField& other);
+    Field(const Field& that);
 
   private:
     friend class Jvm;
 
-    JField(const JClass& clazz, const jfieldID id);
+    Field(const Class& clazz, const jfieldID id);
 
-    const JClass clazz;
+    const Class clazz;
     const jfieldID id;
   };
 
 
-  // RAII container for c++/jvm thread binding management.
-  class Attach
+  // Base class for all JVM objects. This object "stores" the
+  // underlying global reference and performs the appropriate
+  // operations across copies and assignments.
+  class Object
   {
   public:
-    Attach(Jvm* jvm, bool daemon = true);
-    ~Attach();
+    Object() : object(NULL) {}
+
+    Object(jobject _object)
+      : object(Jvm::get()->newGlobalRef(_object)) {}
+
+    Object(const Object& that)
+    {
+      object = Jvm::get()->newGlobalRef(that.object);
+    }
+
+    ~Object()
+    {
+      if (object != NULL) {
+        Jvm::get()->deleteGlobalRef(object);
+      }
+    }
+
+    Object& operator = (const Object& that)
+    {
+      if (object != NULL) {
+        Jvm::get()->deleteGlobalRef(object);
+      }
+      object = Jvm::get()->newGlobalRef(that.object);
+      return *this;
+    }
+
+    operator jobject () const
+    {
+      return object;
+    }
+
+  protected:
+    friend class Jvm; // For manipulating object.
+
+    jobject object;
+  };
+
+  // Helper for providing access to static variables in a class. You
+  // can use this to delay the variable lookup until it's actually
+  // accessed in order to keep the JVM from getting constructed too
+  // early. See Level in jvm/org/apache/log4j.hpp for an example.
+  // TODO(benh): Make this work for instance variables too (i.e.,
+  // StaticVariable -> Variable).
+  // TODO(benh): Provide template specialization for primitive
+  // types (e.g., StaticVariable<int>, StaticVariable<short>,
+  // StaticVariable<std::string>).
+  template <typename T, const char* name>
+  class StaticVariable
+  {
+  public:
+    StaticVariable(const Class& _clazz)
+      : clazz(_clazz)
+    {
+      // Check that T extends Object.
+      { T* t = NULL; Object* o = t; (void) o; }
+    }
+
+    operator T () const
+    {
+      // Note that we actually look up the field lazily (upon first
+      // invocation operator) so that we don't possibly create the JVM
+      // too early.
+      static Field field = Jvm::get()->findStaticField(clazz, name);
+      T t;
+      t.object = Jvm::get()->getStaticField<jobject>(field);
+      return t;
+    }
 
   private:
-    Jvm* _jvm;
+    const Class clazz;
   };
 
-  friend class Attach;
-
-  enum JNIVersion
+  // Each thread that wants to interact with the JVM needs a JNI
+  // environment which must be obtained by "attaching" to the JVM. We
+  // use the following RAII class to provide the environment and also
+  // make sure a thread is attached and properly detached. Note that
+  // nested constructions are no-ops and use the same environment (and
+  // without detaching too early).
+  // TODO(benh): Support putting a 'Jvm::Env' into a thread-local
+  // variable so we can "attach" to the JVM once.
+  class Env
   {
-    v_1_1 = JNI_VERSION_1_1,
-    v_1_2 = JNI_VERSION_1_2,
-    v_1_4 = JNI_VERSION_1_4,
-    v_1_6 = JNI_VERSION_1_6
+  public:
+    Env(bool daemon = true);
+    ~Env();
+
+    JNIEnv* operator -> () const { return env; }
+
+    operator JNIEnv* () const { return env; }
+
+  private:
+    JNIEnv* env;
+    bool detach; // A nested use of Env should not detach the thread.
   };
 
-  // Starts a new embedded jvm with the given -D options.  Each option supplied
-  // should be of the standard form: '-Dproperty=value'.
-  //
-  // TODO(John Sirois): Consider elevating classpath as a top level jvm
-  // configuration parameter since it will likely always need to be specified.
-  // Ditto for and non -X java option.
-  Jvm(const std::vector<std::string>& options,
-      JNIVersion jniVersion = Jvm::v_1_6);
-  ~Jvm();
+  friend class Env;
 
-  const JClass voidClass;
-  const JClass booleanClass;
-  const JClass byteClass;
-  const JClass charClass;
-  const JClass shortClass;
-  const JClass intClass;
-  const JClass longClass;
-  const JClass floatClass;
-  const JClass doubleClass;
-  const JClass stringClass;
+  const Class voidClass;
+  const Class booleanClass;
+  const Class byteClass;
+  const Class charClass;
+  const Class shortClass;
+  const Class intClass;
+  const Class longClass;
+  const Class floatClass;
+  const Class doubleClass;
+  const Class stringClass;
 
-  jobject string(const std::string& str);
+  jstring string(const std::string& s);
 
-  JConstructor findConstructor(const ConstructorFinder& constructor);
-  JMethod findMethod(const MethodSignature& signature);
-  JMethod findStaticMethod(const MethodSignature& signature);
-  JField findStaticField(const JClass& clazz, const std::string& name);
+  Constructor findConstructor(const ConstructorFinder& finder);
+  Method findMethod(const MethodSignature& signature);
+  Method findStaticMethod(const MethodSignature& signature);
+  Field findStaticField(const Class& clazz, const std::string& name);
 
-  jobject invoke(const JConstructor& ctor, ...);
+  // TODO(John Sirois): Add "type checking" to variadic method
+  // calls. Possibly a way to do this with typelists, type
+  // concatenation and unwinding builder inheritance.
+
+  jobject invoke(const Constructor& ctor, ...);
 
   template <typename T>
-  T invoke(const jobject receiver, const JMethod& method, ...);
+  T invoke(const jobject receiver, const Method& method, ...);
 
   template <typename T>
-  T invokeStatic(const JMethod& method, ...);
+  T invokeStatic(const Method& method, ...);
 
   template <typename T>
-  T getStaticField(const JField& field);
+  T getStaticField(const Field& field);
+
+  // Checks the exception state of an environment.
+  void check(JNIEnv* env);
 
+private:
+  friend class Object; // For creating global references.
+
+  Jvm(JavaVM* jvm, JNI::Version version, bool exceptions);
+  ~Jvm();
+
+private:
   jobject newGlobalRef(const jobject object);
   void deleteGlobalRef(const jobject object);
-  void deleteGlobalRefSafe(const jobject object);
 
-private:
-  jclass findClass(const JClass& clazz);
+  jclass findClass(const Class& clazz);
 
-  jmethodID findMethod(const Jvm::JClass& clazz,
+  jmethodID findMethod(const Jvm::Class& clazz,
                        const std::string& name,
-                       const Jvm::JClass& returnType,
-                       const std::vector<Jvm::JClass> argTypes,
+                       const Jvm::Class& returnType,
+                       const std::vector<Jvm::Class>& argTypes,
                        bool isStatic);
 
   template <typename T>
   T invokeV(const jobject receiver, const jmethodID id, va_list args);
 
   template <typename T>
-  T invokeStaticV(const JClass& receiver, const jmethodID id, va_list args);
+  T invokeStaticV(const Class& receiver, const jmethodID id, va_list args);
 
-  void attachDaemon();
-  void attach();
-  void detach();
+  // Singleton instance.
+  static Jvm* instance;
 
   JavaVM* jvm;
-  JNIEnv* env;
+  const JNI::Version version;
+  const bool exceptions;
 };
 
 
 template <>
-void Jvm::invoke<void>(const jobject receiver, const JMethod& method, ...);
+void Jvm::invoke<void>(const jobject receiver, const Method& method, ...);
 
 
 template <typename T>
-T Jvm::invoke(const jobject receiver, const JMethod& method, ...)
+T Jvm::invoke(const jobject receiver, const Method& method, ...)
 {
   va_list args;
   va_start(args, method);
@@ -292,11 +410,11 @@ T Jvm::invoke(const jobject receiver, const JMethod& method, ...)
 
 
 template <>
-void Jvm::invokeStatic<void>(const JMethod& method, ...);
+void Jvm::invokeStatic<void>(const Method& method, ...);
 
 
 template <typename T>
-T Jvm::invokeStatic(const JMethod& method, ...)
+T Jvm::invokeStatic(const Method& method, ...)
 {
   va_list args;
   va_start(args, method);
@@ -305,7 +423,4 @@ T Jvm::invokeStatic(const JMethod& method, ...)
   return result;
 }
 
-} // namespace internal
-} // namespace mesos
-
 #endif // __JVM_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/org/apache/log4j.cpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/log4j.cpp b/src/jvm/org/apache/log4j.cpp
new file mode 100644
index 0000000..b73df8c
--- /dev/null
+++ b/src/jvm/org/apache/log4j.cpp
@@ -0,0 +1,16 @@
+#include <jvm/org/apache/log4j.hpp>
+
+namespace org {
+namespace apache {
+namespace log4j {
+
+// Static storage and initialization.
+const char LEVEL_OFF[] = "OFF";
+
+Jvm::StaticVariable<Level, LEVEL_OFF> Level::OFF =
+  Jvm::StaticVariable<Level, LEVEL_OFF>(
+      Jvm::Class::named("org/apache/log4j/Level"));
+
+} // namespace log4j {
+} // namespace apache {
+} // namespace org {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/org/apache/log4j.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/log4j.hpp b/src/jvm/org/apache/log4j.hpp
new file mode 100644
index 0000000..6b5ba4b
--- /dev/null
+++ b/src/jvm/org/apache/log4j.hpp
@@ -0,0 +1,69 @@
+#ifndef __ORG_APACHE_LOG4J_HPP__
+#define __ORG_APACHE_LOG4J_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace org {
+namespace apache {
+namespace log4j {
+
+// Forward declaration.
+extern const char LEVEL_OFF[];
+
+
+class Level : public Jvm::Object // TODO(benh): Extends Priority.
+{
+public:
+  friend class Jvm::StaticVariable<Level, LEVEL_OFF>;
+
+  static Jvm::StaticVariable<Level, LEVEL_OFF> OFF;
+
+  Level() {} // No default constuctors.
+};
+
+
+class Category : public Jvm::Object
+{
+public:
+  void setLevel(const Level& level)
+  {
+    static Jvm::Method method = Jvm::get()->findMethod(
+        Jvm::Class::named("org/apache/log4j/Category")
+        .method("setLevel")
+        .parameter(Jvm::Class::named("org/apache/log4j/Level"))
+        .returns(Jvm::get()->voidClass));
+
+    Jvm::get()->invoke<void>(object, method, (jobject) level);
+  }
+
+protected:
+  Category() {} // No default constructors.
+};
+
+
+class Logger : public Category
+{
+public:
+  static Logger getRootLogger()
+  {
+    static Jvm::Method method = Jvm::get()->findStaticMethod(
+        Jvm::Class::named("org/apache/log4j/Logger")
+        .method("getRootLogger")
+        .returns(Jvm::Class::named("org/apache/log4j/Logger")));
+
+    Logger logger;
+    logger.object = Jvm::get()->invokeStatic<jobject>(method);
+
+    return logger;
+  }
+
+protected:
+  Logger() {} // No default constructors.
+};
+
+
+} // namespace log4j {
+} // namespace apache {
+} // namespace org {
+
+#endif // __ORG_APACHE_LOG4J_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/org/apache/zookeeper.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/zookeeper.hpp b/src/jvm/org/apache/zookeeper.hpp
new file mode 100644
index 0000000..dac1456
--- /dev/null
+++ b/src/jvm/org/apache/zookeeper.hpp
@@ -0,0 +1,168 @@
+#ifndef __ORG_APACHE_ZOOKEEPER_HPP__
+#define __ORG_APACHE_ZOOKEEPER_HPP__
+
+#include <jvm/jvm.hpp>
+
+#include <jvm/java/io.hpp>
+#include <jvm/java/net.hpp>
+
+// Package 'org.apache.zookeeper.persistence'.
+
+namespace org {
+namespace apache {
+namespace zookeeper {
+namespace persistence {
+
+class FileTxnSnapLog : public Jvm::Object
+{
+public:
+  FileTxnSnapLog(const java::io::File& dataDir,
+                 const java::io::File& snapDir)
+  {
+    static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+        Jvm::Class::named(
+            "org/apache/zookeeper/server/persistence/FileTxnSnapLog")
+        .constructor()
+        .parameter(Jvm::Class::named("java/io/File"))
+        .parameter(Jvm::Class::named("java/io/File")));
+
+    object = Jvm::get()->invoke(
+        constructor, (jobject) dataDir, (jobject) snapDir);
+  }
+};
+
+} // namespace persistence {
+} // namespace zookeeper {
+} // namespace apache {
+} // namespace org {
+
+
+// Package 'org.apache.zookeeper.server'.
+
+namespace org {
+namespace apache {
+namespace zookeeper {
+namespace server {
+
+class ZooKeeperServer : public Jvm::Object
+{
+public:
+  class DataTreeBuilder : public Jvm::Object {};
+
+  class BasicDataTreeBuilder : public DataTreeBuilder
+  {
+  public:
+    BasicDataTreeBuilder()
+    {
+      static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+          Jvm::Class::named(
+              "org/apache/zookeeper/server/ZooKeeperServer$BasicDataTreeBuilder")
+          .constructor());
+
+      object = Jvm::get()->invoke(constructor);
+    }
+  };
+
+  ZooKeeperServer(const persistence::FileTxnSnapLog& txnLogFactory,
+                  const DataTreeBuilder& treeBuilder)
+  {
+    static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+        Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer")
+        .constructor()
+        .parameter(
+            Jvm::Class::named(
+                "org/apache/zookeeper/server/persistence/FileTxnSnapLog"))
+        .parameter(
+            Jvm::Class::named(
+                "org/apache/zookeeper/server/ZooKeeperServer$DataTreeBuilder")));
+
+    object = Jvm::get()->invoke(
+        constructor, (jobject) txnLogFactory, (jobject) treeBuilder);
+  }
+
+  int getClientPort()
+  {
+    static Jvm::Method method = Jvm::get()->findMethod(
+        Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer")
+        .method("getClientPort")
+        .returns(Jvm::get()->intClass));
+
+    return Jvm::get()->invoke<int>(object, method);
+  }
+
+  void closeSession(int64_t sessionId)
+  {
+    static Jvm::Method method = Jvm::get()->findMethod(
+        Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer")
+        .method("closeSession")
+        .parameter(Jvm::get()->longClass)
+        .returns(Jvm::get()->voidClass));
+
+    Jvm::get()->invoke<void>(object, method, sessionId);
+  }
+};
+
+
+class NIOServerCnxn : public Jvm::Object
+{
+public:
+  class Factory : public Jvm::Object // TODO(benh): Extends Thread.
+  {
+  public:
+    Factory(const java::net::InetSocketAddress& addr)
+    {
+      static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+          Jvm::Class::named(
+              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+          .constructor()
+          .parameter(Jvm::Class::named("java/net/InetSocketAddress")));
+
+      object = Jvm::get()->invoke(constructor, (jobject) addr);
+    }
+
+    void startup(const ZooKeeperServer& zks)
+    {
+      static Jvm::Method method = Jvm::get()->findMethod(
+          Jvm::Class::named(
+              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+          .method("startup")
+          .parameter(Jvm::Class::named(
+                         "org/apache/zookeeper/server/ZooKeeperServer"))
+          .returns(Jvm::get()->voidClass));
+
+      Jvm::get()->invoke<void>(object, method, (jobject) zks);
+    }
+
+    bool isAlive()
+    {
+      static Jvm::Method method = Jvm::get()->findMethod(
+          Jvm::Class::named(
+              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+          .method("isAlive")
+          .returns(Jvm::get()->booleanClass));
+
+      return Jvm::get()->invoke<bool>(object, method);
+    }
+
+    void shutdown()
+    {
+      static Jvm::Method method = Jvm::get()->findMethod(
+          Jvm::Class::named(
+              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+          .method("shutdown")
+          .returns(Jvm::get()->voidClass));
+
+      Jvm::get()->invoke<void>(object, method);
+    }
+  };
+
+private:
+  NIOServerCnxn() {} // No default constructors.
+};
+
+} // namespace server {
+} // namespace zookeeper {
+} // namespace apache {
+} // namespace org {
+
+#endif // __ORG_APACHE_ZOOKEEPER_HPP__

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test.cpp b/src/tests/zookeeper_test.cpp
index fb61f2d..90c6aba 100644
--- a/src/tests/zookeeper_test.cpp
+++ b/src/tests/zookeeper_test.cpp
@@ -24,14 +24,17 @@
 
 #include <tr1/functional>
 
+#include <jvm/jvm.hpp>
+
+#include <jvm/org/apache/log4j.hpp>
+#include <jvm/org/apache/log4j.hpp>
+
 #include <stout/lambda.hpp>
 
 #include "common/lock.hpp"
 
 #include "logging/logging.hpp"
 
-#include "jvm/jvm.hpp"
-
 #include "tests/utils.hpp"
 #include "tests/zookeeper_test.hpp"
 #include "tests/zookeeper_test_server.hpp"
@@ -40,45 +43,12 @@ namespace mesos {
 namespace internal {
 namespace tests {
 
-const Milliseconds ZooKeeperTest::NO_TIMEOUT(5000);
-
-// Note that we NEVER delete the Jvm instance because you can only
-// create one JVM since destructing a JVM has issues (see:
-// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4712793).
-Jvm* ZooKeeperTest::jvm = NULL;
-
-
-static void silenceServerLogs(Jvm* jvm)
-{
-  Jvm::Attach attach(jvm);
-
-  Jvm::JClass loggerClass = Jvm::JClass::forName("org/apache/log4j/Logger");
-  jobject rootLogger =jvm->invokeStatic<jobject>(
-      jvm->findStaticMethod(loggerClass
-                            .method("getRootLogger")
-                            .returns(loggerClass)));
-
-  Jvm::JClass levelClass = Jvm::JClass::forName("org/apache/log4j/Level");
-  jvm->invoke<void>(
-      rootLogger,
-      jvm->findMethod(loggerClass
-                      .method("setLevel")
-                      .parameter(levelClass)
-                      .returns(jvm->voidClass)),
-      jvm->getStaticField<jobject>(jvm->findStaticField(levelClass, "OFF")));
-}
-
-
-static void silenceClientLogs()
-{
-  // TODO(jsirois): Put this in the C++ API.
-  zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR);
-}
+const Duration ZooKeeperTest::NO_TIMEOUT = Milliseconds(5000);
 
 
 void ZooKeeperTest::SetUpTestCase()
 {
-  if (jvm == NULL) {
+  if (!Jvm::created()) {
     std::string zkHome = flags.build_dir +
       "/third_party/zookeeper-" ZOOKEEPER_VERSION;
 
@@ -88,13 +58,19 @@ void ZooKeeperTest::SetUpTestCase()
 
     LOG(INFO) << "Using classpath setup: " << classpath << std::endl;
 
-    std::vector<std::string> opts;
-    opts.push_back(classpath);
-    jvm = new Jvm(opts);
+    std::vector<std::string> options;
+    options.push_back(classpath);
+    Try<Jvm*> jvm = Jvm::create(options);
+    CHECK_SOME(jvm);
 
     if (!flags.verbose) {
-      silenceServerLogs(jvm);
-      silenceClientLogs();
+      // Silence server logs.
+      org::apache::log4j::Logger::getRootLogger()
+        .setLevel(org::apache::log4j::Level::OFF);
+
+      // Silence client logs.
+      // TODO(jsirois): Create C++ ZooKeeper::setLevel.
+      zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR);
     }
   }
 }
@@ -102,18 +78,8 @@ void ZooKeeperTest::SetUpTestCase()
 
 void ZooKeeperTest::SetUp()
 {
-  MesosTest::SetUp();
-  server = new ZooKeeperTestServer(jvm);
   server->startNetwork();
-};
-
-
-void ZooKeeperTest::TearDown()
-{
-  delete server;
-  server = NULL;
-  MesosTest::TearDown();
-};
+}
 
 
 ZooKeeperTest::TestWatcher::TestWatcher()

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test.hpp b/src/tests/zookeeper_test.hpp
index 61a3d25..7bd396b 100644
--- a/src/tests/zookeeper_test.hpp
+++ b/src/tests/zookeeper_test.hpp
@@ -29,8 +29,6 @@
 
 #include <stout/duration.hpp>
 
-#include "jvm/jvm.hpp"
-
 #include "tests/utils.hpp"
 #include "tests/zookeeper_test_server.hpp"
 
@@ -82,7 +80,6 @@ public:
   class TestWatcher : public Watcher
   {
   public:
-
     // Encapsulates all the state of a ZooKeeper watcher event.
     struct Event {
       Event(int _type, int _state, const std::string& _path)
@@ -119,21 +116,18 @@ public:
     pthread_cond_t cond;
   };
 
-  ZooKeeperTest() : server(NULL) {}
+  ZooKeeperTest() : server(new ZooKeeperTestServer()) {}
+  virtual ~ZooKeeperTest() { delete server; }
 
   static void SetUpTestCase();
 
 protected:
   virtual void SetUp();
-  virtual void TearDown();
 
   // A very long session timeout that simulates no timeout for test cases.
-  static const Milliseconds NO_TIMEOUT;
+  static const Duration NO_TIMEOUT;
 
   ZooKeeperTestServer* server;
-
-private:
-  static Jvm* jvm;
 };
 
 } // namespace tests {

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test_server.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test_server.cpp b/src/tests/zookeeper_test_server.cpp
index 5c82a1e..8051b4d 100644
--- a/src/tests/zookeeper_test_server.cpp
+++ b/src/tests/zookeeper_test_server.cpp
@@ -16,130 +16,48 @@
  * limitations under the License.
  */
 
-#include <jni.h>
-#include <stdarg.h>
+#include <jvm/jvm.hpp>
 
-#include <glog/logging.h>
+#include <jvm/java/io.hpp>
+#include <jvm/java/net.hpp>
 
-#include <sstream>
-#include <vector>
+#include <jvm/org/apache/zookeeper.hpp>
 
-#include <stout/uuid.hpp>
+#include <stout/os.hpp>
 
-#include "jvm/jvm.hpp"
+#include "logging/logging.hpp"
 
 #include "tests/zookeeper_test_server.hpp"
 
+using org::apache::zookeeper::persistence::FileTxnSnapLog;
+
+using org::apache::zookeeper::server::NIOServerCnxn;
+using org::apache::zookeeper::server::ZooKeeperServer;
+
 namespace mesos {
 namespace internal {
 namespace tests {
 
-ZooKeeperTestServer::ZooKeeperTestServer(Jvm* _jvm)
-  : jvm(_jvm),
+ZooKeeperTestServer::ZooKeeperTestServer()
+  : zooKeeperServer(NULL),
+    connectionFactory(NULL),
     port(0),
     started(false)
 {
-  Jvm::Attach attach(jvm);
-
-  Jvm::JClass fileClass = Jvm::JClass::forName("java/io/File");
-  fileConstructor = new Jvm::JConstructor(
-      jvm->findConstructor(
-          fileClass
-          .constructor()
-          .parameter(jvm->stringClass)));
-
-  Jvm::JClass inetSocketAddressClass =
-      Jvm::JClass::forName("java/net/InetSocketAddress");
-  inetSocketAddressConstructor = new Jvm::JConstructor(
-      jvm->findConstructor(
-          inetSocketAddressClass
-          .constructor()
-          .parameter(jvm->intClass)));
-
-  Jvm::JClass cnxnFactoryClass =
-      Jvm::JClass::forName("org/apache/zookeeper/server/NIOServerCnxn$Factory");
-  cnxnFactoryConstructor = new Jvm::JConstructor(
-      jvm->findConstructor(
-          cnxnFactoryClass
-          .constructor()
-          .parameter(inetSocketAddressClass)));
-
-  Jvm::JClass zkServerClass =
-      Jvm::JClass::forName("org/apache/zookeeper/server/ZooKeeperServer");
-  startup = new Jvm::JMethod(
-      jvm->findMethod(
-          cnxnFactoryClass
-          .method("startup")
-          .parameter(zkServerClass)
-          .returns(jvm->voidClass)));
-
-  isAlive = new Jvm::JMethod(
-      jvm->findMethod(
-          cnxnFactoryClass
-          .method("isAlive")
-          .returns(jvm->booleanClass)));
-
-  shutdown = new Jvm::JMethod(
-      jvm->findMethod(
-          cnxnFactoryClass
-          .method("shutdown")
-          .returns(jvm->voidClass)));
-
-  dataDir = createTempDir();
-  snapDir = createTempDir();
-  Jvm::JClass snapLogClass =
-    Jvm::JClass::forName(
-        "org/apache/zookeeper/server/"
-        "persistence/FileTxnSnapLog");
-
-  snapLog = jvm->newGlobalRef(
-      jvm->invoke(
-          jvm->findConstructor(snapLogClass
-                               .constructor()
-                               .parameter(fileClass)
-                               .parameter(fileClass)),
-          dataDir->file,
-          snapDir->file));
-
-  dataTreeBuilder = jvm->newGlobalRef(
-      jvm->invoke(
-          jvm->findConstructor(
-              Jvm::JClass::forName(
-                  "org/apache/zookeeper/server/"
-                  "ZooKeeperServer$BasicDataTreeBuilder").constructor())));
-
-  Jvm::JClass dataTreeBuilderClass(
-      Jvm::JClass::forName("org/apache/zookeeper/server/"
-                           "ZooKeeperServer$DataTreeBuilder"));
-
-  zooKeeperServer = jvm->newGlobalRef(
-      jvm->invoke(
-          jvm->findConstructor(zkServerClass
-                               .constructor()
-                               .parameter(snapLogClass)
-                               .parameter(dataTreeBuilderClass)),
-          snapLog,
-          dataTreeBuilder));
-
-  getClientPort = new Jvm::JMethod(
-      jvm->findMethod(zkServerClass
-                      .method("getClientPort")
-                      .returns(jvm->intClass)));
-
-  closeSession = new Jvm::JMethod(
-      jvm->findMethod(zkServerClass
-                      .method("closeSession")
-                      .parameter(jvm->longClass)
-                      .returns(jvm->voidClass)));
-}
-
-
-const ZooKeeperTestServer::TemporaryDirectory* ZooKeeperTestServer::createTempDir()
-{
-  std::string tmpdir = "/tmp/zks-" + UUID::random().toString();
-  jobject file =
-    jvm->newGlobalRef(jvm->invoke(*fileConstructor, jvm->string(tmpdir)));
-  return new TemporaryDirectory(jvm, tmpdir, file);
+  // Create temporary directories for the FileTxnSnapLog.
+  Try<std::string> directory = os::mkdtemp();
+  CHECK_SOME(directory);
+  java::io::File dataDir(directory.get());
+  dataDir.deleteOnExit();
+
+  directory = os::mkdtemp();
+  CHECK_SOME(directory);
+  java::io::File snapDir(directory.get());
+  snapDir.deleteOnExit();
+
+  zooKeeperServer = new ZooKeeperServer(
+      FileTxnSnapLog(dataDir, snapDir),
+      ZooKeeperServer::BasicDataTreeBuilder());
 }
 
 
@@ -147,51 +65,30 @@ ZooKeeperTestServer::~ZooKeeperTestServer()
 {
   shutdownNetwork();
 
-  Jvm::Attach attach(jvm);
-
-  jvm->deleteGlobalRefSafe(inetSocketAddress);
-  jvm->deleteGlobalRefSafe(connectionFactory);
-  jvm->deleteGlobalRefSafe(snapLog);
-  jvm->deleteGlobalRefSafe(dataTreeBuilder);
-  jvm->deleteGlobalRefSafe(zooKeeperServer);
-
-  delete fileConstructor;
-  delete getClientPort;
-  delete closeSession;
-
-  delete inetSocketAddressConstructor;
-  delete cnxnFactoryConstructor;
-
-  delete startup;
-  delete isAlive;
-  delete shutdown;
-
-  delete dataDir;
-  delete snapDir;
+  delete zooKeeperServer;
+  delete connectionFactory;
 }
 
 
 void ZooKeeperTestServer::expireSession(int64_t sessionId)
 {
-  Jvm::Attach attach(jvm);
-
-  jvm->invoke<void>(zooKeeperServer, *closeSession, sessionId);
+  zooKeeperServer->closeSession(sessionId);
 }
 
 
 std::string ZooKeeperTestServer::connectString() const
 {
-  checkStarted();
+  CHECK(port > 0) << "Illegal state, must call startNetwork first!";
   return "127.0.0.1:" + stringify(port);
 }
 
 
 void ZooKeeperTestServer::shutdownNetwork()
 {
-  Jvm::Attach attach(jvm);
-
-  if (started && jvm->invoke<bool>(connectionFactory, *isAlive)) {
-    jvm->invoke<void>(connectionFactory, *shutdown);
+  if (started && connectionFactory->isAlive()) {
+    connectionFactory->shutdown();
+    delete connectionFactory;
+    connectionFactory = NULL;
     LOG(INFO) << "Shutdown ZooKeeperTestServer on port " << port << std::endl;
   }
 }
@@ -199,28 +96,24 @@ void ZooKeeperTestServer::shutdownNetwork()
 
 int ZooKeeperTestServer::startNetwork()
 {
-  Jvm::Attach attach(jvm);
+  connectionFactory = new NIOServerCnxn::Factory(
+      java::net::InetSocketAddress(port));
 
-  inetSocketAddress =
-      jvm->newGlobalRef(jvm->invoke(*inetSocketAddressConstructor, port));
-  connectionFactory =
-      jvm->newGlobalRef(
-          jvm->invoke(*cnxnFactoryConstructor, inetSocketAddress));
+  connectionFactory->startup(*zooKeeperServer);
+
+  if (port == 0) {
+    // We save the ephemeral port so if/when we restart the network
+    // the clients will reconnect to the same server. Note that this
+    // might not actually be kosher because it's possible that another
+    // process could bind to our ephemeral port after we unbind.
+    port = zooKeeperServer->getClientPort();
+  }
 
-  jvm->invoke<void>(connectionFactory, *startup, zooKeeperServer);
-  port = jvm->invoke<int>(zooKeeperServer, *getClientPort);
   LOG(INFO) << "Started ZooKeeperTestServer on port " << port;
   started = true;
   return port;
 }
 
-
-void ZooKeeperTestServer::checkStarted() const
-{
-  CHECK(port > 0) << "Illegal state, must call startNetwork first!";
-}
-
 } // namespace tests {
 } // namespace internal {
 } // namespace mesos {
-

http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test_server.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test_server.hpp b/src/tests/zookeeper_test_server.hpp
index bfa841c..97a8524 100644
--- a/src/tests/zookeeper_test_server.hpp
+++ b/src/tests/zookeeper_test_server.hpp
@@ -19,13 +19,13 @@
 #ifndef __ZOOKEEPER_TEST_SERVER_HPP__
 #define __ZOOKEEPER_TEST_SERVER_HPP__
 
-#include <jni.h>
+#include <string>
 
 #include <glog/logging.h>
 
-#include <stout/os.hpp>
+#include <jvm/org/apache/zookeeper.hpp>
 
-#include "jvm/jvm.hpp"
+#include <stout/os.hpp>
 
 #include "zookeeper/zookeeper.hpp"
 
@@ -40,7 +40,7 @@ namespace tests {
 class ZooKeeperTestServer
 {
 public:
-  ZooKeeperTestServer(Jvm* jvm);
+  ZooKeeperTestServer();
   ~ZooKeeperTestServer();
 
   // Gets a connection string that can be used to attach a ZooKeeper client to
@@ -67,54 +67,11 @@ public:
   void expireSession(int64_t sessionId);
 
 private:
-  // TODO(John Sirois): factor out TemporaryDirectory + createTempDir() to utils
-  struct TemporaryDirectory
-  {
-    Jvm* jvm;
-    const std::string path;
-    const jobject file;
-
-    TemporaryDirectory(Jvm* _jvm,
-                       const std::string& _path,
-                       const jobject _file) : jvm(_jvm),
-                                              path(_path),
-                                              file(_file) {}
-
-    ~TemporaryDirectory()
-    {
-      jvm->deleteGlobalRef(file);
-      Try<Nothing> rmdir = os::rmdir(path);
-      if (rmdir.isError()) {
-        LOG(WARNING) << "Failed to delete temp dir '"
-                     << path << "': " << rmdir.error();
-      }
-    }
-  };
-
-  Jvm* jvm;
-
-  Jvm::JConstructor* fileConstructor;
-  jobject snapLog;
-  jobject dataTreeBuilder;
-  jobject zooKeeperServer;
-  Jvm::JMethod* getClientPort;
-  Jvm::JMethod* closeSession;
-
-  Jvm::JConstructor* inetSocketAddressConstructor;
-  jobject inetSocketAddress;
-  Jvm::JConstructor* cnxnFactoryConstructor;
-  jobject connectionFactory;
-  Jvm::JMethod* startup;
-  Jvm::JMethod* isAlive;
-  Jvm::JMethod* shutdown;
+  org::apache::zookeeper::server::ZooKeeperServer* zooKeeperServer;
+  org::apache::zookeeper::server::NIOServerCnxn::Factory* connectionFactory;
 
   int port;
   bool started;
-  const TemporaryDirectory* dataDir;
-  const TemporaryDirectory* snapDir;
-
-  const TemporaryDirectory* createTempDir();
-  void checkStarted() const;
 };
 
 } // namespace tests {