diff options
-rw-r--r-- | src/core/Registry.cpp | 10 | ||||
-rw-r--r-- | src/core/resource/ResourceLocator.cpp | 24 | ||||
-rw-r--r-- | src/plugins/filesystem/FileLocator.cpp | 28 | ||||
-rw-r--r-- | src/plugins/filesystem/FileLocator.hpp | 11 | ||||
-rw-r--r-- | src/plugins/filesystem/SpecialPaths.cpp | 8 | ||||
-rw-r--r-- | test/plugins/filesystem/FileLocatorTest.cpp | 116 |
6 files changed, 116 insertions, 81 deletions
diff --git a/src/core/Registry.cpp b/src/core/Registry.cpp index 9427aed..86665a2 100644 --- a/src/core/Registry.cpp +++ b/src/core/Registry.cpp @@ -70,16 +70,6 @@ bool Registry::locateResource(Resource &resource, const std::string &path, } } - // If this did not work out, retry but use the UNKNOWN type. - if (type != ResourceType::UNKNOWN) { - for (auto &locator : locators) { - if (locator->locate(resource, path, ResourceType::UNKNOWN, - relativeTo)) { - return true; - } - } - } - return false; } } diff --git a/src/core/resource/ResourceLocator.cpp b/src/core/resource/ResourceLocator.cpp index 1b8490d..b19542e 100644 --- a/src/core/resource/ResourceLocator.cpp +++ b/src/core/resource/ResourceLocator.cpp @@ -29,17 +29,28 @@ bool ResourceLocator::locate(Resource &resource, const std::string &path, const ResourceType type, const Resource &relativeTo) const { + // If the locator of the given relative resource is this locator instance, + // use the location specified in the resource, otherwise just use no + // "relativeTo" path. if (&relativeTo.getLocator() == this) { - return doLocate(resource, path, type, relativeTo.getLocation()); + return locate(resource, path, type, relativeTo.getLocation()); } - return doLocate(resource, path, type, ""); + return locate(resource, path, type, ""); } bool ResourceLocator::locate(Resource &resource, const std::string &path, const ResourceType type, const std::string &relativeTo) const { - return doLocate(resource, path, type, relativeTo); + // Try to locate the resource for the specified type, if not found, use + // the "UNKNOWN" type. + if (doLocate(resource, path, type, relativeTo)) { + return true; + } + if (type != ResourceType::UNKNOWN) { + return doLocate(resource, path, ResourceType::UNKNOWN, relativeTo); + } + return false; } std::unique_ptr<std::istream> ResourceLocator::stream( @@ -50,9 +61,10 @@ std::unique_ptr<std::istream> ResourceLocator::stream( /* Class StaticResourceLocator */ -bool StaticResourceLocator::doLocate( - Resource &resource, const std::string &path, const ResourceType type, - const std::string &relativeTo) const +bool StaticResourceLocator::doLocate(Resource &resource, + const std::string &path, + const ResourceType type, + const std::string &relativeTo) const { auto it = resources.find(path); if (it != resources.end()) { diff --git a/src/plugins/filesystem/FileLocator.cpp b/src/plugins/filesystem/FileLocator.cpp index 7bb3a58..9a558eb 100644 --- a/src/plugins/filesystem/FileLocator.cpp +++ b/src/plugins/filesystem/FileLocator.cpp @@ -17,6 +17,10 @@ */ #ifndef NDEBUG +//#define FILELOCATOR_DEBUG_PRINT +#endif + +#ifdef FILELOCATOR_DEBUG_PRINT #include <iostream> #endif @@ -44,6 +48,7 @@ void FileLocator::addPath(const std::string &path, void FileLocator::addSearchPath(const std::string &path, std::set<ResourceType> types) { + // Skip empty or non-existant paths if (path.empty() || !fs::exists(path)) { return; } @@ -51,7 +56,7 @@ void FileLocator::addSearchPath(const std::string &path, // Canonicalize the given path, check whether it exists std::string canonicalPath = fs::canonical(path).generic_string(); -#ifndef NDEBUG +#ifdef FILELOCATOR_DEBUG_PRINT std::cout << "FileLocator: Adding search path " << canonicalPath << std::endl; #endif @@ -99,14 +104,22 @@ void FileLocator::addDefaultSearchPaths() addDefaultSearchPaths(SpecialPaths::getLocalDataDir()); #ifndef NDEBUG addDefaultSearchPaths(SpecialPaths::getDebugDataDir()); - addDefaultSearchPaths(SpecialPaths::getDebugTestdataDir()); #endif } +void FileLocator::addUnittestSearchPath(const std::string &subdir, ResourceType type) +{ + addSearchPath((fs::path{SpecialPaths::getDebugTestdataDir()} / subdir) + .generic_string(), type); +} + bool FileLocator::doLocate(Resource &resource, const std::string &path, const ResourceType type, const std::string &relativeTo) const { +#ifdef FILELOCATOR_DEBUG_PRINT + std::cout << "FileLocator: Searching for \"" << path << "\"" << std::endl; +#endif if (!relativeTo.empty()) { fs::path base(relativeTo); if (fs::exists(base)) { @@ -122,7 +135,7 @@ bool FileLocator::doLocate(Resource &resource, const std::string &path, // If we already found a fitting resource there, use that. if (fs::exists(base)) { std::string location = fs::canonical(base).generic_string(); -#ifndef NDEBUG +#ifdef FILELOCATOR_DEBUG_PRINT std::cout << "FileLocator: Found \"" << path << "\" at " << location << std::endl; #endif @@ -138,16 +151,15 @@ bool FileLocator::doLocate(Resource &resource, const std::string &path, if (it != searchPaths.end()) { const auto &paths = it->second; for (auto it = paths.rbegin(); it != paths.rend(); it++) { -#ifndef NDEBUG - std::cout << "FileLocator: Searching for \"" << path << "\" in " - << *it << std::endl; +#ifdef FILELOCATOR_DEBUG_PRINT + std::cout << "FileLocator: Entering " << *it << std::endl; #endif fs::path p{*it}; p /= path; if (fs::exists(p)) { std::string location = fs::canonical(p).generic_string(); -#ifndef NDEBUG - std::cout << "FileLocator: Found \"" << path << "\" at " +#ifdef FILELOCATOR_DEBUG_PRINT + std::cout << "FileLocator: Found \"" << path << "\" in " << location << std::endl; #endif resource = Resource(true, *this, type, location); diff --git a/src/plugins/filesystem/FileLocator.hpp b/src/plugins/filesystem/FileLocator.hpp index 6d3bbf0..16fa3f7 100644 --- a/src/plugins/filesystem/FileLocator.hpp +++ b/src/plugins/filesystem/FileLocator.hpp @@ -122,6 +122,17 @@ public: void addDefaultSearchPaths(); /** + * Adds a search path for a unit test. This function should not be used + * outside the code in the "test" folder. + * + * @param subdir is the subdirectory in the "testdata" directory that should + * be added. + * @param type is a single type for which the path should be added. + */ + void addUnittestSearchPath(const std::string &subdir, + ResourceType type = ResourceType::UNKNOWN); + + /** * Returns the backing map containing all search paths for a given type. * This is read-only. */ diff --git a/src/plugins/filesystem/SpecialPaths.cpp b/src/plugins/filesystem/SpecialPaths.cpp index 97bdb9c..47ac0f0 100644 --- a/src/plugins/filesystem/SpecialPaths.cpp +++ b/src/plugins/filesystem/SpecialPaths.cpp @@ -59,8 +59,12 @@ std::string SpecialPaths::getDebugDataDir() std::string SpecialPaths::getDebugTestdataDir() { - fs::path debug{OUSIA_DEBUG_DIR}; - return (debug / "testdata").generic_string(); + std::string debug{OUSIA_DEBUG_DIR}; + if (debug.empty()) { + return "./testdata"; + } else { + return (fs::path{debug} / "testdata").generic_string(); + } } } diff --git a/test/plugins/filesystem/FileLocatorTest.cpp b/test/plugins/filesystem/FileLocatorTest.cpp index 056d05e..c1f1369 100644 --- a/test/plugins/filesystem/FileLocatorTest.cpp +++ b/test/plugins/filesystem/FileLocatorTest.cpp @@ -19,9 +19,12 @@ #include <gtest/gtest.h> #include <plugins/filesystem/FileLocator.hpp> +#include <plugins/filesystem/SpecialPaths.hpp> #include <boost/filesystem.hpp> +namespace fs = boost::filesystem; + namespace ousia { TEST(FileLocator, testAddSearchPath) { @@ -29,8 +32,7 @@ TEST(FileLocator, testAddSearchPath) ASSERT_EQ(0U, instance.getSearchPaths().size()); // Read the canonical path of "." - std::string canonicalPath = - boost::filesystem::canonical(".").generic_string(); + std::string canonicalPath = fs::canonical(".").generic_string(); // Add one path for three types. instance.addSearchPath(".", @@ -54,14 +56,44 @@ TEST(FileLocator, testAddSearchPath) ASSERT_EQ(1U, it->second.size()); ASSERT_EQ(canonicalPath, it->second[0]); + it = instance.getSearchPaths().find(ResourceType::ATTRIBUTES); + ASSERT_EQ(it, instance.getSearchPaths().end()); + + // Adding the path another time should not increase the number of found + // paths, except for new resource types + instance.addSearchPath(canonicalPath, + {ResourceType::DOMAIN_DESC, ResourceType::SCRIPT, + ResourceType::TYPESYSTEM, ResourceType::ATTRIBUTES}); + + ASSERT_EQ(4U, instance.getSearchPaths().size()); + + it = instance.getSearchPaths().find(ResourceType::DOMAIN_DESC); + + ASSERT_EQ(1U, it->second.size()); + ASSERT_EQ(canonicalPath, it->second[0]); + + it = instance.getSearchPaths().find(ResourceType::SCRIPT); + + ASSERT_EQ(1U, it->second.size()); + ASSERT_EQ(canonicalPath, it->second[0]); + + it = instance.getSearchPaths().find(ResourceType::TYPESYSTEM); + + ASSERT_EQ(1U, it->second.size()); + ASSERT_EQ(canonicalPath, it->second[0]); + + it = instance.getSearchPaths().find(ResourceType::ATTRIBUTES); + + ASSERT_EQ(1U, it->second.size()); + ASSERT_EQ(canonicalPath, it->second[0]); + // Add another path for only one of those types. - std::string canonicalPath2 = - boost::filesystem::canonical("..").generic_string(); + std::string canonicalPath2 = fs::canonical("..").generic_string(); instance.addSearchPath("..", {ResourceType::DOMAIN_DESC}); - ASSERT_EQ(3U, instance.getSearchPaths().size()); + ASSERT_EQ(4U, instance.getSearchPaths().size()); it = instance.getSearchPaths().find(ResourceType::DOMAIN_DESC); @@ -77,8 +109,8 @@ void assert_located(const FileLocator &instance, const std::string &path, Resource res; ASSERT_TRUE(instance.locate(res, path, type, relativeTo)); ASSERT_TRUE(res.isValid()); - boost::filesystem::path p(res.getLocation()); - ASSERT_TRUE(boost::filesystem::exists(p)); + fs::path p(res.getLocation()); + ASSERT_TRUE(fs::exists(p)); ASSERT_EQ(path, p.filename()); } @@ -93,63 +125,37 @@ void assert_not_located(const FileLocator &instance, const std::string &path, TEST(FileLocator, testLocate) { - // Initialization - boost::filesystem::path start("."); - start = boost::filesystem::canonical(start); - std::string relativeTo; - - if (start.filename() == "build") { - relativeTo = ".."; - start = start.parent_path(); - } else if (start.filename() == "application") { - relativeTo = "."; - } else { - ASSERT_TRUE(false); - } - FileLocator instance; + FileLocator locator; + locator.addUnittestSearchPath("filesystem"); - // We should be able to find the CMakeLists file in the main directory. - assert_located(instance, "CMakeLists.txt", relativeTo); - // But not the FileLocator.hpp - assert_not_located(instance, "FileLocator.hpp", relativeTo); + // We should be able to find a.txt, but not c.txt + assert_located(locator, "a.txt", ""); + assert_not_located(locator, "c.txt", ""); + + // Add the respective search path + locator.addUnittestSearchPath("filesystem/b", ResourceType::DOMAIN_DESC); - // Add the respective search path. - instance.addSearchPath((start / "src/plugins/filesystem").generic_string(), - {ResourceType::DOMAIN_DESC}); // Now we should be able to find both. - assert_located(instance, "CMakeLists.txt", relativeTo); - assert_located(instance, "FileLocator.hpp", relativeTo); - // but only with the correct type. - assert_not_located(instance, "FileLocator.hpp", relativeTo, - ResourceType::SCRIPT); + assert_located(locator, "a.txt", ""); + assert_located(locator, "c.txt", ""); + + // But only with the correct type. + assert_not_located(locator, "c.txt", "", ResourceType::SCRIPT); } TEST(FileLocator, testStream) { - // Initialization - boost::filesystem::path start("."); - start = boost::filesystem::canonical(start); - std::string relativeTo; - - if (start.filename() == "build") { - relativeTo = ".."; - start = start.parent_path(); - } else if (start.filename() == "application") { - relativeTo = "."; - } else { - ASSERT_TRUE(false); - } - FileLocator instance; + FileLocator locator; + locator.addUnittestSearchPath("filesystem"); + // Locate the CMakeLists.txt Resource res; - instance.locate(res, "CMakeLists.txt", ResourceType::DOMAIN_DESC, - relativeTo); - // Stream the content. + locator.locate(res, "a.txt"); + + // Fetch the input stream and read the first line auto is_ptr = res.stream(); - // get the beginning. - char buf[256]; - is_ptr->getline(buf, 256); - std::string first_line(buf); - ASSERT_EQ("# Ousía", first_line); + std::string line; + std::getline(*is_ptr, line); + ASSERT_EQ("file a", line); } } |