Repository: mesos
Updated Branches:
  refs/heads/master 718f40a35 -> 0fcfa5018


Added setup/teardown for module API tests.

During the one-time setup of the test cases, we do the following:
1. set LD_LIBRARY_PATH to also point to the src/.libs directory.
   The original LD_LIBRARY_PATH is restored at the end of all tests.
2. dlopen() examplemodule library and retrieve the pointer to
   ModuleBase for the test module.  This pointer is later used to
   reset the Mesos and module API versions during per-test teardown.

During the tear-down after each test, we unload the module to allow
later loads to succeed.

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


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

Branch: refs/heads/master
Commit: 0fcfa50187499e8af958bfdb6f83423c6e7bd75a
Parents: 718f40a
Author: Kapil Arya <[email protected]>
Authored: Mon Oct 20 18:09:31 2014 -0700
Committer: Niklas Q. Nielsen <[email protected]>
Committed: Mon Oct 20 18:09:31 2014 -0700

----------------------------------------------------------------------
 src/examples/example_module_impl.cpp |   4 +-
 src/tests/module_tests.cpp           | 343 ++++++++++++------------------
 2 files changed, 143 insertions(+), 204 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/0fcfa501/src/examples/example_module_impl.cpp
----------------------------------------------------------------------
diff --git a/src/examples/example_module_impl.cpp 
b/src/examples/example_module_impl.cpp
index 27c0520..169453a 100644
--- a/src/examples/example_module_impl.cpp
+++ b/src/examples/example_module_impl.cpp
@@ -59,8 +59,8 @@ static TestModule* create()
 mesos::Module<TestModule> org_apache_mesos_TestModule(
     MESOS_MODULE_API_VERSION,
     MESOS_VERSION,
-    "author",
-    "[email protected]",
+    "Apache Mesos",
+    "[email protected]",
     "This is a test module.",
     compatible,
     create);

http://git-wip-us.apache.org/repos/asf/mesos/blob/0fcfa501/src/tests/module_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/module_tests.cpp b/src/tests/module_tests.cpp
index 7dd47fb..e92d871 100644
--- a/src/tests/module_tests.cpp
+++ b/src/tests/module_tests.cpp
@@ -34,29 +34,101 @@ using namespace mesos;
 using namespace mesos::internal;
 using namespace mesos::internal::tests;
 
+const char* DEFAULT_MODULE_LIBRARY_NAME = "examplemodule";
+const char* DEFAULT_MODULE_NAME = "org_apache_mesos_TestModule";
 
-class ModuleTest : public MesosTest {};
 
-
-static const string getLibraryDirectory()
-{
-  return path::join(tests::flags.build_dir, "src", ".libs");
-}
-
-
-static const string getLibraryPath(const string& libraryName)
+class ModuleTest : public MesosTest
 {
-  return path::join(
-     getLibraryDirectory(),
-     os::libraries::expandName(libraryName));
-}
+protected:
+  // During the one-time setup of the test cases, we do the
+  // following:
+  // 1. set LD_LIBRARY_PATH to also point to the src/.libs directory.
+  //    The original LD_LIBRARY_PATH is restored at the end of all
+  //    tests.
+  // 2. dlopen() examplemodule library and retrieve the pointer to
+  //    ModuleBase for the test module. This pointer is later used to
+  //    reset the Mesos and module API versions during per-test
+  //    teardown.
+  static void SetUpTestCase()
+  {
+    libraryDirectory = path::join(tests::flags.build_dir, "src", ".libs");
+
+    // Get the current value of LD_LIBRARY_PATH.
+    originalLdLibraryPath = os::libraries::paths();
+
+    // Append our library path to LD_LIBRARY_PATH so that dlopen can
+    // search the library directory for module libraries.
+    os::libraries::appendPaths(libraryDirectory);
+
+    EXPECT_SOME(dynamicLibrary.open(
+        os::libraries::expandName(DEFAULT_MODULE_LIBRARY_NAME)));
+
+    Try<void*> symbol = dynamicLibrary.loadSymbol(DEFAULT_MODULE_NAME);
+    EXPECT_SOME(symbol);
+
+    moduleBase = (ModuleBase*) symbol.get();
+  }
+
+  static void TearDownTestCase()
+  {
+    // Close the module library.
+    dynamicLibrary.close();
+
+    // Restore LD_LIBRARY_PATH environment variable.
+    os::libraries::setPaths(originalLdLibraryPath);
+  }
+
+  ModuleTest()
+    : module(None())
+  {
+    Modules::Library* library = defaultModules.add_libraries();
+    library->set_file(path::join(
+        libraryDirectory,
+        os::libraries::expandName(DEFAULT_MODULE_LIBRARY_NAME)));
+    library->add_modules(DEFAULT_MODULE_NAME);
+  }
+
+  // During the per-test tear-down, we unload the module to allow
+  // later loads to succeed.
+  ~ModuleTest()
+  {
+    // The TestModule instance is created by calling new. Let's
+    // delete it to avoid memory leaks.
+    if (module.isSome()) {
+      delete module.get();
+    }
+
+    // Reset module API version and Mesos version in case the test
+    // changed them.
+    moduleBase->moduleApiVersion = MESOS_MODULE_API_VERSION;
+    moduleBase->mesosVersion = MESOS_VERSION;
+
+    // Unload the module so a subsequent loading may succeed.
+    ModuleManager::unload(DEFAULT_MODULE_NAME);
+  }
+
+  Modules defaultModules;
+  Result<TestModule*> module;
+
+  static DynamicLibrary dynamicLibrary;
+  static mesos::ModuleBase* moduleBase;
+  static string originalLdLibraryPath;
+  static string libraryDirectory;
+};
+
+
+DynamicLibrary ModuleTest::dynamicLibrary;
+ModuleBase* ModuleTest::moduleBase = NULL;
+string ModuleTest::originalLdLibraryPath;
+string ModuleTest::libraryDirectory;
 
 
 static Modules getModules(const string& libraryName, const string& moduleName)
 {
   Modules modules;
   Modules::Library* library = modules.add_libraries();
-  library->set_file(getLibraryPath(libraryName));
+  library->set_file(os::libraries::expandName(libraryName));
   library->add_modules(moduleName);
   return modules;
 }
@@ -64,17 +136,12 @@ static Modules getModules(const string& libraryName, const 
string& moduleName)
 
 // Test that a module library gets loaded,  and its contents
 // version-verified. The provided test library matches the current
-// Mesos version exactly. Parse the library and module request from a
-// JSON string.
-TEST_F(ModuleTest, ExampleModuleParseStringTest)
+// Mesos version exactly.
+TEST_F(ModuleTest, ExampleModuleLoadTest)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  Modules modules = getModules(libraryName, moduleName);
-  EXPECT_SOME(ModuleManager::load(modules));
+  EXPECT_SOME(ModuleManager::load(defaultModules));
 
-  Try<TestModule*> module = ModuleManager::create<TestModule>(moduleName);
+  module = ModuleManager::create<TestModule>(DEFAULT_MODULE_NAME);
   EXPECT_SOME(module);
 
   // The TestModuleImpl module's implementation of foo() returns
@@ -82,29 +149,35 @@ TEST_F(ModuleTest, ExampleModuleParseStringTest)
   // product.
   EXPECT_EQ(module.get()->foo('A', 1024), 1089);
   EXPECT_EQ(module.get()->bar(0.5, 10.8), 5);
-
-  EXPECT_SOME(ModuleManager::unload(moduleName));
 }
 
 
-// Test for correct author name, author email and library description.
-TEST_F(ModuleTest, AuthorInfoTest)
+// Test that unloading a module succeeds if it has not been unloaded
+// already.  Unloading unknown modules should fail as well.
+TEST_F(ModuleTest, ExampleModuleUnloadTest)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
+  EXPECT_SOME(ModuleManager::load(defaultModules));
+
+  module = ModuleManager::create<TestModule>(DEFAULT_MODULE_NAME);
+  EXPECT_SOME(module);
+
+  // Unloading the module should succeed the first time.
+  EXPECT_SOME(ModuleManager::unload(DEFAULT_MODULE_NAME));
+
+  // Unloading the same module a second time should fail.
+  EXPECT_ERROR(ModuleManager::unload(DEFAULT_MODULE_NAME));
 
-  DynamicLibrary library;
-  EXPECT_SOME(library.open(getLibraryPath(libraryName)));
+  // Unloading an unknown module should fail.
+  EXPECT_ERROR(ModuleManager::unload("unknown"));
+}
 
-  // Check the return values against the values defined in
-  // test_module_impl.cpp.
-  Try<void*> symbol = library.loadSymbol(moduleName);
-  EXPECT_SOME(symbol);
 
-  ModuleBase* moduleBase = (ModuleBase*) symbol.get();
-  EXPECT_EQ(stringify(moduleBase->authorName), "author");
-  EXPECT_EQ(stringify(moduleBase->authorEmail), "[email protected]");
-  EXPECT_EQ(stringify(moduleBase->description), "This is a test module.");
+// Test for correct author name, author email and library description.
+TEST_F(ModuleTest, AuthorInfoTest)
+{
+  EXPECT_STREQ(moduleBase->authorName, "Apache Mesos");
+  EXPECT_STREQ(moduleBase->authorEmail, "[email protected]");
+  EXPECT_STREQ(moduleBase->description, "This is a test module.");
 }
 
 
