You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2015/07/25 01:38:05 UTC
[12/12] mesos git commit: Moved containerizer related tests under
src/tests/containerizer.
Moved containerizer related tests under src/tests/containerizer.
Review: https://reviews.apache.org/r/36801
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/96351372
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/96351372
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/96351372
Branch: refs/heads/master
Commit: 963513722ecf121cc9ec8c1d4b63922398fc0658
Parents: 50696fa
Author: Jie Yu <yu...@gmail.com>
Authored: Fri Jul 24 15:42:43 2015 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Jul 24 16:37:23 2015 -0700
----------------------------------------------------------------------
src/Makefile.am | 174 +-
src/tests/cgroups_isolator_tests.cpp | 46 -
src/tests/cgroups_tests.cpp | 1234 --------
src/tests/composing_containerizer_tests.cpp | 171 -
.../containerizer/cgroups_isolator_tests.cpp | 46 +
src/tests/containerizer/cgroups_tests.cpp | 1235 ++++++++
.../composing_containerizer_tests.cpp | 171 +
src/tests/containerizer/containerizer_tests.cpp | 732 +++++
.../docker_containerizer_tests.cpp | 2955 ++++++++++++++++++
src/tests/containerizer/docker_tests.cpp | 421 +++
.../external_containerizer_test.cpp | 267 ++
src/tests/containerizer/fs_tests.cpp | 170 +
src/tests/containerizer/isolator.hpp | 101 +
src/tests/containerizer/isolator_tests.cpp | 1317 ++++++++
src/tests/containerizer/launch_tests.cpp | 238 ++
src/tests/containerizer/launcher.hpp | 119 +
.../containerizer/memory_pressure_tests.cpp | 293 ++
src/tests/containerizer/memory_test_helper.cpp | 321 ++
src/tests/containerizer/memory_test_helper.hpp | 89 +
.../containerizer/memory_test_helper_main.cpp | 32 +
src/tests/containerizer/ns_tests.cpp | 302 ++
src/tests/containerizer/perf_tests.cpp | 183 ++
src/tests/containerizer/port_mapping_tests.cpp | 2296 ++++++++++++++
src/tests/containerizer/routing_tests.cpp | 1416 +++++++++
src/tests/containerizer/sched_tests.cpp | 96 +
src/tests/containerizer/setns_test_helper.cpp | 63 +
src/tests/containerizer/setns_test_helper.hpp | 35 +
.../containerizer/setns_test_helper_main.cpp | 30 +
src/tests/containerizer_tests.cpp | 731 -----
src/tests/docker_containerizer_tests.cpp | 2955 ------------------
src/tests/docker_tests.cpp | 421 ---
src/tests/external_containerizer_test.cpp | 266 --
src/tests/fs_tests.cpp | 170 -
src/tests/isolator.hpp | 101 -
src/tests/isolator_tests.cpp | 1316 --------
src/tests/launch_tests.cpp | 238 --
src/tests/launcher.hpp | 119 -
src/tests/memory_pressure_tests.cpp | 293 --
src/tests/memory_test_helper.cpp | 320 --
src/tests/memory_test_helper.hpp | 89 -
src/tests/memory_test_helper_main.cpp | 32 -
src/tests/ns_tests.cpp | 301 --
src/tests/perf_tests.cpp | 183 --
src/tests/port_mapping_tests.cpp | 2296 --------------
src/tests/routing_tests.cpp | 1416 ---------
src/tests/sched_tests.cpp | 96 -
src/tests/setns_test_helper.cpp | 63 -
src/tests/setns_test_helper.hpp | 35 -
src/tests/setns_test_helper_main.cpp | 30 -
49 files changed, 13015 insertions(+), 13009 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/96351372/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 93a6a7a..a7104bb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -658,17 +658,17 @@ libmesos_no_3rdparty_la_SOURCES += \
tests/containerizer.hpp \
tests/environment.hpp \
tests/flags.hpp \
- tests/isolator.hpp \
- tests/launcher.hpp \
tests/limiter.hpp \
- tests/memory_test_helper.hpp \
tests/mesos.hpp \
tests/module.hpp \
tests/script.hpp \
- tests/setns_test_helper.hpp \
tests/utils.hpp \
tests/zookeeper.hpp \
tests/zookeeper_test_server.hpp \
+ tests/containerizer/isolator.hpp \
+ tests/containerizer/launcher.hpp \
+ tests/containerizer/memory_test_helper.hpp \
+ tests/containerizer/setns_test_helper.hpp \
usage/usage.hpp \
watcher/whitelist_watcher.hpp \
zookeeper/authentication.hpp \
@@ -1383,8 +1383,8 @@ persistent_volume_framework_LDADD = libmesos.la $(LDADD)
if OS_LINUX
check_PROGRAMS += setns-test-helper
setns_test_helper_SOURCES = \
- tests/setns_test_helper_main.cpp \
- tests/setns_test_helper.cpp
+ tests/containerizer/setns_test_helper_main.cpp \
+ tests/containerizer/setns_test_helper.cpp
setns_test_helper_CPPFLAGS = $(MESOS_CPPFLAGS)
setns_test_helper_LDADD = libmesos.la $(LDADD)
@@ -1393,8 +1393,8 @@ endif
check_PROGRAMS += memory-test-helper
memory_test_helper_SOURCES = \
tests/flags.cpp \
- tests/memory_test_helper_main.cpp \
- tests/memory_test_helper.cpp
+ tests/containerizer/memory_test_helper_main.cpp \
+ tests/containerizer/memory_test_helper.cpp
memory_test_helper_CPPFLAGS = $(mesos_tests_CPPFLAGS)
memory_test_helper_LDADD = libmesos.la $(LDADD)
@@ -1474,74 +1474,74 @@ libtestqos_controller_la_SOURCES = \
libtestqos_controller_la_CPPFLAGS = $(MESOS_CPPFLAGS)
libtestqos_controller_la_LDFLAGS = $(MESOS_TEST_MODULE_LDFLAGS)
-mesos_tests_SOURCES = \
- tests/anonymous_tests.cpp \
- tests/attributes_tests.cpp \
- tests/authentication_tests.cpp \
- tests/authorization_tests.cpp \
- tests/common/http_tests.cpp \
- tests/composing_containerizer_tests.cpp \
- tests/containerizer.cpp \
- tests/containerizer_tests.cpp \
- tests/cram_md5_authentication_tests.cpp \
- tests/credentials_tests.cpp \
- tests/disk_quota_tests.cpp \
- tests/docker_containerizer_tests.cpp \
- tests/docker_tests.cpp \
- tests/environment.cpp \
- tests/examples_tests.cpp \
- tests/exception_tests.cpp \
- tests/external_containerizer_test.cpp \
- tests/health_check_tests.cpp \
- tests/fault_tolerance_tests.cpp \
- tests/fetcher_cache_tests.cpp \
- tests/fetcher_tests.cpp \
- tests/files_tests.cpp \
- tests/flags.cpp \
- tests/gc_tests.cpp \
- tests/hierarchical_allocator_tests.cpp \
- tests/hook_tests.cpp \
- tests/http_api_tests.cpp \
- tests/isolator_tests.cpp \
- tests/log_tests.cpp \
- tests/logging_tests.cpp \
- tests/main.cpp \
- tests/master_allocator_tests.cpp \
- tests/master_authorization_tests.cpp \
- tests/master_contender_detector_tests.cpp \
- tests/master_slave_reconciliation_tests.cpp \
- tests/master_tests.cpp \
- tests/master_validation_tests.cpp \
- tests/memory_test_helper.cpp \
- tests/mesos.cpp \
- tests/metrics_tests.cpp \
- tests/module.cpp \
- tests/module_tests.cpp \
- tests/monitor_tests.cpp \
- tests/oversubscription_tests.cpp \
- tests/partition_tests.cpp \
- tests/paths_tests.cpp \
- tests/persistent_volume_tests.cpp \
- tests/protobuf_io_tests.cpp \
- tests/rate_limiting_tests.cpp \
- tests/reconciliation_tests.cpp \
- tests/registrar_tests.cpp \
- tests/repair_tests.cpp \
- tests/reservation_tests.cpp \
- tests/resource_offers_tests.cpp \
- tests/resources_tests.cpp \
- tests/scheduler_tests.cpp \
- tests/scheduler_event_call_tests.cpp \
- tests/script.cpp \
- tests/slave_recovery_tests.cpp \
- tests/slave_tests.cpp \
- tests/sorter_tests.cpp \
- tests/state_tests.cpp \
- tests/status_update_manager_tests.cpp \
- tests/teardown_tests.cpp \
- tests/utils.cpp \
- tests/values_tests.cpp \
- tests/zookeeper_url_tests.cpp
+mesos_tests_SOURCES = \
+ tests/anonymous_tests.cpp \
+ tests/attributes_tests.cpp \
+ tests/authentication_tests.cpp \
+ tests/authorization_tests.cpp \
+ tests/containerizer.cpp \
+ tests/cram_md5_authentication_tests.cpp \
+ tests/credentials_tests.cpp \
+ tests/disk_quota_tests.cpp \
+ tests/environment.cpp \
+ tests/examples_tests.cpp \
+ tests/exception_tests.cpp \
+ tests/health_check_tests.cpp \
+ tests/fault_tolerance_tests.cpp \
+ tests/fetcher_cache_tests.cpp \
+ tests/fetcher_tests.cpp \
+ tests/files_tests.cpp \
+ tests/flags.cpp \
+ tests/gc_tests.cpp \
+ tests/hierarchical_allocator_tests.cpp \
+ tests/hook_tests.cpp \
+ tests/http_api_tests.cpp \
+ tests/log_tests.cpp \
+ tests/logging_tests.cpp \
+ tests/main.cpp \
+ tests/master_allocator_tests.cpp \
+ tests/master_authorization_tests.cpp \
+ tests/master_contender_detector_tests.cpp \
+ tests/master_slave_reconciliation_tests.cpp \
+ tests/master_tests.cpp \
+ tests/master_validation_tests.cpp \
+ tests/mesos.cpp \
+ tests/metrics_tests.cpp \
+ tests/module.cpp \
+ tests/module_tests.cpp \
+ tests/monitor_tests.cpp \
+ tests/oversubscription_tests.cpp \
+ tests/partition_tests.cpp \
+ tests/paths_tests.cpp \
+ tests/persistent_volume_tests.cpp \
+ tests/protobuf_io_tests.cpp \
+ tests/rate_limiting_tests.cpp \
+ tests/reconciliation_tests.cpp \
+ tests/registrar_tests.cpp \
+ tests/repair_tests.cpp \
+ tests/reservation_tests.cpp \
+ tests/resource_offers_tests.cpp \
+ tests/resources_tests.cpp \
+ tests/scheduler_tests.cpp \
+ tests/scheduler_event_call_tests.cpp \
+ tests/script.cpp \
+ tests/slave_recovery_tests.cpp \
+ tests/slave_tests.cpp \
+ tests/sorter_tests.cpp \
+ tests/state_tests.cpp \
+ tests/status_update_manager_tests.cpp \
+ tests/teardown_tests.cpp \
+ tests/utils.cpp \
+ tests/values_tests.cpp \
+ tests/zookeeper_url_tests.cpp \
+ tests/common/http_tests.cpp \
+ tests/containerizer/composing_containerizer_tests.cpp \
+ tests/containerizer/containerizer_tests.cpp \
+ tests/containerizer/docker_containerizer_tests.cpp \
+ tests/containerizer/docker_tests.cpp \
+ tests/containerizer/external_containerizer_test.cpp \
+ tests/containerizer/isolator_tests.cpp \
+ tests/containerizer/memory_test_helper.cpp
mesos_tests_CPPFLAGS = $(MESOS_CPPFLAGS)
mesos_tests_CPPFLAGS += -DSOURCE_DIR=\"$(abs_top_srcdir)\"
@@ -1554,20 +1554,20 @@ mesos_tests_LDADD = ../$(LIBPROCESS)/3rdparty/libgmock.la libmesos.la -ldl $(LDA
mesos_tests_DEPENDENCIES = # Initialized to allow += below.
if OS_LINUX
- mesos_tests_SOURCES += tests/cgroups_isolator_tests.cpp
- mesos_tests_SOURCES += tests/cgroups_tests.cpp
- mesos_tests_SOURCES += tests/fs_tests.cpp
- mesos_tests_SOURCES += tests/launch_tests.cpp
- mesos_tests_SOURCES += tests/memory_pressure_tests.cpp
- mesos_tests_SOURCES += tests/ns_tests.cpp
- mesos_tests_SOURCES += tests/perf_tests.cpp
- mesos_tests_SOURCES += tests/sched_tests.cpp
- mesos_tests_SOURCES += tests/setns_test_helper.cpp
+ mesos_tests_SOURCES += tests/containerizer/cgroups_isolator_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/cgroups_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/fs_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/launch_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/memory_pressure_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/ns_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/perf_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/sched_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/setns_test_helper.cpp
endif
if WITH_NETWORK_ISOLATOR
- mesos_tests_SOURCES += tests/routing_tests.cpp
- mesos_tests_SOURCES += tests/port_mapping_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/routing_tests.cpp
+ mesos_tests_SOURCES += tests/containerizer/port_mapping_tests.cpp
endif
if HAS_JAVA
http://git-wip-us.apache.org/repos/asf/mesos/blob/96351372/src/tests/cgroups_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/cgroups_isolator_tests.cpp b/src/tests/cgroups_isolator_tests.cpp
deleted file mode 100644
index a4ccc8e..0000000
--- a/src/tests/cgroups_isolator_tests.cpp
+++ /dev/null
@@ -1,46 +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 <map>
-#include <utility>
-
-#include <gtest/gtest.h>
-
-#include <stout/foreach.hpp>
-#include <stout/proc.hpp>
-#include <stout/stringify.hpp>
-
-#include "slave/containerizer/mesos/containerizer.hpp"
-
-#include "tests/script.hpp"
-
-using std::map;
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-
-// Run the balloon framework under a mesos containerizer.
-TEST_SCRIPT(ContainerizerTest,
- ROOT_CGROUPS_BalloonFramework,
- "balloon_framework_test.sh")
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/96351372/src/tests/cgroups_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/cgroups_tests.cpp b/src/tests/cgroups_tests.cpp
deleted file mode 100644
index b63d956..0000000
--- a/src/tests/cgroups_tests.cpp
+++ /dev/null
@@ -1,1234 +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 <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <gmock/gmock.h>
-
-#include <process/gtest.hpp>
-#include <process/owned.hpp>
-
-#include <stout/gtest.hpp>
-#include <stout/hashmap.hpp>
-#include <stout/numify.hpp>
-#include <stout/option.hpp>
-#include <stout/os.hpp>
-#include <stout/path.hpp>
-#include <stout/proc.hpp>
-#include <stout/stringify.hpp>
-#include <stout/strings.hpp>
-
-#include "linux/cgroups.hpp"
-#include "linux/perf.hpp"
-
-#include "tests/memory_test_helper.hpp"
-#include "tests/mesos.hpp" // For TEST_CGROUPS_(HIERARCHY|ROOT).
-#include "tests/utils.hpp"
-
-using namespace process;
-
-using cgroups::memory::pressure::Level;
-using cgroups::memory::pressure::Counter;
-
-using std::set;
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-
-class CgroupsTest : public TemporaryDirectoryTest
-{
-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));
- }
-};
-
-
-// A fixture which is used to name tests that expect NO hierarchy to
-// exist in order to test the ability to create a hierarchy (since
-// most likely existing hierarchies will have all or most subsystems
-// attached rendering our ability to create a hierarchy fruitless).
-class CgroupsNoHierarchyTest : public CgroupsTest
-{
-public:
- static void SetUpTestCase()
- {
- CgroupsTest::SetUpTestCase();
-
- Try<std::set<std::string> > hierarchies = cgroups::hierarchies();
- ASSERT_SOME(hierarchies);
- 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"
- << "-------------------------------------------------------------";
- }
-};
-
-
-// A fixture that assumes ANY hierarchy is acceptable for use provided
-// it has the subsystems attached that were specified in the
-// constructor. If no hierarchy could be found that has all the
-// required subsystems then we attempt to create a new hierarchy.
-class CgroupsAnyHierarchyTest : public CgroupsTest
-{
-public:
- CgroupsAnyHierarchyTest(const std::string& _subsystems = "cpu")
- : subsystems(_subsystems) {}
-
-protected:
- virtual void SetUp()
- {
- CgroupsTest::SetUp();
-
- foreach (const std::string& subsystem, strings::tokenize(subsystems, ",")) {
- // Establish the base hierarchy if this is the first subsystem checked.
- if (baseHierarchy.empty()) {
- Result<std::string> hierarchy = cgroups::hierarchy(subsystem);
- ASSERT_FALSE(hierarchy.isError());
-
- if (hierarchy.isNone()) {
- baseHierarchy = TEST_CGROUPS_HIERARCHY;
- } else {
- // Strip the subsystem to get the base hierarchy.
- Try<std::string> baseDirname = Path(hierarchy.get()).dirname();
- ASSERT_SOME(baseDirname);
- baseHierarchy = baseDirname.get();
- }
- }
-
- // Mount the subsystem if necessary.
- std::string hierarchy = path::join(baseHierarchy, subsystem);
- Try<bool> mounted = cgroups::mounted(hierarchy, subsystem);
- ASSERT_SOME(mounted);
- if (!mounted.get()) {
- ASSERT_SOME(cgroups::mount(hierarchy, subsystem))
- << "-------------------------------------------------------------\n"
- << "We cannot run any cgroups tests that require\n"
- << "a hierarchy with subsystem '" << subsystem << "'\n"
- << "because we failed to find an existing hierarchy\n"
- << "or create a new one (tried '" << hierarchy << "').\n"
- << "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"
- << "-------------------------------------------------------------";
- }
-
- Try<std::vector<std::string> > cgroups = cgroups::get(hierarchy);
- CHECK_SOME(cgroups);
-
- foreach (const std::string& cgroup, cgroups.get()) {
- // Remove any cgroups that start with TEST_CGROUPS_ROOT.
- if (cgroup == TEST_CGROUPS_ROOT) {
- AWAIT_READY(cgroups::destroy(hierarchy, cgroup));
- }
- }
- }
- }
-
- virtual void TearDown()
- {
- // Remove all *our* cgroups.
- foreach (const std::string& subsystem, strings::tokenize(subsystems, ",")) {
- std::string hierarchy = path::join(baseHierarchy, subsystem);
-
- Try<std::vector<std::string> > cgroups = cgroups::get(hierarchy);
- CHECK_SOME(cgroups);
-
- foreach (const std::string& cgroup, cgroups.get()) {
- // Remove any cgroups that start with TEST_CGROUPS_ROOT.
- if (cgroup == TEST_CGROUPS_ROOT) {
- AWAIT_READY(cgroups::destroy(hierarchy, cgroup));
- }
- }
- }
-
- CgroupsTest::TearDown();
- }
-
- const std::string subsystems; // Subsystems required to run tests.
- std::string baseHierarchy; // Path to the hierarchy being used.
-};
-
-
-class CgroupsAnyHierarchyWithCpuMemoryTest
- : public CgroupsAnyHierarchyTest
-{
-public:
- CgroupsAnyHierarchyWithCpuMemoryTest()
- : CgroupsAnyHierarchyTest("cpu,memory") {}
-};
-
-
-class CgroupsAnyHierarchyWithFreezerTest
- : public CgroupsAnyHierarchyTest
-{
-public:
- CgroupsAnyHierarchyWithFreezerTest()
- : CgroupsAnyHierarchyTest("freezer") {}
-};
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Enabled)
-{
- EXPECT_SOME_TRUE(cgroups::enabled(""));
- EXPECT_SOME_TRUE(cgroups::enabled(","));
- EXPECT_SOME_TRUE(cgroups::enabled("cpu"));
- EXPECT_SOME_TRUE(cgroups::enabled(",cpu"));
- EXPECT_SOME_TRUE(cgroups::enabled("cpu,memory"));
- EXPECT_SOME_TRUE(cgroups::enabled("cpu,memory,"));
- EXPECT_ERROR(cgroups::enabled("invalid"));
- EXPECT_ERROR(cgroups::enabled("cpu,invalid"));
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_Busy)
-{
- EXPECT_SOME_FALSE(cgroups::busy(""));
- EXPECT_SOME_FALSE(cgroups::busy(","));
- EXPECT_SOME_TRUE(cgroups::busy("cpu"));
- EXPECT_SOME_TRUE(cgroups::busy(",cpu"));
- EXPECT_SOME_TRUE(cgroups::busy("cpu,memory"));
- EXPECT_SOME_TRUE(cgroups::busy("cpu,memory,"));
- EXPECT_ERROR(cgroups::busy("invalid"));
- EXPECT_ERROR(cgroups::busy("cpu,invalid"));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Subsystems)
-{
- Try<std::set<std::string> > names = cgroups::subsystems();
- ASSERT_SOME(names);
-
- Option<std::string> cpu;
- Option<std::string> memory;
- foreach (const std::string& name, names.get()) {
- if (name == "cpu") {
- cpu = name;
- } else if (name == "memory") {
- memory = name;
- }
- }
-
- EXPECT_SOME(cpu);
- EXPECT_SOME(memory);
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_SubsystemsHierarchy)
-{
- std::string cpuHierarchy = path::join(baseHierarchy, "cpu");
-
- Try<std::set<std::string> > names = cgroups::subsystems(cpuHierarchy);
- ASSERT_SOME(names);
-
- Option<std::string> cpu;
- Option<std::string> memory;
- foreach (const std::string& name, names.get()) {
- if (name == "cpu") {
- cpu = name;
- } else if (name == "memory") {
- memory = name;
- }
- }
-
- EXPECT_SOME(cpu);
- EXPECT_NONE(memory);
-
- std::string memoryHierarchy = path::join(baseHierarchy, "memory");
- names = cgroups::subsystems(memoryHierarchy);
- ASSERT_SOME(names);
-
- cpu = None();
- memory = None();
- foreach (const std::string& name, names.get()) {
- if (name == "cpu") {
- cpu = name;
- } else if (name == "memory") {
- memory = name;
- }
- }
- EXPECT_NONE(cpu);
- EXPECT_SOME(memory);
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_FindCgroupSubsystems)
-{
- pid_t pid = ::getpid();
- Result<std::string> cpuHierarchy = cgroups::cpu::cgroup(pid);
- EXPECT_FALSE(cpuHierarchy.isError());
- EXPECT_SOME(cpuHierarchy);
-
- Result<std::string> memHierarchy = cgroups::memory::cgroup(pid);
- EXPECT_FALSE(memHierarchy.isError());
- EXPECT_SOME(memHierarchy);
-}
-
-
-TEST_F(CgroupsNoHierarchyTest, ROOT_CGROUPS_NOHIERARCHY_MountUnmountHierarchy)
-{
- EXPECT_ERROR(cgroups::mount("/tmp", "cpu"));
- EXPECT_ERROR(cgroups::mount(TEST_CGROUPS_HIERARCHY, "invalid"));
-
- // Try to mount a valid hierarchy, retrying as necessary since the
- // previous unmount might not have taken effect yet due to a bug in
- // Ubuntu 12.04.
- ASSERT_SOME(cgroups::mount(TEST_CGROUPS_HIERARCHY, "cpu,memory", 10));
- EXPECT_ERROR(cgroups::mount(TEST_CGROUPS_HIERARCHY, "cpuset"));
- EXPECT_ERROR(cgroups::unmount("/tmp"));
- ASSERT_SOME(cgroups::unmount(TEST_CGROUPS_HIERARCHY));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Mounted)
-{
- EXPECT_SOME_FALSE(cgroups::mounted("/tmp-nonexist"));
- EXPECT_SOME_FALSE(cgroups::mounted("/tmp"));
- EXPECT_SOME_FALSE(cgroups::mounted(baseHierarchy + "/not_expected"));
- EXPECT_SOME_TRUE(cgroups::mounted(baseHierarchy + "/cpu"));
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_MountedSubsystems)
-{
- EXPECT_SOME_FALSE(cgroups::mounted("/tmp-nonexist", "cpu"));
- EXPECT_SOME_FALSE(cgroups::mounted("/tmp", "cpu,memory"));
- EXPECT_SOME_FALSE(cgroups::mounted("/tmp", "cpu"));
- EXPECT_SOME_FALSE(cgroups::mounted("/tmp", "invalid"));
- EXPECT_SOME_TRUE(cgroups::mounted(path::join(baseHierarchy, "cpu"), "cpu"));
- EXPECT_SOME_TRUE(cgroups::mounted(
- path::join(baseHierarchy, "memory"), "memory"));
- EXPECT_SOME_FALSE(cgroups::mounted(baseHierarchy, "invalid"));
- EXPECT_SOME_FALSE(cgroups::mounted(baseHierarchy + "/not_expected", "cpu"));
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_CreateRemove)
-{
- EXPECT_ERROR(cgroups::create("/tmp", "test"));
- EXPECT_ERROR(cgroups::create(baseHierarchy, "mesos_test_missing/1"));
- ASSERT_SOME(cgroups::create(
- path::join(baseHierarchy, "cpu"), "mesos_test_missing"));
- EXPECT_ERROR(cgroups::remove(baseHierarchy, "invalid"));
- ASSERT_SOME(cgroups::remove(
- path::join(baseHierarchy, "cpu"), "mesos_test_missing"));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Get)
-{
- std::string hierarchy = path::join(baseHierarchy, "cpu");
-
- ASSERT_SOME(cgroups::create(hierarchy, "mesos_test1"));
- ASSERT_SOME(cgroups::create(hierarchy, "mesos_test2"));
-
- Try<std::vector<std::string>> cgroups = cgroups::get(hierarchy);
- ASSERT_SOME(cgroups);
-
- EXPECT_NE(cgroups.get().end(),
- find(cgroups.get().begin(), cgroups.get().end(), "mesos_test2"));
- EXPECT_NE(cgroups.get().end(),
- find(cgroups.get().begin(), cgroups.get().end(), "mesos_test1"));
-
- ASSERT_SOME(cgroups::remove(hierarchy, "mesos_test1"));
- ASSERT_SOME(cgroups::remove(hierarchy, "mesos_test2"));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_NestedCgroups)
-{
- std::string hierarchy = path::join(baseHierarchy, "cpu");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
- std::string cgroup1 = path::join(TEST_CGROUPS_ROOT, "1");
- std::string cgroup2 = path::join(TEST_CGROUPS_ROOT, "2");
-
- ASSERT_SOME(cgroups::create(hierarchy, cgroup1))
- << "-------------------------------------------------------------\n"
- << "We cannot run this test because it appears you do not have\n"
- << "a modern enough version of the Linux kernel. You won't be\n"
- << "able to use the cgroups isolator, but feel free to disable\n"
- << "this test.\n"
- << "-------------------------------------------------------------";
-
- ASSERT_SOME(cgroups::create(hierarchy, cgroup2));
-
- Try<std::vector<std::string>> cgroups =
- cgroups::get(hierarchy, TEST_CGROUPS_ROOT);
- ASSERT_SOME(cgroups);
-
- ASSERT_EQ(2u, cgroups.get().size());
-
- EXPECT_NE(cgroups.get().end(),
- find(cgroups.get().begin(), cgroups.get().end(), cgroup2));
- EXPECT_NE(cgroups.get().end(),
- find(cgroups.get().begin(), cgroups.get().end(), cgroup1));
-
- ASSERT_SOME(cgroups::remove(hierarchy, cgroup1));
- ASSERT_SOME(cgroups::remove(hierarchy, cgroup2));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Tasks)
-{
- pid_t pid = ::getpid();
-
- Result<std::string> cgroup = cgroups::cpu::cgroup(pid);
- ASSERT_SOME(cgroup);
-
- std::string hierarchy = path::join(baseHierarchy, "cpu");
-
- Try<std::set<pid_t>> pids = cgroups::processes(hierarchy, cgroup.get());
- ASSERT_SOME(pids);
-
- EXPECT_NE(0u, pids.get().count(pid));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Read)
-{
- std::string hierarchy = path::join(baseHierarchy, "cpu");
-
- EXPECT_ERROR(cgroups::read(hierarchy, TEST_CGROUPS_ROOT, "invalid42"));
-
- pid_t pid = ::getpid();
-
- Result<std::string> cgroup = cgroups::cpu::cgroup(pid);
- ASSERT_SOME(cgroup);
-
- Try<std::string> read = cgroups::read(hierarchy, cgroup.get(), "tasks");
- ASSERT_SOME(read);
-
- EXPECT_TRUE(strings::contains(read.get(), stringify(pid)));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Write)
-{
- std::string hierarchy = path::join(baseHierarchy, "cpu");
- EXPECT_ERROR(
- cgroups::write(hierarchy, TEST_CGROUPS_ROOT, "invalid", "invalid"));
-
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- pid_t pid = ::fork();
- ASSERT_NE(-1, pid);
-
- if (pid == 0) {
- // In child process, wait for kill signal.
- while (true) { sleep(1); }
-
- // Should not reach here.
- const char* message = "Error, child should be killed before reaching here";
- while (write(STDERR_FILENO, message, strlen(message)) == -1 &&
- errno == EINTR);
-
- _exit(1);
- }
-
- // In parent process.
- ASSERT_SOME(
- cgroups::write(hierarchy,
- TEST_CGROUPS_ROOT,
- "cgroup.procs",
- stringify(pid)));
-
- Try<std::set<pid_t> > pids = cgroups::processes(hierarchy, TEST_CGROUPS_ROOT);
- ASSERT_SOME(pids);
-
- EXPECT_NE(0u, pids.get().count(pid));
-
- // Kill the child process.
- ASSERT_NE(-1, ::kill(pid, SIGKILL));
-
- // Wait for the child process.
- int status;
- EXPECT_NE(-1, ::waitpid((pid_t) -1, &status, 0));
- ASSERT_TRUE(WIFSIGNALED(status));
- EXPECT_EQ(SIGKILL, WTERMSIG(status));
-}
-
-
-TEST_F(CgroupsAnyHierarchyTest, ROOT_CGROUPS_Cfs_Big_Quota)
-{
- std::string hierarchy = path::join(baseHierarchy, "cpu");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- Duration quota = Seconds(100); // Big quota.
- ASSERT_SOME(cgroups::cpu::cfs_quota_us(hierarchy, TEST_CGROUPS_ROOT, quota));
-
- // Ensure we can read back the correct quota.
- ASSERT_SOME_EQ(
- quota,
- cgroups::cpu::cfs_quota_us(hierarchy, TEST_CGROUPS_ROOT));
-}
-
-
-class CgroupsAnyHierarchyWithCpuAcctMemoryTest
- : public CgroupsAnyHierarchyTest
-{
-public:
- CgroupsAnyHierarchyWithCpuAcctMemoryTest()
- : CgroupsAnyHierarchyTest("cpuacct,memory") {}
-};
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuAcctMemoryTest, ROOT_CGROUPS_Stat)
-{
- EXPECT_ERROR(cgroups::stat(baseHierarchy, TEST_CGROUPS_ROOT, "invalid"));
-
- Try<hashmap<std::string, uint64_t> > result =
- cgroups::stat(
- path::join(baseHierarchy, "cpuacct"), "/", "cpuacct.stat");
- ASSERT_SOME(result);
- EXPECT_TRUE(result.get().contains("user"));
- EXPECT_TRUE(result.get().contains("system"));
- EXPECT_GT(result.get().get("user").get(), 0llu);
- EXPECT_GT(result.get().get("system").get(), 0llu);
-
- result = cgroups::stat(
- path::join(baseHierarchy, "memory"), "/", "memory.stat");
- ASSERT_SOME(result);
- EXPECT_TRUE(result.get().contains("rss"));
- EXPECT_GT(result.get().get("rss").get(), 0llu);
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_Listen)
-{
- std::string hierarchy = path::join(baseHierarchy, "memory");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
- ASSERT_SOME(
- cgroups::memory::oom::killer::enabled(hierarchy, TEST_CGROUPS_ROOT))
- << "-------------------------------------------------------------\n"
- << "We cannot run this test because it appears you do not have\n"
- << "a modern enough version of the Linux kernel. You won't be\n"
- << "able to use the cgroups isolator, but feel free to disable\n"
- << "this test.\n"
- << "-------------------------------------------------------------";
-
- const Bytes limit = Megabytes(64);
-
- ASSERT_SOME(cgroups::memory::limit_in_bytes(
- hierarchy, TEST_CGROUPS_ROOT, limit));
-
- // Listen on oom events for test cgroup.
- Future<Nothing> future =
- cgroups::memory::oom::listen(hierarchy, TEST_CGROUPS_ROOT);
-
- ASSERT_FALSE(future.isFailed());
-
- // Test the cancellation.
- future.discard();
-
- // Test the normal operation below.
- future = cgroups::memory::oom::listen(hierarchy, TEST_CGROUPS_ROOT);
- ASSERT_FALSE(future.isFailed());
-
- MemoryTestHelper helper;
- ASSERT_SOME(helper.spawn());
- ASSERT_SOME(helper.pid());
-
- EXPECT_SOME(cgroups::assign(
- hierarchy, TEST_CGROUPS_ROOT, helper.pid().get()));
-
- // Request more RSS memory in the subprocess than the limit.
- // NOTE: We enable the kernel oom killer in this test. If it were
- // disabled, the subprocess might hang and the following call won't
- // return. By enabling the oom killer, we let the subprocess get
- // killed and expect that an error is returned.
- EXPECT_ERROR(helper.increaseRSS(limit * 2));
-
- AWAIT_READY(future);
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithFreezerTest, ROOT_CGROUPS_Freeze)
-{
- int pipes[2];
- int dummy;
- ASSERT_NE(-1, ::pipe(pipes));
-
- std::string hierarchy = path::join(baseHierarchy, "freezer");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- pid_t pid = ::fork();
- ASSERT_NE(-1, pid);
-
- if (pid == 0) {
- // In child process.
- ::close(pipes[0]);
-
- // Put self into the test cgroup.
- Try<Nothing> assign =
- cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, ::getpid());
-
- if (assign.isError()) {
- std::cerr << "Failed to assign cgroup: " << assign.error() << std::endl;
- abort();
- }
-
- // Notify the parent.
- if (::write(pipes[1], &dummy, sizeof(dummy)) != sizeof(dummy)) {
- perror("Failed to notify the parent");
- abort();
- }
- ::close(pipes[1]);
-
- // Infinite loop here.
- while (true);
-
- // Should not reach here.
- std::cerr << "Reach an unreachable statement!" << std::endl;
- abort();
- }
-
- // In parent process.
- ::close(pipes[1]);
-
- // Wait until child has assigned the cgroup.
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ::close(pipes[0]);
-
- // Freeze the test cgroup.
- AWAIT_EXPECT_READY(cgroups::freezer::freeze(hierarchy, TEST_CGROUPS_ROOT));
-
- // Thaw the test cgroup.
- AWAIT_EXPECT_READY(cgroups::freezer::thaw(hierarchy, TEST_CGROUPS_ROOT));
-
- // Kill the child process.
- ASSERT_NE(-1, ::kill(pid, SIGKILL));
-
- // Wait for the child process.
- int status;
- EXPECT_NE(-1, ::waitpid((pid_t) -1, &status, 0));
- ASSERT_TRUE(WIFSIGNALED(status));
- EXPECT_EQ(SIGKILL, WTERMSIG(status));
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithCpuMemoryTest, ROOT_CGROUPS_FreezeNonFreezer)
-{
- std::string hierarchy = path::join(baseHierarchy, "cpu");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- AWAIT_EXPECT_FAILED(cgroups::freezer::freeze(hierarchy, TEST_CGROUPS_ROOT));
- AWAIT_EXPECT_FAILED(cgroups::freezer::thaw(hierarchy, TEST_CGROUPS_ROOT));
-
- // The cgroup is empty so we should still be able to destroy it.
- AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithFreezerTest, ROOT_CGROUPS_Kill)
-{
- int pipes[2];
- int dummy;
- ASSERT_NE(-1, ::pipe(pipes));
-
- std::string hierarchy = path::join(baseHierarchy, "freezer");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- pid_t pid = ::fork();
- ASSERT_NE(-1, pid);
-
- if (pid > 0) {
- // In parent process.
- ::close(pipes[1]);
-
- // Wait until all children have assigned the cgroup.
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ::close(pipes[0]);
-
- Try<Nothing> kill = cgroups::kill(hierarchy, TEST_CGROUPS_ROOT, SIGKILL);
- EXPECT_SOME(kill);
-
- int status;
- EXPECT_NE(-1, ::waitpid((pid_t) -1, &status, 0));
- ASSERT_TRUE(WIFSIGNALED(status));
- EXPECT_EQ(SIGKILL, WTERMSIG(status));
- } else {
- // In child process.
-
- // We create 4 child processes here using two forks to test the case in
- // which there are multiple active processes in the given cgroup.
- ::fork();
- ::fork();
-
- // Put self into the test cgroup.
- Try<Nothing> assign =
- cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, ::getpid());
-
- if (assign.isError()) {
- std::cerr << "Failed to assign cgroup: " << assign.error() << std::endl;
- abort();
- }
-
- // Notify the parent.
- ::close(pipes[0]); // TODO(benh): Close after first fork?
- if (::write(pipes[1], &dummy, sizeof(dummy)) != sizeof(dummy)) {
- perror("Failed to notify the parent");
- abort();
- }
- ::close(pipes[1]);
-
- // Wait kill signal from parent.
- while (true);
-
- // Should not reach here.
- std::cerr << "Reach an unreachable statement!" << std::endl;
- abort();
- }
-}
-
-
-// TODO(benh): Write a version of this test with nested cgroups.
-TEST_F(CgroupsAnyHierarchyWithFreezerTest, ROOT_CGROUPS_Destroy)
-{
- int pipes[2];
- int dummy;
- ASSERT_NE(-1, ::pipe(pipes));
-
- std::string hierarchy = path::join(baseHierarchy, "freezer");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- pid_t pid = ::fork();
- ASSERT_NE(-1, pid);
-
- if (pid > 0) {
- // In parent process.
- ::close(pipes[1]);
-
- // Wait until all children have assigned the cgroup.
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ASSERT_LT(0, ::read(pipes[0], &dummy, sizeof(dummy)));
- ::close(pipes[0]);
-
- AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
-
- // cgroups::destroy will reap all processes in the cgroup so we should
- // *not* be able to reap it now.
- int status;
- EXPECT_EQ(-1, ::waitpid(pid, &status, 0));
- EXPECT_EQ(ECHILD, errno);
- } else {
- // In child process.
-
- // We create 4 child processes here using two forks to test the case in
- // which there are multiple active processes in the given cgroup.
- ::fork();
- ::fork();
-
- // Put self into the test cgroup.
- Try<Nothing> assign =
- cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, ::getpid());
-
- if (assign.isError()) {
- std::cerr << "Failed to assign cgroup: " << assign.error() << std::endl;
- abort();
- }
-
- // Notify the parent.
- ::close(pipes[0]); // TODO(benh): Close after first fork?
- if (::write(pipes[1], &dummy, sizeof(dummy)) != sizeof(dummy)) {
- perror("Failed to notify the parent");
- abort();
- }
- ::close(pipes[1]);
-
- // Wait kill signal from parent.
- while (true) {}
-
- // Should not reach here.
- std::cerr << "Reach an unreachable statement!" << std::endl;
- abort();
- }
-}
-
-
-void* threadFunction(void*)
-{
- // Newly created threads have PTHREAD_CANCEL_ENABLE and
- // PTHREAD_CANCEL_DEFERRED so they can be cancelled from the main thread.
- while (true) { sleep(1); }
-
- return NULL;
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithFreezerTest, ROOT_CGROUPS_AssignThreads)
-{
- size_t numThreads = 5;
-
- pthread_t pthreads[numThreads];
-
- // Create additional threads.
- for (size_t i = 0; i < numThreads; i++)
- {
- EXPECT_EQ(0, pthread_create(&pthreads[i], NULL, threadFunction, NULL));
- }
-
- std::string hierarchy = path::join(baseHierarchy, "freezer");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- // Check the test cgroup is initially empty.
- Try<set<pid_t> > cgroupThreads =
- cgroups::threads(hierarchy, TEST_CGROUPS_ROOT);
- EXPECT_SOME(cgroupThreads);
- EXPECT_EQ(0u, cgroupThreads.get().size());
-
- // Assign ourselves to the test cgroup.
- CHECK_SOME(cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, ::getpid()));
-
- // Get our threads (may be more than the numThreads we created if
- // other threads are running).
- Try<set<pid_t> > threads = proc::threads(::getpid());
- ASSERT_SOME(threads);
-
- // Check the test cgroup now only contains all child threads.
- cgroupThreads = cgroups::threads(hierarchy, TEST_CGROUPS_ROOT);
- EXPECT_SOME(cgroupThreads);
- EXPECT_SOME_EQ(threads.get(), cgroupThreads);
-
- // Terminate the additional threads.
- for (size_t i = 0; i < numThreads; i++)
- {
- EXPECT_EQ(0, pthread_cancel(pthreads[i]));
- EXPECT_EQ(0, pthread_join(pthreads[i], NULL));
- }
-
- // Move ourselves to the root cgroup.
- CHECK_SOME(cgroups::assign(hierarchy, "", ::getpid()));
-
- // Destroy the cgroup.
- AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithFreezerTest, ROOT_CGROUPS_DestroyStoppedProcess)
-{
- std::string hierarchy = path::join(baseHierarchy, "freezer");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- pid_t pid = ::fork();
- ASSERT_NE(-1, pid);
-
- if (pid == 0) {
- // In child process.
- while (true) { sleep(1); }
-
- ABORT("Child should not reach this statement");
- }
-
- // In parent process.
-
- // Put child into the freezer cgroup.
- Try<Nothing> assign = cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, pid);
-
- // Stop the child process.
- EXPECT_EQ(0, kill(pid, SIGSTOP));
-
- AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
-
- // cgroups::destroy will reap all processes in the cgroup so we should
- // *not* be able to reap it now.
- int status;
- EXPECT_EQ(-1, ::waitpid(pid, &status, 0));
- EXPECT_EQ(ECHILD, errno);
-}
-
-
-TEST_F(CgroupsAnyHierarchyWithFreezerTest, ROOT_CGROUPS_DestroyTracedProcess)
-{
- std::string hierarchy = path::join(baseHierarchy, "freezer");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- pid_t pid = ::fork();
- ASSERT_NE(-1, pid);
-
- if (pid == 0) {
- // In child process.
- while (true) { sleep(1); }
-
- ABORT("Child should not reach this statement");
- }
-
- // In parent process.
- Try<Nothing> assign = cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, pid);
- ASSERT_SOME(assign);
-
- // Attach to the child process.
- ASSERT_EQ(0, ptrace(PT_ATTACH, pid, NULL, NULL));
-
- // Wait until the process is in traced state ('t' or 'T').
- Duration elapsed = Duration::zero();
- while (true) {
- Result<proc::ProcessStatus> process = proc::status(pid);
- ASSERT_SOME(process);
-
- if (process.get().state == 'T' || process.get().state == 't') {
- break;
- }
-
- if (elapsed > Seconds(1)) {
- FAIL() << "Failed to wait for process to be traced";
- }
-
- os::sleep(Milliseconds(5));
- elapsed += Milliseconds(5);
- }
-
- // Now destroy the cgroup.
- AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
-
- // cgroups::destroy will reap all processes in the cgroup so we should
- // *not* be able to reap it now.
- int status;
- EXPECT_EQ(-1, ::waitpid(pid, &status, 0));
- EXPECT_EQ(ECHILD, errno);
-}
-
-
-class CgroupsAnyHierarchyWithPerfEventTest
- : public CgroupsAnyHierarchyTest
-{
-public:
- CgroupsAnyHierarchyWithPerfEventTest()
- : CgroupsAnyHierarchyTest("perf_event") {}
-};
-
-
-TEST_F(CgroupsAnyHierarchyWithPerfEventTest, ROOT_CGROUPS_Perf)
-{
- int pipes[2];
- int dummy;
- ASSERT_NE(-1, ::pipe(pipes));
-
- std::string hierarchy = path::join(baseHierarchy, "perf_event");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- pid_t pid = ::fork();
- ASSERT_NE(-1, pid);
-
- if (pid == 0) {
- // In child process.
- ::close(pipes[1]);
-
- // Wait until parent has assigned us to the cgroup.
- ssize_t len;
- while ((len = ::read(pipes[0], &dummy, sizeof(dummy))) == -1 &&
- errno == EINTR);
- ASSERT_EQ((ssize_t) sizeof(dummy), len);
- ::close(pipes[0]);
-
- while (true) {
- // Don't sleep so 'perf' can actually sample something.
- }
-
- ABORT("Child should not reach here");
- }
-
- // In parent.
- ::close(pipes[0]);
-
- // Put child into the test cgroup.
- ASSERT_SOME(cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, pid));
-
- ssize_t len;
- while ((len = ::write(pipes[1], &dummy, sizeof(dummy))) == -1 &&
- errno == EINTR);
- ASSERT_EQ((ssize_t) sizeof(dummy), len);
- ::close(pipes[1]);
-
- std::set<std::string> events;
- // Hardware event.
- events.insert("cycles");
- // Software event.
- events.insert("task-clock");
-
- // NOTE: Wait at least 2 seconds as we've seen some variance in how
- // well 'perf' does across Linux distributions (e.g., Ubuntu 14.04)
- // and we want to make sure that we collect some non-zero values.
- Future<mesos::PerfStatistics> statistics =
- perf::sample(events, TEST_CGROUPS_ROOT, Seconds(2));
- AWAIT_READY(statistics);
-
- ASSERT_TRUE(statistics.get().has_cycles());
-
- // TODO(benh): Some Linux distributions (Ubuntu 14.04) fail to
- // properly sample 'cycles' with 'perf', so we don't explicitly
- // check the value here. See MESOS-3082.
- // EXPECT_LT(0u, statistics.get().cycles());
-
- ASSERT_TRUE(statistics.get().has_task_clock());
- EXPECT_LT(0.0, statistics.get().task_clock());
-
- // Kill the child process.
- ASSERT_NE(-1, ::kill(pid, SIGKILL));
-
- // Wait for the child process.
- int status;
- EXPECT_NE(-1, ::waitpid((pid_t) -1, &status, 0));
- ASSERT_TRUE(WIFSIGNALED(status));
- EXPECT_EQ(SIGKILL, WTERMSIG(status));
-
- // Destroy the cgroup.
- Future<Nothing> destroy = cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT);
- AWAIT_READY(destroy);
-}
-
-
-class CgroupsAnyHierarchyMemoryPressureTest
- : public CgroupsAnyHierarchyTest
-{
-public:
- CgroupsAnyHierarchyMemoryPressureTest()
- : CgroupsAnyHierarchyTest("memory"),
- cgroup(TEST_CGROUPS_ROOT) {}
-
-protected:
- virtual void SetUp()
- {
- CgroupsAnyHierarchyTest::SetUp();
-
- hierarchy = path::join(baseHierarchy, "memory");
-
- ASSERT_SOME(cgroups::create(hierarchy, cgroup));
- }
-
- void listen()
- {
- const std::vector<Level> levels = {
- Level::LOW,
- Level::MEDIUM,
- Level::CRITICAL
- };
-
- foreach (Level level, levels) {
- Try<Owned<Counter>> counter = Counter::create(hierarchy, cgroup, level);
- EXPECT_SOME(counter);
-
- counters[level] = counter.get();
- }
- }
-
- std::string hierarchy;
- const std::string cgroup;
-
- hashmap<Level, Owned<Counter>> counters;
-};
-
-
-TEST_F(CgroupsAnyHierarchyMemoryPressureTest, ROOT_IncreaseUnlockedRSS)
-{
- MemoryTestHelper helper;
- ASSERT_SOME(helper.spawn());
- ASSERT_SOME(helper.pid());
-
- const Bytes limit = Megabytes(16);
-
- // Move the memory test helper into a cgroup and set the limit.
- EXPECT_SOME(cgroups::memory::limit_in_bytes(hierarchy, cgroup, limit));
- EXPECT_SOME(cgroups::assign(hierarchy, cgroup, helper.pid().get()));
-
- listen();
-
- // Used to save the counter readings from last iteration.
- uint64_t previousLow = 0;
- uint64_t previousMedium = 0;
- uint64_t previousCritical = 0;
-
- // Used to save the counter readings from this iteration.
- uint64_t low;
- uint64_t medium;
- uint64_t critical;
-
- // Use a guard to error out if it's been too long.
- // TODO(chzhcn): Use a better way to set testing time limit.
- uint64_t iterationLimit = limit.bytes() / getpagesize() * 10;
-
- for (uint64_t i = 0; i < iterationLimit; i++) {
- EXPECT_SOME(helper.increaseRSS(getpagesize()));
-
- Future<uint64_t> _low = counters[Level::LOW]->value();
- Future<uint64_t> _medium = counters[Level::MEDIUM]->value();
- Future<uint64_t> _critical = counters[Level::CRITICAL]->value();
-
- AWAIT_READY(_low);
- AWAIT_READY(_medium);
- AWAIT_READY(_critical);
-
- low = _low.get();
- medium = _medium.get();
- critical = _critical.get();
-
- // We need to know the readings are the same as last time to be
- // sure they are stable, because the reading is not atomic. For
- // example, the medium could turn positive after we read low to be
- // 0, but this should be fixed by the next read immediately.
- if ((low == previousLow &&
- medium == previousMedium &&
- critical == previousCritical)) {
- if (low != 0) {
- EXPECT_LE(medium, low);
- EXPECT_LE(critical, medium);
-
- // When child's RSS is full, it will be OOM-kill'ed if we
- // don't stop it right away.
- break;
- } else {
- EXPECT_EQ(0u, medium);
- EXPECT_EQ(0u, critical);
- }
- }
-
- previousLow = low;
- previousMedium = medium;
- previousCritical = critical;
- }
-}
-
-
-TEST_F(CgroupsAnyHierarchyMemoryPressureTest, ROOT_IncreasePageCache)
-{
- MemoryTestHelper helper;
- ASSERT_SOME(helper.spawn());
- ASSERT_SOME(helper.pid());
-
- const Bytes limit = Megabytes(16);
-
- // Move the memory test helper into a cgroup and set the limit.
- EXPECT_SOME(cgroups::memory::limit_in_bytes(hierarchy, cgroup, limit));
- EXPECT_SOME(cgroups::assign(hierarchy, cgroup, helper.pid().get()));
-
- listen();
-
- // Used to save the counter readings from last iteration.
- uint64_t previousLow = 0;
- uint64_t previousMedium = 0;
- uint64_t previousCritical = 0;
-
- // Used to save the counter readings from this iteration.
- uint64_t low;
- uint64_t medium;
- uint64_t critical;
-
- // Use a guard to error out if it's been too long.
- // TODO(chzhcn): Use a better way to set testing time limit.
- uint64_t iterationLimit = limit.bytes() / Megabytes(1).bytes() * 2;
-
- for (uint64_t i = 0; i < iterationLimit; i++) {
- EXPECT_SOME(helper.increasePageCache(Megabytes(1)));
-
- Future<uint64_t> _low = counters[Level::LOW]->value();
- Future<uint64_t> _medium = counters[Level::MEDIUM]->value();
- Future<uint64_t> _critical = counters[Level::CRITICAL]->value();
-
- AWAIT_READY(_low);
- AWAIT_READY(_medium);
- AWAIT_READY(_critical);
-
- low = _low.get();
- medium = _medium.get();
- critical = _critical.get();
-
- // We need to know the readings are the same as last time to be
- // sure they are stable, because the reading is not atomic. For
- // example, the medium could turn positive after we read low to be
- // 0, but this should be fixed by the next read immediately.
- if ((low == previousLow &&
- medium == previousMedium &&
- critical == previousCritical)) {
- if (low != 0) {
- EXPECT_LE(medium, low);
- EXPECT_LE(critical, medium);
-
- // Different from the RSS test, since the child is only
- // consuming at a slow rate the page cache, which is evictable
- // and reclaimable, we could therefore be in this state
- // forever. Our guard will let us out shortly.
- } else {
- EXPECT_EQ(0u, medium);
- EXPECT_EQ(0u, critical);
- }
- }
-
- previousLow = low;
- previousMedium = medium;
- previousCritical = critical;
- }
-
- EXPECT_LT(0u, low);
-}
-
-// Tests the cpuacct::stat API. This test just tests for ANY value returned by
-// the API.
-TEST_F(CgroupsAnyHierarchyWithCpuAcctMemoryTest, ROOT_CGROUPS_CpuAcctsStats)
-{
- const std::string hierarchy = path::join(baseHierarchy, "cpuacct");
- ASSERT_SOME(cgroups::create(hierarchy, TEST_CGROUPS_ROOT));
-
- CHECK_SOME(cgroups::assign(hierarchy, TEST_CGROUPS_ROOT, ::getpid()));
-
- ASSERT_SOME(cgroups::cpuacct::stat(hierarchy, TEST_CGROUPS_ROOT));
-
- // Move ourselves to the root cgroup.
- CHECK_SOME(cgroups::assign(hierarchy, "", ::getpid()));
-
- AWAIT_READY(cgroups::destroy(hierarchy, TEST_CGROUPS_ROOT));
-}
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/96351372/src/tests/composing_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/composing_containerizer_tests.cpp b/src/tests/composing_containerizer_tests.cpp
deleted file mode 100644
index d66f519..0000000
--- a/src/tests/composing_containerizer_tests.cpp
+++ /dev/null
@@ -1,171 +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 <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <vector>
-
-#include <process/future.hpp>
-#include <process/gmock.hpp>
-
-#include <stout/option.hpp>
-
-#include "messages/messages.hpp"
-
-#include "slave/containerizer/containerizer.hpp"
-#include "slave/containerizer/composing.hpp"
-
-#include "tests/mesos.hpp"
-
-using namespace mesos::internal::slave;
-
-using namespace process;
-
-using std::vector;
-
-using testing::_;
-using testing::Return;
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-
-class ComposingContainerizerTest : public MesosTest {};
-
-class MockContainerizer : public slave::Containerizer
-{
-public:
- MOCK_METHOD1(
- recover,
- process::Future<Nothing>(
- const Option<slave::state::SlaveState>&));
-
- MOCK_METHOD7(
- launch,
- process::Future<bool>(
- const ContainerID&,
- const ExecutorInfo&,
- const std::string&,
- const Option<std::string>&,
- const SlaveID&,
- const process::PID<Slave>&,
- bool));
-
- MOCK_METHOD8(
- launch,
- process::Future<bool>(
- const ContainerID&,
- const TaskInfo&,
- const ExecutorInfo&,
- const std::string&,
- const Option<std::string>&,
- const SlaveID&,
- const process::PID<Slave>&,
- bool));
-
- MOCK_METHOD2(
- update,
- process::Future<Nothing>(
- const ContainerID&,
- const Resources&));
-
- MOCK_METHOD1(
- usage,
- process::Future<ResourceStatistics>(
- const ContainerID&));
-
- MOCK_METHOD1(
- wait,
- process::Future<containerizer::Termination>(
- const ContainerID&));
-
- MOCK_METHOD1(
- destroy,
- void(const ContainerID&));
-
- MOCK_METHOD0(
- containers,
- process::Future<hashset<ContainerID> >());
-};
-
-
-// This test checks if destroy is called while container is being
-// launched, the composing containerizer still calls the underlying
-// containerizer's destroy and skip calling the rest of the
-// containerizers.
-TEST_F(ComposingContainerizerTest, DestroyWhileLaunching)
-{
- vector<Containerizer*> containerizers;
-
- MockContainerizer* mockContainerizer = new MockContainerizer();
- MockContainerizer* mockContainerizer2 = new MockContainerizer();
-
- containerizers.push_back(mockContainerizer);
- containerizers.push_back(mockContainerizer2);
-
- ComposingContainerizer containerizer(containerizers);
- ContainerID containerId;
- containerId.set_value("container");
- TaskInfo taskInfo;
- ExecutorInfo executorInfo;
- SlaveID slaveId;
- PID<Slave> slavePid;
-
- Promise<bool> launchPromise;
-
- EXPECT_CALL(*mockContainerizer, launch(_, _, _, _, _, _, _, _))
- .WillOnce(Return(launchPromise.future()));
-
- Future<Nothing> destroy;
-
- EXPECT_CALL(*mockContainerizer, destroy(_))
- .WillOnce(FutureSatisfy(&destroy));
-
- Future<bool> launch = containerizer.launch(
- containerId,
- taskInfo,
- executorInfo,
- "dir",
- "user",
- slaveId,
- slavePid,
- false);
-
- Resources resources = Resources::parse("cpus:1;mem:256").get();
-
- EXPECT_TRUE(launch.isPending());
-
- containerizer.destroy(containerId);
-
- EXPECT_CALL(*mockContainerizer2, launch(_, _, _, _, _, _, _, _))
- .Times(0);
-
- // We make sure the destroy is being called on the first containerizer.
- // The second containerizer shouldn't be called as well since the
- // container is already destroyed.
- AWAIT_READY(destroy);
-
- launchPromise.set(false);
- AWAIT_FAILED(launch);
-}
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/96351372/src/tests/containerizer/cgroups_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/cgroups_isolator_tests.cpp b/src/tests/containerizer/cgroups_isolator_tests.cpp
new file mode 100644
index 0000000..a4ccc8e
--- /dev/null
+++ b/src/tests/containerizer/cgroups_isolator_tests.cpp
@@ -0,0 +1,46 @@
+/**
+ * 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 <map>
+#include <utility>
+
+#include <gtest/gtest.h>
+
+#include <stout/foreach.hpp>
+#include <stout/proc.hpp>
+#include <stout/stringify.hpp>
+
+#include "slave/containerizer/mesos/containerizer.hpp"
+
+#include "tests/script.hpp"
+
+using std::map;
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+
+// Run the balloon framework under a mesos containerizer.
+TEST_SCRIPT(ContainerizerTest,
+ ROOT_CGROUPS_BalloonFramework,
+ "balloon_framework_test.sh")
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {