// Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include #include #include #include #include #include #include #include #include #include #include #include using namespace isc; using namespace isc::hooks; using namespace std; namespace { /// @brief Library manager collection test class class LibraryManagerCollectionTest : public ::testing::Test, public HooksCommonTestClass { private: /// To avoid unused variable errors std::string dummy(int i) { if (i == 0) { return (MARKER_FILE); } else if (i > 0) { return (LOAD_CALLOUT_LIBRARY); } else { return (LOAD_ERROR_CALLOUT_LIBRARY); } } }; } // namespace namespace isc { namespace hooks { /// @brief Public library manager collection class /// /// This is an instance of the LibraryManagerCollection class but with the /// protected methods made public for test purposes. class PublicLibraryManagerCollection : public LibraryManagerCollection { public: /// @brief Constructor /// /// @param List of libraries that this collection will manage. The order /// of the libraries is important. PublicLibraryManagerCollection(const HookLibsCollection& libraries) : LibraryManagerCollection(libraries) { } /// Public methods that call protected methods on the superclass. using LibraryManagerCollection::unloadLibraries; }; } // namespace hooks } // namespace isc namespace { // This is effectively the same test as for LibraryManager, but using the // LibraryManagerCollection object. TEST_F(LibraryManagerCollectionTest, LoadLibraries) { // Set up the list of libraries to be loaded. HookLibsCollection library_names; library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), data::ConstElementPtr())); library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), data::ConstElementPtr())); // Set up the library manager collection and get the callout manager we'll // be using. PublicLibraryManagerCollection lm_collection(library_names); // Load the libraries. EXPECT_TRUE(lm_collection.loadLibraries()); EXPECT_EQ(2, lm_collection.getLoadedLibraryCount()); // Execute the callouts. The first library implements the calculation. // // r3 = (7 * d1 - d2) * d3 // // The last-loaded library implements the calculation // // r3 = (10 + d1) * d2 - d3 // // Putting the processing for each library together in the appropriate // order, we get: // // r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3 boost::shared_ptr manager = lm_collection.getCalloutManager(); { SCOPED_TRACE("Doing calculation with libraries loaded"); executeCallCallouts(manager, 10, 3, 33, 2, 62, 3, 183); } // Try unloading the libraries. EXPECT_NO_THROW(lm_collection.unloadLibraries()); EXPECT_EQ(0, lm_collection.getLoadedLibraryCount()); // Re-execute the calculation - callouts can be called but as nothing // happens, the result should always be -1. { SCOPED_TRACE("Doing calculation with libraries not loaded"); executeCallCallouts(manager, -1, 3, -1, 22, -1, 83, -1); } } // This is effectively the same test as above, but with a library generating // an error when loaded. It is expected that no libraries will be loaded. TEST_F(LibraryManagerCollectionTest, LoadLibrariesWithError) { // Set up the list of libraries to be loaded. HookLibsCollection library_names; library_names.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), data::ConstElementPtr())); library_names.push_back(make_pair(std::string(INCORRECT_VERSION_LIBRARY), data::ConstElementPtr())); library_names.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), data::ConstElementPtr())); // Set up the library manager collection and get the callout manager we'll // be using. PublicLibraryManagerCollection lm_collection(library_names); // Load the libraries. We expect a failure status to be returned as // one of the libraries failed to load. EXPECT_FALSE(lm_collection.loadLibraries()); // Expect no libraries were loaded. EXPECT_EQ(0, lm_collection.getLoadedLibraryCount()); } // Check that everything works even with no libraries loaded. TEST_F(LibraryManagerCollectionTest, NoLibrariesLoaded) { // Set up the list of libraries to be loaded. HookLibsCollection library_names; // Set up the library manager collection and get the callout manager we'll // be using. LibraryManagerCollection lm_collection(library_names); EXPECT_TRUE(lm_collection.loadLibraries()); EXPECT_EQ(0, lm_collection.getLoadedLibraryCount()); boost::shared_ptr manager = lm_collection.getCalloutManager(); // Execute the calculation - callouts can be called but as nothing // happens, the result should always be -1. executeCallCallouts(manager, -1, 3, -1, 22, -1, 83, -1); } // Check that we can get the names of the libraries. TEST_F(LibraryManagerCollectionTest, LibraryNames) { // Set up the list of libraries to be loaded. HookLibsCollection libraries; libraries.push_back(make_pair(std::string(FULL_CALLOUT_LIBRARY), data::ConstElementPtr())); libraries.push_back(make_pair(std::string(BASIC_CALLOUT_LIBRARY), data::ConstElementPtr())); // Set up the library manager collection and get the callout manager we'll // be using. PublicLibraryManagerCollection lm_collection(libraries); // Check the names before the libraries are loaded. std::vector collection_names = lm_collection.getLibraryNames(); EXPECT_TRUE(extractNames(libraries) == collection_names); // Load the libraries and check the names again. EXPECT_TRUE(lm_collection.loadLibraries()); EXPECT_EQ(2, lm_collection.getLoadedLibraryCount()); collection_names = lm_collection.getLibraryNames(); EXPECT_TRUE(extractNames(libraries) == collection_names); } // Test the library validation function. TEST_F(LibraryManagerCollectionTest, validateLibraries) { // Vector of libraries that failed validation std::vector failed; // Test different vectors of libraries. // No libraries should return a success. std::vector libraries; failed = LibraryManagerCollection::validateLibraries(libraries); EXPECT_TRUE(failed.empty()); // Single valid library should validate. libraries.clear(); libraries.push_back(BASIC_CALLOUT_LIBRARY); failed = LibraryManagerCollection::validateLibraries(libraries); EXPECT_TRUE(failed.empty()); // Multiple valid libraries should succeed. libraries.clear(); libraries.push_back(BASIC_CALLOUT_LIBRARY); libraries.push_back(FULL_CALLOUT_LIBRARY); libraries.push_back(UNLOAD_CALLOUT_LIBRARY); libraries.push_back(CALLOUT_PARAMS_LIBRARY); failed = LibraryManagerCollection::validateLibraries(libraries); EXPECT_TRUE(failed.empty()); // Single invalid library should fail. libraries.clear(); libraries.push_back(NOT_PRESENT_LIBRARY); failed = LibraryManagerCollection::validateLibraries(libraries); EXPECT_TRUE(failed == libraries); // Multiple invalid libraries should fail. libraries.clear(); libraries.push_back(INCORRECT_VERSION_LIBRARY); libraries.push_back(NO_VERSION_LIBRARY); libraries.push_back(FRAMEWORK_EXCEPTION_LIBRARY); failed = LibraryManagerCollection::validateLibraries(libraries); EXPECT_TRUE(failed == libraries); // Combination of valid and invalid (first one valid) should fail. libraries.clear(); libraries.push_back(FULL_CALLOUT_LIBRARY); libraries.push_back(INCORRECT_VERSION_LIBRARY); libraries.push_back(NO_VERSION_LIBRARY); std::vector expected_failures; expected_failures.push_back(INCORRECT_VERSION_LIBRARY); expected_failures.push_back(NO_VERSION_LIBRARY); failed = LibraryManagerCollection::validateLibraries(libraries); EXPECT_TRUE(failed == expected_failures); // Combination of valid and invalid (first one invalid) should fail. libraries.clear(); libraries.push_back(NO_VERSION_LIBRARY); libraries.push_back(FULL_CALLOUT_LIBRARY); libraries.push_back(INCORRECT_VERSION_LIBRARY); expected_failures.clear(); expected_failures.push_back(NO_VERSION_LIBRARY); expected_failures.push_back(INCORRECT_VERSION_LIBRARY); failed = LibraryManagerCollection::validateLibraries(libraries); EXPECT_TRUE(failed == expected_failures); } // This test verifies if getLibraryNames and getLibraryInfo are returning // expected values if there are no libraries configured. TEST_F(LibraryManagerCollectionTest, libraryGetEmpty) { HookLibsCollection empty; boost::shared_ptr mgr; // Instantiate library manager collection with no libraries EXPECT_NO_THROW(mgr.reset(new LibraryManagerCollection(empty))); // Check that getLibraryInfo returns empty list properly. HookLibsCollection returned = mgr->getLibraryInfo(); EXPECT_TRUE(returned.empty()); // Check that getLibraryNames return empty list, too. vector names(3, "rubbish"); // just put something in it. EXPECT_NO_THROW(names = mgr->getLibraryNames()); EXPECT_TRUE(names.empty()); } // This test verifies if getLibraryNames and getLibraryInfo are returning // expected values when there are libraries configured. TEST_F(LibraryManagerCollectionTest, libraryGet) { using namespace data; HookLibsCollection libs; ElementPtr param1(Element::fromJSON("{ \"param1\": \"foo\" }")); ElementPtr param2(Element::fromJSON("{ \"param2\": \"bar\" }")); libs.push_back(make_pair("libone", param1)); libs.push_back(make_pair("libtwo", param2)); boost::shared_ptr mgr; EXPECT_NO_THROW(mgr.reset(new LibraryManagerCollection(libs))); EXPECT_TRUE(libs == mgr->getLibraryInfo()); vector exp_names; exp_names.push_back("libone"); exp_names.push_back("libtwo"); EXPECT_TRUE(exp_names == mgr->getLibraryNames()); } } // Anonymous namespace