@@ -112,27 +185,12 @@ TEST_F(ModuleTest, AuthorInfoTest)
 // library name without any extension and without the "lib" prefix.
 TEST_F(ModuleTest, LibraryNameWithoutExtension)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
-  const string ldLibraryPath = "LD_LIBRARY_PATH";
-
-  // Append our library path to LD_LIBRARY_PATH.
-  const string oldLdLibraryPath = os::getenv(ldLibraryPath, false);
-  const string newLdLibraryPath =
-    getLibraryDirectory() + ":" + oldLdLibraryPath;
-  os::setenv(ldLibraryPath, newLdLibraryPath);
-
   Modules modules;
   Modules::Library* library = modules.add_libraries();
-  library->set_name(libraryName);
-  library->add_modules(moduleName);
+  library->set_name(DEFAULT_MODULE_LIBRARY_NAME);
+  library->add_modules(DEFAULT_MODULE_NAME);
 
   EXPECT_SOME(ModuleManager::load(modules));
-
-  // Reset LD_LIBRARY_PATH environment variable.
-  os::setenv(ldLibraryPath, oldLdLibraryPath);
-
-  EXPECT_SOME(ModuleManager::unload(moduleName));
 }
 
 
@@ -140,68 +198,36 @@ TEST_F(ModuleTest, LibraryNameWithoutExtension)
 // found in LD_LIBRARY_PATH.
 TEST_F(ModuleTest, LibraryNameWithExtension)
 {
-  const string libraryName = os::libraries::expandName("examplemodule");
-  const string moduleName = "org_apache_mesos_TestModule";
-  const string ldLibraryPath = "LD_LIBRARY_PATH";
-
-  // Append our library path to LD_LIBRARY_PATH.
-  const string oldLdLibraryPath = os::getenv(ldLibraryPath, false);
-  const string newLdLibraryPath =
-    getLibraryDirectory() + ":" + oldLdLibraryPath;
-  os::setenv(ldLibraryPath, newLdLibraryPath);
-
   Modules modules;
   Modules::Library* library = modules.add_libraries();
-  library->set_file(libraryName);
-  library->add_modules(moduleName);
+  library->set_file(os::libraries::expandName(DEFAULT_MODULE_LIBRARY_NAME));
+  library->add_modules(DEFAULT_MODULE_NAME);
 
   EXPECT_SOME(ModuleManager::load(modules));
-
-  // Reset LD_LIBRARY_PATH environment variable.
-  os::setenv(ldLibraryPath, oldLdLibraryPath);
-
-  EXPECT_SOME(ModuleManager::unload(moduleName));
 }
 
 
 // Test that module library loading fails when filename is empty.
 TEST_F(ModuleTest, EmptyLibraryFilename)
 {
-  const string libraryName = "";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  Modules modules = getModules(libraryName, moduleName);
-
+  Modules modules = getModules("", "org_apache_mesos_TestModule");
   EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
 }
 
 
 // Test that module library loading fails when module name is empty.
 TEST_F(ModuleTest, EmptyModuleName)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "";
-
-  Modules modules = getModules(libraryName, moduleName);
+  Modules modules = getModules("examplemodule", "");
   EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
 }
 
 
 // Test that module library loading fails when given an unknown path.
 TEST_F(ModuleTest, UnknownLibraryTest)
 {
-  const string libraryName = "unknown";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  Modules modules = getModules(libraryName, moduleName);
-
+  Modules modules = getModules("unknown", "org_apache_mesos_TestModule");
   EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
 }
 
 
@@ -209,13 +235,8 @@ TEST_F(ModuleTest, UnknownLibraryTest)
 // the commandline.
 TEST_F(ModuleTest, UnknownModuleTest)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "unknown";
-
-  Modules modules = getModules(libraryName, moduleName);
+  Modules modules = getModules("examplemodule", "unknown");
   EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
 }
 
 
@@ -223,148 +244,66 @@ TEST_F(ModuleTest, UnknownModuleTest)
 // name.
 TEST_F(ModuleTest, UnknownModuleInstantiationTest)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  Modules modules = getModules(libraryName, moduleName);
-  EXPECT_SOME(ModuleManager::load(modules));
-
+  EXPECT_SOME(ModuleManager::load(defaultModules));
   EXPECT_ERROR(ModuleManager::create<TestModule>("unknown"));
