nextcloud-desktop/test/csync/csync_tests/check_csync_update.cpp
Jocelyn Turcotte e0fa5723eb
Use a C++ contructor and destructor for CSYNC
Merge csync_create and csync_init into the constructor and
replace csync_destroy with the destructor.

Also use a QByteArray for csync_s::root_perms and flatten
csync_rename_s as a rename sub-struct of csync_s since it
can now handle C++ types.
2017-10-05 22:01:04 +02:00

412 lines
12 KiB
C++

/*
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
*
* 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "torture.h"
#include "csync_update.cpp"
#define TESTDB "/tmp/check_csync/journal.db"
static int firstrun = 1;
static void statedb_create_metadata_table(sqlite3 *db)
{
int rc = 0;
if( db ) {
const char *sql = "CREATE TABLE IF NOT EXISTS metadata("
"phash INTEGER(8),"
"pathlen INTEGER,"
"path VARCHAR(4096),"
"inode INTEGER,"
"uid INTEGER,"
"gid INTEGER,"
"mode INTEGER,"
"modtime INTEGER(8),"
"type INTEGER,"
"md5 VARCHAR(32),"
"fileid VARCHAR(128),"
"remotePerm VARCHAR(128),"
"filesize BIGINT,"
"ignoredChildrenRemote INT,"
"contentChecksum TEXT,"
"contentChecksumTypeId INTEGER,"
"PRIMARY KEY(phash));";
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
//const char *msg = sqlite3_errmsg(db);
assert_int_equal( rc, SQLITE_OK );
sql = "CREATE TABLE IF NOT EXISTS checksumtype("
"id INTEGER PRIMARY KEY,"
"name TEXT UNIQUE"
");";
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
assert_int_equal( rc, SQLITE_OK );
}
}
static void statedb_insert_metadata(sqlite3 *db)
{
int rc = 0;
if( db ) {
char *stmt = sqlite3_mprintf("INSERT INTO metadata"
"(phash, pathlen, path, inode, uid, gid, mode, modtime,type,md5) VALUES"
"(%lld, %d, '%q', %d, %d, %d, %d, %lld, %d, '%q');",
(long long signed int)42,
42,
"I_was_wurst_before_I_became_wurstsalat",
619070,
42,
42,
42,
(long long signed int)42,
0,
"4711");
char *errmsg;
rc = sqlite3_exec(db, stmt, NULL, NULL, &errmsg);
sqlite3_free(stmt);
assert_int_equal( rc, SQLITE_OK );
}
}
static int setup(void **state)
{
CSYNC *csync;
int rc;
unlink(TESTDB);
rc = system("mkdir -p /tmp/check_csync");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
csync = new CSYNC("/tmp/check_csync1", TESTDB);
/* Create a new db with metadata */
sqlite3 *db;
// csync->statedb.file = c_strdup(TESTDB);
rc = sqlite3_open(csync->statedb.file, &db);
statedb_create_metadata_table(db);
if( firstrun ) {
statedb_insert_metadata(db);
firstrun = 0;
}
sqlite3_close(db);
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
assert_int_equal(rc, 0);
*state = csync;
return 0;
}
static int setup_ftw(void **state)
{
CSYNC *csync;
int rc;
rc = system("mkdir -p /tmp/check_csync");
assert_int_equal(rc, 0);
rc = system("mkdir -p /tmp/check_csync1");
assert_int_equal(rc, 0);
csync = new CSYNC("/tmp", TESTDB);
sqlite3 *db = NULL;
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
assert_int_equal(rc, SQLITE_OK);
statedb_create_metadata_table(db);
rc = sqlite3_close(db);
assert_int_equal(rc, SQLITE_OK);
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
assert_int_equal(rc, 0);
csync->statedb.file = c_strdup( TESTDB );
*state = csync;
return 0;
}
static int teardown(void **state)
{
CSYNC *csync = (CSYNC*)*state;
unlink( csync->statedb.file);
delete csync;
*state = NULL;
return 0;
}
static int teardown_rm(void **state) {
int rc;
teardown(state);
rc = system("rm -rf /tmp/check_csync");
assert_int_equal(rc, 0);
rc = system("rm -rf /tmp/check_csync1");
assert_int_equal(rc, 0);
return 0;
}
/* create a file stat, caller must free memory */
static std::unique_ptr<csync_file_stat_t> create_fstat(const char *name,
ino_t inode,
time_t mtime)
{
std::unique_ptr<csync_file_stat_t> fs(new csync_file_stat_t);
time_t t;
if (name && *name) {
fs->path = name;
} else {
fs->path = "file.txt";
}
fs->type = CSYNC_FTW_TYPE_FILE;
if (inode == 0) {
fs->inode = 619070;
} else {
fs->inode = inode;
}
fs->size = 157459;
if (mtime == 0) {
fs->modtime = time(&t);
} else {
fs->modtime = mtime;
}
return fs;
}
static int failing_fn(CSYNC *ctx,
const char *file,
const csync_file_stat_t *fs,
int flag)
{
(void) ctx;
(void) file;
(void) fs;
(void) flag;
return -1;
}
/* detect a new file */
static void check_csync_detect_update(void **state)
{
CSYNC *csync = (CSYNC*)*state;
csync_file_stat_t *st;
std::unique_ptr<csync_file_stat_t> fs;
int rc;
fs = create_fstat("file.txt", 0, 1217597845);
rc = _csync_detect_update(csync,
"/tmp/check_csync1/file.txt",
fs.get(),
CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, 0);
/* the instruction should be set to new */
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
/* create a statedb */
csync_set_status(csync, 0xFFFF);
}
/* Test behaviour in case no db is there. For that its important that the
* test before this one uses teardown_rm.
*/
static void check_csync_detect_update_db_none(void **state)
{
CSYNC *csync = (CSYNC*)*state;
csync_file_stat_t *st;
std::unique_ptr<csync_file_stat_t> fs;
int rc;
fs = create_fstat("file.txt", 0, 1217597845);
rc = _csync_detect_update(csync,
"/tmp/check_csync1/file.txt",
fs.get(),
CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, 0);
/* the instruction should be set to new */
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
/* create a statedb */
csync_set_status(csync, 0xFFFF);
}
static void check_csync_detect_update_db_eval(void **state)
{
CSYNC *csync = (CSYNC*)*state;
csync_file_stat_t *st;
std::unique_ptr<csync_file_stat_t> fs;
int rc;
fs = create_fstat("file.txt", 0, 42);
rc = _csync_detect_update(csync,
"/tmp/check_csync1/file.txt",
fs.get(),
CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, 0);
/* the instruction should be set to new */
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
/* create a statedb */
csync_set_status(csync, 0xFFFF);
}
static void check_csync_detect_update_db_rename(void **state)
{
CSYNC *csync = (CSYNC*)*state;
// csync_file_stat_t *st;
std::unique_ptr<csync_file_stat_t> fs;
int rc = 0;
fs = create_fstat("wurst.txt", 0, 42);
csync_set_statedb_exists(csync, 1);
rc = _csync_detect_update(csync,
"/tmp/check_csync1/wurst.txt",
fs.get(),
CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, 0);
/* the instruction should be set to rename */
/*
* temporarily broken.
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_RENAME);
st->instruction = CSYNC_INSTRUCTION_UPDATED;
*/
/* create a statedb */
csync_set_status(csync, 0xFFFF);
}
static void check_csync_detect_update_db_new(void **state)
{
CSYNC *csync = (CSYNC*)*state;
csync_file_stat_t *st;
std::unique_ptr<csync_file_stat_t> fs;
int rc;
fs = create_fstat("file.txt", 42000, 0);
rc = _csync_detect_update(csync,
"/tmp/check_csync1/file.txt",
fs.get(),
CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, 0);
/* the instruction should be set to new */
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
/* create a statedb */
csync_set_status(csync, 0xFFFF);
}
static void check_csync_detect_update_null(void **state)
{
CSYNC *csync = (CSYNC*)*state;
std::unique_ptr<csync_file_stat_t> fs;
int rc;
fs = create_fstat("file.txt", 0, 0);
rc = _csync_detect_update(csync,
NULL,
fs.get(),
CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, -1);
rc = _csync_detect_update(csync,
"/tmp/check_csync1/file.txt",
NULL,
CSYNC_FTW_TYPE_FILE);
assert_int_equal(rc, -1);
}
static void check_csync_ftw(void **state)
{
CSYNC *csync = (CSYNC*)*state;
int rc;
rc = csync_ftw(csync, "/tmp", csync_walker, MAX_DEPTH);
assert_int_equal(rc, 0);
}
static void check_csync_ftw_empty_uri(void **state)
{
CSYNC *csync = (CSYNC*)*state;
int rc;
rc = csync_ftw(csync, "", csync_walker, MAX_DEPTH);
assert_int_equal(rc, -1);
}
static void check_csync_ftw_failing_fn(void **state)
{
CSYNC *csync = (CSYNC*)*state;
int rc;
rc = csync_ftw(csync, "/tmp", failing_fn, MAX_DEPTH);
assert_int_equal(rc, -1);
}
int torture_run_tests(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(check_csync_detect_update, setup, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_none, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_eval, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_rename, setup, teardown),
cmocka_unit_test_setup_teardown(check_csync_detect_update_db_new, setup, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_detect_update_null, setup, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_ftw, setup_ftw, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_ftw_empty_uri, setup_ftw, teardown_rm),
cmocka_unit_test_setup_teardown(check_csync_ftw_failing_fn, setup_ftw, teardown_rm),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}