END_TEST START_TEST(dbcheck_with_filled_cache) { int forcesave = 0; linuxonly; initdb(); defaultcfg(); disable_logprints(); ck_assert_int_eq(remove_directory(TESTDIR), 1); ck_assert_int_eq(cachecount(), 0); strcpy(data.interface, "ethbasic"); ck_assert_int_eq(cacheupdate(), 1); strcpy(data.interface, "ethactive"); ck_assert_int_eq(cacheupdate(), 1); strcpy(data.interface, "ethnotactive"); data.active = 0; ck_assert_int_eq(cacheupdate(), 1); ck_assert_int_eq(cachecount(), 3); ck_assert_int_eq(cacheactivecount(), 2); fake_proc_net_dev("w", "ethbasic", 1, 2, 3, 4); fake_proc_net_dev("a", "ethnotactive", 5, 6, 7, 8); ck_assert_int_ne(dbcheck(0, &forcesave), 0); ck_assert_int_eq(forcesave, 1); }
END_TEST START_TEST(database_outputs_do_not_crash) { int i; initdb(); defaultcfg(); strcpy(data.interface, "something"); strcpy(data.nick, "nothing"); data.totalrx = 1; data.totaltx = 2; data.currx = 3; data.curtx = 4; data.totalrxk = 5; data.totaltxk = 6; data.btime = 7; for (i=0; i<30; i++) { data.day[i].date = i+1; data.day[i].rx = data.day[i].tx = i*100; data.day[i].rxk = data.day[i].txk = i; data.day[i].used = 1; } for (i=0; i<10; i++) { data.top10[i].date = i+1; data.top10[i].rx = data.top10[i].tx = i*100; data.top10[i].rxk = data.top10[i].txk = i; data.top10[i].used = 1; } for (i=0; i<12; i++) { data.month[i].month = i+1; data.month[i].rx = data.month[i].tx = i*100; data.month[i].rxk = data.month[i].txk = i; data.month[i].used = 1; } for (i=0; i<24; i++) { data.hour[i].date = i+1; data.hour[i].rx = data.hour[i].tx = i*100; } suppress_output(); showdb(0); showdb(1); showdb(2); showdb(3); showdb(4); showdb(5); showdb(6); showdb(7); showdb(8); showdb(9); }
END_TEST START_TEST(printcfgfile_default) { defaultcfg(); ck_assert_int_eq(ibwadd("name1", 1), 1); ck_assert_int_eq(ibwadd("name2", 2), 1); suppress_output(); printcfgfile(); }
END_TEST START_TEST(mosecs_does_not_change_struct_tm_pointer_content) { struct tm *stm; time_t current; current = time(NULL); stm = localtime(¤t); defaultcfg(); ck_assert_int_eq(cfg.monthrotate, 1); ck_assert_int_eq(current, timelocal(stm)); ck_assert_int_ne(mosecs(1, 2), 0); ck_assert_int_ne(mosecs(1, 2), 1); ck_assert_int_eq(current, timelocal(stm)); }
END_TEST START_TEST(mosecs_return_values) { time_t a, b; defaultcfg(); cfg.monthrotate = 1; ck_assert_int_eq(mosecs(0, 0), 1); a = mosecs(172800, 173000); ck_assert_int_gt(a, 1); cfg.monthrotate = 2; b = mosecs(172800, 173000); ck_assert_int_gt(b, 1); ck_assert_int_gt(a, b); }
END_TEST START_TEST(cachestatus_full) { int i; char buffer[8]; initdb(); defaultcfg(); disable_logprints(); ck_assert_int_eq(cachecount(), 0); for (i=1; i<=50; i++) { snprintf(buffer, 8, "name%d", i); ck_assert_int_eq(cacheadd(buffer, 0), 1); ck_assert_int_eq(ibwadd(buffer, 50-i), 1); } ck_assert_int_eq(cachecount(), 50); cachestatus(); }
END_TEST START_TEST(showbar_with_half_and_half) { int pipe, len; char buffer[512]; memset(&buffer, '\0', sizeof(buffer)); defaultcfg(); cfg.rxchar[0] = 'r'; cfg.txchar[0] = 't'; pipe = pipe_output(); len = showbar(0, 1, 0, 1, 2, 10); ck_assert_int_eq(len, 10); fflush(stdout); len = read(pipe, buffer, 512); ck_assert_str_eq(buffer, " rrrrrttttt"); }
END_TEST START_TEST(showbar_can_also_do_mb_calculations) { int pipe, len; char buffer[512]; memset(&buffer, '\0', sizeof(buffer)); defaultcfg(); cfg.rxchar[0] = 'r'; cfg.txchar[0] = 't'; pipe = pipe_output(); len = showbar(0, 1024, 0, 1024, 2048, 2); ck_assert_int_eq(len, 2); fflush(stdout); len = read(pipe, buffer, 512); ck_assert_str_eq(buffer, " rt"); }
END_TEST START_TEST(timeused_tracks_used_time) { int i, j = 0; double used; defaultcfg(); used = timeused("quick_func", 1); ck_assert(used == 0.0); /* assume that this spends some non-zero time */ for (i = 0; i < 10000; i++) { j = j + 2; } used = timeused("quick_func", 0); ck_assert(used > 0.0); }
END_TEST START_TEST(mosecs_does_not_change_tz) { #if defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE) || defined(__APPLE__) || defined(__linux__) extern long timezone; #else long timezone = 0; #endif long timezone_before_call; tzset(); timezone_before_call = timezone; defaultcfg(); ck_assert_int_eq(cfg.monthrotate, 1); ck_assert_int_ne(mosecs(1, 2), 0); ck_assert_int_ne(mosecs(1, 2), 1); ck_assert_int_eq(timezone_before_call, timezone); }
END_TEST START_TEST(timeused_debug_does_not_output_anything_when_debug_is_disabled) { int pipe, len; char buffer[512]; memset(&buffer, '\0', sizeof(buffer)); defaultcfg(); debug = 0; pipe = pipe_output(); /* the assumption here is that the next two steps can always execute in less than one second resulting in a duration that starts with a zero */ timeused_debug("other_func", 1); timeused_debug("other_func", 0); printf("-"); // stdout needs to contain something so that read doesn't block fflush(stdout); len = (int)read(pipe, buffer, 512); ck_assert_int_eq(len, 1); }
END_TEST START_TEST(timeused_debug_outputs_something_expected_when_debug_is_enabled) { int pipe, len; char buffer[512]; memset(&buffer, '\0', sizeof(buffer)); defaultcfg(); debug = 1; pipe = pipe_output(); /* the assumption here is that the next two steps can always execute in less than one second resulting in a duration that starts with a zero */ timeused_debug("that_func", 1); timeused_debug("that_func", 0); fflush(stdout); len = (int)read(pipe, buffer, 512); ck_assert_int_gt(len, 1); ck_assert_ptr_ne(strstr(buffer, "that_func() in 0"), NULL); }
int loadcfg(const char *cfgfile) { FILE *fd; int i, linelen, cfglen; char value[512], cfgline[512]; struct cfgsetting cset[] = { /* cfg string, char var name, int var name, char len, fill status */ { "Interface", cfg.iface, 0, 32, 0 }, { "DatabaseDir", cfg.dbdir, 0, 512, 0 }, { "Locale", cfg.locale, 0, 32, 0 }, { "MonthRotate", 0, &cfg.monthrotate, 0, 0 }, { "DayFormat", cfg.dformat, 0, 64, 0 }, { "MonthFormat", cfg.mformat, 0, 64, 0 }, { "TopFormat", cfg.tformat, 0, 64, 0 }, { "RXCharacter", cfg.rxchar, 0, 2, 0 }, { "TXCharacter", cfg.txchar, 0, 2, 0 }, { "RXHourCharacter", cfg.rxhourchar, 0, 2, 0 }, { "TXHourCharacter", cfg.txhourchar, 0, 2, 0 }, { "UnitMode", 0, &cfg.unitmode, 0, 0 }, { "RateUnitMode", 0, &cfg.rateunitmode, 0, 0 }, { "OutputStyle", 0, &cfg.ostyle, 0, 0 }, { "RateUnit", 0, &cfg.rateunit, 0, 0 }, { "BandwidthDetection", 0, &cfg.bwdetection, 0, 0 }, { "MaxBandwidth", 0, &cfg.maxbw, 0, 0 }, { "Sampletime", 0, &cfg.sampletime, 0, 0 }, { "QueryMode", 0, &cfg.qmode, 0, 0 }, { "CheckDiskSpace", 0, &cfg.spacecheck, 0, 0 }, { "UseFileLocking", 0, &cfg.flock, 0, 0 }, { "BootVariation", 0, &cfg.bvar, 0, 0 }, { "TrafficlessDays", 0, &cfg.traflessday, 0, 0 }, { "DaemonUser", cfg.daemonuser, 0, 33, 0 }, { "DaemonGroup", cfg.daemongroup, 0, 33, 0 }, { "UpdateInterval", 0, &cfg.updateinterval, 0, 0 }, { "PollInterval", 0, &cfg.pollinterval, 0, 0 }, { "SaveInterval", 0, &cfg.saveinterval, 0, 0 }, { "OfflineSaveInterval", 0, &cfg.offsaveinterval, 0, 0 }, { "BandwidthDetectionInterval", 0, &cfg.bwdetectioninterval, 0, 0 }, { "SaveOnStatusChange", 0, &cfg.savestatus, 0, 0 }, { "UseLogging", 0, &cfg.uselogging, 0, 0 }, { "CreateDirs", 0, &cfg.createdirs, 0, 0 }, { "UpdateFileOwner", 0, &cfg.updatefileowner, 0, 0 }, { "LogFile", cfg.logfile, 0, 512, 0 }, { "PidFile", cfg.pidfile, 0, 512, 0 }, { "HeaderFormat", cfg.hformat, 0, 64, 0 }, { "HourlyRate", 0, &cfg.hourlyrate, 0, 0 }, { "SummaryRate", 0, &cfg.summaryrate, 0, 0 }, { "SummaryLayout", 0, &cfg.slayout, 0, 0 }, { "TransparentBg", 0, &cfg.transbg, 0, 0 }, { "CBackground", cfg.cbg, 0, 8, 0 }, { "CEdge", cfg.cedge, 0, 8, 0 }, { "CHeader", cfg.cheader, 0, 8, 0 }, { "CHeaderTitle", cfg.cheadertitle, 0, 8, 0 }, { "CHeaderDate", cfg.cheaderdate, 0, 8, 0 }, { "CText", cfg.ctext, 0, 8, 0 }, { "CLine", cfg.cline, 0, 8, 0 }, { "CLineL", cfg.clinel, 0, 8, 0 }, { "CRx", cfg.crx, 0, 8, 0 }, { "CRxD", cfg.crxd, 0, 8, 0 }, { "CTx", cfg.ctx, 0, 8, 0 }, { "CTxD", cfg.ctxd, 0, 8, 0 }, { 0, 0, 0, 0, 0 } }; /* load default config */ defaultcfg(); i = opencfgfile(cfgfile, &fd); if (i != 2) return i; rewind(fd); /* parse every config file line */ while (!feof(fd)) { cfgline[0] = '\0'; if (fgets(cfgline, 512, fd)==NULL) { break; } linelen = (int)strlen(cfgline); if (linelen<=2 || cfgline[0]=='#') { continue; } for (i=0; cset[i].name!=0; i++) { if (cset[i].found) { continue; } cfglen = (int)strlen(cset[i].name); if ( (linelen<(cfglen+2)) || (strncasecmp(cfgline, cset[i].name, cfglen)!=0) ) { continue; } if (!extractcfgvalue(value, cfgline, cfglen)) { if (debug) printf(" c: %s -> \"%s\" with no value, keeping default.\n", cfgline, cset[i].name); cset[i].found = 1; break; } if (!setcfgvalue(&cset[i], value, cfgline)) { continue; } cset[i].found = 1; break; } if ((debug) && (!cset[i].found) && (strncasecmp(cfgline, "MaxBW", 5)!=0)) printf("Unknown configuration line: %s", cfgline); } fclose(fd); /* validate config */ validatecfg(); return 1; }
int loadcfg(const char *cfgfile) { FILE *fd; char buffer[512]; int i, j, k, linelen, cfglen, tryhome; char value[512], cfgline[512]; struct cfgsetting cset[] = { /* cfg string, char var name, int var name, char len, fill status */ { "Interface", cfg.iface, 0, 32, 0 }, { "DatabaseDir", cfg.dbdir, 0, 512, 0 }, { "Locale", cfg.locale, 0, 32, 0 }, { "MonthRotate", 0, &cfg.monthrotate, 0, 0 }, { "DayFormat", cfg.dformat, 0, 64, 0 }, { "MonthFormat", cfg.mformat, 0, 64, 0 }, { "TopFormat", cfg.tformat, 0, 64, 0 }, { "RXCharacter", cfg.rxchar, 0, 2, 0 }, { "TXCharacter", cfg.txchar, 0, 2, 0 }, { "RXHourCharacter", cfg.rxhourchar, 0, 2, 0 }, { "TXHourCharacter", cfg.txhourchar, 0, 2, 0 }, { "UnitMode", 0, &cfg.unit, 0, 0 }, { "OutputStyle", 0, &cfg.ostyle, 0, 0 }, { "RateUnit", 0, &cfg.rateunit, 0, 0 }, { "MaxBandwidth", 0, &cfg.maxbw, 0, 0 }, { "Sampletime", 0, &cfg.sampletime, 0, 0 }, { "QueryMode", 0, &cfg.qmode, 0, 0 }, { "CheckDiskSpace", 0, &cfg.spacecheck, 0, 0 }, { "UseFileLocking", 0, &cfg.flock, 0, 0 }, { "BootVariation", 0, &cfg.bvar, 0, 0 }, { "TrafficlessDays", 0, &cfg.traflessday, 0, 0 }, { "DaemonUser", cfg.daemonuser, 0, 33, 0 }, { "DaemonGroup", cfg.daemongroup, 0, 33, 0 }, { "UpdateInterval", 0, &cfg.updateinterval, 0, 0 }, { "PollInterval", 0, &cfg.pollinterval, 0, 0 }, { "SaveInterval", 0, &cfg.saveinterval, 0, 0 }, { "OfflineSaveInterval", 0, &cfg.offsaveinterval, 0, 0 }, { "SaveOnStatusChange", 0, &cfg.savestatus, 0, 0 }, { "UseLogging", 0, &cfg.uselogging, 0, 0 }, { "CreateDirs", 0, &cfg.createdirs, 0, 0 }, { "UpdateFileOwner", 0, &cfg.updatefileowner, 0, 0 }, { "LogFile", cfg.logfile, 0, 512, 0 }, { "PidFile", cfg.pidfile, 0, 512, 0 }, { "HeaderFormat", cfg.hformat, 0, 64, 0 }, { "HourlyRate", 0, &cfg.hourlyrate, 0, 0 }, { "SummaryRate", 0, &cfg.summaryrate, 0, 0 }, { "SummaryLayout", 0, &cfg.slayout, 0, 0 }, { "TransparentBg", 0, &cfg.transbg, 0, 0 }, { "CBackground", cfg.cbg, 0, 8, 0 }, { "CEdge", cfg.cedge, 0, 8, 0 }, { "CHeader", cfg.cheader, 0, 8, 0 }, { "CHeaderTitle", cfg.cheadertitle, 0, 8, 0 }, { "CHeaderDate", cfg.cheaderdate, 0, 8, 0 }, { "CText", cfg.ctext, 0, 8, 0 }, { "CLine", cfg.cline, 0, 8, 0 }, { "CLineL", cfg.clinel, 0, 8, 0 }, { "CRx", cfg.crx, 0, 8, 0 }, { "CRxD", cfg.crxd, 0, 8, 0 }, { "CTx", cfg.ctx, 0, 8, 0 }, { "CTxD", cfg.ctxd, 0, 8, 0 }, { 0, 0, 0, 0, 0 } }; ifacebw = NULL; /* clear buffer */ for (i=0; i<512; i++) { buffer[i] = '\0'; } /* load default config */ defaultcfg(); /* possible config files: 1) --config 2) $HOME/.vnstatrc 3) /etc/vnstat.conf 4) none */ if (cfgfile[0]!='\0') { /* try to open given file */ if ((fd=fopen(cfgfile, "r"))!=NULL) { if (debug) printf("Config file: --config\n"); } else { snprintf(errorstring, 512, "Unable to open given config file \"%s\": %s\n", cfgfile, strerror(errno)); printe(PT_Error); return 0; } } else { if (getenv("HOME")) { strncpy_nt(buffer, getenv("HOME"), 500); strcat(buffer, "/.vnstatrc"); tryhome = 1; } else { tryhome = 0; } /* try to open first available config file */ if (tryhome && (fd=fopen(buffer, "r"))!=NULL) { if (debug) printf("Config file: $HOME/.vnstatrc\n"); } else if ((fd=fopen("/etc/vnstat.conf", "r"))!=NULL) { if (debug) printf("Config file: /etc/vnstat.conf\n"); } else { if (debug) printf("Config file: none\n"); return 1; } } rewind(fd); /* parse every config file line */ while (!feof(fd)) { cfgline[0] = '\0'; /* get current line */ if (fgets(cfgline, 512, fd)==NULL) { break; } linelen = (int)strlen(cfgline); if (linelen>2 && cfgline[0]!='#') { for (i=0; cset[i].name!=0; i++) { if (cset[i].found) { continue; } cfglen = (int)strlen(cset[i].name); if ( (linelen>=(cfglen+2)) && (strncasecmp(cfgline, cset[i].name, cfglen)==0) ) { /* clear value buffer */ for (j=0; j<512; j++) { value[j]='\0'; } /* search value */ j = 0; for (k=cfglen; k<linelen; k++) { if (cfgline[k]=='\n' || cfgline[k]=='\r') { break; } else if (cfgline[k]=='\"') { if (j==0) { continue; } else { break; } } else { if (j==0 && (cfgline[k]==' ' || cfgline[k]=='=' || cfgline[k]=='\t')) { continue; } else { value[j] = cfgline[k]; j++; } } } /* set value and get new line if valid value was found */ if (strlen(value)!=0) { if (cset[i].namelen>0) { strncpy_nt(cset[i].locc, value, cset[i].namelen); cset[i].locc[cset[i].namelen-1]='\0'; if (debug) printf(" c: %s -> \"%s\": \"%s\"\n", cfgline, cset[i].name, cset[i].locc); } else if (isdigit(value[0])) { *cset[i].loci = atoi(value); if (debug) printf(" i: %s -> \"%s\": %d\n", cfgline, cset[i].name, *cset[i].loci); } else { continue; } cset[i].found = 1; break; } else if (strlen(value)==0) { if (debug) printf(" c: %s -> \"%s\" with no value, keeping default.\n", cfgline, cset[i].name); cset[i].found = 1; break; } } /* if */ } /* for */ if ((debug) && (!cset[i].found) && (strncasecmp(cfgline, "MaxBW", 5)!=0)) printf("Unknown configuration line: %s", cfgline); } /* if */ } /* while */ /* search for interface specific limits */ ibwcfgread(fd); fclose(fd); if (debug) ibwlist(); /* validate config */ validatecfg(); return 1; }