diff options
author | Costa Tsaousis (ktsaou) <costa@tsaousis.gr> | 2016-01-21 01:09:53 +0200 |
---|---|---|
committer | Costa Tsaousis (ktsaou) <costa@tsaousis.gr> | 2016-01-21 01:09:53 +0200 |
commit | b475c58273d0f76e51ab43d30b5bc31249fdd0d7 (patch) | |
tree | c9d87c7cc0ebb96740701beab8b5f665db3fe213 /src | |
parent | 60c13081dcdbfd522f2a0affe47a52c3ab0aab31 (diff) |
added more unit tests; fixed the issue where incremental values where gracefully interpolated
Diffstat (limited to 'src')
-rwxr-xr-x | src/main.c | 18 | ||||
-rwxr-xr-x | src/rrd.c | 178 | ||||
-rwxr-xr-x | src/unit_test.c | 455 | ||||
-rwxr-xr-x | src/unit_test.h | 1 |
4 files changed, 562 insertions, 90 deletions
diff --git a/src/main.c b/src/main.c index be101dea6e..8f3870bdc9 100755 --- a/src/main.c +++ b/src/main.c @@ -208,7 +208,7 @@ int main(int argc, char **argv) } i++; } - else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("global", "debug flags", argv[i+1]); i++; } + else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("global", "debug flags", argv[i+1]); debug_flags = strtoull(argv[i+1], NULL, 0); i++; } else if(strcmp(argv[i], "-p") == 0 && (i+1) < argc) { config_set("global", "port", argv[i+1]); i++; } else if(strcmp(argv[i], "-u") == 0 && (i+1) < argc) { config_set("global", "run as user", argv[i+1]); i++; } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); i++; } @@ -216,21 +216,9 @@ int main(int argc, char **argv) else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set("global", "host access prefix", argv[i+1]); i++; } else if(strcmp(argv[i], "-nodeamon") == 0 || strcmp(argv[i], "-nd") == 0) dont_fork = 1; else if(strcmp(argv[i], "--unittest") == 0) { - if(unit_test_storage()) exit(1); - exit(0); rrd_update_every = 1; - if(unit_test(1000000, 0)) exit(1); - if(unit_test(1000000, 500000)) exit(1); - if(unit_test(1000000, 100000)) exit(1); - if(unit_test(1000000, 900000)) exit(1); - if(unit_test(2000000, 0)) exit(1); - if(unit_test(2000000, 500000)) exit(1); - if(unit_test(2000000, 100000)) exit(1); - if(unit_test(2000000, 900000)) exit(1); - if(unit_test(500000, 500000)) exit(1); - //if(unit_test(500000, 100000)) exit(1); // FIXME: the expected numbers are wrong - //if(unit_test(500000, 900000)) exit(1); // FIXME: the expected numbers are wrong - if(unit_test(500000, 0)) exit(1); + if(run_all_mockup_tests()) exit(1); + if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); exit(0); } @@ -804,6 +804,8 @@ void rrdset_next(RRDSET *st) gettimeofday(&now, NULL); microseconds = usecdiff(&now, &st->last_collected_time); } + // prevent infinite loop + else microseconds = st->update_every * 1000000ULL; rrdset_next_usec(st, microseconds); } @@ -818,7 +820,8 @@ unsigned long long rrdset_done(RRDSET *st) debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name); RRDDIM *rd, *last; - int oldstate, store_this_entry = 1; + int oldstate, store_this_entry = 1, first_entry = 0, in_the_same_interpolation_point = 0; + unsigned long long last_ut, now_ut, next_ut; if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)) error("Cannot set pthread cancel state to DISABLE."); @@ -829,11 +832,12 @@ unsigned long long rrdset_done(RRDSET *st) // enable the chart, if it was disabled st->enabled = 1; - // check if the chart has a long time to be refreshed + // check if the chart has a long time to be updated if(unlikely(st->usec_since_last_update > st->entries * st->update_every * 1000000ULL)) { info("%s: took too long to be updated (%0.3Lf secs). Reseting it.", st->name, (long double)(st->usec_since_last_update / 1000000.0)); rrdset_reset(st); st->usec_since_last_update = st->update_every * 1000000ULL; + first_entry = 1; } if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: microseconds since last update: %llu", st->name, st->usec_since_last_update); @@ -845,15 +849,16 @@ unsigned long long rrdset_done(RRDSET *st) // the first entry should not be stored store_this_entry = 0; + first_entry = 1; - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: initializing last_collected to now. Will not store the next entry.", st->name); + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: has not set last_collected_time. Setting it now. Will not store the next entry.", st->name); } else { // it is not the first entry // calculate the proper last_collected_time, using usec_since_last_update unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec + st->usec_since_last_update; - st->last_collected_time.tv_sec = (__time_t) (ut / 1000000ULL); - st->last_collected_time.tv_usec = (__suseconds_t) (ut % 1000000ULL); + st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL); + st->last_collected_time.tv_usec = (useconds_t) (ut % 1000000ULL); } // if this set has not been updated in the past @@ -862,11 +867,12 @@ unsigned long long rrdset_done(RRDSET *st) // it has never been updated before // set a fake last_updated, in the past using usec_since_last_update unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update; - st->last_updated.tv_sec = (__time_t) (ut / 1000000ULL); - st->last_updated.tv_usec = (__suseconds_t) (ut % 1000000ULL); + st->last_updated.tv_sec = (time_t) (ut / 1000000ULL); + st->last_updated.tv_usec = (useconds_t) (ut % 1000000ULL); // the first entry should not be stored store_this_entry = 0; + first_entry = 1; if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: initializing last_updated to now - %llu microseconds (%0.3Lf). Will not store the next entry.", st->name, st->usec_since_last_update, (long double)ut/1000000.0); } @@ -881,20 +887,26 @@ unsigned long long rrdset_done(RRDSET *st) gettimeofday(&st->last_collected_time, NULL); unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update; - st->last_updated.tv_sec = (__time_t) (ut / 1000000ULL); - st->last_updated.tv_usec = (__suseconds_t) (ut % 1000000ULL); + st->last_updated.tv_sec = (time_t) (ut / 1000000ULL); + st->last_updated.tv_usec = (useconds_t) (ut % 1000000ULL); // the first entry should not be stored store_this_entry = 0; + first_entry = 1; } // these are the 3 variables that will help us in interpolation // last_ut = the last time we added a value to the storage // now_ut = the time the current value is taken at // next_ut = the time of the next interpolation point - unsigned long long last_ut = st->last_updated.tv_sec * 1000000ULL + st->last_updated.tv_usec; - unsigned long long now_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec; - unsigned long long next_ut = (st->last_updated.tv_sec + st->update_every) * 1000000ULL; + last_ut = st->last_updated.tv_sec * 1000000ULL + st->last_updated.tv_usec; + now_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec; + next_ut = (st->last_updated.tv_sec + st->update_every) * 1000000ULL; + + if(unlikely(!first_entry && now_ut < next_ut)) { + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name); + in_the_same_interpolation_point = 1; + } if(unlikely(st->debug)) { debug(D_RRD_STATS, "%s: last ut = %0.3Lf (last updated time)", st->name, (long double)last_ut/1000000.0); @@ -921,12 +933,7 @@ unsigned long long rrdset_done(RRDSET *st) // at this stage we do not interpolate anything for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) { - if(unlikely(!rd->updated || rd->counter <= 1)) { - rd->calculated_value = 0; - continue; - } - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: " + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: START " " last_collected_value = " COLLECTED_NUMBER_FORMAT " collected_value = " COLLECTED_NUMBER_FORMAT " last_calculated_value = " CALCULATED_NUMBER_FORMAT @@ -939,26 +946,24 @@ unsigned long long rrdset_done(RRDSET *st) ); switch(rd->algorithm) { - case RRDDIM_PCENT_OVER_DIFF_TOTAL: - // the percentage of the current increment - // over the increment of all dimensions together - if(unlikely(st->collected_total == st->last_collected_total)) rd->calculated_value = rd->last_calculated_value; - else rd->calculated_value = - (calculated_number)100 - * (calculated_number)(rd->collected_value - rd->last_collected_value) - / (calculated_number)(st->collected_total - st->last_collected_total); - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF " - CALCULATED_NUMBER_FORMAT " = 100" - " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" - " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" - , st->id, rd->name - , rd->calculated_value - , rd->collected_value, rd->last_collected_value - , st->collected_total, st->last_collected_total - ); - break; + case RRDDIM_ABSOLUTE: + rd->calculated_value = (calculated_number)rd->collected_value + * (calculated_number)rd->multiplier + / (calculated_number)rd->divisor; + + if(unlikely(st->debug)) + debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN " + CALCULATED_NUMBER_FORMAT " = " + COLLECTED_NUMBER_FORMAT + " * " CALCULATED_NUMBER_FORMAT + " / " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->calculated_value + , rd->collected_value + , (calculated_number)rd->multiplier + , (calculated_number)rd->divisor + ); + break; case RRDDIM_PCENT_OVER_ROW_TOTAL: if(unlikely(!st->collected_total)) rd->calculated_value = 0; @@ -983,6 +988,11 @@ unsigned long long rrdset_done(RRDSET *st) break; case RRDDIM_INCREMENTAL: + if(unlikely(!rd->updated || rd->counter <= 1)) { + rd->calculated_value = 0; + continue; + } + // if the new is smaller than the old (an overflow, or reset), set the old equal to the new // to reset the calculation (it will give zero as the calculation for this second) if(unlikely(rd->last_collected_value > rd->collected_value)) { @@ -994,17 +1004,21 @@ unsigned long long rrdset_done(RRDSET *st) rd->last_collected_value = rd->collected_value; } - rd->calculated_value += (calculated_number)(rd->collected_value - rd->last_collected_value) + if(!in_the_same_interpolation_point) { + rd->last_calculated_value = rd->calculated_value; + } + + rd->calculated_value = (calculated_number)(rd->collected_value - rd->last_collected_value) * (calculated_number)rd->multiplier / (calculated_number)rd->divisor; if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC INC " - CALCULATED_NUMBER_FORMAT " += (" + debug(D_RRD_STATS, "%s/%s: CALC INC PRE " + CALCULATED_NUMBER_FORMAT " = (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT - " * %ld" - " / %ld" ")" + " * " CALCULATED_NUMBER_FORMAT + " / " CALCULATED_NUMBER_FORMAT , st->id, rd->name , rd->calculated_value , rd->collected_value, rd->last_collected_value @@ -1013,22 +1027,33 @@ unsigned long long rrdset_done(RRDSET *st) ); break; - case RRDDIM_ABSOLUTE: - rd->calculated_value = (calculated_number)rd->collected_value - * (calculated_number)rd->multiplier - / (calculated_number)rd->divisor; + case RRDDIM_PCENT_OVER_DIFF_TOTAL: + if(unlikely(!rd->updated || rd->counter <= 1)) { + rd->calculated_value = 0; + continue; + } + + // the percentage of the current increment + // over the increment of all dimensions together + if(unlikely(st->collected_total == st->last_collected_total)) rd->calculated_value = rd->last_calculated_value; + else rd->calculated_value = + (calculated_number)100 + * (calculated_number)(rd->collected_value - rd->last_collected_value) + / (calculated_number)(st->collected_total - st->last_collected_total); + + if(!in_the_same_interpolation_point) { + rd->last_calculated_value = rd->calculated_value; + } if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN " - CALCULATED_NUMBER_FORMAT " = " - COLLECTED_NUMBER_FORMAT - " * %ld" - " / %ld" + debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF " + CALCULATED_NUMBER_FORMAT " = 100" + " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" + " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" , st->id, rd->name , rd->calculated_value - , rd->collected_value - , (calculated_number)rd->multiplier - , (calculated_number)rd->divisor + , rd->collected_value, rd->last_collected_value + , st->collected_total, st->last_collected_total ); break; @@ -1045,6 +1070,19 @@ unsigned long long rrdset_done(RRDSET *st) ); break; } + + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: END " + " last_collected_value = " COLLECTED_NUMBER_FORMAT + " collected_value = " COLLECTED_NUMBER_FORMAT + " last_calculated_value = " CALCULATED_NUMBER_FORMAT + " calculated_value = " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->last_collected_value + , rd->collected_value + , rd->last_calculated_value + , rd->calculated_value + ); + } // at this point we have all the calculated values ready @@ -1052,10 +1090,11 @@ unsigned long long rrdset_done(RRDSET *st) unsigned long long first_ut = last_ut; long long iterations = (now_ut - last_ut) / (st->update_every * 1000000ULL); + if((now_ut % (st->update_every * 1000000ULL)) == 0) iterations++; for( ; likely(next_ut <= now_ut) ; next_ut += st->update_every * 1000000ULL, iterations-- ) { #ifdef NETDATA_INTERNAL_CHECKS - if(iterations <= 0) error("iterations calculation wrapped!"); + if(iterations <= 0) { error("iterations calculation wrapped!"); } #endif if(unlikely(st->debug)) { @@ -1063,7 +1102,7 @@ unsigned long long rrdset_done(RRDSET *st) debug(D_RRD_STATS, "%s: next ut = %0.3Lf (next interpolation point)", st->name, (long double)next_ut/1000000.0); } - st->last_updated.tv_sec = (__time_t) (next_ut / 1000000ULL); + st->last_updated.tv_sec = (time_t) (next_ut / 1000000ULL); st->last_updated.tv_usec = 0; for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) { @@ -1091,6 +1130,8 @@ unsigned long long rrdset_done(RRDSET *st) ); rd->calculated_value -= new_value; + new_value += rd->last_calculated_value; + rd->last_calculated_value = 0; new_value /= (calculated_number)st->update_every; break; @@ -1198,10 +1239,29 @@ unsigned long long rrdset_done(RRDSET *st) last_ut = next_ut; } + // align next interpolation to last collection point + st->last_updated.tv_sec = st->last_collected_time.tv_sec; + st->last_updated.tv_usec = st->last_collected_time.tv_usec; + for( rd = st->dimensions; likely(rd) ; rd = rd->next ) { if(unlikely(!rd->updated)) continue; - rd->last_collected_value = rd->collected_value; - rd->last_calculated_value = rd->calculated_value; + + int is_incremental = 0; + if(rd->algorithm == RRDDIM_PCENT_OVER_DIFF_TOTAL || rd->algorithm == RRDDIM_INCREMENTAL) + is_incremental = 1; + + if((is_incremental && !in_the_same_interpolation_point) || !is_incremental || !store_this_entry) { + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_collected_value (old: " COLLECTED_NUMBER_FORMAT ") to last_collected_value (new: " COLLECTED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_collected_value, rd->collected_value); + rd->last_collected_value = rd->collected_value; + + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value, rd->calculated_value); + rd->last_calculated_value = rd->calculated_value; + } + else { + if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: discarding calculated_value (old: " CALCULATED_NUMBER_FORMAT ") new: 0", st->id, rd->name, rd->calculated_value); + rd->calculated_value = 0; + } + rd->collected_value = 0; rd->updated = 0; diff --git a/src/unit_test.c b/src/unit_test.c index c3d1e8357a..0582819f0c 100755 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -241,6 +241,426 @@ int unit_test_storage() return r; } + +// -------------------------------------------------------------------------------------------------------------------- + +struct feed_values { + unsigned long long microseconds; + calculated_number value; +}; + +struct test { + char name[100]; + char description[1024]; + + int update_every; + unsigned long long multiplier; + unsigned long long divisor; + int algorithm; + + unsigned long feed_entries; + unsigned long result_entries; + struct feed_values *feed; + calculated_number *results; +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test1 +// test absolute values stored + +struct feed_values test1_feed[] = { + { 0, 10 }, + { 1000000, 20 }, + { 1000000, 30 }, + { 1000000, 40 }, + { 1000000, 50 }, + { 1000000, 60 }, + { 1000000, 70 }, + { 1000000, 80 }, + { 1000000, 90 }, + { 1000000, 100 }, +}; + +calculated_number test1_results[] = { + 20, 30, 40, 50, 60, 70, 80, 90, 100 +}; + +struct test test1 = { + "test1", // name + "test absolute values stored at exactly second boundaries", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_ABSOLUTE, // algorithm + 10, // feed entries + 9, // result entries + test1_feed, // feed + test1_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test2 +// test absolute values stored in the middle of second boundaries + +struct feed_values test2_feed[] = { + { 500000, 10 }, + { 1000000, 20 }, + { 1000000, 30 }, + { 1000000, 40 }, + { 1000000, 50 }, + { 1000000, 60 }, + { 1000000, 70 }, + { 1000000, 80 }, + { 1000000, 90 }, + { 1000000, 100 }, +}; + +calculated_number test2_results[] = { + 20, 30, 40, 50, 60, 70, 80, 90, 100 +}; + +struct test test2 = { + "test2", // name + "test absolute values stored in the middle of second boundaries", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_ABSOLUTE, // algorithm + 10, // feed entries + 9, // result entries + test2_feed, // feed + test2_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test3 + +struct feed_values test3_feed[] = { + { 0, 10 }, + { 1000000, 20 }, + { 1000000, 30 }, + { 1000000, 40 }, + { 1000000, 50 }, + { 1000000, 60 }, + { 1000000, 70 }, + { 1000000, 80 }, + { 1000000, 90 }, + { 1000000, 100 }, +}; + +calculated_number test3_results[] = { + 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +struct test test3 = { + "test3", // name + "test incremental values stored at exactly second boundaries", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_INCREMENTAL, // algorithm + 10, // feed entries + 9, // result entries + test3_feed, // feed + test3_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test4 + +struct feed_values test4_feed[] = { + { 500000, 10 }, + { 1000000, 20 }, + { 1000000, 30 }, + { 1000000, 40 }, + { 1000000, 50 }, + { 1000000, 60 }, + { 1000000, 70 }, + { 1000000, 80 }, + { 1000000, 90 }, + { 1000000, 100 }, +}; + +calculated_number test4_results[] = { + 5, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +struct test test4 = { + "test4", // name + "test incremental values stored in the middle of second boundaries", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_INCREMENTAL, // algorithm + 10, // feed entries + 9, // result entries + test4_feed, // feed + test4_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test5 + +struct feed_values test5_feed[] = { + { 500000, 1000 }, + { 1000000, 2000 }, + { 1000000, 2000 }, + { 1000000, 2000 }, + { 1000000, 3000 }, + { 1000000, 2000 }, + { 1000000, 2000 }, + { 1000000, 2000 }, + { 1000000, 2000 }, + { 1000000, 2000 }, +}; + +calculated_number test5_results[] = { + 500, 500, 0, 500, 500, 0, 0, 0, 0 +}; + +struct test test5 = { + "test5", // name + "test incremental values ups and downs", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_INCREMENTAL, // algorithm + 10, // feed entries + 9, // result entries + test5_feed, // feed + test5_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test6 + +struct feed_values test6_feed[] = { + { 250000, 1000 }, + { 250000, 2000 }, + { 250000, 3000 }, + { 250000, 4000 }, + { 250000, 5000 }, + { 250000, 6000 }, + { 250000, 7000 }, + { 250000, 8000 }, + { 250000, 9000 }, + { 250000, 10000 }, + { 250000, 11000 }, + { 250000, 12000 }, + { 250000, 13000 }, + { 250000, 14000 }, + { 250000, 15000 }, + { 250000, 16000 }, +}; + +calculated_number test6_results[] = { + 3000, 4000, 4000, 4000 +}; + +struct test test6 = { + "test6", // name + "test incremental values updated within the same second", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_INCREMENTAL, // algorithm + 16, // feed entries + 4, // result entries + test6_feed, // feed + test6_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test7 + +struct feed_values test7_feed[] = { + { 500000, 1000 }, + { 2000000, 2000 }, + { 2000000, 3000 }, + { 2000000, 4000 }, + { 2000000, 5000 }, + { 2000000, 6000 }, + { 2000000, 7000 }, + { 2000000, 8000 }, + { 2000000, 9000 }, + { 2000000, 10000 }, +}; + +calculated_number test7_results[] = { + 250, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500 +}; + +struct test test7 = { + "test7", // name + "test incremental values updated in long durations", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_INCREMENTAL, // algorithm + 10, // feed entries + 18, // result entries + test7_feed, // feed + test7_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test8 + +struct feed_values test8_feed[] = { + { 500000, 1000 }, + { 2000000, 2000 }, + { 2000000, 3000 }, + { 2000000, 4000 }, + { 2000000, 5000 }, + { 2000000, 6000 }, +}; + +calculated_number test8_results[] = { + 1250, 2000, 2250, 3000, 3250, 4000, 4250, 5000, 5250, 6000 +}; + +struct test test8 = { + "test8", // name + "test absolute values updated in long durations", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_ABSOLUTE, // algorithm + 6, // feed entries + 10, // result entries + test8_feed, // feed + test8_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- +// test9 + +struct feed_values test9_feed[] = { + { 250000, 1000 }, + { 250000, 2000 }, + { 250000, 3000 }, + { 250000, 4000 }, + { 250000, 5000 }, + { 250000, 6000 }, + { 250000, 7000 }, + { 250000, 8000 }, + { 250000, 9000 }, + { 250000, 10000 }, + { 250000, 11000 }, + { 250000, 12000 }, + { 250000, 13000 }, + { 250000, 14000 }, + { 250000, 15000 }, + { 250000, 16000 }, +}; + +calculated_number test9_results[] = { + 4000, 8000, 12000, 16000 +}; + +struct test test9 = { + "test9", // name + "test absolute values updated within the same second", + 1, // update_every + 1, // multiplier + 1, // divisor + RRDDIM_ABSOLUTE, // algorithm + 16, // feed entries + 4, // result entries + test9_feed, // feed + test9_results // results +}; + +// -------------------------------------------------------------------------------------------------------------------- + +int run_test(struct test *test) +{ + fprintf(stderr, "\nRunning test '%s':\n%s\n", test->name, test->description); + + rrd_memory_mode = RRD_MEMORY_MODE_RAM; + rrd_update_every = test->update_every; + + char name[101]; + snprintf(name, 100, "unittest-%s", test->name); + + // create the chart + RRDSET *st = rrdset_create("netdata", name, name, "netdata", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE); + RRDDIM *rd = rrddim_add(st, "dimension", NULL, test->multiplier, test->divisor, test->algorithm); + st->debug = 1; + + // feed it with the test data + unsigned long c; + for(c = 0; c < test->feed_entries; c++) { + if(debug_flags) fprintf(stderr, "\n\n"); + + if(c) { + fprintf(stderr, " > %s: feeding position %lu, after %llu microseconds, with value " CALCULATED_NUMBER_FORMAT "\n", test->name, c+1, test->feed[c].microseconds, test->feed[c].value); + rrdset_next_usec(st, test->feed[c].microseconds); + } + else { + fprintf(stderr, " > %s: feeding position %lu with value " CALCULATED_NUMBER_FORMAT "\n", test->name, c+1, test->feed[c].value); + } + + rrddim_set(st, "dimension", test->feed[c].value); + rrdset_done(st); + + // align the first entry to second boundary + if(!c) { + fprintf(stderr, " > %s: fixing first collection time to be %llu microseconds to second boundary\n", test->name, test->feed[c].microseconds); + rd->last_collected_time.tv_usec = st->last_collected_time.tv_usec = st->last_updated.tv_usec = test->feed[c].microseconds; + } + } + + // check the result + int errors = 0; + + if(st->counter != test->result_entries) { + fprintf(stderr, " %s stored %lu entries, but we were expecting %lu, ### E R R O R ###\n", test->name, st->counter, test->result_entries); + errors++; + } + + unsigned long max = (st->counter < test->result_entries)?st->counter:test->result_entries; + for(c = 0 ; c < max ; c++) { + calculated_number v = unpack_storage_number(rd->values[c]), n = test->results[c]; + fprintf(stderr, " %s: checking position %lu, expecting value " CALCULATED_NUMBER_FORMAT ", found " CALCULATED_NUMBER_FORMAT ", %s\n", test->name, c+1, n, v, (v == n)?"OK":"### E R R O R ###"); + if(v != n) errors++; + } + + return errors; +} + +int run_all_mockup_tests(void) +{ + if(run_test(&test1)) + return 1; + + if(run_test(&test2)) + return 1; + + if(run_test(&test3)) + return 1; + + if(run_test(&test4)) + return 1; + + if(run_test(&test5)) + return 1; + + if(run_test(&test6)) + return 1; + + if(run_test(&test7)) + return 1; + + if(run_test(&test8)) + return 1; + + if(run_test(&test9)) + return 1; + + return 0; +} + int unit_test(long delay, long shift) { static int repeat = 0; @@ -249,14 +669,14 @@ int unit_test(long delay, long shift) char name[101]; snprintf(name, 100, "unittest-%d-%ld-%ld", repeat, delay, shift); - debug_flags = 0xffffffff; + //debug_flags = 0xffffffff; rrd_memory_mode = RRD_MEMORY_MODE_RAM; rrd_update_every = 1; int do_abs = 1; int do_inc = 1; - int do_abst = 1; - int do_absi = 1; + int do_abst = 0; + int do_absi = 0; RRDSET *st = rrdset_create("netdata", name, name, "netdata", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE); st->debug = 1; @@ -296,7 +716,8 @@ int unit_test(long delay, long shift) } // prevent it from deleting the dimensions - for(rd = st->dimensions ; rd ; rd = rd->next) rd->last_collected_time.tv_sec = st->last_collected_time.tv_sec; + for(rd = st->dimensions ; rd ; rd = rd->next) + rd->last_collected_time.tv_sec = st->last_collected_time.tv_sec; rrdset_done(st); } @@ -306,27 +727,30 @@ int unit_test(long delay, long shift) fprintf(stderr, "\n\nORIGINAL INCREMENT: %lu, INCREMENT %lu, DELAY %lu, SHIFT %lu\n", oincrement * 10, increment * 10, delay, shift); int ret = 0; - storage_number v; + storage_number sn; + calculated_number cn, v; for(c = 0 ; c < st->counter ; c++) { - fprintf(stderr, "\nPOSITION: c = %lu, VALUE %lu\n", c, (oincrement + c * increment + increment * (1000000 - shift) / 1000000 )* 10); + fprintf(stderr, "\nPOSITION: c = %lu, EXPECTED VALUE %lu\n", c, (oincrement + c * increment + increment * (1000000 - shift) / 1000000 )* 10); for(rd = st->dimensions ; rd ; rd = rd->next) { - fprintf(stderr, "\t %s " STORAGE_NUMBER_FORMAT " -> ", rd->id, rd->values[c]); + sn = rd->values[c]; + cn = unpack_storage_number(sn); + fprintf(stderr, "\t %s " CALCULATED_NUMBER_FORMAT " (PACKED AS " STORAGE_NUMBER_FORMAT ") -> ", rd->id, cn, sn); if(rd == rdabs) v = ( oincrement - + (increment * (1000000 - shift) / 1000000) - + c * increment - ) * 10; + // + (increment * (1000000 - shift) / 1000000) + + (c + 1) * increment + ); - else if(rd == rdinc) v = (c?(increment):(increment * (1000000 - shift) / 1000000)) * 10; - else if(rd == rdabst) v = oincrement / dimensions; - else if(rd == rdabsi) v = oincrement / dimensions; + else if(rd == rdinc) v = (c?(increment):(increment * (1000000 - shift) / 1000000)); + else if(rd == rdabst) v = oincrement / dimensions / 10; + else if(rd == rdabsi) v = oincrement / dimensions / 10; else v = 0; - if(v == rd->values[c]) fprintf(stderr, "passed.\n"); + if(v == cn) fprintf(stderr, "passed.\n"); else { - fprintf(stderr, "ERROR! (expected " STORAGE_NUMBER_FORMAT ")\n", v); + fprintf(stderr, "ERROR! (expected " CALCULATED_NUMBER_FORMAT ")\n", v); ret = 1; } } @@ -337,4 +761,3 @@ int unit_test(long delay, long shift) return ret; } - diff --git a/src/unit_test.h b/src/unit_test.h index c402d2cf16..916ad71f23 100755 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -3,5 +3,6 @@ extern int unit_test_storage(void); extern int unit_test(long delay, long shift); +extern int run_all_mockup_tests(void); #endif /* NETDATA_UNIT_TEST_H */ |