int initcachevalues(datacache **dc)
{
- uint64_t rx, tx;
+ interfaceinfo info;
- if (!db_getcounters((*dc)->interface, &rx, &tx)) {
+ if (!db_getinterfaceinfo((*dc)->interface, &info)) {
return 0;
}
- (*dc)->currx = rx;
- (*dc)->curtx = tx;
- /* TODO: "updated" should come from database */
- (*dc)->updated = time(NULL);
+ (*dc)->currx = info.rxcounter;
+ (*dc)->curtx = info.txcounter;
+ (*dc)->updated = info.updated;
(*dc)->filled = 1;
return 1;
case SIGHUP:
snprintf(errorstring, 512, "SIGHUP received, flushing data to disk and reloading config.");
printe(PT_Info);
- /* TODO: cleanup: cacheflush(s->dirname); */
+ flushcachetodisk(s);
+ datacache_clear(&s->dcache);
s->dbcount = 0;
ibwflush();
db_close();
}
ibwloadcfg(s->cfgfile);
db_open(1);
+ /* TODO: verify that everything continues correctly after this point */
break;
case SIGINT:
return 1;
}
+int db_getinterfaceinfo(const char *iface, interfaceinfo *info)
+{
+ int rc;
+ char sql[512];
+ sqlite3_int64 ifaceid = 0;
+ sqlite3_stmt *sqlstmt;
+
+ ifaceid = db_getinterfaceid(iface, 0);
+ if (ifaceid == 0) {
+ return 0;
+ }
+
+ sqlite3_snprintf(512, sql, "select name, alias, active, created, updated, rxcounter, txcounter, rxtotal, txtotal from interface where id=%"PRId64";", (int64_t)ifaceid);
+ rc = sqlite3_prepare_v2(db, sql, -1, &sqlstmt, NULL);
+ if (rc) {
+ return 0;
+ }
+ if (sqlite3_column_count(sqlstmt) != 9) {
+ return 0;
+ }
+ if (sqlite3_step(sqlstmt) == SQLITE_ROW) {
+ if (sqlite3_column_text(sqlstmt, 0) != NULL) {
+ strncpy_nt(info->name, (const char *)sqlite3_column_text(sqlstmt, 0), 32);
+ } else {
+ info->name[0] = '\0';
+ }
+ if (sqlite3_column_text(sqlstmt, 1) != NULL) {
+ strncpy_nt(info->alias, (const char *)sqlite3_column_text(sqlstmt, 1), 32);
+ } else {
+ info->alias[0] = '\0';
+ }
+ info->active = sqlite3_column_int(sqlstmt, 2);
+ info->created = (time_t)sqlite3_column_int64(sqlstmt, 3);
+ info->updated = (time_t)sqlite3_column_int64(sqlstmt, 4);
+ info->rxcounter = (uint64_t)sqlite3_column_int64(sqlstmt, 5);
+ info->txcounter = (uint64_t)sqlite3_column_int64(sqlstmt, 6);
+ info->rxtotal = (uint64_t)sqlite3_column_int64(sqlstmt, 7);
+ info->txtotal = (uint64_t)sqlite3_column_int64(sqlstmt, 8);
+ }
+ sqlite3_finalize(sqlstmt);
+
+ return 1;
+}
+
int db_setalias(const char *iface, const char *alias)
{
char sql[512];
return buffer;
}
if (sqlite3_step(sqlstmt) == SQLITE_ROW) {
- strncpy_nt(buffer, (const char *)sqlite3_column_text(sqlstmt, 0), 64);
+ if (sqlite3_column_text(sqlstmt, 0) != NULL) {
+ strncpy_nt(buffer, (const char *)sqlite3_column_text(sqlstmt, 0), 64);
+ }
}
sqlite3_finalize(sqlstmt);
rc = 0;
while (sqlite3_step(sqlstmt) == SQLITE_ROW) {
+ if (sqlite3_column_text(sqlstmt, 0) == NULL) {
+ continue;
+ }
if (!dbiflistadd(dbifl, (const char *)sqlite3_column_text(sqlstmt, 0))) {
break;
}
struct dbiflist *next;
} dbiflist;
+typedef struct interfaceinfo {
+ char name[32], alias[32];
+ int active;
+ time_t created, updated;
+ uint64_t rxcounter, txcounter;
+ uint64_t rxtotal, txtotal;
+} interfaceinfo;
+
int db_open(int createifnotfound);
int db_close(void);
int db_exec(const char *sql);
int db_setactive(const char *iface, const int active);
int db_setcounters(const char *iface, const uint64_t rxcounter, const uint64_t txcounter);
int db_getcounters(const char *iface, uint64_t *rxcounter, uint64_t *txcounter);
+int db_getinterfaceinfo(const char *iface, interfaceinfo *info);
int db_setalias(const char *iface, const char *alias);
int db_setinfo(const char *name, const char *value, const int createifnotfound);
char *db_getinfo(const char *name);
}
END_TEST
+START_TEST(can_panic)
+{
+ suppress_output();
+ fclose(stderr);
+ panicexit(__FILE__, __LINE__);
+}
+END_TEST
+
void add_common_tests(Suite *s)
{
TCase *tc_common = tcase_create("Common");
tcase_add_test(tc_common, isnumeric_it_is);
tcase_add_test(tc_common, isnumeric_it_is_not);
tcase_add_test(tc_common, getversion_returns_a_version);
+ tcase_add_exit_test(tc_common, can_panic, 1);
suite_add_tcase(s, tc_common);
}
defaultcfg();
initdstate(&s);
disable_logprints();
- strncpy_nt(cfg.dbdir, TESTDBDIR, 512);
+ strncpy_nt(cfg.dbdir, TESTDBDIR, 512);
strncpy_nt(s.dirname, TESTDBDIR, 512);
s.sync = 1;
ck_assert_int_eq(remove_directory(TESTDIR), 1);
}
END_TEST
+START_TEST(initcachevalues_does_not_init_without_database)
+{
+ int ret;
+ DSTATE s;
+
+ defaultcfg();
+ initdstate(&s);
+ disable_logprints();
+
+ ret = datacache_add(&s.dcache, "eth0", 0);
+ ck_assert_int_eq(ret, 1);
+
+ ret = initcachevalues(&s.dcache);
+ ck_assert_int_eq(ret, 0);
+}
+END_TEST
+
+START_TEST(initcachevalues_does_init)
+{
+ int ret;
+ DSTATE s;
+
+ defaultcfg();
+ initdstate(&s);
+ disable_logprints();
+ ck_assert_int_eq(remove_directory(TESTDIR), 1);
+ ck_assert_int_eq(clean_testdbdir(), 1);
+ strncpy_nt(cfg.dbdir, TESTDBDIR, 512);
+ ret = db_open(1);
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_addinterface("eth0");
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_setcounters("eth0", 1, 2);
+ ck_assert_int_eq(ret, 1);
+
+ ret = datacache_add(&s.dcache, "eth0", 0);
+ ck_assert_int_eq(ret, 1);
+
+ ret = initcachevalues(&s.dcache);
+ ck_assert_int_eq(ret, 1);
+
+ ck_assert_int_eq(s.dcache->currx, 1);
+ ck_assert_int_eq(s.dcache->curtx, 2);
+ ck_assert_int_ne(s.dcache->updated, 0);
+
+ ret = db_close();
+ ck_assert_int_eq(ret, 1);
+}
+END_TEST
+
void add_daemon_tests(Suite *s)
{
TCase *tc_daemon = tcase_create("Daemon");
tcase_add_test(tc_daemon, interfacechangecheck_with_filled_cache);
tcase_add_test(tc_daemon, simplehash_with_empty_strings);
tcase_add_test(tc_daemon, simplehash_with_simple_strings);
+ tcase_add_test(tc_daemon, initcachevalues_does_not_init_without_database);
+ tcase_add_test(tc_daemon, initcachevalues_does_init);
suite_add_tcase(s, tc_daemon);
}
}
END_TEST
-START_TEST(db_counters_with_interface)
+START_TEST(db_interface_info_manipulation)
{
int ret;
- uint64_t rx, tx;
+ uint64_t rx, tx, c;
+ interfaceinfo info;
defaultcfg();
strncpy_nt(cfg.dbdir, TESTDBDIR, 512);
ck_assert_int_eq(ret, 1);
ret = db_addinterface("eth0");
ck_assert_int_eq(ret, 1);
+ ret = db_addinterface("eth1");
+ ck_assert_int_eq(ret, 1);
ret = db_getcounters("eth0", &rx, &tx);
ck_assert_int_eq(ret, 1);
ck_assert_int_eq(rx, 2);
ck_assert_int_eq(tx, 2);
+ ret = db_settotal("eth1", 42, 24);
+ ck_assert_int_eq(ret, 1);
+
+ c = (uint64_t)time(NULL) - 100;
+ ret = db_setcreation("eth1", c);
+
+ ret = db_getinterfaceinfo("eth0", &info);
+ ck_assert_int_eq(ret, 1);
+ ck_assert_int_eq(info.active, 1);
+ ck_assert_int_eq(info.rxcounter, 2);
+ ck_assert_int_eq(info.txcounter, 2);
+ ck_assert_int_eq(info.rxtotal, 0);
+ ck_assert_int_eq(info.txtotal, 0);
+ ck_assert_int_ne(info.created, 0);
+
+ ck_assert_int_eq(db_setactive("eth1", 0), 1);
+
+ ret = db_getinterfaceinfo("eth1", &info);
+ ck_assert_int_eq(ret, 1);
+ ck_assert_int_eq(info.active, 0);
+ ck_assert_int_eq(info.rxcounter, 0);
+ ck_assert_int_eq(info.txcounter, 0);
+ ck_assert_int_eq(info.rxtotal, 42);
+ ck_assert_int_eq(info.txtotal, 24);
+ ck_assert_int_eq(info.created, c);
+
ret = db_close();
ck_assert_int_eq(ret, 1);
}
}
END_TEST
+START_TEST(db_maintenance_does_not_crash)
+{
+ int ret;
+
+ defaultcfg();
+ strncpy_nt(cfg.dbdir, TESTDBDIR, 512);
+ ck_assert_int_eq(clean_testdbdir(), 1);
+
+ ret = db_open(1);
+ ck_assert_int_eq(ret, 1);
+ ret = db_addinterface("eth0");
+ ck_assert_int_eq(ret, 1);
+ ret = db_addinterface("eth1");
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_vacuum();
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_removeoldentries();
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_close();
+ ck_assert_int_eq(ret, 1);
+}
+END_TEST
+
+START_TEST(db_data_can_be_inserted)
+{
+ int ret;
+ interfaceinfo info;
+
+ defaultcfg();
+ strncpy_nt(cfg.dbdir, TESTDBDIR, 512);
+ ck_assert_int_eq(clean_testdbdir(), 1);
+
+ ret = db_open(1);
+ ck_assert_int_eq(ret, 1);
+ ret = db_addinterface("eth0");
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_insertdata("foo", "eth0", 1, 2, 3);
+ ck_assert_int_eq(ret, 0);
+
+ ret = db_insertdata("hour", "eth1", 1, 2, 3);
+ ck_assert_int_eq(ret, 0);
+
+ ret = db_insertdata("hour", "eth0", 1, 2, 3);
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_insertdata("day", "eth0", 1, 2, 3);
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_insertdata("month", "eth0", 1, 2, 3);
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_insertdata("year", "eth0", 1, 2, 3);
+ ck_assert_int_eq(ret, 1);
+
+ ret = db_insertdata("top", "eth0", 1, 2, 3);
+ ck_assert_int_eq(ret, 1);
+
+ /* verify that totals don't get changed */
+ ret = db_getinterfaceinfo("eth0", &info);
+ ck_assert_int_eq(ret, 1);
+ ck_assert_int_eq(info.active, 1);
+ ck_assert_int_eq(info.rxcounter, 0);
+ ck_assert_int_eq(info.txcounter, 0);
+ ck_assert_int_eq(info.rxtotal, 0);
+ ck_assert_int_eq(info.txtotal, 0);
+ ck_assert_int_ne(info.created, 0);
+
+ ret = db_close();
+ ck_assert_int_eq(ret, 1);
+}
+END_TEST
+
void add_dbsql_tests(Suite *s)
{
TCase *tc_dbsql = tcase_create("DB SQL");
tcase_add_test(tc_dbsql, db_addinterface_can_not_add_same_interface_twice);
tcase_add_test(tc_dbsql, db_getcounters_with_no_interface);
tcase_add_test(tc_dbsql, db_setcounters_with_no_interface);
- tcase_add_test(tc_dbsql, db_counters_with_interface);
+ tcase_add_test(tc_dbsql, db_interface_info_manipulation);
tcase_add_test(tc_dbsql, db_getiflist_lists_interfaces);
+ tcase_add_test(tc_dbsql, db_maintenance_does_not_crash);
+ tcase_add_test(tc_dbsql, db_data_can_be_inserted);
suite_add_tcase(s, tc_dbsql);
}
}
END_TEST
+START_TEST(setuser_with_empty_user)
+{
+ suppress_output();
+ setuser("");
+}
+END_TEST
+
+START_TEST(setgroup_with_empty_group)
+{
+ suppress_output();
+ setgroup("");
+}
+END_TEST
+
void add_id_tests(Suite *s)
{
TCase *tc_id = tcase_create("ID");
tcase_add_test(tc_id, getgroup_root_numeric);
tcase_add_exit_test(tc_id, getgroup_no_such_user_string, 1);
tcase_add_exit_test(tc_id, getgroup_no_such_user_numeric, 1);
+ tcase_add_test(tc_id, setuser_with_empty_user);
+ tcase_add_test(tc_id, setgroup_with_empty_group);
suite_add_tcase(s, tc_id);
}
}
END_TEST
+START_TEST(isifavailable_knows_interface_availability)
+{
+ linuxonly;
+
+ suppress_output();
+
+ ck_assert_int_eq(remove_directory(TESTDIR), 1);
+ fake_proc_net_dev("w", "eth0", 10, 20, 30, 40);
+ fake_proc_net_dev("a", "eth1", 1, 2, 3, 4);
+
+ ck_assert_int_eq(isifavailable("eth0"), 1);
+ ck_assert_int_eq(isifavailable("eth1"), 1);
+ ck_assert_int_eq(isifavailable("eth2"), 0);
+}
+END_TEST
+
void add_ifinfo_tests(Suite *s)
{
TCase *tc_ifinfo = tcase_create("Ifinfo");
tcase_add_test(tc_ifinfo, readsysclassnet_success);
tcase_add_test(tc_ifinfo, getifinfo_not_found);
tcase_add_test(tc_ifinfo, getifinfo_success);
+ tcase_add_test(tc_ifinfo, isifavailable_knows_interface_availability);
suite_add_tcase(s, tc_ifinfo);
}