master
c 1,794 lines 62.8 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "common.h"
4 #include "web/api/formatters/rrd2json.h"
5 #include "database/contexts/rrdcontext-internal.h"
6
7 #if defined(OS_LINUX)
8 #include "collectors/proc.plugin/plugin_proc.h"
9 #endif
10
11 static bool cmd_arg_sanitization_test(const char *expected, const char *src, char *dst, size_t dst_size) {
12 bool ok = sanitize_command_argument_string(dst, src, dst_size);
13
14 if (!expected)
15 return ok == false;
16
17 return strcmp(expected, dst) == 0;
18 }
19
20 bool command_argument_sanitization_tests() {
21 char dst[1024];
22
23 for (size_t i = 0; i != 5; i++) {
24 const char *expected = i == 4 ? "'\\''" : NULL;
25 if (cmd_arg_sanitization_test(expected, "'", dst, i) == false) {
26 fprintf(stderr, "expected: >>>%s<<<, got: >>>%s<<<\n", expected, dst);
27 return 1;
28 }
29 }
30
31 for (size_t i = 0; i != 9; i++) {
32 const char *expected = i == 8 ? "'\\'''\\''" : NULL;
33 if (cmd_arg_sanitization_test(expected, "''", dst, i) == false) {
34 fprintf(stderr, "expected: >>>%s<<<, got: >>>%s<<<\n", expected, dst);
35 return 1;
36 }
37 }
38
39 for (size_t i = 0; i != 7; i++) {
40 const char *expected = i == 6 ? "'\\''a" : NULL;
41 if (cmd_arg_sanitization_test(expected, "'a", dst, i) == false) {
42 fprintf(stderr, "expected: >>>%s<<<, got: >>>%s<<<\n", expected, dst);
43 return 1;
44 }
45 }
46
47 for (size_t i = 0; i != 7; i++) {
48 const char *expected = i == 6 ? "a'\\''" : NULL;
49 if (cmd_arg_sanitization_test(expected, "a'", dst, i) == false) {
50 fprintf(stderr, "expected: >>>%s<<<, got: >>>%s<<<\n", expected, dst);
51 return 1;
52 }
53 }
54
55 for (size_t i = 0; i != 22; i++) {
56 const char *expected = i == 21 ? "foo'\\''a'\\'''\\'''\\''b" : NULL;
57 if (cmd_arg_sanitization_test(expected, "--foo'a'''b", dst, i) == false) {
58 fprintf(stderr, "expected: >>>%s<<<, got: >>>%s<<<\n length: %zu\n", expected, dst, strlen(dst));
59 return 1;
60 }
61 }
62
63 return 0;
64 }
65
66 static int check_number_printing(void) {
67 struct {
68 NETDATA_DOUBLE n;
69 const char *correct;
70 } values[] = {
71 { .n = 0, .correct = "0" },
72 { .n = 0.0000001, .correct = "0.0000001" },
73 { .n = 0.00000009, .correct = "0.0000001" },
74 { .n = 0.000000001, .correct = "0" },
75 { .n = 99.99999999999999999, .correct = "100" },
76 { .n = -99.99999999999999999, .correct = "-100" },
77 { .n = 123.4567899123456789, .correct = "123.4567899" },
78 { .n = 123.4567890123456789, .correct = "123.456789" },
79 { .n = 123.4567800123456789, .correct = "123.45678" },
80 { .n = 123.4567000123456789, .correct = "123.4567" },
81 { .n = 123.4560000123456789, .correct = "123.456" },
82 { .n = 123.4500000123456789, .correct = "123.45" },
83 { .n = 123.4000000123456789, .correct = "123.4" },
84 { .n = 123.0000000123456789, .correct = "123" },
85 { .n = 123.0000000923456789, .correct = "123.0000001" },
86 { .n = 4294967295.123456789, .correct = "4294967295.123457" },
87 { .n = 8294967295.123456789, .correct = "8294967295.123457" },
88 { .n = 1.000000000000002e+19, .correct = "1.000000000000001998e+19" },
89 { .n = 9.2233720368547676e+18, .correct = "9.223372036854767584e+18" },
90 { .n = 18446744073709541376.0, .correct = "1.84467440737095424e+19" },
91 { .n = 18446744073709551616.0, .correct = "1.844674407370955136e+19" },
92 { .n = 12318446744073710600192.0, .correct = "1.231844674407371008e+22" },
93 { .n = 1677721499999999885312.0, .correct = "1.677721499999999872e+21" },
94 { .n = -1677721499999999885312.0, .correct = "-1.677721499999999872e+21" },
95 { .n = -1.677721499999999885312e40, .correct = "-1.677721499999999872e+40" },
96 { .n = -16777214999999997337621690403742592008192.0, .correct = "-1.677721499999999616e+40" },
97 { .n = 9999.9999999, .correct = "9999.9999999" },
98 { .n = -9999.9999999, .correct = "-9999.9999999" },
99 { .n = 0, .correct = NULL },
100 };
101
102 char netdata[512 + 2], system[512 + 2];
103 int i, failed = 0;
104 for(i = 0; values[i].correct ; i++) {
105 print_netdata_double(netdata, values[i].n);
106 snprintfz(system, sizeof(system) - 1, "%0.12" NETDATA_DOUBLE_MODIFIER, (NETDATA_DOUBLE)values[i].n);
107
108 int ok = 1;
109 if(strcmp(netdata, values[i].correct) != 0) {
110 ok = 0;
111 failed++;
112 }
113
114 NETDATA_DOUBLE parsed_netdata = str2ndd(netdata, NULL);
115 NETDATA_DOUBLE parsed_system = strtondd(netdata, NULL);
116
117 if(parsed_system != parsed_netdata)
118 failed++;
119
120 fprintf(stderr, "[%d]. '%s' (system) printed as '%s' (netdata): PRINT %s, "
121 "PARSED %0.12" NETDATA_DOUBLE_MODIFIER " (system), %0.12" NETDATA_DOUBLE_MODIFIER " (netdata): %s\n",
122 i,
123 system, netdata, ok?"OK":"FAILED",
124 parsed_system, parsed_netdata,
125 parsed_netdata == parsed_system ? "OK" : "FAILED");
126 }
127
128 if(failed) return 1;
129 return 0;
130 }
131
132 static int check_rrdcalc_comparisons(void) {
133 RRDCALC_STATUS a, b;
134
135 // make sure calloc() sets the status to UNINITIALIZED
136 memset(&a, 0, sizeof(RRDCALC_STATUS));
137 if(a != RRDCALC_STATUS_UNINITIALIZED) {
138 fprintf(stderr, "%s is not zero.\n", rrdcalc_status2string(RRDCALC_STATUS_UNINITIALIZED));
139 return 1;
140 }
141
142 a = RRDCALC_STATUS_REMOVED;
143 b = RRDCALC_STATUS_UNDEFINED;
144 if(!(a < b)) {
145 fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
146 return 1;
147 }
148
149 a = RRDCALC_STATUS_UNDEFINED;
150 b = RRDCALC_STATUS_UNINITIALIZED;
151 if(!(a < b)) {
152 fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
153 return 1;
154 }
155
156 a = RRDCALC_STATUS_UNINITIALIZED;
157 b = RRDCALC_STATUS_CLEAR;
158 if(!(a < b)) {
159 fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
160 return 1;
161 }
162
163 a = RRDCALC_STATUS_CLEAR;
164 b = RRDCALC_STATUS_RAISED;
165 if(!(a < b)) {
166 fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
167 return 1;
168 }
169
170 a = RRDCALC_STATUS_RAISED;
171 b = RRDCALC_STATUS_WARNING;
172 if(!(a < b)) {
173 fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
174 return 1;
175 }
176
177 a = RRDCALC_STATUS_WARNING;
178 b = RRDCALC_STATUS_CRITICAL;
179 if(!(a < b)) {
180 fprintf(stderr, "%s is not less than %s\n", rrdcalc_status2string(a), rrdcalc_status2string(b));
181 return 1;
182 }
183
184 fprintf(stderr, "RRDCALC_STATUSes are sortable.\n");
185
186 return 0;
187 }
188
189 int check_storage_number(NETDATA_DOUBLE n, int debug) {
190 char buffer[100];
191 uint32_t flags = SN_DEFAULT_FLAGS;
192
193 storage_number s = pack_storage_number(n, flags);
194 NETDATA_DOUBLE d = unpack_storage_number(s);
195
196 if(!does_storage_number_exist(s)) {
197 fprintf(stderr, "Exists flags missing for number " NETDATA_DOUBLE_FORMAT "!\n", n);
198 return 5;
199 }
200
201 NETDATA_DOUBLE ddiff = d - n;
202 NETDATA_DOUBLE dcdiff = ddiff * 100.0 / n;
203
204 if(dcdiff < 0) dcdiff = -dcdiff;
205
206 size_t len = (size_t)print_netdata_double(buffer, d);
207 NETDATA_DOUBLE p = str2ndd(buffer, NULL);
208 NETDATA_DOUBLE pdiff = n - p;
209 NETDATA_DOUBLE pcdiff = pdiff * 100.0 / n;
210 if(pcdiff < 0) pcdiff = -pcdiff;
211
212 if(debug) {
213 fprintf(stderr,
214 NETDATA_DOUBLE_FORMAT
215 " original\n" NETDATA_DOUBLE_FORMAT " packed and unpacked, (stored as 0x%08X, diff " NETDATA_DOUBLE_FORMAT
216 ", " NETDATA_DOUBLE_FORMAT "%%)\n"
217 "%s printed after unpacked (%zu bytes)\n" NETDATA_DOUBLE_FORMAT
218 " re-parsed from printed (diff " NETDATA_DOUBLE_FORMAT ", " NETDATA_DOUBLE_FORMAT "%%)\n\n",
219 n,
220 d, s, ddiff, dcdiff,
221 buffer, len,
222 p, pdiff, pcdiff
223 );
224 if(len != strlen(buffer)) fprintf(stderr, "ERROR: printed number %s is reported to have length %zu but it has %zu\n", buffer, len, strlen(buffer));
225
226 if(dcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT)
227 fprintf(stderr, "WARNING: packing number " NETDATA_DOUBLE_FORMAT " has accuracy loss " NETDATA_DOUBLE_FORMAT " %%\n", n, dcdiff);
228
229 if(pcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT)
230 fprintf(stderr, "WARNING: re-parsing the packed, unpacked and printed number " NETDATA_DOUBLE_FORMAT
231 " has accuracy loss " NETDATA_DOUBLE_FORMAT " %%\n", n, pcdiff);
232 }
233
234 if(len != strlen(buffer)) return 1;
235 if(dcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT) return 3;
236 if(pcdiff > ACCURACY_LOSS_ACCEPTED_PERCENT) return 4;
237 return 0;
238 }
239
240 NETDATA_DOUBLE storage_number_min(NETDATA_DOUBLE n) {
241 NETDATA_DOUBLE r = 1, last;
242
243 do {
244 last = n;
245 n /= 2.0;
246 storage_number t = pack_storage_number(n, SN_DEFAULT_FLAGS);
247 r = unpack_storage_number(t);
248 } while(r != 0.0 && r != last);
249
250 return last;
251 }
252
253 void benchmark_storage_number(int loop, int multiplier) {
254 int i, j;
255 NETDATA_DOUBLE n, d;
256 storage_number s;
257 unsigned long long user, system, total, mine, their;
258
259 NETDATA_DOUBLE storage_number_positive_min = unpack_storage_number(STORAGE_NUMBER_POSITIVE_MIN_RAW);
260 NETDATA_DOUBLE storage_number_positive_max = unpack_storage_number(STORAGE_NUMBER_POSITIVE_MAX_RAW);
261
262 char buffer[100];
263
264 struct rusage now, last;
265
266 fprintf(stderr, "\n\nBenchmarking %d numbers, please wait...\n\n", loop);
267
268 // ------------------------------------------------------------------------
269
270 fprintf(stderr, "SYSTEM LONG DOUBLE SIZE: %zu bytes\n", sizeof(NETDATA_DOUBLE));
271 fprintf(stderr, "NETDATA FLOATING POINT SIZE: %zu bytes\n", sizeof(storage_number));
272
273 mine = (NETDATA_DOUBLE)sizeof(storage_number) * (NETDATA_DOUBLE)loop;
274 their = (NETDATA_DOUBLE)sizeof(NETDATA_DOUBLE) * (NETDATA_DOUBLE)loop;
275
276 if(mine > their) {
277 fprintf(stderr, "\nNETDATA NEEDS %0.2" NETDATA_DOUBLE_MODIFIER " TIMES MORE MEMORY. Sorry!\n", (NETDATA_DOUBLE)(mine / their));
278 }
279 else {
280 fprintf(stderr, "\nNETDATA INTERNAL FLOATING POINT ARITHMETICS NEEDS %0.2" NETDATA_DOUBLE_MODIFIER " TIMES LESS MEMORY.\n", (NETDATA_DOUBLE)(their / mine));
281 }
282
283 fprintf(stderr, "\nNETDATA FLOATING POINT\n");
284 fprintf(stderr, "MIN POSITIVE VALUE " NETDATA_DOUBLE_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_POSITIVE_MIN_RAW));
285 fprintf(stderr, "MAX POSITIVE VALUE " NETDATA_DOUBLE_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_POSITIVE_MAX_RAW));
286 fprintf(stderr, "MIN NEGATIVE VALUE " NETDATA_DOUBLE_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_NEGATIVE_MIN_RAW));
287 fprintf(stderr, "MAX NEGATIVE VALUE " NETDATA_DOUBLE_FORMAT "\n", unpack_storage_number(STORAGE_NUMBER_NEGATIVE_MAX_RAW));
288 fprintf(stderr, "Maximum accuracy loss accepted: " NETDATA_DOUBLE_FORMAT "%%\n\n\n", (NETDATA_DOUBLE)ACCURACY_LOSS_ACCEPTED_PERCENT);
289
290 // ------------------------------------------------------------------------
291
292 fprintf(stderr, "INTERNAL LONG DOUBLE PRINTING: ");
293 getrusage(RUSAGE_SELF, &last);
294
295 // do the job
296 for(j = 1; j < 11 ;j++) {
297 n = storage_number_positive_min * j;
298
299 for(i = 0; i < loop ;i++) {
300 n *= multiplier;
301 if(n > storage_number_positive_max) n = storage_number_positive_min;
302
303 print_netdata_double(buffer, n);
304 }
305 }
306
307 getrusage(RUSAGE_SELF, &now);
308 user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
309 system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
310 total = user + system;
311 mine = total;
312
313 fprintf(stderr, "user %0.5" NETDATA_DOUBLE_MODIFIER ", system %0.5" NETDATA_DOUBLE_MODIFIER
314 ", total %0.5" NETDATA_DOUBLE_MODIFIER "\n", (NETDATA_DOUBLE)(user / 1000000.0), (NETDATA_DOUBLE)(system / 1000000.0), (NETDATA_DOUBLE)(total / 1000000.0));
315
316 // ------------------------------------------------------------------------
317
318 fprintf(stderr, "SYSTEM LONG DOUBLE PRINTING: ");
319 getrusage(RUSAGE_SELF, &last);
320
321 // do the job
322 for(j = 1; j < 11 ;j++) {
323 n = storage_number_positive_min * j;
324
325 for(i = 0; i < loop ;i++) {
326 n *= multiplier;
327 if(n > storage_number_positive_max) n = storage_number_positive_min;
328 snprintfz(buffer, sizeof(buffer) - 1, NETDATA_DOUBLE_FORMAT, n);
329 }
330 }
331
332 getrusage(RUSAGE_SELF, &now);
333 user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
334 system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
335 total = user + system;
336 their = total;
337
338 fprintf(stderr, "user %0.5" NETDATA_DOUBLE_MODIFIER ", system %0.5" NETDATA_DOUBLE_MODIFIER
339 ", total %0.5" NETDATA_DOUBLE_MODIFIER "\n", (NETDATA_DOUBLE)(user / 1000000.0), (NETDATA_DOUBLE)(system / 1000000.0), (NETDATA_DOUBLE)(total / 1000000.0));
340
341 if(mine > total) {
342 fprintf(stderr, "NETDATA CODE IS SLOWER %0.2" NETDATA_DOUBLE_MODIFIER " %%\n", (NETDATA_DOUBLE)(mine * 100.0 / their - 100.0));
343 }
344 else {
345 fprintf(stderr, "NETDATA CODE IS F A S T E R %0.2" NETDATA_DOUBLE_MODIFIER " %%\n", (NETDATA_DOUBLE)(their * 100.0 / mine - 100.0));
346 }
347
348 // ------------------------------------------------------------------------
349
350 fprintf(stderr, "\nINTERNAL LONG DOUBLE PRINTING WITH PACK / UNPACK: ");
351 getrusage(RUSAGE_SELF, &last);
352
353 // do the job
354 for(j = 1; j < 11 ;j++) {
355 n = storage_number_positive_min * j;
356
357 for(i = 0; i < loop ;i++) {
358 n *= multiplier;
359 if(n > storage_number_positive_max) n = storage_number_positive_min;
360
361 s = pack_storage_number(n, SN_DEFAULT_FLAGS);
362 d = unpack_storage_number(s);
363 print_netdata_double(buffer, d);
364 }
365 }
366
367 getrusage(RUSAGE_SELF, &now);
368 user = now.ru_utime.tv_sec * 1000000ULL + now.ru_utime.tv_usec - last.ru_utime.tv_sec * 1000000ULL + last.ru_utime.tv_usec;
369 system = now.ru_stime.tv_sec * 1000000ULL + now.ru_stime.tv_usec - last.ru_stime.tv_sec * 1000000ULL + last.ru_stime.tv_usec;
370 total = user + system;
371 mine = total;
372
373 fprintf(stderr, "user %0.5" NETDATA_DOUBLE_MODIFIER ", system %0.5" NETDATA_DOUBLE_MODIFIER
374 ", total %0.5" NETDATA_DOUBLE_MODIFIER "\n", (NETDATA_DOUBLE)(user / 1000000.0), (NETDATA_DOUBLE)(system / 1000000.0), (NETDATA_DOUBLE)(total / 1000000.0));
375
376 if(mine > their) {
377 fprintf(stderr, "WITH PACKING UNPACKING NETDATA CODE IS SLOWER %0.2" NETDATA_DOUBLE_MODIFIER " %%\n", (NETDATA_DOUBLE)(mine * 100.0 / their - 100.0));
378 }
379 else {
380 fprintf(stderr, "EVEN WITH PACKING AND UNPACKING, NETDATA CODE IS F A S T E R %0.2" NETDATA_DOUBLE_MODIFIER " %%\n", (NETDATA_DOUBLE)(their * 100.0 / mine - 100.0));
381 }
382
383 // ------------------------------------------------------------------------
384
385 }
386
387 static int check_storage_number_exists() {
388 uint32_t flags = SN_DEFAULT_FLAGS;
389 NETDATA_DOUBLE n = 0.0;
390
391 storage_number s = pack_storage_number(n, flags);
392 NETDATA_DOUBLE d = unpack_storage_number(s);
393
394 if(n != d) {
395 fprintf(stderr, "Wrong number returned. Expected " NETDATA_DOUBLE_FORMAT ", returned " NETDATA_DOUBLE_FORMAT "!\n", n, d);
396 return 1;
397 }
398
399 return 0;
400 }
401
402 int unit_test_storage() {
403 if(check_storage_number_exists()) return 0;
404
405 NETDATA_DOUBLE storage_number_positive_min = unpack_storage_number(STORAGE_NUMBER_POSITIVE_MIN_RAW);
406 NETDATA_DOUBLE storage_number_negative_max = unpack_storage_number(STORAGE_NUMBER_NEGATIVE_MAX_RAW);
407
408 NETDATA_DOUBLE c, a = 0;
409 int i, j, g, r = 0;
410
411 for(g = -1; g <= 1 ; g++) {
412 a = 0;
413
414 if(!g) continue;
415
416 for(j = 0; j < 9 ;j++) {
417 a += 0.0000001;
418 c = a * g;
419 for(i = 0; i < 21 ;i++, c *= 10) {
420 if(c > 0 && c < storage_number_positive_min) continue;
421 if(c < 0 && c > storage_number_negative_max) continue;
422
423 if(check_storage_number(c, 1)) return 1;
424 }
425 }
426 }
427
428 // if(check_storage_number(858993459.1234567, 1)) return 1;
429 benchmark_storage_number(1000000, 2);
430 return r;
431 }
432
433 int unit_test_str2ld() {
434 is_system_ieee754_double();
435
436 char *values[] = {
437 "1.2345678",
438 "-35.6",
439 "0.00123",
440 "23842384234234.2",
441 ".1",
442 "1.2e-10",
443 "18446744073709551616.0",
444 "18446744073709551616123456789123456789123456789123456789123456789123456789123456789.0",
445 "1.8446744073709551616123456789123456789123456789123456789123456789123456789123456789e+300",
446 "9.",
447 "9.e2",
448 "1.2e",
449 "1.2e+",
450 "1.2e-",
451 "1.2e0",
452 "1.2e-0",
453 "1.2e+0",
454 "-1.2e+1",
455 "-1.2e-1",
456 "1.2e1",
457 "1.2e400",
458 "hello",
459 "1wrong",
460 "nan",
461 "inf",
462 NULL
463 };
464
465 int i;
466 for(i = 0; values[i] ; i++) {
467 char *e_mine = "hello", *e_sys = "world";
468 NETDATA_DOUBLE mine = str2ndd(values[i], &e_mine);
469 NETDATA_DOUBLE sys = strtondd(values[i], &e_sys);
470
471 if(isnan(mine)) {
472 if(!isnan(sys)) {
473 fprintf(stderr, "Value '%s' is parsed as %" NETDATA_DOUBLE_MODIFIER
474 ", but system believes it is %" NETDATA_DOUBLE_MODIFIER ".\n", values[i], mine, sys);
475 return -1;
476 }
477 }
478 else if(isinf(mine)) {
479 if(!isinf(sys)) {
480 fprintf(stderr, "Value '%s' is parsed as %" NETDATA_DOUBLE_MODIFIER
481 ", but system believes it is %" NETDATA_DOUBLE_MODIFIER ".\n", values[i], mine, sys);
482 return -1;
483 }
484 }
485 else if(mine != sys && ABS(mine-sys) > 0.000001) {
486 fprintf(stderr, "Value '%s' is parsed as %" NETDATA_DOUBLE_MODIFIER
487 ", but system believes it is %" NETDATA_DOUBLE_MODIFIER ", delta %" NETDATA_DOUBLE_MODIFIER ".\n", values[i], mine, sys, sys-mine);
488 return -1;
489 }
490
491 if(e_mine != e_sys) {
492 fprintf(stderr, "Value '%s' is parsed correctly, but endptr is not right (netdata returned %d, but system returned %d)\n",
493 values[i], (int)(e_mine - values[i]), (int)(e_sys - values[i]));
494 return -1;
495 }
496
497 fprintf(stderr, "str2ndd() parsed value '%s' exactly the same way with strtold(), returned %" NETDATA_DOUBLE_MODIFIER
498 " vs %" NETDATA_DOUBLE_MODIFIER "\n", values[i], mine, sys);
499 }
500
501 return 0;
502 }
503
504 int unit_test_buffer() {
505 BUFFER *wb = buffer_create(1, NULL);
506 char string[2048 + 1];
507 char final[9000 + 1];
508 int i;
509
510 for(i = 0; i < 2048; i++)
511 string[i] = (char)((i % 24) + 'a');
512 string[2048] = '\0';
513
514 const char *fmt = "string1: %s\nstring2: %s\nstring3: %s\nstring4: %s";
515 buffer_sprintf(wb, fmt, string, string, string, string);
516 snprintfz(final, sizeof(final) - 1, fmt, string, string, string, string);
517
518 const char *s = buffer_tostring(wb);
519
520 if(buffer_strlen(wb) != strlen(final) || strcmp(s, final) != 0) {
521 fprintf(stderr, "\nbuffer_sprintf() is faulty.\n");
522 fprintf(stderr, "\nstring : %s (length %zu)\n", string, strlen(string));
523 fprintf(stderr, "\nbuffer : %s (length %zu)\n", s, buffer_strlen(wb));
524 fprintf(stderr, "\nexpected: %s (length %zu)\n", final, strlen(final));
525 buffer_free(wb);
526 return -1;
527 }
528
529 fprintf(stderr, "buffer_sprintf() works as expected.\n");
530 buffer_free(wb);
531 return 0;
532 }
533
534 int unit_test_static_threads() {
535 struct netdata_static_thread *static_threads = static_threads_get();
536
537 /*
538 * make sure enough static threads have been registered
539 */
540 if (!static_threads) {
541 fprintf(stderr, "empty static_threads array\n");
542 return 1;
543 }
544
545 int n;
546 for (n = 0; static_threads[n].start_routine != NULL; n++) {}
547
548 if (n < 2) {
549 fprintf(stderr, "only %d static threads registered", n);
550 freez(static_threads);
551 return 1;
552 }
553
554 /*
555 * verify that each thread's start routine is unique.
556 */
557 for (int i = 0; i != n - 1; i++) {
558 for (int j = i + 1; j != n; j++) {
559 if (static_threads[i].start_routine != static_threads[j].start_routine)
560 continue;
561
562 fprintf(stderr, "Found duplicate threads with name: %s\n", static_threads[i].name);
563 freez(static_threads);
564 return 1;
565 }
566 }
567
568 freez(static_threads);
569 return 0;
570 }
571
572 // --------------------------------------------------------------------------------------------------------------------
573
574 struct feed_values {
575 unsigned long long microseconds;
576 collected_number value;
577 };
578
579 struct test {
580 char name[100];
581 char description[1024];
582
583 int update_every;
584 unsigned long long multiplier;
585 unsigned long long divisor;
586 RRD_ALGORITHM algorithm;
587
588 unsigned long feed_entries;
589 unsigned long result_entries;
590 struct feed_values *feed;
591 NETDATA_DOUBLE *results;
592
593 collected_number *feed2;
594 NETDATA_DOUBLE *results2;
595 };
596
597 // --------------------------------------------------------------------------------------------------------------------
598 // test1
599 // test absolute values stored
600
601 struct feed_values test1_feed[] = {
602 { 0, 10 },
603 { 1000000, 20 },
604 { 1000000, 30 },
605 { 1000000, 40 },
606 { 1000000, 50 },
607 { 1000000, 60 },
608 { 1000000, 70 },
609 { 1000000, 80 },
610 { 1000000, 90 },
611 { 1000000, 100 },
612 };
613
614 NETDATA_DOUBLE test1_results[] = {
615 20, 30, 40, 50, 60, 70, 80, 90, 100
616 };
617
618 struct test test1 = {
619 "test1", // name
620 "test absolute values stored at exactly second boundaries",
621 1, // update_every
622 1, // multiplier
623 1, // divisor
624 RRD_ALGORITHM_ABSOLUTE, // algorithm
625 10, // feed entries
626 9, // result entries
627 test1_feed, // feed
628 test1_results, // results
629 NULL, // feed2
630 NULL // results2
631 };
632
633 // --------------------------------------------------------------------------------------------------------------------
634 // test2
635 // test absolute values stored in the middle of second boundaries
636
637 struct feed_values test2_feed[] = {
638 { 500000, 10 },
639 { 1000000, 20 },
640 { 1000000, 30 },
641 { 1000000, 40 },
642 { 1000000, 50 },
643 { 1000000, 60 },
644 { 1000000, 70 },
645 { 1000000, 80 },
646 { 1000000, 90 },
647 { 1000000, 100 },
648 };
649
650 NETDATA_DOUBLE test2_results[] = {
651 20, 30, 40, 50, 60, 70, 80, 90, 100
652 };
653
654 struct test test2 = {
655 "test2", // name
656 "test absolute values stored in the middle of second boundaries",
657 1, // update_every
658 1, // multiplier
659 1, // divisor
660 RRD_ALGORITHM_ABSOLUTE, // algorithm
661 10, // feed entries
662 9, // result entries
663 test2_feed, // feed
664 test2_results, // results
665 NULL, // feed2
666 NULL // results2
667 };
668
669 // --------------------------------------------------------------------------------------------------------------------
670 // test3
671
672 struct feed_values test3_feed[] = {
673 { 0, 10 },
674 { 1000000, 20 },
675 { 1000000, 30 },
676 { 1000000, 40 },
677 { 1000000, 50 },
678 { 1000000, 60 },
679 { 1000000, 70 },
680 { 1000000, 80 },
681 { 1000000, 90 },
682 { 1000000, 100 },
683 };
684
685 NETDATA_DOUBLE test3_results[] = {
686 10, 10, 10, 10, 10, 10, 10, 10, 10
687 };
688
689 struct test test3 = {
690 "test3", // name
691 "test incremental values stored at exactly second boundaries",
692 1, // update_every
693 1, // multiplier
694 1, // divisor
695 RRD_ALGORITHM_INCREMENTAL, // algorithm
696 10, // feed entries
697 9, // result entries
698 test3_feed, // feed
699 test3_results, // results
700 NULL, // feed2
701 NULL // results2
702 };
703
704 // --------------------------------------------------------------------------------------------------------------------
705 // test4
706
707 struct feed_values test4_feed[] = {
708 { 500000, 10 },
709 { 1000000, 20 },
710 { 1000000, 30 },
711 { 1000000, 40 },
712 { 1000000, 50 },
713 { 1000000, 60 },
714 { 1000000, 70 },
715 { 1000000, 80 },
716 { 1000000, 90 },
717 { 1000000, 100 },
718 };
719
720 NETDATA_DOUBLE test4_results[] = {
721 10, 10, 10, 10, 10, 10, 10, 10, 10
722 };
723
724 struct test test4 = {
725 "test4", // name
726 "test incremental values stored in the middle of second boundaries",
727 1, // update_every
728 1, // multiplier
729 1, // divisor
730 RRD_ALGORITHM_INCREMENTAL, // algorithm
731 10, // feed entries
732 9, // result entries
733 test4_feed, // feed
734 test4_results, // results
735 NULL, // feed2
736 NULL // results2
737 };
738
739 // --------------------------------------------------------------------------------------------------------------------
740 // test5 - 32 bit overflows
741
742 struct feed_values test5_feed[] = {
743 { 0, 0x00000000FFFFFFFFULL / 15 * 0 },
744 { 1000000, 0x00000000FFFFFFFFULL / 15 * 7 },
745 { 1000000, 0x00000000FFFFFFFFULL / 15 * 14 },
746 { 1000000, 0x00000000FFFFFFFFULL / 15 * 0 },
747 { 1000000, 0x00000000FFFFFFFFULL / 15 * 7 },
748 { 1000000, 0x00000000FFFFFFFFULL / 15 * 14 },
749 { 1000000, 0x00000000FFFFFFFFULL / 15 * 0 },
750 { 1000000, 0x00000000FFFFFFFFULL / 15 * 7 },
751 { 1000000, 0x00000000FFFFFFFFULL / 15 * 14 },
752 { 1000000, 0x00000000FFFFFFFFULL / 15 * 0 },
753 };
754
755 NETDATA_DOUBLE test5_results[] = {
756 0x00000000FFFFFFFFULL / 15 * 7,
757 0x00000000FFFFFFFFULL / 15 * 7,
758 0x00000000FFFFFFFFULL / 15,
759 0x00000000FFFFFFFFULL / 15 * 7,
760 0x00000000FFFFFFFFULL / 15 * 7,
761 0x00000000FFFFFFFFULL / 15,
762 0x00000000FFFFFFFFULL / 15 * 7,
763 0x00000000FFFFFFFFULL / 15 * 7,
764 0x00000000FFFFFFFFULL / 15,
765 };
766
767 struct test test5 = {
768 "test5", // name
769 "test 32-bit incremental values overflow",
770 1, // update_every
771 1, // multiplier
772 1, // divisor
773 RRD_ALGORITHM_INCREMENTAL, // algorithm
774 10, // feed entries
775 9, // result entries
776 test5_feed, // feed
777 test5_results, // results
778 NULL, // feed2
779 NULL // results2
780 };
781
782 // --------------------------------------------------------------------------------------------------------------------
783 // test5b - 64 bit overflows
784
785 struct feed_values test5b_feed[] = {
786 { 0, 0xFFFFFFFFFFFFFFFFULL / 15 * 0 },
787 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 7 },
788 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 14 },
789 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 0 },
790 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 7 },
791 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 14 },
792 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 0 },
793 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 7 },
794 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 14 },
795 { 1000000, 0xFFFFFFFFFFFFFFFFULL / 15 * 0 },
796 };
797
798 NETDATA_DOUBLE test5b_results[] = {
799 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15 * (NETDATA_DOUBLE)7,
800 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15 * (NETDATA_DOUBLE)7,
801 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15,
802 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15 * (NETDATA_DOUBLE)7,
803 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15 * (NETDATA_DOUBLE)7,
804 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15,
805 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15 * (NETDATA_DOUBLE)7,
806 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15 * (NETDATA_DOUBLE)7,
807 (NETDATA_DOUBLE)0xFFFFFFFFFFFFFFFFULL / (NETDATA_DOUBLE)15,
808 };
809
810 struct test test5b = {
811 "test5b", // name
812 "test 64-bit incremental values overflow",
813 1, // update_every
814 1, // multiplier
815 1, // divisor
816 RRD_ALGORITHM_INCREMENTAL, // algorithm
817 10, // feed entries
818 9, // result entries
819 test5b_feed, // feed
820 test5b_results, // results
821 NULL, // feed2
822 NULL // results2
823 };
824
825 // --------------------------------------------------------------------------------------------------------------------
826 // test6
827
828 struct feed_values test6_feed[] = {
829 { 250000, 1000 },
830 { 250000, 2000 },
831 { 250000, 3000 },
832 { 250000, 4000 },
833 { 250000, 5000 },
834 { 250000, 6000 },
835 { 250000, 7000 },
836 { 250000, 8000 },
837 { 250000, 9000 },
838 { 250000, 10000 },
839 { 250000, 11000 },
840 { 250000, 12000 },
841 { 250000, 13000 },
842 { 250000, 14000 },
843 { 250000, 15000 },
844 { 250000, 16000 },
845 };
846
847 NETDATA_DOUBLE test6_results[] = {
848 4000, 4000, 4000, 4000
849 };
850
851 struct test test6 = {
852 "test6", // name
853 "test incremental values updated within the same second",
854 1, // update_every
855 1, // multiplier
856 1, // divisor
857 RRD_ALGORITHM_INCREMENTAL, // algorithm
858 16, // feed entries
859 4, // result entries
860 test6_feed, // feed
861 test6_results, // results
862 NULL, // feed2
863 NULL // results2
864 };
865
866 // --------------------------------------------------------------------------------------------------------------------
867 // test7
868
869 struct feed_values test7_feed[] = {
870 { 500000, 1000 },
871 { 2000000, 2000 },
872 { 2000000, 3000 },
873 { 2000000, 4000 },
874 { 2000000, 5000 },
875 { 2000000, 6000 },
876 { 2000000, 7000 },
877 { 2000000, 8000 },
878 { 2000000, 9000 },
879 { 2000000, 10000 },
880 };
881
882 NETDATA_DOUBLE test7_results[] = {
883 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500
884 };
885
886 struct test test7 = {
887 "test7", // name
888 "test incremental values updated in long durations",
889 1, // update_every
890 1, // multiplier
891 1, // divisor
892 RRD_ALGORITHM_INCREMENTAL, // algorithm
893 10, // feed entries
894 18, // result entries
895 test7_feed, // feed
896 test7_results, // results
897 NULL, // feed2
898 NULL // results2
899 };
900
901 // --------------------------------------------------------------------------------------------------------------------
902 // test8
903
904 struct feed_values test8_feed[] = {
905 { 500000, 1000 },
906 { 2000000, 2000 },
907 { 2000000, 3000 },
908 { 2000000, 4000 },
909 { 2000000, 5000 },
910 { 2000000, 6000 },
911 };
912
913 NETDATA_DOUBLE test8_results[] = {
914 1250, 2000, 2250, 3000, 3250, 4000, 4250, 5000, 5250, 6000
915 };
916
917 struct test test8 = {
918 "test8", // name
919 "test absolute values updated in long durations",
920 1, // update_every
921 1, // multiplier
922 1, // divisor
923 RRD_ALGORITHM_ABSOLUTE, // algorithm
924 6, // feed entries
925 10, // result entries
926 test8_feed, // feed
927 test8_results, // results
928 NULL, // feed2
929 NULL // results2
930 };
931
932 // --------------------------------------------------------------------------------------------------------------------
933 // test9
934
935 struct feed_values test9_feed[] = {
936 { 250000, 1000 },
937 { 250000, 2000 },
938 { 250000, 3000 },
939 { 250000, 4000 },
940 { 250000, 5000 },
941 { 250000, 6000 },
942 { 250000, 7000 },
943 { 250000, 8000 },
944 { 250000, 9000 },
945 { 250000, 10000 },
946 { 250000, 11000 },
947 { 250000, 12000 },
948 { 250000, 13000 },
949 { 250000, 14000 },
950 { 250000, 15000 },
951 { 250000, 16000 },
952 };
953
954 NETDATA_DOUBLE test9_results[] = {
955 4000, 8000, 12000, 16000
956 };
957
958 struct test test9 = {
959 "test9", // name
960 "test absolute values updated within the same second",
961 1, // update_every
962 1, // multiplier
963 1, // divisor
964 RRD_ALGORITHM_ABSOLUTE, // algorithm
965 16, // feed entries
966 4, // result entries
967 test9_feed, // feed
968 test9_results, // results
969 NULL, // feed2
970 NULL // results2
971 };
972
973 // --------------------------------------------------------------------------------------------------------------------
974 // test10
975
976 struct feed_values test10_feed[] = {
977 { 500000, 1000 },
978 { 600000, 1000 + 600 },
979 { 200000, 1600 + 200 },
980 { 1000000, 1800 + 1000 },
981 { 200000, 2800 + 200 },
982 { 2000000, 3000 + 2000 },
983 { 600000, 5000 + 600 },
984 { 400000, 5600 + 400 },
985 { 900000, 6000 + 900 },
986 { 1000000, 6900 + 1000 },
987 };
988
989 NETDATA_DOUBLE test10_results[] = {
990 1000, 1000, 1000, 1000, 1000, 1000, 1000
991 };
992
993 struct test test10 = {
994 "test10", // name
995 "test incremental values updated in short and long durations",
996 1, // update_every
997 1, // multiplier
998 1, // divisor
999 RRD_ALGORITHM_INCREMENTAL, // algorithm
1000 10, // feed entries
1001 7, // result entries
1002 test10_feed, // feed
1003 test10_results, // results
1004 NULL, // feed2
1005 NULL // results2
1006 };
1007
1008 // --------------------------------------------------------------------------------------------------------------------
1009 // test11
1010
1011 struct feed_values test11_feed[] = {
1012 { 0, 10 },
1013 { 1000000, 20 },
1014 { 1000000, 30 },
1015 { 1000000, 40 },
1016 { 1000000, 50 },
1017 { 1000000, 60 },
1018 { 1000000, 70 },
1019 { 1000000, 80 },
1020 { 1000000, 90 },
1021 { 1000000, 100 },
1022 };
1023
1024 collected_number test11_feed2[] = {
1025 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
1026 };
1027
1028 NETDATA_DOUBLE test11_results[] = {
1029 50, 50, 50, 50, 50, 50, 50, 50, 50
1030 };
1031
1032 NETDATA_DOUBLE test11_results2[] = {
1033 50, 50, 50, 50, 50, 50, 50, 50, 50
1034 };
1035
1036 struct test test11 = {
1037 "test11", // name
1038 "test percentage-of-incremental-row with equal values",
1039 1, // update_every
1040 1, // multiplier
1041 1, // divisor
1042 RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm
1043 10, // feed entries
1044 9, // result entries
1045 test11_feed, // feed
1046 test11_results, // results
1047 test11_feed2, // feed2
1048 test11_results2 // results2
1049 };
1050
1051 // --------------------------------------------------------------------------------------------------------------------
1052 // test12
1053
1054 struct feed_values test12_feed[] = {
1055 { 0, 10 },
1056 { 1000000, 20 },
1057 { 1000000, 30 },
1058 { 1000000, 40 },
1059 { 1000000, 50 },
1060 { 1000000, 60 },
1061 { 1000000, 70 },
1062 { 1000000, 80 },
1063 { 1000000, 90 },
1064 { 1000000, 100 },
1065 };
1066
1067 collected_number test12_feed2[] = {
1068 10*3, 20*3, 30*3, 40*3, 50*3, 60*3, 70*3, 80*3, 90*3, 100*3
1069 };
1070
1071 NETDATA_DOUBLE test12_results[] = {
1072 25, 25, 25, 25, 25, 25, 25, 25, 25
1073 };
1074
1075 NETDATA_DOUBLE test12_results2[] = {
1076 75, 75, 75, 75, 75, 75, 75, 75, 75
1077 };
1078
1079 struct test test12 = {
1080 "test12", // name
1081 "test percentage-of-incremental-row with equal values",
1082 1, // update_every
1083 1, // multiplier
1084 1, // divisor
1085 RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm
1086 10, // feed entries
1087 9, // result entries
1088 test12_feed, // feed
1089 test12_results, // results
1090 test12_feed2, // feed2
1091 test12_results2 // results2
1092 };
1093
1094 // --------------------------------------------------------------------------------------------------------------------
1095 // test13
1096
1097 struct feed_values test13_feed[] = {
1098 { 500000, 1000 },
1099 { 600000, 1000 + 600 },
1100 { 200000, 1600 + 200 },
1101 { 1000000, 1800 + 1000 },
1102 { 200000, 2800 + 200 },
1103 { 2000000, 3000 + 2000 },
1104 { 600000, 5000 + 600 },
1105 { 400000, 5600 + 400 },
1106 { 900000, 6000 + 900 },
1107 { 1000000, 6900 + 1000 },
1108 };
1109
1110 NETDATA_DOUBLE test13_results[] = {
1111 83.3333300, 100, 100, 100, 100, 100, 100
1112 };
1113
1114 struct test test13 = {
1115 "test13", // name
1116 "test incremental values updated in short and long durations",
1117 1, // update_every
1118 1, // multiplier
1119 1, // divisor
1120 RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm
1121 10, // feed entries
1122 7, // result entries
1123 test13_feed, // feed
1124 test13_results, // results
1125 NULL, // feed2
1126 NULL // results2
1127 };
1128
1129 // --------------------------------------------------------------------------------------------------------------------
1130 // test14
1131
1132 struct feed_values test14_feed[] = {
1133 { 0, 0x015397dc42151c41ULL },
1134 { 13573000, 0x015397e612e3ff5dULL },
1135 { 29969000, 0x015397f905ecdaa8ULL },
1136 { 29958000, 0x0153980c2a6cb5e4ULL },
1137 { 30054000, 0x0153981f4032fb83ULL },
1138 { 34952000, 0x015398355efadaccULL },
1139 { 25046000, 0x01539845ba4b09f8ULL },
1140 { 29947000, 0x0153985948bf381dULL },
1141 { 30054000, 0x0153986c5b9c27e2ULL },
1142 { 29942000, 0x0153987f888982d0ULL },
1143 };
1144
1145 NETDATA_DOUBLE test14_results[] = {
1146 23.1383300, 21.8515600, 21.8804600, 21.7788000, 22.0112200, 22.4386100, 22.0906100, 21.9150800
1147 };
1148
1149 struct test test14 = {
1150 "test14", // name
1151 "issue #981 with real data",
1152 30, // update_every
1153 8, // multiplier
1154 1000000000, // divisor
1155 RRD_ALGORITHM_INCREMENTAL, // algorithm
1156 10, // feed entries
1157 8, // result entries
1158 test14_feed, // feed
1159 test14_results, // results
1160 NULL, // feed2
1161 NULL // results2
1162 };
1163
1164 struct feed_values test14b_feed[] = {
1165 { 0, 0 },
1166 { 13573000, 13573000 },
1167 { 29969000, 13573000 + 29969000 },
1168 { 29958000, 13573000 + 29969000 + 29958000 },
1169 { 30054000, 13573000 + 29969000 + 29958000 + 30054000 },
1170 { 34952000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 },
1171 { 25046000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 },
1172 { 29947000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 + 29947000 },
1173 { 30054000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 + 29947000 + 30054000 },
1174 { 29942000, 13573000 + 29969000 + 29958000 + 30054000 + 34952000 + 25046000 + 29947000 + 30054000 + 29942000 },
1175 };
1176
1177 NETDATA_DOUBLE test14b_results[] = {
1178 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000
1179 };
1180
1181 struct test test14b = {
1182 "test14b", // name
1183 "issue #981 with dummy data",
1184 30, // update_every
1185 1, // multiplier
1186 1, // divisor
1187 RRD_ALGORITHM_INCREMENTAL, // algorithm
1188 10, // feed entries
1189 8, // result entries
1190 test14b_feed, // feed
1191 test14b_results, // results
1192 NULL, // feed2
1193 NULL // results2
1194 };
1195
1196 struct feed_values test14c_feed[] = {
1197 { 29000000, 29000000 },
1198 { 1000000, 29000000 + 1000000 },
1199 { 30000000, 29000000 + 1000000 + 30000000 },
1200 { 30000000, 29000000 + 1000000 + 30000000 + 30000000 },
1201 { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 },
1202 { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 },
1203 { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
1204 { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
1205 { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
1206 { 30000000, 29000000 + 1000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 + 30000000 },
1207 };
1208
1209 NETDATA_DOUBLE test14c_results[] = {
1210 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000, 1000000
1211 };
1212
1213 struct test test14c = {
1214 "test14c", // name
1215 "issue #981 with dummy data, checking for late start",
1216 30, // update_every
1217 1, // multiplier
1218 1, // divisor
1219 RRD_ALGORITHM_INCREMENTAL, // algorithm
1220 10, // feed entries
1221 9, // result entries
1222 test14c_feed, // feed
1223 test14c_results, // results
1224 NULL, // feed2
1225 NULL // results2
1226 };
1227
1228 // --------------------------------------------------------------------------------------------------------------------
1229 // test15
1230
1231 struct feed_values test15_feed[] = {
1232 { 0, 1068066388 },
1233 { 1008752, 1068822698 },
1234 { 993809, 1069573072 },
1235 { 995911, 1070324135 },
1236 { 1014562, 1071078166 },
1237 { 994684, 1071831349 },
1238 { 993128, 1072235739 },
1239 { 1010332, 1072958871 },
1240 { 1003394, 1073707019 },
1241 { 995201, 1074460255 },
1242 };
1243
1244 collected_number test15_feed2[] = {
1245 178825286, 178825286, 178825286, 178825286, 178825498, 178825498, 179165652, 179202964, 179203282, 179204130
1246 };
1247
1248 NETDATA_DOUBLE test15_results[] = {
1249 5857.4080000, 5898.4540000, 5891.6590000, 5806.3160000, 5914.2640000, 3202.2630000, 5589.6560000, 5822.5260000, 5911.7520000
1250 };
1251
1252 NETDATA_DOUBLE test15_results2[] = {
1253 0.0000000, 0.0000000, 0.0024944, 1.6324779, 0.0212777, 2655.1890000, 290.5387000, 5.6733610, 6.5960220
1254 };
1255
1256 struct test test15 = {
1257 "test15", // name
1258 "test incremental with 2 dimensions",
1259 1, // update_every
1260 8, // multiplier
1261 1024, // divisor
1262 RRD_ALGORITHM_INCREMENTAL, // algorithm
1263 10, // feed entries
1264 9, // result entries
1265 test15_feed, // feed
1266 test15_results, // results
1267 test15_feed2, // feed2
1268 test15_results2 // results2
1269 };
1270
1271 // --------------------------------------------------------------------------------------------------------------------
1272
1273 int run_test(struct test *test)
1274 {
1275 fprintf(stderr, "\nRunning test '%s':\n%s\n", test->name, test->description);
1276
1277 default_rrd_memory_mode = RRD_DB_MODE_ALLOC;
1278 nd_profile.update_every = test->update_every;
1279
1280 char name[101];
1281 snprintfz(name, sizeof(name) - 1, "unittest-%s", test->name);
1282
1283 // create the chart
1284 RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", "unittest", NULL, 1
1285 , test->update_every, RRDSET_TYPE_LINE);
1286 RRDDIM *rd = rrddim_add(st, "dim1", NULL, test->multiplier, test->divisor, test->algorithm);
1287
1288 RRDDIM *rd2 = NULL;
1289 if(test->feed2)
1290 rd2 = rrddim_add(st, "dim2", NULL, test->multiplier, test->divisor, test->algorithm);
1291
1292 rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
1293
1294 // feed it with the test data
1295 time_t time_now = 0, time_start = now_realtime_sec();
1296 unsigned long c;
1297 collected_number last = 0;
1298 for(c = 0; c < test->feed_entries; c++) {
1299 if(debug_flags) fprintf(stderr, "\n\n");
1300
1301 if(c) {
1302 time_now += test->feed[c].microseconds;
1303 fprintf(stderr, " > %s: feeding position %lu, after %0.3f seconds (%0.3f seconds from start), delta " NETDATA_DOUBLE_FORMAT
1304 ", rate " NETDATA_DOUBLE_FORMAT "\n",
1305 test->name, c+1,
1306 (float)test->feed[c].microseconds / 1000000.0,
1307 (float)time_now / 1000000.0,
1308 ((NETDATA_DOUBLE)test->feed[c].value - (NETDATA_DOUBLE)last) * (NETDATA_DOUBLE)test->multiplier / (NETDATA_DOUBLE)test->divisor,
1309 (((NETDATA_DOUBLE)test->feed[c].value - (NETDATA_DOUBLE)last) * (NETDATA_DOUBLE)test->multiplier / (NETDATA_DOUBLE)test->divisor) / (NETDATA_DOUBLE)test->feed[c].microseconds * (NETDATA_DOUBLE)1000000);
1310
1311 // rrdset_next_usec_unfiltered(st, test->feed[c].microseconds);
1312 st->usec_since_last_update = test->feed[c].microseconds;
1313 }
1314 else {
1315 fprintf(stderr, " > %s: feeding position %lu\n", test->name, c+1);
1316 }
1317
1318 fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rrddim_name(rd), test->feed[c].value);
1319 rrddim_set(st, "dim1", test->feed[c].value);
1320 last = test->feed[c].value;
1321
1322 if(rd2) {
1323 fprintf(stderr, " >> %s with value " COLLECTED_NUMBER_FORMAT "\n", rrddim_name(rd2), test->feed2[c]);
1324 rrddim_set(st, "dim2", test->feed2[c]);
1325 }
1326
1327 struct timeval now;
1328 now_realtime_timeval(&now);
1329 rrdset_timed_done(st, now, false);
1330
1331 // align the first entry to second boundary
1332 if(!c) {
1333 fprintf(stderr, " > %s: fixing first collection time to be %llu microseconds to second boundary\n", test->name, test->feed[c].microseconds);
1334 rd->collector.last_collected_time.tv_usec = st->last_collected_time.tv_usec = st->last_updated.tv_usec = test->feed[c].microseconds;
1335 // time_start = st->last_collected_time.tv_sec;
1336 }
1337 }
1338
1339 // check the result
1340 int errors = 0;
1341
1342 if(st->counter != test->result_entries) {
1343 fprintf(stderr, " %s stored %u entries, but we were expecting %lu, ### E R R O R ###\n",
1344 test->name, st->counter, test->result_entries);
1345 errors++;
1346 }
1347
1348 unsigned long max = (st->counter < test->result_entries)?st->counter:test->result_entries;
1349 for(c = 0 ; c < max ; c++) {
1350 NETDATA_DOUBLE v = unpack_storage_number(rd->db.data[c]);
1351 NETDATA_DOUBLE n = unpack_storage_number(pack_storage_number(test->results[c], SN_DEFAULT_FLAGS));
1352 int same = (roundndd(v * 10000000.0) == roundndd(n * 10000000.0))?1:0;
1353 fprintf(stderr, " %s/%s: checking position %lu (at %"PRId64" secs), expecting value " NETDATA_DOUBLE_FORMAT
1354 ", found " NETDATA_DOUBLE_FORMAT ", %s\n",
1355 test->name, rrddim_name(rd), c+1,
1356 (int64_t)((rrdset_first_entry_s(st) + c * st->update_every) - time_start),
1357 n, v, (same)?"OK":"### E R R O R ###");
1358
1359 if(!same) errors++;
1360
1361 if(rd2) {
1362 v = unpack_storage_number(rd2->db.data[c]);
1363 n = test->results2[c];
1364 same = (roundndd(v * 10000000.0) == roundndd(n * 10000000.0))?1:0;
1365 fprintf(stderr, " %s/%s: checking position %lu (at %"PRId64" secs), expecting value " NETDATA_DOUBLE_FORMAT
1366 ", found " NETDATA_DOUBLE_FORMAT ", %s\n",
1367 test->name, rrddim_name(rd2), c+1,
1368 (int64_t)((rrdset_first_entry_s(st) + c * st->update_every) - time_start),
1369 n, v, (same)?"OK":"### E R R O R ###");
1370 if(!same) errors++;
1371 }
1372 }
1373
1374 return errors;
1375 }
1376
1377 static int test_variable_renames(void) {
1378 fprintf(stderr, "%s() running...\n", __FUNCTION__ );
1379
1380 fprintf(stderr, "Creating chart\n");
1381 RRDSET *st = rrdset_create_localhost("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", "unittest", NULL, 1, 1, RRDSET_TYPE_LINE);
1382 fprintf(stderr, "Created chart with id '%s', name '%s'\n", rrdset_id(st), rrdset_name(st));
1383
1384 fprintf(stderr, "Creating dimension DIM1\n");
1385 RRDDIM *rd1 = rrddim_add(st, "DIM1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1386 fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rrddim_id(rd1), rrddim_name(rd1));
1387
1388 fprintf(stderr, "Creating dimension DIM2\n");
1389 RRDDIM *rd2 = rrddim_add(st, "DIM2", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1390 fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rrddim_id(rd2), rrddim_name(rd2));
1391
1392 fprintf(stderr, "Renaming chart to CHARTNAME1\n");
1393 rrdset_reset_name(st, "CHARTNAME1");
1394 fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", rrdset_id(st), rrdset_name(st));
1395
1396 fprintf(stderr, "Renaming chart to CHARTNAME2\n");
1397 rrdset_reset_name(st, "CHARTNAME2");
1398 fprintf(stderr, "Renamed chart with id '%s' to name '%s'\n", rrdset_id(st), rrdset_name(st));
1399
1400 fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME1\n");
1401 rrddim_reset_name(st, rd1, "DIM1NAME1");
1402 fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rrddim_id(rd1), rrddim_name(rd1));
1403
1404 fprintf(stderr, "Renaming dimension DIM1 to DIM1NAME2\n");
1405 rrddim_reset_name(st, rd1, "DIM1NAME2");
1406 fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rrddim_id(rd1), rrddim_name(rd1));
1407
1408 fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME1\n");
1409 rrddim_reset_name(st, rd2, "DIM2NAME1");
1410 fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rrddim_id(rd2), rrddim_name(rd2));
1411
1412 fprintf(stderr, "Renaming dimension DIM2 to DIM2NAME2\n");
1413 rrddim_reset_name(st, rd2, "DIM2NAME2");
1414 fprintf(stderr, "Renamed dimension with id '%s' to name '%s'\n", rrddim_id(rd2), rrddim_name(rd2));
1415
1416 BUFFER *buf = buffer_create(1, NULL);
1417 health_api_v1_chart_variables2json(st, buf);
1418 fprintf(stderr, "%s", buffer_tostring(buf));
1419 buffer_free(buf);
1420 return 1;
1421 }
1422
1423 int check_strdupz_path_subpath() {
1424
1425 struct strdupz_path_subpath_checks {
1426 const char *path;
1427 const char *subpath;
1428 const char *result;
1429 } checks[] = {
1430 { "", "", "." },
1431 { "/", "", "/" },
1432 { "/etc/netdata", "", "/etc/netdata" },
1433 { "/etc/netdata///", "", "/etc/netdata" },
1434 { "/etc/netdata///", "health.d", "/etc/netdata/health.d" },
1435 { "/etc/netdata///", "///health.d", "/etc/netdata/health.d" },
1436 { "/etc/netdata", "///health.d", "/etc/netdata/health.d" },
1437 { "", "///health.d", "./health.d" },
1438 { "/", "///health.d", "/health.d" },
1439
1440 // terminator
1441 { NULL, NULL, NULL }
1442 };
1443
1444 size_t i;
1445 for(i = 0; checks[i].result ; i++) {
1446 char *s = filename_from_path_entry_strdupz(checks[i].path, checks[i].subpath);
1447 fprintf(stderr, "filename_from_path_entry_strdupz(\"%s\", \"%s\") = \"%s\": ", checks[i].path, checks[i].subpath, s);
1448 if(!s || strcmp(s, checks[i].result) != 0) {
1449 freez(s);
1450 fprintf(stderr, "FAILED\n");
1451 return 1;
1452 }
1453 else {
1454 freez(s);
1455 fprintf(stderr, "OK\n");
1456 }
1457 }
1458
1459 return 0;
1460 }
1461
1462 static int test_incremental_sum_lookup_respects_update_every(void) {
1463 fprintf(stderr, "%s() running...\n", __FUNCTION__);
1464
1465 const time_t update_every = 10;
1466 const collected_number increment = 100;
1467 const size_t samples = 6;
1468 RRD_DB_MODE old_default_rrd_memory_mode = default_rrd_memory_mode;
1469 time_t old_update_every = nd_profile.update_every;
1470
1471 default_rrd_memory_mode = RRD_DB_MODE_ALLOC;
1472 nd_profile.update_every = update_every;
1473
1474 char name[101];
1475 snprintfz(name, sizeof(name) - 1, "unittest-incremental-sum-lookup");
1476
1477 RRDSET *st = rrdset_create_localhost(
1478 "netdata", name, name, "netdata", NULL, "Unit Testing", "requests", "unittest", NULL, 1,
1479 update_every, RRDSET_TYPE_LINE);
1480 RRDDIM *rd = rrddim_add(st, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1481
1482 time_t first_update_s = MAX(2 * API_RELATIVE_TIME_MAX, 200000000);
1483 st->last_collected_time.tv_sec = st->last_updated.tv_sec = first_update_s - update_every;
1484 st->last_collected_time.tv_usec = st->last_updated.tv_usec = 0;
1485 rd->collector.last_collected_time = st->last_collected_time;
1486
1487 for(size_t i = 0; i <= samples; i++) {
1488 struct timeval now = {
1489 .tv_sec = first_update_s + (time_t)(i * update_every),
1490 .tv_usec = 0,
1491 };
1492
1493 st->usec_since_last_update = update_every * USEC_PER_SEC;
1494 rrddim_timed_set_by_pointer(st, rd, now, (collected_number)(i * increment));
1495 rrdset_timed_done(st, now, false);
1496 }
1497
1498 time_t before = rrdset_last_entry_s(st);
1499 time_t after = before - (time_t)(samples * update_every);
1500
1501 ONEWAYALLOC *owa = onewayalloc_create(0);
1502 NETDATA_DOUBLE value = NAN;
1503 int value_is_null = 0;
1504 int ret = rrdset2value_api_v1_with_owa(
1505 owa, st, NULL, &value, "requests", 1, after, before, RRDR_GROUPING_SUM, NULL, 0,
1506 RRDR_OPTION_NOT_ALIGNED | RRDR_OPTION_SELECTED_TIER | RRDR_OPTION_MATCH_IDS, NULL, NULL, NULL, NULL,
1507 NULL, &value_is_null, NULL, 0, 0, QUERY_SOURCE_UNITTEST, STORAGE_PRIORITY_SYNCHRONOUS);
1508 onewayalloc_destroy(owa);
1509
1510 NETDATA_DOUBLE expected = (NETDATA_DOUBLE)(samples * increment);
1511 int rc = 0;
1512 if(ret != HTTP_RESP_OK || value_is_null || fabsndd(value - expected) > 0.000001) {
1513 fprintf(
1514 stderr,
1515 "incremental sum lookup failed: ret=%d, null=%d, expected " NETDATA_DOUBLE_FORMAT
1516 ", got " NETDATA_DOUBLE_FORMAT "\n",
1517 ret, value_is_null, expected, value);
1518 rc = 1;
1519 }
1520
1521 default_rrd_memory_mode = old_default_rrd_memory_mode;
1522 nd_profile.update_every = old_update_every;
1523 return rc;
1524 }
1525
1526 static int test_rrdmetric_algorithm_follows_rrddim(void) {
1527 fprintf(stderr, "%s() running...\n", __FUNCTION__);
1528
1529 RRD_DB_MODE old_default_rrd_memory_mode = default_rrd_memory_mode;
1530 default_rrd_memory_mode = RRD_DB_MODE_ALLOC;
1531
1532 RRDSET *st = rrdset_create_localhost(
1533 "netdata", "unittest-algo-track", "unittest-algo-track", "netdata", NULL,
1534 "Unit Testing", "x", "unittest", NULL, 1,
1535 nd_profile.update_every, RRDSET_TYPE_LINE);
1536 RRDDIM *rd = rrddim_add(st, "d", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1537
1538 int rc = 0;
1539 RRDMETRIC *rm = rrdmetric_acquired_value(rd->rrdcontexts.rrdmetric);
1540 if(!rm || rrdmetric_algorithm_atomic_load(rm) != RRD_ALGORITHM_INCREMENTAL) {
1541 fprintf(stderr, "%s: after rrddim_add INCREMENTAL, rm->algorithm = %d (want %d)\n",
1542 __FUNCTION__, rm ? (int)rrdmetric_algorithm_atomic_load(rm) : -1,
1543 (int)RRD_ALGORITHM_INCREMENTAL);
1544 rc = 1;
1545 }
1546
1547 rrddim_set_algorithm(st, rd, RRD_ALGORITHM_ABSOLUTE);
1548 rm = rrdmetric_acquired_value(rd->rrdcontexts.rrdmetric);
1549 if(!rm || rrdmetric_algorithm_atomic_load(rm) != RRD_ALGORITHM_ABSOLUTE) {
1550 fprintf(stderr, "%s: after rrddim_set_algorithm ABSOLUTE, rm->algorithm = %d (want %d)\n",
1551 __FUNCTION__, rm ? (int)rrdmetric_algorithm_atomic_load(rm) : -1,
1552 (int)RRD_ALGORITHM_ABSOLUTE);
1553 rc = 1;
1554 }
1555
1556 default_rrd_memory_mode = old_default_rrd_memory_mode;
1557 return rc;
1558 }
1559
1560 int run_all_mockup_tests(void)
1561 {
1562 fprintf(stderr, "%s() running...\n", __FUNCTION__ );
1563 if(check_strdupz_path_subpath())
1564 return 1;
1565
1566 if(check_number_printing())
1567 return 1;
1568
1569 if(check_rrdcalc_comparisons())
1570 return 1;
1571
1572 #if defined(OS_LINUX)
1573 if(proc_interrupts_unittest())
1574 return 1;
1575 #endif
1576 if(test_incremental_sum_lookup_respects_update_every())
1577 return 1;
1578
1579 if(test_rrdmetric_algorithm_follows_rrddim())
1580 return 1;
1581
1582 if(!test_variable_renames())
1583 return 1;
1584
1585 if(run_test(&test1))
1586 return 1;
1587
1588 if(run_test(&test2))
1589 return 1;
1590
1591 if(run_test(&test3))
1592 return 1;
1593
1594 if(run_test(&test4))
1595 return 1;
1596
1597 if(run_test(&test5))
1598 return 1;
1599
1600 if(run_test(&test5b))
1601 return 1;
1602
1603 if(run_test(&test6))
1604 return 1;
1605
1606 if(run_test(&test7))
1607 return 1;
1608
1609 if(run_test(&test8))
1610 return 1;
1611
1612 if(run_test(&test9))
1613 return 1;
1614
1615 if(run_test(&test10))
1616 return 1;
1617
1618 if(run_test(&test11))
1619 return 1;
1620
1621 if(run_test(&test12))
1622 return 1;
1623
1624 if(run_test(&test13))
1625 return 1;
1626
1627 if(run_test(&test14))
1628 return 1;
1629
1630 if(run_test(&test14b))
1631 return 1;
1632
1633 if(run_test(&test14c))
1634 return 1;
1635
1636 if(run_test(&test15))
1637 return 1;
1638
1639
1640
1641 return 0;
1642 }
1643
1644 int unit_test(long delay, long shift)
1645 {
1646 fprintf(stderr, "%s() running...\n", __FUNCTION__ );
1647 static int repeat = 0;
1648 repeat++;
1649
1650 char name[101];
1651 snprintfz(name, sizeof(name) - 1, "unittest-%d-%ld-%ld", repeat, delay, shift);
1652
1653 //debug_flags = 0xffffffff;
1654 default_rrd_memory_mode = RRD_DB_MODE_ALLOC;
1655 nd_profile.update_every = 1;
1656
1657 int do_abs = 1;
1658 int do_inc = 1;
1659 int do_abst = 0;
1660 int do_absi = 0;
1661
1662 RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", "unittest", NULL, 1, 1
1663 , RRDSET_TYPE_LINE);
1664 rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
1665
1666 RRDDIM *rdabs = NULL;
1667 RRDDIM *rdinc = NULL;
1668 RRDDIM *rdabst = NULL;
1669 RRDDIM *rdabsi = NULL;
1670
1671 if(do_abs) rdabs = rrddim_add(st, "absolute", "absolute", 1, 1, RRD_ALGORITHM_ABSOLUTE);
1672 if(do_inc) rdinc = rrddim_add(st, "incremental", "incremental", 1, 1, RRD_ALGORITHM_INCREMENTAL);
1673 if(do_abst) rdabst = rrddim_add(st, "percentage-of-absolute-row", "percentage-of-absolute-row", 1, 1, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL);
1674 if(do_absi) rdabsi = rrddim_add(st, "percentage-of-incremental-row", "percentage-of-incremental-row", 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
1675
1676 long increment = 1000;
1677 collected_number i = 0;
1678
1679 unsigned long c, dimensions = rrdset_number_of_dimensions(st);
1680 RRDDIM *rd;
1681
1682 for(c = 0; c < 20 ;c++) {
1683 i += increment;
1684
1685 fprintf(stderr, "\n\nLOOP = %lu, DELAY = %ld, VALUE = " COLLECTED_NUMBER_FORMAT "\n", c, delay, i);
1686 if(c) {
1687 // rrdset_next_usec_unfiltered(st, delay);
1688 st->usec_since_last_update = delay;
1689 }
1690 if(do_abs) rrddim_set(st, "absolute", i);
1691 if(do_inc) rrddim_set(st, "incremental", i);
1692 if(do_abst) rrddim_set(st, "percentage-of-absolute-row", i);
1693 if(do_absi) rrddim_set(st, "percentage-of-incremental-row", i);
1694
1695 if(!c) {
1696 now_realtime_timeval(&st->last_collected_time);
1697 st->last_collected_time.tv_usec = shift;
1698 }
1699
1700 // prevent it from deleting the dimensions
1701 rrddim_foreach_read(rd, st) {
1702 rd->collector.last_collected_time.tv_sec = st->last_collected_time.tv_sec;
1703 }
1704 rrddim_foreach_done(rd);
1705
1706 rrdset_done(st);
1707 }
1708
1709 unsigned long oincrement = increment;
1710 increment = increment * st->update_every * 1000000 / delay;
1711 fprintf(stderr, "\n\nORIGINAL INCREMENT: %lu, INCREMENT %ld, DELAY %ld, SHIFT %ld\n", oincrement * 10, increment * 10, delay, shift);
1712
1713 int ret = 0;
1714 storage_number sn;
1715 NETDATA_DOUBLE cn, v;
1716 for(c = 0 ; c < st->counter ; c++) {
1717 fprintf(stderr, "\nPOSITION: c = %lu, EXPECTED VALUE %lu\n", c, (oincrement + c * increment + increment * (1000000 - shift) / 1000000 )* 10);
1718
1719 rrddim_foreach_read(rd, st) {
1720 sn = rd->db.data[c];
1721 cn = unpack_storage_number(sn);
1722 fprintf(stderr, "\t %s " NETDATA_DOUBLE_FORMAT " (PACKED AS " STORAGE_NUMBER_FORMAT ") -> ", rrddim_id(rd), cn, sn);
1723
1724 if(rd == rdabs) v =
1725 ( oincrement
1726 // + (increment * (1000000 - shift) / 1000000)
1727 + (c + 1) * increment
1728 );
1729
1730 else if(rd == rdinc) v = (c?(increment):(increment * (1000000 - shift) / 1000000));
1731 else if(rd == rdabst) v = oincrement / dimensions / 10;
1732 else if(rd == rdabsi) v = oincrement / dimensions / 10;
1733 else v = 0;
1734
1735 if(v == cn) fprintf(stderr, "passed.\n");
1736 else {
1737 fprintf(stderr, "ERROR! (expected " NETDATA_DOUBLE_FORMAT ")\n", v);
1738 ret = 1;
1739 }
1740 }
1741 rrddim_foreach_done(rd);
1742 }
1743
1744 if(ret)
1745 fprintf(stderr, "\n\nUNIT TEST(%ld, %ld) FAILED\n\n", delay, shift);
1746
1747 return ret;
1748 }
1749
1750 int test_sqlite(void) {
1751 fprintf(stderr, "%s() running...\n", __FUNCTION__ );
1752 sqlite3 *db_mt;
1753 fprintf(stderr, "Testing SQLIte\n");
1754
1755 int rc = sqlite3_open(":memory:", &db_mt);
1756 if (rc != SQLITE_OK) {
1757 fprintf(stderr,"Failed to test SQLite: DB init failed\n");
1758 return 1;
1759 }
1760
1761 rc = sqlite3_exec_monitored(db_mt, "CREATE TABLE IF NOT EXISTS mine (id1, id2);", 0, 0, NULL);
1762 if (rc != SQLITE_OK) {
1763 fprintf(stderr,"Failed to test SQLite: Create table failed\n");
1764 return 1;
1765 }
1766
1767 rc = sqlite3_exec_monitored(db_mt, "DELETE FROM MINE LIMIT 1;", 0, 0, NULL);
1768 if (rc != SQLITE_OK) {
1769 fprintf(stderr,"Failed to test SQLite: Delete with LIMIT failed\n");
1770 return 1;
1771 }
1772
1773 rc = sqlite3_exec_monitored(db_mt, "UPDATE MINE SET id1=1 LIMIT 1;", 0, 0, NULL);
1774 if (rc != SQLITE_OK) {
1775 fprintf(stderr,"Failed to test SQLite: Update with LIMIT failed\n");
1776 return 1;
1777 }
1778
1779 rc = sqlite3_create_function(db_mt, "now_usec", 1, SQLITE_ANY, 0, sqlite_now_usec, 0, 0);
1780 if (unlikely(rc != SQLITE_OK)) {
1781 fprintf(stderr, "Failed to register internal now_usec function");
1782 return 1;
1783 }
1784
1785 rc = sqlite3_exec_monitored(db_mt, "UPDATE MINE SET id1=now_usec(0);", 0, 0, NULL);
1786 if (rc != SQLITE_OK) {
1787 fprintf(stderr,"Failed to test SQLite: Update with now_usec() failed\n");
1788 return 1;
1789 }
1790
1791 fprintf(stderr,"SQLite is OK\n");
1792 (void) sqlite3_close_v2(db_mt);
1793 return 0;
1794 }