aboutsummaryrefslogtreecommitdiff
path: root/libs/usvfs/test/shared_test/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/usvfs/test/shared_test/main.cpp')
-rw-r--r--libs/usvfs/test/shared_test/main.cpp248
1 files changed, 248 insertions, 0 deletions
diff --git a/libs/usvfs/test/shared_test/main.cpp b/libs/usvfs/test/shared_test/main.cpp
new file mode 100644
index 0000000..c6b5be6
--- /dev/null
+++ b/libs/usvfs/test/shared_test/main.cpp
@@ -0,0 +1,248 @@
+#include <boost/interprocess/containers/string.hpp>
+#include <boost/interprocess/shared_memory_object.hpp>
+#include <boost/predef.h>
+#include <gtest/gtest.h>
+#include <shared_memory.h>
+#include <spdlog/sinks/stdout_sinks.h>
+#include <wildcard.h>
+#include <windows_sane.h>
+
+#define PRIVATE public
+#include <directory_tree.h>
+#undef PRIVATE
+
+#include <tree_container.h>
+
+using namespace usvfs::shared;
+
+using namespace boost::interprocess;
+
+static const char g_SHMName[] = "treetest_shm";
+static const char TreeName[] = "treetest_tree";
+
+typedef DirectoryTree<int> TreeType;
+typedef TreeContainer<TreeType> ContainerType;
+
+typedef boost::container::scoped_allocator_adaptor<
+ boost::interprocess::allocator<void, SegmentManagerT>>
+ VoidAllocator;
+typedef VoidAllocator::rebind<char>::other CharAllocator;
+typedef basic_string<char, std::char_traits<char>, CharAllocator> SHMString;
+typedef DirectoryTree<SHMString> ComplexTreeType;
+typedef TreeContainer<ComplexTreeType> ComplexContainerType;
+
+template <>
+struct usvfs::shared::SHMDataCreator<int, int>
+{
+ static int create(int source, const VoidAllocatorT&) { return source; }
+};
+
+template <>
+inline int usvfs::shared::createDataEmpty<int>(const typename VoidAllocatorT&)
+{
+ return 0;
+}
+
+template <>
+inline void usvfs::shared::dataAssign<int>(int& destination, const int& source)
+{
+ destination = source;
+}
+
+template <>
+inline SHMString
+usvfs::shared::createDataEmpty<SHMString>(const typename VoidAllocatorT& allocator)
+{
+ return SHMString("", allocator);
+}
+
+template <>
+inline void usvfs::shared::dataAssign<SHMString>(SHMString& destination,
+ const SHMString& source)
+{
+ destination.assign(source.c_str());
+}
+
+static std::shared_ptr<spdlog::logger> logger()
+{
+ std::shared_ptr<spdlog::logger> result = spdlog::get("test");
+ if (result.get() == nullptr) {
+ result = spdlog::stdout_logger_mt("test");
+ }
+ return result;
+}
+
+TEST(WildcardTest, MatchWildcard)
+{
+ EXPECT_TRUE(wildcard::Match(TEXT("abc"), TEXT("a*")));
+ EXPECT_TRUE(wildcard::Match(TEXT("abc"), TEXT("a*c")));
+ EXPECT_TRUE(wildcard::Match(TEXT("abc"), TEXT("a?c")));
+ EXPECT_TRUE(wildcard::Match(TEXT("abc"), TEXT("abc")));
+ EXPECT_TRUE(wildcard::Match(TEXT("abc"), TEXT("abc*")));
+
+ EXPECT_TRUE(wildcard::Match("abc", "*.*"));
+ EXPECT_TRUE(wildcard::Match("abc.def", "*"));
+ EXPECT_TRUE(wildcard::Match(TEXT("abc"), TEXT("*.*")));
+ EXPECT_TRUE(wildcard::Match(TEXT("abc.def"), TEXT("*")));
+
+ EXPECT_NE(nullptr, wildcard::PartialMatch("abc", "*.*"));
+ EXPECT_NE(nullptr, wildcard::PartialMatch("abc.def", "*"));
+ EXPECT_EQ('\0', *wildcard::PartialMatch("abc", "*.*"));
+ EXPECT_EQ('\0', *wildcard::PartialMatch("abc.def", "*"));
+
+ EXPECT_FALSE(wildcard::Match(TEXT("abc"), TEXT("b*")));
+}
+
+TEST(DirectoryTreeTest, SimpleTreeInit)
+{
+ EXPECT_NO_THROW({
+ ContainerType tree(g_SHMName, 4096);
+ TreeType::NodePtrT p = tree.addFile(R"(C:\temp\test.txt)", 42, false);
+ EXPECT_NE(TreeType::NodePtrT(), p);
+ });
+}
+
+TEST(DirectoryTreeTest, FindNode)
+{
+ shared_memory_object::remove(g_SHMName);
+ ContainerType tree(g_SHMName, 64 * 1024);
+ EXPECT_NE(nullptr, tree.addFile(R"(C:\temp\bla)", 0x42, 0, false));
+
+ EXPECT_NE(nullptr, tree->findNode(R"(C:\temp)").get());
+ EXPECT_EQ(nullptr, tree->findNode(R"(C:\temp\bla\blubb)").get());
+}
+
+struct TestVisitor
+{
+ TreeType::NodePtrT lastNode;
+ bool flag40{false};
+
+ void operator()(const TreeType::NodePtrT& node)
+ {
+ lastNode = node;
+ flag40 = node->hasFlag(0x40);
+ logger()->debug("{0} - {1}", lastNode->name(), flag40);
+ // BOOST_LOG_SEV(globalLogger::get(), LogLevel::Debug) << lastNode->name() << " - "
+ // << flag40;
+ }
+};
+
+TEST(DirectoryTreeTest, VisitPath)
+{
+ shared_memory_object::remove(g_SHMName);
+ ContainerType tree(g_SHMName, 64 * 1024);
+ EXPECT_NE(nullptr, tree.addFile(R"(C:\temp\bla)", 1, 0x40, false));
+
+ TestVisitor visitor;
+
+ tree->visitPath(R"(C:\temp\bla\blubb)",
+ TreeType::VisitorFunction([&](const TreeType::NodePtrT& node) {
+ visitor(node);
+ }));
+ EXPECT_TRUE(visitor.flag40);
+ EXPECT_EQ("bla", visitor.lastNode->name());
+}
+
+TEST(DirectoryTreeTest, WildCardFind)
+{
+ shared_memory_object::remove(g_SHMName);
+ EXPECT_NO_THROW({
+ ContainerType tree(g_SHMName, 64 * 1024);
+
+ EXPECT_NE(nullptr, tree.addFile(R"(C:\temp)", 1, FLAG_DIRECTORY, false));
+ EXPECT_NE(nullptr, tree.addFile(R"(C:\temp\abc)", 1, 0, false));
+ EXPECT_NE(nullptr, tree.addFile(R"(C:\temp\abd)", 2, 0, false));
+ EXPECT_NE(nullptr, tree.addFile(R"(C:\temp\ace)", 3, 0, false));
+
+ EXPECT_EQ(3, tree->find(R"(C:\temp\*)").size());
+ EXPECT_NE(nullptr, tree->node("C:"));
+ EXPECT_EQ(1, tree->node("C:")->find("*").size());
+ EXPECT_NE(nullptr, tree->node("C:")->node("temp"));
+ EXPECT_EQ(3, tree->node("C:")->node("temp")->find("*").size()); // alternative
+ // search on the top-level
+ EXPECT_EQ(1, tree->find("*").size());
+ // * should work
+ EXPECT_EQ(2, tree->find(R"(C:\temp\ab*)").size());
+ // * does not match directory separators
+ EXPECT_EQ(0, tree->find("*ab*").size());
+ // matches only the directory itself
+ EXPECT_EQ(1, tree->find(R"(C:\temp*)").size());
+ });
+}
+
+TEST(DirectoryTreeTest, SHMAllocation)
+{
+ EXPECT_NO_THROW({
+ ContainerType create(g_SHMName, 64 * 1024);
+
+ { // creation
+ create.addFile(R"(C:\temp\abc)", 1, false);
+ create.addFile(R"(C:\temp\abd)", 2, false);
+ create.addFile(R"(C:\temp\ace)", 3, false);
+ }
+
+ { // access
+ ContainerType access(g_SHMName, 64 * 1024);
+ EXPECT_NE(nullptr, access.get());
+ std::vector<TreeType::NodePtrT> res = access->find(R"(C:\temp\*)");
+ EXPECT_EQ(3, res.size()); // matches the three files
+ EXPECT_EQ(access->m_Self.lock().get(), access->node("C:")->parent().get());
+ }
+ });
+}
+
+TEST(DirectoryTreeTest, SHMAllocationError)
+{
+ EXPECT_NO_THROW({
+ try {
+ ContainerType tree(g_SHMName, 4096);
+ int c = 0;
+ for (char i = 'a'; i <= 'z'; ++i) {
+ for (char j = 'a'; j <= 'z'; ++j) {
+ std::string name = std::string(R"(C:\temp\)") + i + j;
+ tree.addFile(name, ++c, false);
+ }
+ }
+
+ EXPECT_EQ(1, tree->node("C:")->node("temp")->node("aa", MissingThrow)->data());
+ EXPECT_EQ(26, tree->node("C:")->node("temp")->node("az", MissingThrow)->data());
+ } catch (const std::exception& e) {
+ logger()->error("{0}", e.what());
+ // BOOST_LOG_SEV(globalLogger::get(), LogLevel::Error) << e.what();
+ throw;
+ }
+ });
+}
+
+TEST(DirectoryTreeTest, SHMAllocationErrorComplex)
+{
+ EXPECT_NO_THROW({
+ try {
+ ComplexContainerType tree(g_SHMName, 4096);
+ SHMString str = tree.create("gaga");
+ for (char i = 'a'; i <= 'z'; ++i) {
+ for (char j = 'a'; j <= 'z'; ++j) {
+ std::string name = std::string(R"(C:\temp\)") + i + j;
+ tree.addFile(name, str, false);
+ }
+ }
+ EXPECT_STREQ(
+ str.c_str(),
+ tree->node("C:")->node("temp")->node("aa", MissingThrow)->data().c_str());
+ EXPECT_STREQ(
+ str.c_str(),
+ tree->node("C:")->node("temp")->node("az", MissingThrow)->data().c_str());
+ } catch (const std::exception& e) {
+ logger()->error("{}", e.what());
+ throw;
+ }
+ });
+}
+
+int main(int argc, char** argv)
+{
+ auto logger = spdlog::stdout_logger_mt("usvfs");
+ logger->set_level(spdlog::level::warn);
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}