-
-  EXPECT_SOME(ModuleManager::unload(moduleName));
 }
 
 
 // Test that loading a non-module library fails.
 TEST_F(ModuleTest, NonModuleLibrary)
 {
-  const string libraryName = "mesos";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  Modules modules = getModules(libraryName, moduleName);
+  // Trying to load libmesos.so (libmesos.dylib on OS X) as a module
+  // library should fail.
+  Modules modules = getModules("mesos", DEFAULT_MODULE_NAME);
   EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
 }
 
 
 // Test that loading a duplicate module fails.
 TEST_F(ModuleTest, DuplicateModule)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  Modules modules = getModules(libraryName, moduleName);
-
   // Add duplicate module.
-  Modules::Library* library = modules.add_libraries();
-  library->set_file(getLibraryPath(libraryName));
-  library->add_modules(moduleName);
-
-  EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_SOME(ModuleManager::unload(moduleName));
-}
-
-
-// NOTE: We expect to pass 'version' which will outlive this function
-// since we set it to the external module's 'mesosVersion'.
-static void updateModuleLibraryVersion(
-    DynamicLibrary* library,
-    const string& moduleName,
-    const char* version)
-{
-  Try<void*> symbol = library->loadSymbol(moduleName);
-  EXPECT_SOME(symbol);
-
-  ModuleBase* moduleBase = (ModuleBase*) symbol.get();
-  moduleBase->mesosVersion = version;
-}
-
-
-// NOTE: Like above, we expect to pass 'version' which will outlive
-// this function since we set it to the external module's
-// 'mesosApiVersion'.
-static void updateModuleApiVersion(
-    DynamicLibrary* library,
-    const string& moduleName,
-    const char* version)
-{
-  Try<void*> symbol = library->loadSymbol(moduleName);
-  EXPECT_SOME(symbol);
+  Modules::Library* library = defaultModules.add_libraries();
+  library->set_name(DEFAULT_MODULE_LIBRARY_NAME);
+  library->add_modules(DEFAULT_MODULE_NAME);
 
-  ModuleBase* moduleBase = (ModuleBase*) symbol.get();
-  moduleBase->moduleApiVersion = version;
+  EXPECT_ERROR(ModuleManager::load(defaultModules));
 }
 
 
 // Test that loading a module library with a different API version
 // fails
-TEST_F(ModuleTest, DISABLED_DifferentApiVersion)
+TEST_F(ModuleTest, DifferentApiVersion)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  DynamicLibrary library;
-  EXPECT_SOME(library.open(getLibraryPath(libraryName)));
-
-  Modules modules = getModules(libraryName, moduleName);
-
   // Make the API version '0'.
-  updateModuleApiVersion(&library, moduleName, "0");
-  EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
+  moduleBase->moduleApiVersion = "0";
+  EXPECT_ERROR(ModuleManager::load(defaultModules));
 
   // Make the API version arbitrarily high.
-  updateModuleApiVersion(&library, moduleName, "1000");
-  EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
+  moduleBase->moduleApiVersion = "1000";
+  EXPECT_ERROR(ModuleManager::load(defaultModules));
 
   // Make the API version some random string.
-  updateModuleApiVersion(&library, moduleName, "ThisIsNotAnAPIVersion!");
-  EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
+  moduleBase->moduleApiVersion = "ThisIsNotAnAPIVersion!";
+  EXPECT_ERROR(ModuleManager::load(defaultModules));
 }
 
 
 // Test that loading a module library compiled with a newer Mesos
 // fails.
-TEST_F(ModuleTest, DISABLED_NewerModuleLibrary)
+TEST_F(ModuleTest, NewerModuleLibrary)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  DynamicLibrary library;
-  EXPECT_SOME(library.open(getLibraryPath(libraryName)));
-
-  Modules modules = getModules(libraryName, moduleName);
-
   // Make the library version arbitrarily high.
-  updateModuleLibraryVersion(&library, moduleName, "100.1.0");
-  EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
+  moduleBase->mesosVersion = "100.1.0";
+  EXPECT_ERROR(ModuleManager::load(defaultModules));
 }
 
 
 // Test that loading a module library compiled with a really old
 // Mesos fails.
-TEST_F(ModuleTest, DISABLED_OlderModuleLibrary)
+TEST_F(ModuleTest, OlderModuleLibrary)
 {
-  const string libraryName = "examplemodule";
-  const string moduleName = "org_apache_mesos_TestModule";
-
-  DynamicLibrary library;
-  EXPECT_SOME(library.open(getLibraryPath(libraryName)));
-
-  Modules modules = getModules(libraryName, moduleName);
-
   // Make the library version arbitrarily low.
-  updateModuleLibraryVersion(&library, moduleName, "0.1.0");
-  EXPECT_ERROR(ModuleManager::load(modules));
-
-  EXPECT_ERROR(ModuleManager::unload(moduleName));
+  moduleBase->mesosVersion = "0.1.0";
+  EXPECT_ERROR(ModuleManager::load(defaultModules));
 }

Reply via email to