mirror of https://github.com/djcb/mu.git
parent
805c5aa287
commit
2f5602b938
|
@ -50,8 +50,8 @@ exec guile -e main -s $0 $@
|
||||||
(n-results-or-exit "file:custer.*" 1)
|
(n-results-or-exit "file:custer.*" 1)
|
||||||
(n-results-or-exit "j:sit*" 1)
|
(n-results-or-exit "j:sit*" 1)
|
||||||
(n-results-or-exit "mime:image/jpeg" 1)
|
(n-results-or-exit "mime:image/jpeg" 1)
|
||||||
(n-results-or-exit "mime:text/plain" 13)
|
(n-results-or-exit "mime:text/plain" 14)
|
||||||
(n-results-or-exit "y:text*" 13)
|
(n-results-or-exit "y:text*" 14)
|
||||||
(n-results-or-exit "y:image*" 1)
|
(n-results-or-exit "y:image*" 1)
|
||||||
(n-results-or-exit "mime:message/rfc822" 2))
|
(n-results-or-exit "mime:message/rfc822" 2))
|
||||||
|
|
||||||
|
@ -97,8 +97,8 @@ exec guile -e main -s $0 $@
|
||||||
(define (test-stats)
|
(define (test-stats)
|
||||||
"Test statistical functions."
|
"Test statistical functions."
|
||||||
;; average
|
;; average
|
||||||
(num-equal-or-exit (mu:average mu:size) 82152/13)
|
(num-equal-or-exit (mu:average mu:size) 82601/14)
|
||||||
(num-equal-or-exit (floor (mu:stddev mu:size)) 13020.0)
|
(num-equal-or-exit (floor (mu:stddev mu:size)) 12637.0)
|
||||||
(num-equal-or-exit (mu:max mu:size) 46308)
|
(num-equal-or-exit (mu:max mu:size) 46308)
|
||||||
(num-equal-or-exit (mu:min mu:size) 111))
|
(num-equal-or-exit (mu:min mu:size) 111))
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,13 @@ test('test-query-xapianizer',
|
||||||
dependencies: [lib_mu_dep]))
|
dependencies: [lib_mu_dep]))
|
||||||
|
|
||||||
|
|
||||||
|
test('test-indexer',
|
||||||
|
executable('test-indexer', 'mu-indexer.cc',
|
||||||
|
install: false,
|
||||||
|
cpp_args: ['-DBUILD_TESTS'],
|
||||||
|
dependencies: [glib_dep, config_h_dep,
|
||||||
|
lib_mu_dep]))
|
||||||
|
|
||||||
test('test-scanner',
|
test('test-scanner',
|
||||||
executable('test-scanner', 'mu-scanner.cc',
|
executable('test-scanner', 'mu-scanner.cc',
|
||||||
install: false,
|
install: false,
|
||||||
|
|
|
@ -61,6 +61,8 @@ test_basic()
|
||||||
MemDb db;
|
MemDb db;
|
||||||
Config conf_db{db};
|
Config conf_db{db};
|
||||||
|
|
||||||
|
g_assert_false(conf_db.read_only());
|
||||||
|
|
||||||
using Id = Config::Id;
|
using Id = Config::Id;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -69,7 +71,9 @@ test_basic()
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
conf_db.set<Id::RootMaildir>("/home/djcb/Maildir");
|
auto res = conf_db.set<Id::RootMaildir>("/home/djcb/Maildir");
|
||||||
|
assert_valid_result(res);
|
||||||
|
|
||||||
const auto rmd = conf_db.get<Id::RootMaildir>();
|
const auto rmd = conf_db.get<Id::RootMaildir>();
|
||||||
assert_equal(rmd, "/home/djcb/Maildir");
|
assert_equal(rmd, "/home/djcb/Maildir");
|
||||||
}
|
}
|
||||||
|
|
|
@ -471,3 +471,87 @@ Indexer::completed() const
|
||||||
{
|
{
|
||||||
return priv_->completed_;
|
return priv_->completed_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if BUILD_TESTS
|
||||||
|
#include "mu-test-utils.hh"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_index_basic()
|
||||||
|
{
|
||||||
|
allow_warnings();
|
||||||
|
|
||||||
|
TempDir tdir;
|
||||||
|
auto store = Store::make_new(tdir.path(), MU_TESTMAILDIR2);
|
||||||
|
assert_valid_result(store);
|
||||||
|
g_assert_true(store->empty());
|
||||||
|
|
||||||
|
Indexer& idx{store->indexer()};
|
||||||
|
|
||||||
|
g_assert_false(idx.is_running());
|
||||||
|
g_assert_true(idx.stop());
|
||||||
|
g_assert_cmpuint(idx.completed(),==, 0);
|
||||||
|
|
||||||
|
const auto& prog{idx.progress()};
|
||||||
|
g_assert_false(prog.running);
|
||||||
|
g_assert_cmpuint(prog.checked,==, 0);
|
||||||
|
g_assert_cmpuint(prog.updated,==, 0);
|
||||||
|
g_assert_cmpuint(prog.removed,==, 0);
|
||||||
|
|
||||||
|
Indexer::Config conf{};
|
||||||
|
conf.ignore_noupdate = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto start{time({})};
|
||||||
|
g_assert_true(idx.start(conf));
|
||||||
|
while (idx.is_running())
|
||||||
|
g_usleep(10000);
|
||||||
|
|
||||||
|
g_assert_false(idx.is_running());
|
||||||
|
g_assert_true(idx.stop());
|
||||||
|
|
||||||
|
g_assert_cmpuint(idx.completed() - start, <, 5);
|
||||||
|
|
||||||
|
g_assert_false(prog.running);
|
||||||
|
g_assert_cmpuint(prog.checked,==, 14);
|
||||||
|
g_assert_cmpuint(prog.updated,==, 14);
|
||||||
|
g_assert_cmpuint(prog.removed,==, 0);
|
||||||
|
|
||||||
|
g_assert_cmpuint(store->size(),==,14);
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.lazy_check = true;
|
||||||
|
conf.max_threads = 1;
|
||||||
|
conf.ignore_noupdate = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto start{time({})};
|
||||||
|
g_assert_true(idx.start(conf));
|
||||||
|
while (idx.is_running())
|
||||||
|
g_usleep(10000);
|
||||||
|
|
||||||
|
g_assert_false(idx.is_running());
|
||||||
|
g_assert_true(idx.stop());
|
||||||
|
|
||||||
|
g_assert_cmpuint(idx.completed() - start, <, 3);
|
||||||
|
|
||||||
|
g_assert_false(prog.running);
|
||||||
|
g_assert_cmpuint(prog.checked,==, 0);
|
||||||
|
g_assert_cmpuint(prog.updated,==, 0);
|
||||||
|
g_assert_cmpuint(prog.removed,==, 0);
|
||||||
|
|
||||||
|
g_assert_cmpuint(store->size(),==, 14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
mu_test_init(&argc, &argv);
|
||||||
|
|
||||||
|
g_test_add_func("/index/basic", test_index_basic);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /*BUILD_TESTS*/
|
||||||
|
|
|
@ -74,9 +74,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Stop indexing. If not indexing, do nothing.
|
* Stop indexing. If not indexing, do nothing.
|
||||||
*
|
*
|
||||||
*
|
* @return true if we stopped indexing, or indexing was not underway; false otherwise.
|
||||||
* @return true if we stopped indexing, or indexing was not underway.
|
|
||||||
* False otherwise.
|
|
||||||
*/
|
*/
|
||||||
bool stop();
|
bool stop();
|
||||||
|
|
||||||
|
@ -89,12 +87,10 @@ public:
|
||||||
|
|
||||||
// Object describing current progress
|
// Object describing current progress
|
||||||
struct Progress {
|
struct Progress {
|
||||||
void reset()
|
void reset() {
|
||||||
{
|
|
||||||
running = false;
|
running = false;
|
||||||
checked = updated = removed = 0;
|
checked = updated = removed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::atomic<bool> running{}; /**< Is an index operation in progress? */
|
std::atomic<bool> running{}; /**< Is an index operation in progress? */
|
||||||
std::atomic<size_t> checked{}; /**< Number of messages checked for changes */
|
std::atomic<size_t> checked{}; /**< Number of messages checked for changes */
|
||||||
std::atomic<size_t> updated{}; /**< Number of messages (re)parsed/added/updated */
|
std::atomic<size_t> updated{}; /**< Number of messages (re)parsed/added/updated */
|
||||||
|
|
|
@ -161,18 +161,11 @@ get_target_fullpath(const std::string& src, const std::string& targetpath,
|
||||||
* including a hash of the srcname in the targetname. This helps if
|
* including a hash of the srcname in the targetname. This helps if
|
||||||
* there are copies of a message (which all have the same basename)
|
* there are copies of a message (which all have the same basename)
|
||||||
*/
|
*/
|
||||||
std::string fulltargetpath;
|
|
||||||
if (unique_names)
|
if (unique_names)
|
||||||
fulltargetpath = join_paths(targetpath,
|
return join_paths(targetpath, in_cur ? "cur" : "new",
|
||||||
in_cur ? "cur" : "new",
|
mu_format("{:08x}-{}", g_str_hash(src.c_str()), srcfile));
|
||||||
mu_format("{:08x}-{}",
|
|
||||||
g_str_hash(src.c_str()),
|
|
||||||
srcfile));
|
|
||||||
else
|
else
|
||||||
fulltargetpath = join_paths(targetpath,
|
return join_paths(targetpath, in_cur ? "cur" : "new", srcfile.c_str());
|
||||||
in_cur ? "cur" : "new",
|
|
||||||
srcfile.c_str());
|
|
||||||
return fulltargetpath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void>
|
Result<void>
|
||||||
|
@ -251,6 +244,7 @@ Mu::maildir_clear_links(const std::string& path)
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* LCOV_EXCL_START*/
|
||||||
static Mu::Result<void>
|
static Mu::Result<void>
|
||||||
msg_move_verify(const std::string& src, const std::string& dst)
|
msg_move_verify(const std::string& src, const std::string& dst)
|
||||||
{
|
{
|
||||||
|
@ -270,7 +264,11 @@ msg_move_verify(const std::string& src, const std::string& dst)
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
/* LCOV_EXCL_STOP*/
|
||||||
|
|
||||||
|
/* LCOV_EXCL_START*/
|
||||||
|
// don't use this right now, since it gives as (false alarm)
|
||||||
|
// valgrind warning in tests
|
||||||
/* use GIO to move files; this is slower than rename() so only use
|
/* use GIO to move files; this is slower than rename() so only use
|
||||||
* this when needed: when moving across filesystems */
|
* this when needed: when moving across filesystems */
|
||||||
G_GNUC_UNUSED static Mu::Result<void>
|
G_GNUC_UNUSED static Mu::Result<void>
|
||||||
|
@ -291,6 +289,7 @@ msg_move_g_file(const std::string& src, const std::string& dst)
|
||||||
else
|
else
|
||||||
return Err(Error::Code::File, &err, "error moving {} -> {}", src, dst);
|
return Err(Error::Code::File, &err, "error moving {} -> {}", src, dst);
|
||||||
}
|
}
|
||||||
|
/* LCOV_EXCL_STOPT*/
|
||||||
|
|
||||||
/* use mv to move files; this is slower than rename() so only use this when
|
/* use mv to move files; this is slower than rename() so only use this when
|
||||||
* needed: when moving across filesystems */
|
* needed: when moving across filesystems */
|
||||||
|
|
|
@ -431,6 +431,7 @@ test_xapian()
|
||||||
// to be the same between versions
|
// to be the same between versions
|
||||||
auto&& zz{make_xapian_query(store, R"(subject:"hello world")")};
|
auto&& zz{make_xapian_query(store, R"(subject:"hello world")")};
|
||||||
assert_valid_result(zz);
|
assert_valid_result(zz);
|
||||||
|
/* LCOV_EXCL_START*/
|
||||||
if (zz->get_description() != R"(Query((Shello PHRASE 2 Sworld)))") {
|
if (zz->get_description() != R"(Query((Shello PHRASE 2 Sworld)))") {
|
||||||
if (mu_test_mu_hacker()) {
|
if (mu_test_mu_hacker()) {
|
||||||
// in the mu hacker case, we want to be warned if Xapian changed.
|
// in the mu hacker case, we want to be warned if Xapian changed.
|
||||||
|
@ -441,6 +442,7 @@ test_xapian()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* LCOV_EXCL_STOP*/
|
||||||
|
|
||||||
std::vector<TestCase> cases = {
|
std::vector<TestCase> cases = {
|
||||||
|
|
||||||
|
|
|
@ -103,20 +103,16 @@ ignore_dentry(const dentry_t& dentry)
|
||||||
(d_name[2] == '\0' && d_name[0] == '.' && d_name[1] == '.'))
|
(d_name[2] == '\0' && d_name[0] == '.' && d_name[1] == '.'))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (g_strcmp0(d_name, "tmp") == 0)
|
if (d_name[0] != 't' && d_name[0] != 'h' && d_name[0] != '.')
|
||||||
return true;
|
return false; /* don't ignore */
|
||||||
|
|
||||||
if (d_name[0] == '.') {
|
if (::strcmp(d_name, "tmp") == 0 || ::strcmp(d_name, "hcache.db") == 0)
|
||||||
if (d_name[1] == '#') /* emacs? */
|
return true; // ignore
|
||||||
return true;
|
|
||||||
if (g_strcmp0(d_name + 1, "nnmaildir") == 0) /* gnus? */
|
|
||||||
return true;
|
|
||||||
if (g_strcmp0(d_name + 1, "notmuch") == 0) /* notmuch? */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_strcmp0(d_name, "hcache.db") == 0) /* mutt cache? */
|
if (d_name[0] == '.')
|
||||||
return true;
|
for (auto dname : { "nnmaildir", "notmuch", "noindex", "noupdate"})
|
||||||
|
if (::strcmp(d_name + 1, dname) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false; /* don't ignore */
|
return false; /* don't ignore */
|
||||||
}
|
}
|
||||||
|
@ -373,20 +369,13 @@ test_count_maildirs()
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char* argv[])
|
main(int argc, char* argv[])
|
||||||
try {
|
{
|
||||||
g_test_init(&argc, &argv, NULL);
|
mu_test_init(&argc, &argv);
|
||||||
|
|
||||||
g_test_add_func("/index/scan-maildirs", test_scan_maildirs);
|
g_test_add_func("/index/scan-maildirs", test_scan_maildirs);
|
||||||
g_test_add_func("/index/count-maildirs", test_count_maildirs);
|
g_test_add_func("/index/count-maildirs", test_count_maildirs);
|
||||||
|
|
||||||
return g_test_run();
|
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*/
|
#endif /*BUILD_TESTS*/
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## Copyright (C) 2021 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
## Copyright (C) 2021-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
##
|
##
|
||||||
## This program is free software; you can redistribute it and/or modify
|
## 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
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
|
||||||
**
|
|
||||||
** 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 the
|
|
||||||
** Free Software Foundation; either version 3, or (at your option) any
|
|
||||||
** later version.
|
|
||||||
**
|
|
||||||
** This program 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 this program; if not, write to the Free Software Foundation,
|
|
||||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "mu-indexer.hh"
|
|
||||||
#include "utils/mu-utils.hh"
|
|
||||||
#include "test-mu-common.h"
|
|
||||||
|
|
||||||
using namespace Mu;
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_index_maildir()
|
|
||||||
{
|
|
||||||
allow_warnings();
|
|
||||||
|
|
||||||
Store store{test_mu_common_get_random_tmpdir(), std::string{MU_TESTMAILDIR}};
|
|
||||||
Indexer idx{Indexer::Config{}, store};
|
|
||||||
|
|
||||||
g_assert_true(idx.start());
|
|
||||||
while (idx.is_running()) {
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_print("again!\n");
|
|
||||||
|
|
||||||
g_assert_true(idx.start());
|
|
||||||
while (idx.is_running()) {
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char* argv[])
|
|
||||||
try {
|
|
||||||
g_test_init(&argc, &argv, NULL);
|
|
||||||
|
|
||||||
g_test_add_func("/indexer/index-maildir", test_index_maildir);
|
|
||||||
|
|
||||||
return g_test_run();
|
|
||||||
|
|
||||||
} catch (const std::runtime_error& re) {
|
|
||||||
std::cerr << re.what() << "\n";
|
|
||||||
return 1;
|
|
||||||
} catch (...) {
|
|
||||||
std::cerr << "caught exception\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
|
@ -45,7 +45,7 @@ static Store
|
||||||
make_test_store(const std::string& test_path, const TestMap& test_map,
|
make_test_store(const std::string& test_path, const TestMap& test_map,
|
||||||
Option<const Config&> conf={})
|
Option<const Config&> conf={})
|
||||||
{
|
{
|
||||||
std::string maildir = test_path + "/Maildir/";
|
const auto maildir{join_paths(test_path, "/Maildir/")};
|
||||||
// note the trailing '/'
|
// note the trailing '/'
|
||||||
g_test_bug("2513");
|
g_test_bug("2513");
|
||||||
|
|
||||||
|
@ -819,7 +819,7 @@ html
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_cjk()
|
test_ngrams()
|
||||||
{
|
{
|
||||||
g_test_bug("2167");
|
g_test_bug("2167");
|
||||||
|
|
||||||
|
@ -882,9 +882,8 @@ main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
mu_test_init(&argc, &argv);
|
mu_test_init(&argc, &argv);
|
||||||
|
|
||||||
//_test_add_func("/store/query/cjk", test_cjk);
|
g_test_add_func("/store/query/simple",
|
||||||
|
test_simple);
|
||||||
g_test_add_func("/store/query/simple", test_simple);
|
|
||||||
g_test_add_func("/store/query/spam-address-components",
|
g_test_add_func("/store/query/spam-address-components",
|
||||||
test_spam_address_components);
|
test_spam_address_components);
|
||||||
g_test_add_func("/store/query/dups-related",
|
g_test_add_func("/store/query/dups-related",
|
||||||
|
@ -905,9 +904,8 @@ main(int argc, char* argv[])
|
||||||
test_related_dup_threaded);
|
test_related_dup_threaded);
|
||||||
g_test_add_func("/store/query/html",
|
g_test_add_func("/store/query/html",
|
||||||
test_html);
|
test_html);
|
||||||
|
g_test_add_func("/store/query/ngrams",
|
||||||
g_test_add_func("/store/query/cjk-once-more", test_cjk);
|
test_ngrams);
|
||||||
|
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -558,7 +558,7 @@ search_func(const std::string& expr, size_t expected)
|
||||||
static void
|
static void
|
||||||
test_mu_find_empty_query(void)
|
test_mu_find_empty_query(void)
|
||||||
{
|
{
|
||||||
search("\"\"", 13);
|
search("\"\"", 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -601,8 +601,8 @@ static void
|
||||||
test_mu_find_mime(void)
|
test_mu_find_mime(void)
|
||||||
{
|
{
|
||||||
search("mime:image/jpeg", 1);
|
search("mime:image/jpeg", 1);
|
||||||
search("mime:text/plain", 13);
|
search("mime:text/plain", 14);
|
||||||
search("y:text*", 13);
|
search("y:text*", 14);
|
||||||
search("y:image*", 1);
|
search("y:image*", 1);
|
||||||
search("mime:message/rfc822", 2);
|
search("mime:message/rfc822", 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
Date: Mon, 11 Sep 2023 19:57:25 -0400
|
||||||
|
From: "Tommy" <tommy@example.com>
|
||||||
|
Subject: Hide and seek
|
||||||
|
To: "Andreas" <andy@example.com>
|
||||||
|
Message-id: <3BE9E65sdfklsajdfl3E7A1A20D852173@msg.id>
|
||||||
|
MIME-version: 1.0
|
||||||
|
|
||||||
|
Behind the polished barrier
|
||||||
|
The pending storm draws near
|
||||||
|
Although it's an inferno
|
||||||
|
You can not step back for your fears
|
||||||
|
Hurry son I need to rest
|
||||||
|
finish the puzzle you do it best
|
||||||
|
I'll do what I can
|
||||||
|
But I am telling you
|
||||||
|
It can't be done without you!
|
Loading…
Reference in New Issue