diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a5cc14c..18175704 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,10 +292,15 @@ if(FUSE_FOUND AND (WITH_LEGACY_FUSE OR NOT FUSE3_FOUND)) endif() if(WITH_TESTS) - add_executable(dwarfs_test test/dwarfs.cpp test/loremipsum.cpp) + add_library(test_helpers test/test_helpers.cpp test/loremipsum.cpp) + target_link_libraries(test_helpers folly) +endif() + +if(WITH_TESTS) + add_executable(dwarfs_test test/dwarfs.cpp) add_executable(dwarfs_compat_test test/dwarfs_compat.cpp) - target_link_libraries(dwarfs_test gtest_main) + target_link_libraries(dwarfs_test test_helpers gtest_main) target_link_libraries(dwarfs_compat_test gtest_main) list(APPEND BINARY_TARGETS dwarfs_test dwarfs_compat_test) diff --git a/test/dwarfs.cpp b/test/dwarfs.cpp index 2a40c404..668e738a 100644 --- a/test/dwarfs.cpp +++ b/test/dwarfs.cpp @@ -36,155 +36,11 @@ #include "dwarfs/logger.h" #include "dwarfs/mmif.h" #include "dwarfs/options.h" -#include "dwarfs/os_access.h" #include "dwarfs/progress.h" #include "dwarfs/scanner.h" -#include "dwarfs/script.h" #include "loremipsum.h" #include "mmap_mock.h" - -namespace dwarfs { -namespace test { - -class dir_reader_mock : public dir_reader { - public: - dir_reader_mock(std::vector&& files) - : m_files(files) - , m_index(0) {} - - bool read(std::string& name) const override { - if (m_index < m_files.size()) { - name = m_files[m_index++]; - return true; - } - - return false; - } - - private: - std::vector m_files; - mutable size_t m_index; -}; - -namespace { - -struct simplestat { - ::ino_t st_ino; - ::mode_t st_mode; - ::nlink_t st_nlink; - ::uid_t st_uid; - ::gid_t st_gid; - ::off_t st_size; - ::dev_t st_rdev; - uint64_t atime; - uint64_t mtime; - uint64_t ctime; -}; - -std::map statmap{ - {"", {1, S_IFDIR | 0777, 1, 1000, 100, 0, 0, 1, 2, 3}}, - {"/test.pl", {3, S_IFREG | 0644, 2, 1000, 100, 0, 0, 1001, 1002, 1003}}, - {"/somelink", {4, S_IFLNK | 0777, 1, 1000, 100, 16, 0, 2001, 2002, 2003}}, - {"/somedir", {5, S_IFDIR | 0777, 1, 1000, 100, 0, 0, 3001, 3002, 3003}}, - {"/foo.pl", {6, S_IFREG | 0600, 2, 1337, 0, 23456, 0, 4001, 4002, 4003}}, - {"/bar.pl", {6, S_IFREG | 0600, 2, 1337, 0, 23456, 0, 4001, 4002, 4003}}, - {"/baz.pl", {16, S_IFREG | 0600, 2, 1337, 0, 23456, 0, 8001, 8002, 8003}}, - {"/ipsum.txt", - {7, S_IFREG | 0644, 1, 1000, 100, 2000000, 0, 5001, 5002, 5003}}, - {"/somedir/ipsum.py", - {9, S_IFREG | 0644, 1, 1000, 100, 10000, 0, 6001, 6002, 6003}}, - {"/somedir/bad", - {10, S_IFLNK | 0777, 1, 1000, 100, 6, 0, 7001, 7002, 7003}}, - {"/somedir/pipe", - {12, S_IFIFO | 0644, 1, 1000, 100, 0, 0, 8001, 8002, 8003}}, - {"/somedir/null", {13, S_IFCHR | 0666, 1, 0, 0, 0, 259, 9001, 9002, 9003}}, - {"/somedir/zero", - {14, S_IFCHR | 0666, 1, 0, 0, 0, 261, 4000010001, 4000020002, 4000030003}}, -}; -} // namespace - -class os_access_mock : public os_access { - public: - std::shared_ptr opendir(const std::string& path) const override { - if (path.empty()) { - std::vector files{ - ".", "..", "test.pl", "somelink", "somedir", - "foo.pl", "bar.pl", "baz.pl", "ipsum.txt", - }; - - return std::make_shared(std::move(files)); - } else if (path == "/somedir") { - std::vector files{ - ".", "..", "ipsum.py", "bad", "pipe", "null", "zero", - }; - - return std::make_shared(std::move(files)); - } - - throw std::runtime_error("oops"); - } - - void lstat(const std::string& path, struct ::stat* st) const override { - const simplestat& sst = statmap[path]; - std::memset(st, 0, sizeof(*st)); - st->st_ino = sst.st_ino; - st->st_mode = sst.st_mode; - st->st_nlink = sst.st_nlink; - st->st_uid = sst.st_uid; - st->st_gid = sst.st_gid; - st->st_size = sst.st_size; - st->st_atime = sst.atime; - st->st_mtime = sst.mtime; - st->st_ctime = sst.ctime; - st->st_rdev = sst.st_rdev; - } - - std::string readlink(const std::string& path, size_t size) const override { - if (path == "/somelink" && size == 16) { - return "somedir/ipsum.py"; - } else if (path == "/somedir/bad" && size == 6) { - return "../foo"; - } - - throw std::runtime_error("oops"); - } - - std::shared_ptr - map_file(const std::string& path, size_t size) const override { - const simplestat& sst = statmap[path]; - - if (size == static_cast(sst.st_size)) { - return std::make_shared(loremipsum(size)); - } - - throw std::runtime_error("oops"); - } - - int access(const std::string&, int) const override { return 0; } -}; - -class script_mock : public script { - public: - bool has_configure() const override { return true; } - bool has_filter() const override { return true; } - bool has_transform() const override { return true; } - bool has_order() const override { return true; } - - void configure(options_interface const& /*oi*/) override {} - - bool filter(entry_interface const& /*ei*/) override { return true; } - - void transform(entry_interface& /*ei*/) override { - // do nothing - } - - void order(inode_vector& /*iv*/) override { - // do nothing - } -}; - -} // namespace test -} // namespace dwarfs +#include "test_helpers.h" using namespace dwarfs; diff --git a/test/test_helpers.cpp b/test/test_helpers.cpp new file mode 100644 index 00000000..b503a621 --- /dev/null +++ b/test/test_helpers.cpp @@ -0,0 +1,126 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/** + * \author Marcus Holland-Moritz (github@mhxnet.de) + * \copyright Copyright (c) Marcus Holland-Moritz + * + * This file is part of dwarfs. + * + * dwarfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dwarfs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dwarfs. If not, see . + */ + +#include +#include + +#include "loremipsum.h" +#include "mmap_mock.h" +#include "test_helpers.h" + +namespace dwarfs { +namespace test { + +std::map statmap{ + {"", {1, S_IFDIR | 0777, 1, 1000, 100, 0, 0, 1, 2, 3}}, + {"/test.pl", {3, S_IFREG | 0644, 2, 1000, 100, 0, 0, 1001, 1002, 1003}}, + {"/somelink", {4, S_IFLNK | 0777, 1, 1000, 100, 16, 0, 2001, 2002, 2003}}, + {"/somedir", {5, S_IFDIR | 0777, 1, 1000, 100, 0, 0, 3001, 3002, 3003}}, + {"/foo.pl", {6, S_IFREG | 0600, 2, 1337, 0, 23456, 0, 4001, 4002, 4003}}, + {"/bar.pl", {6, S_IFREG | 0600, 2, 1337, 0, 23456, 0, 4001, 4002, 4003}}, + {"/baz.pl", {16, S_IFREG | 0600, 2, 1337, 0, 23456, 0, 8001, 8002, 8003}}, + {"/ipsum.txt", + {7, S_IFREG | 0644, 1, 1000, 100, 2000000, 0, 5001, 5002, 5003}}, + {"/somedir/ipsum.py", + {9, S_IFREG | 0644, 1, 1000, 100, 10000, 0, 6001, 6002, 6003}}, + {"/somedir/bad", + {10, S_IFLNK | 0777, 1, 1000, 100, 6, 0, 7001, 7002, 7003}}, + {"/somedir/pipe", + {12, S_IFIFO | 0644, 1, 1000, 100, 0, 0, 8001, 8002, 8003}}, + {"/somedir/null", {13, S_IFCHR | 0666, 1, 0, 0, 0, 259, 9001, 9002, 9003}}, + {"/somedir/zero", + {14, S_IFCHR | 0666, 1, 0, 0, 0, 261, 4000010001, 4000020002, 4000030003}}, +}; + +dir_reader_mock::dir_reader_mock(std::vector&& files) + : m_files(files) + , m_index(0) {} + +bool dir_reader_mock::read(std::string& name) const { + if (m_index < m_files.size()) { + name = m_files[m_index++]; + return true; + } + + return false; +} + +std::shared_ptr +os_access_mock::opendir(const std::string& path) const { + if (path.empty()) { + std::vector files{ + ".", "..", "test.pl", "somelink", "somedir", + "foo.pl", "bar.pl", "baz.pl", "ipsum.txt", + }; + + return std::make_shared(std::move(files)); + } else if (path == "/somedir") { + std::vector files{ + ".", "..", "ipsum.py", "bad", "pipe", "null", "zero", + }; + + return std::make_shared(std::move(files)); + } + + throw std::runtime_error("oops"); +} + +void os_access_mock::lstat(const std::string& path, struct ::stat* st) const { + const simplestat& sst = statmap[path]; + std::memset(st, 0, sizeof(*st)); + st->st_ino = sst.st_ino; + st->st_mode = sst.st_mode; + st->st_nlink = sst.st_nlink; + st->st_uid = sst.st_uid; + st->st_gid = sst.st_gid; + st->st_size = sst.st_size; + st->st_atime = sst.atime; + st->st_mtime = sst.mtime; + st->st_ctime = sst.ctime; + st->st_rdev = sst.st_rdev; +} + +std::string +os_access_mock::readlink(const std::string& path, size_t size) const { + if (path == "/somelink" && size == 16) { + return "somedir/ipsum.py"; + } else if (path == "/somedir/bad" && size == 6) { + return "../foo"; + } + + throw std::runtime_error("oops"); +} + +std::shared_ptr +os_access_mock::map_file(const std::string& path, size_t size) const { + const simplestat& sst = statmap[path]; + + if (size == static_cast(sst.st_size)) { + return std::make_shared(loremipsum(size)); + } + + throw std::runtime_error("oops"); +} + +int os_access_mock::access(const std::string&, int) const { return 0; } + +} // namespace test +} // namespace dwarfs diff --git a/test/test_helpers.h b/test/test_helpers.h new file mode 100644 index 00000000..1f0917e2 --- /dev/null +++ b/test/test_helpers.h @@ -0,0 +1,95 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/** + * \author Marcus Holland-Moritz (github@mhxnet.de) + * \copyright Copyright (c) Marcus Holland-Moritz + * + * This file is part of dwarfs. + * + * dwarfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dwarfs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dwarfs. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include "dwarfs/os_access.h" +#include "dwarfs/script.h" + +namespace dwarfs { +namespace test { + +class dir_reader_mock : public dir_reader { + public: + dir_reader_mock(std::vector&& files); + + bool read(std::string& name) const override; + + private: + std::vector m_files; + mutable size_t m_index; +}; + +class os_access_mock : public os_access { + public: + std::shared_ptr opendir(const std::string& path) const override; + + void lstat(const std::string& path, struct ::stat* st) const override; + + std::string readlink(const std::string& path, size_t size) const override; + + std::shared_ptr + map_file(const std::string& path, size_t size) const override; + + int access(const std::string&, int) const override; +}; + +class script_mock : public script { + public: + bool has_configure() const override { return true; } + bool has_filter() const override { return true; } + bool has_transform() const override { return true; } + bool has_order() const override { return true; } + + void configure(options_interface const& /*oi*/) override {} + + bool filter(entry_interface const& /*ei*/) override { return true; } + + void transform(entry_interface& /*ei*/) override { + // do nothing + } + + void order(inode_vector& /*iv*/) override { + // do nothing + } +}; + +struct simplestat { + ::ino_t st_ino; + ::mode_t st_mode; + ::nlink_t st_nlink; + ::uid_t st_uid; + ::gid_t st_gid; + ::off_t st_size; + ::dev_t st_rdev; + uint64_t atime; + uint64_t mtime; + uint64_t ctime; +}; + +extern std::map statmap; + +} // namespace test +} // namespace dwarfs