]> granicus.if.org Git - vnstat/commitdiff
improve cache content init, add tests
authorTeemu Toivola <git@humdi.net>
Tue, 10 Jan 2017 20:45:05 +0000 (22:45 +0200)
committerTeemu Toivola <git@humdi.net>
Tue, 10 Jan 2017 20:45:05 +0000 (22:45 +0200)
src/daemon.c
src/dbsql.c
src/dbsql.h
tests/common_tests.c
tests/daemon_tests.c
tests/dbsql_tests.c
tests/id_tests.c
tests/ifinfo_tests.c

index a6458b349fe101b52fad05befe923fc7e739c269..869a60abccbabdea267b2d972eed8affae0d2cb6 100644 (file)
@@ -428,16 +428,15 @@ void processdatacache(DSTATE *s)
 
 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;
@@ -576,7 +575,8 @@ void handleintsignals(DSTATE *s)
                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();
@@ -585,6 +585,7 @@ void handleintsignals(DSTATE *s)
                        }
                        ibwloadcfg(s->cfgfile);
                        db_open(1);
+                       /* TODO: verify that everything continues correctly after this point */
                        break;
 
                case SIGINT:
index a7d40415a8053c7a42e7893a2155e8eb15413cdf..7f00ed2b31ec5c6c38ba1399b7179321e4d10172 100644 (file)
@@ -305,6 +305,50 @@ int db_getcounters(const char *iface, uint64_t *rxcounter, uint64_t *txcounter)
        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];
@@ -351,7 +395,9 @@ char *db_getinfo(const char *name)
                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);
 
@@ -373,6 +419,9 @@ int db_getiflist(dbiflist **dbifl)
 
        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;
                }
index 37b57a2fd82256b5b3e592581a14b4264e719c91..b3de466e5654c9a14bd6cf9e5a5d8c18ca5ed2b7 100644 (file)
@@ -8,6 +8,14 @@ typedef struct dbiflist {
        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);
@@ -19,6 +27,7 @@ sqlite3_int64 db_getinterfaceid(const char *iface, const int createifnotfound);
 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);
index a9f7d397b48977a276a67c0cc03c4362c53d4f68..7928eec0967dc9a9b57457b606c30917d084fbfa 100644 (file)
@@ -384,6 +384,14 @@ START_TEST(getversion_returns_a_version)
 }
 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");
@@ -416,5 +424,6 @@ void add_common_tests(Suite *s)
        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);
 }
index 1b3c16ac2292b4cd16abf7c235e82cc9f163c222..03e2b1fe98262e23da8fbff09fd3071656f8462b 100644 (file)
@@ -335,7 +335,7 @@ START_TEST(filldatabaselist_adds_databases)
        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);
@@ -678,6 +678,58 @@ START_TEST(simplehash_with_simple_strings)
 }
 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");
@@ -710,5 +762,7 @@ void add_daemon_tests(Suite *s)
        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);
 }
index 08ccdc7853f7fd7cb6b4a901453f58a05733e616..73c7e5467323dc08afefb574d7242eabe447c671 100644 (file)
@@ -485,10 +485,11 @@ START_TEST(db_setcounters_with_no_interface)
 }
 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);
@@ -500,6 +501,8 @@ START_TEST(db_counters_with_interface)
        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);
@@ -514,6 +517,32 @@ START_TEST(db_counters_with_interface)
        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);
 }
@@ -565,6 +594,82 @@ START_TEST(db_getiflist_lists_interfaces)
 }
 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");
@@ -593,7 +698,9 @@ void add_dbsql_tests(Suite *s)
        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);
 }
index 263133bd77a49bc667f783da41e4d965e1158e12..337150044b7f369dcea969942968e00180c51707 100644 (file)
@@ -59,6 +59,20 @@ START_TEST(getgroup_no_such_user_numeric)
 }
 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");
@@ -70,5 +84,7 @@ void add_id_tests(Suite *s)
        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);
 }
index 12197e8207421ce3138ff43ab7164087f252d248..4b5b34db094bb4b517788f777d6a0c13260b233b 100644 (file)
@@ -269,6 +269,22 @@ START_TEST(getifinfo_success)
 }
 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");
@@ -288,5 +304,6 @@ void add_ifinfo_tests(Suite *s)
        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);
 }