You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2013/04/13 00:48:12 UTC

svn commit: r1467507 - in /incubator/mesos/trunk/src: Makefile.am tests/isolator.hpp tests/isolator_tests.cpp

Author: bmahler
Date: Fri Apr 12 22:48:11 2013
New Revision: 1467507

URL: http://svn.apache.org/r1467507
Log:
Added isolation module tests for resource usage.

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

Added:
    incubator/mesos/trunk/src/tests/isolator_tests.cpp
Modified:
    incubator/mesos/trunk/src/Makefile.am
    incubator/mesos/trunk/src/tests/isolator.hpp

Modified: incubator/mesos/trunk/src/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/Makefile.am?rev=1467507&r1=1467506&r2=1467507&view=diff
==============================================================================
--- incubator/mesos/trunk/src/Makefile.am (original)
+++ incubator/mesos/trunk/src/Makefile.am Fri Apr 12 22:48:11 2013
@@ -781,6 +781,7 @@ mesos_tests_SOURCES = tests/main.cpp tes
 	              tests/resource_offers_tests.cpp			\
 	              tests/fault_tolerance_tests.cpp			\
 	              tests/files_tests.cpp tests/flags_tests.cpp	\
+	              tests/isolator_tests.cpp				\
 	              tests/log_tests.cpp				\
 	              tests/monitor_tests.cpp				\
 	              tests/resources_tests.cpp				\

Modified: incubator/mesos/trunk/src/tests/isolator.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/isolator.hpp?rev=1467507&r1=1467506&r2=1467507&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/isolator.hpp (original)
+++ incubator/mesos/trunk/src/tests/isolator.hpp Fri Apr 12 22:48:11 2013
@@ -29,6 +29,9 @@
 #include <stout/try.hpp>
 #include <stout/uuid.hpp>
 
+#include "mesos/executor.hpp"
+#include "mesos/mesos.hpp"
+
 #include "slave/isolator.hpp"
 
 namespace mesos {

Added: incubator/mesos/trunk/src/tests/isolator_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/isolator_tests.cpp?rev=1467507&view=auto
==============================================================================
--- incubator/mesos/trunk/src/tests/isolator_tests.cpp (added)
+++ incubator/mesos/trunk/src/tests/isolator_tests.cpp Fri Apr 12 22:48:11 2013
@@ -0,0 +1,209 @@
+/**
+ * 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 <unistd.h>
+
+#include <gmock/gmock.h>
+
+#include <string>
+#include <vector>
+
+#include <process/future.hpp>
+
+#include <stout/os.hpp>
+#include <stout/path.hpp>
+
+#include "common/resources.hpp"
+
+#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"
+#ifdef __linux__
+#include "slave/cgroups_isolator.hpp"
+#endif
+#include "slave/process_isolator.hpp"
+#include "slave/slave.hpp"
+
+#include "tests/utils.hpp"
+
+using namespace mesos;
+using namespace mesos::internal;
+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__
+using mesos::internal::slave::CgroupsIsolator;
+#endif
+using mesos::internal::slave::Isolator;
+using mesos::internal::slave::ProcessIsolator;
+using mesos::internal::slave::Slave;
+
+using std::string;
+using std::vector;
+
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SaveArg;
+
+
+#ifdef __linux__
+typedef ::testing::Types<ProcessIsolator, CgroupsIsolator> IsolatorTypes;
+#else
+typedef ::testing::Types<ProcessIsolator> IsolatorTypes;
+#endif
+
+TYPED_TEST_CASE(IsolatorTest, IsolatorTypes);
+
+// TODO(bmahler): This test is disabled on OSX, until proc::children
+// is implemented for OSX.
+#ifdef __APPLE__
+TYPED_TEST(IsolatorTest, DISABLED_Usage)
+#else
+TYPED_TEST(IsolatorTest, Usage)
+#endif
+{
+  HierarchicalDRFAllocatorProcess allocator;
+  Allocator a(&allocator);
+  Files files;
+  Master m(&a, &files);
+  PID<Master> master = process::spawn(&m);
+
+  TypeParam isolator;
+  Slave s(this->slaveFlags, true, &isolator, &files);
+  PID<Slave> slave = process::spawn(&s);
+
+  BasicMasterDetector detector(master, slave, true);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+
+  Future<FrameworkID> frameworkId;
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .WillOnce(FutureArg<1>(&frameworkId));
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  Future<TaskStatus> status1, status2;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status1))
+    .WillOnce(FutureArg<1>(&status2));
+
+  driver.start();
+
+  AWAIT_UNTIL(frameworkId);
+  AWAIT_UNTIL(offers);
+
+  EXPECT_NE(0u, offers.get().size());
+
+  TaskInfo task;
+  task.set_name("isolator_test");
+  task.mutable_task_id()->set_value("1");
+  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");
+
+  // This task induces user/system load in a child process by
+  // running top in a child process for ten seconds.
+  task.mutable_command()->set_value(
+#ifdef __APPLE__
+      // Use logging mode with 30,000 samples with no interval.
+      "top -l 30000 -s 0 2>&1 > /dev/null & "
+#else
+      // Batch mode, with 30,000 samples with no interval.
+      "top -b -d 0 -n 30000 2>&1 > /dev/null & "
+#endif
+      "touch " + file +  "; " // Signals that the top command is running.
+      "sleep 60");
+
+  vector<TaskInfo> tasks;
+  tasks.push_back(task);
+
+  driver.launchTasks(offers.get()[0].id(), tasks);
+
+  AWAIT_UNTIL(status1);
+
+  EXPECT_EQ(TASK_RUNNING, status1.get().state());
+
+  // Wait for the task to begin inducing cpu time.
+  while (!os::exists(file));
+
+  ExecutorID executorId;
+  executorId.set_value(task.task_id().value());
+
+  // We'll wait up to 10 seconds for the child process to induce
+  // 1/8 of a second of user and system cpu time in total.
+  // TODO(bmahler): Also induce rss memory consumption, by re-using
+  // the balloon framework.
+  ResourceStatistics statistics;
+  Duration waited = Seconds(0);
+  do {
+    const Future<ResourceStatistics>& usage =
+      isolator.usage(frameworkId.get(), executorId);
+
+    ASSERT_FUTURE_WILL_SUCCEED(usage);
+
+    statistics = usage.get();
+
+    // If we meet our usage expectations, we're done!
+    if (statistics.memory_rss() >= 1024u &&
+        statistics.cpu_user_time() >= 0.125 &&
+        statistics.cpu_system_time() >= 0.125) {
+      break;
+    }
+
+    const Duration& sleep = Milliseconds(100);
+    usleep((useconds_t) sleep.us());
+    waited = Seconds(waited.secs() + sleep.secs());
+  } 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);
+
+  driver.killTask(task.task_id());
+
+  AWAIT_FOR(status2, Seconds(5));
+
+  // 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());
+
+  driver.stop();
+  driver.join();
+
+  process::terminate(slave);
+  process::wait(slave);
+
+  process::terminate(master);
+  process::wait(master);
+}