diff --git a/lib/index/meson.build b/lib/index/meson.build index 237adf62..5da34fce 100644 --- a/lib/index/meson.build +++ b/lib/index/meson.build @@ -1,4 +1,4 @@ -## Copyright (C) 2021 Dirk-Jan C. Binnema +## Copyright (C) 2021-2023 Dirk-Jan C. Binnema ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -36,3 +36,14 @@ lib_mu_index=static_library('mu-index', [index_srcs], lib_mu_index_dep = declare_dependency( link_with: lib_mu_index ) + +# +# tests +# + +test('test-scanner', + executable('test-scanner', 'mu-scanner.cc', + install: false, + cpp_args: ['-DBUILD_TESTS'], + dependencies: [glib_dep, config_h_dep, + lib_mu_utils_dep])) diff --git a/lib/index/mu-scanner.cc b/lib/index/mu-scanner.cc index 5072eb9b..0b8aee80 100644 --- a/lib/index/mu-scanner.cc +++ b/lib/index/mu-scanner.cc @@ -134,7 +134,15 @@ Scanner::Private::process_dir(const std::string& path, bool is_maildir) if (!running_) return true; /* we're done */ - const auto dir = opendir(path.c_str()); + if (G_UNLIKELY(path.length() > PATH_MAX)) { + // note: unlikely to hit this, one case would be a + // self-referential symlink; that should be caught earlier, + // so this is just a backstop. + mu_warning("path is too long: {}", path); + return false; + } + + const auto dir{::opendir(path.c_str())}; if (G_UNLIKELY(!dir)) { mu_warning("failed to scan dir {}: {}", path, g_strerror(errno)); return false; @@ -145,7 +153,7 @@ Scanner::Private::process_dir(const std::string& path, bool is_maildir) while (running_) { errno = 0; - const auto dentry{readdir(dir)}; + const auto dentry{::readdir(dir)}; if (G_LIKELY(dentry)) { process_dentry(path, dentry, is_maildir); @@ -169,7 +177,7 @@ Scanner::Private::start() { const auto& path{root_dir_}; if (G_UNLIKELY(path.length() > PATH_MAX)) { - mu_warning("path too long"); + mu_warning("path is too long: {}", path); return false; } @@ -251,3 +259,51 @@ Scanner::is_running() const { return priv_->running_; } + + + + +#if BUILD_TESTS +#include "mu-test-utils.hh" + + +static void +test_scan_maildir() +{ + allow_warnings(); + + size_t count{}; + Scanner scanner{ + MU_TESTMAILDIR, + [&](const std::string& fullpath, const struct stat* statbuf, auto&& htype) -> bool { + mu_debug("{} {}", fullpath, statbuf->st_size); + ++count; + return true; + }}; + g_assert_true(scanner.start()); + + while (scanner.is_running()) { g_usleep(1000); } + + // very rudimentary test... + g_assert_cmpuint(count,==,23); +} + +int +main(int argc, char* argv[]) +try { + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/index/scanner/scan-maildir", test_scan_maildir); + + return g_test_run(); + +} catch (const std::runtime_error& re) { + mu_printerrln("caught runtime error: {}", re.what()); + return 1; +} catch (...) { + mu_printerrln("caught exception"); + return 1; +} + + +#endif /*BUILD_TESTS*/ diff --git a/lib/index/test-scanner.cc b/lib/index/test-scanner.cc deleted file mode 100644 index 4835aa13..00000000 --- a/lib/index/test-scanner.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* -** Copyright (C) 2017 Dirk-Jan C. Binnema -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public License -** as published by the Free Software Foundation; either version 2.1 -** of the License, or (at your option) any later version. -** -** This library 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 -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; if not, write to the Free -** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -** 02110-1301, USA. -*/ - -#include -#include - -#include -#include - -#include "mu-scanner.hh" -#include "mu-utils.hh" - -using namespace Mu; - -static void -test_scan_maildir() -{ - allow_warnings(); - - Scanner scanner{ - "/home/djcb/Maildir", - [](const dirent* dentry) -> bool { - g_print("%02x %s\n", dentry->d_type, dentry->d_name); - return true; - }, - [](const std::string& fullpath, const struct stat* statbuf, auto&& info) -> bool { - g_print("%s %zu\n", fullpath.c_str(), statbuf->st_size); - return true; - }}; - g_assert_true(scanner.start()); - - while (scanner.is_running()) { - sleep(1); - } -} - -int -main(int argc, char* argv[]) -try { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/utils/scanner/scan-maildir", test_scan_maildir); - - return g_test_run(); - -} catch (const std::runtime_error& re) { - std::cerr << re.what() << "\n"; - return 1; -}