Warn when log is duplicated X times 67/243867/24 submit/tizen/20201027.165937
authorAgnieszka Baumann <a.baumann@samsung.com>
Tue, 8 Sep 2020 10:24:29 +0000 (12:24 +0200)
committerMichal Bloch <m.bloch@partner.samsung.com>
Tue, 27 Oct 2020 16:02:51 +0000 (16:02 +0000)
Change-Id: I9302cd761a7de0f090a35940f47ef38de19ba9fa

Makefile.am
include/deduplicate.h
src/libdlog/deduplicate.c
src/libdlog/log.c
src/tests/deduplicate_test.c
tests/dlog_test.in

index e6d4bd6..238987d 100644 (file)
@@ -619,7 +619,7 @@ src_tests_metrics_LDFLAGS = $(AM_LDFLAGS) -lpthread -Wl,--wrap=dlogutil_entry_ge
 
 src_tests_deduplicate_test_SOURCES = src/tests/deduplicate_test.c src/libdlog/log.c src/libdlog/deduplicate.c src/shared/hash.c src/shared/logcommon.c src/shared/loglimiter.c src/libdlog/dynamic_config.c src/shared/logconfig.c src/shared/parsers.c src/shared/ptrs_list.c
 src_tests_deduplicate_test_CFLAGS = $(check_CFLAGS) -pthread
-src_tests_deduplicate_test_LDFLAGS = $(AM_LDFLAGS) -lpthread -Wl,--wrap=clock_gettime,--wrap=log_config_read
+src_tests_deduplicate_test_LDFLAGS = $(AM_LDFLAGS) -lpthread -Wl,--wrap=clock_gettime,--wrap=log_config_read,--wrap=deduplicate_warn
 
 # conf file
 usrlibtmpfilesddir = /usr/lib/tmpfiles.d
index 8e875a0..a4b3b8a 100644 (file)
 // Dlog
 #include "logconfig.h"
 
+typedef enum dlog_deduplicate_e {
+       DLOG_DO_NOT_DEDUPLICATE = 0,
+       DLOG_DEDUPLICATE,
+       DLOG_DO_NOT_DEDUPLICATE_BUT_WARN,
+} dlog_deduplicate_e;
+
+void deduplicate_warn(char *buf, size_t size, size_t len);
 void __configure_deduplicate(struct log_config *config);
 void __deduplicate_destroy();
-extern bool (*deduplicate_func)(const char *, size_t, struct timespec *);
+extern dlog_deduplicate_e (*deduplicate_func)(const char *, size_t, struct timespec *);
 
 #endif /* _DEDUPLICATE_H_ */
index 651392c..5feda7f 100644 (file)
 // Dlog
 #include "deduplicate.h"
 #include "hash.h"
+#include "logcommon.h"
+#include "parsers.h"
 
-bool (*deduplicate_func)(const char *, size_t, struct timespec *);
+#define WARNING_STRING " LOG DUPLICATED %d TIMES"
+#define WARNING_MAX sizeof(" LOG DUPLICATED " STRINGIFY(INT32_MAX) " TIMES")
+
+typedef struct deduplicate_log {
+       uint32_t hash;
+       size_t quantity;
+} deduplicate_log;
+
+dlog_deduplicate_e (*deduplicate_func)(const char *, size_t, struct timespec *);
 
-static uint32_t basic_hash;
 static long last_millisec;
 static long interval_millisec;
 static int known_hashes_capacity;
-static uint32_t *known_hashes_vector;
+static deduplicate_log *known_hashes_vector;
 static int known_hashes_size = 0;
 static pthread_mutex_t deduplication_lock = PTHREAD_MUTEX_INITIALIZER;
+static int warn_quantity;
+static int warning_size;
+static char warning_content[WARNING_MAX];
+static deduplicate_log basic_log;
 
 static void refresh_deduplication_limits()
 {
        known_hashes_size = 0;
 }
 
-static bool is_hash_known(const uint32_t new_hash)
+static size_t *known_hash_count(const uint32_t new_hash)
 {
        for (size_t i = 0; i < known_hashes_size; i++)
-               if (known_hashes_vector[i] == new_hash)
-                       return true;
+               if (known_hashes_vector[i].hash == new_hash)
+                       return &known_hashes_vector[i].quantity;
 
-       return false;
+       return NULL;
 }
 
 static bool compare_milli(struct timespec *tp)
@@ -62,14 +75,23 @@ static bool compare_milli(struct timespec *tp)
        return false;
 }
 
-static bool basic_deduplicate(const char *msg, size_t len, struct timespec *tp)
+static dlog_deduplicate_e basic_deduplicate(const char *msg, size_t len, struct timespec *tp)
 {
        const uint32_t new_hash = create_hash(msg, len);
-       bool compare_hash = (basic_hash == new_hash);
-       basic_hash = new_hash;
+       bool compare_hash = (basic_log.hash == new_hash);
        bool compare_milisec = compare_milli(tp);
 
-       return compare_hash && compare_milisec;
+       if (compare_hash && compare_milisec) {
+               basic_log.quantity++;
+               if (warn_quantity != 0 && (basic_log.quantity % warn_quantity == 0))
+                       return DLOG_DO_NOT_DEDUPLICATE_BUT_WARN;
+               return DLOG_DEDUPLICATE;
+       } else {
+               basic_log.quantity = 1;
+               basic_log.hash = new_hash;
+       }
+
+       return DLOG_DO_NOT_DEDUPLICATE;
 }
 
 static bool add_known_hash(uint32_t new_hash)
@@ -82,30 +104,49 @@ static bool add_known_hash(uint32_t new_hash)
                known_hashes_capacity *= 2;
                known_hashes_vector = temp;
        }
-       known_hashes_vector[known_hashes_size] = new_hash;
+       known_hashes_vector[known_hashes_size].hash = new_hash;
+       known_hashes_vector[known_hashes_size].quantity = 1;
        known_hashes_size++;
 
        return true;
 }
 
-static bool advanced_deduplicate(const char *msg, size_t len, struct timespec *tp)
+static dlog_deduplicate_e advanced_deduplicate(const char *msg, size_t len, struct timespec *tp)
 {
        pthread_mutex_lock(&deduplication_lock);
        bool compare_milisec = compare_milli(tp);
 
        uint32_t new_hash = create_hash(msg, len);
-       int ret = false;
-
-       if (compare_milisec)
-               ret = is_hash_known(new_hash);
-       else
+       size_t *quantity_ptr = NULL;
+       dlog_deduplicate_e output = DLOG_DO_NOT_DEDUPLICATE;
+
+       if (compare_milisec) {
+               quantity_ptr = known_hash_count(new_hash);
+               if (quantity_ptr != NULL) {
+                       *quantity_ptr += 1;
+                       output = DLOG_DEDUPLICATE;
+                       if (warn_quantity != 0 && (*quantity_ptr % warn_quantity == 0))
+                               output = DLOG_DO_NOT_DEDUPLICATE_BUT_WARN;
+               }
+       } else {
                refresh_deduplication_limits();
+       }
 
-       if (ret == false)
+       if (quantity_ptr == NULL)
                add_known_hash(new_hash);
        pthread_mutex_unlock(&deduplication_lock);
 
-       return ret;
+       return output;
+}
+
+void deduplicate_warn(char *buf, size_t size, size_t len)
+{
+       assert(size > warning_size);
+
+       if (len + warning_size < size)
+               strncpy(buf + len, warning_content, size - len);
+       else
+               strncpy(buf + size - warning_size - 1, warning_content, warning_size + 1);
 }
 
 void __configure_deduplicate(struct log_config *config)
@@ -114,13 +155,24 @@ void __configure_deduplicate(struct log_config *config)
        const char *const value = log_config_get(config, "deduplicate_method");
        interval_millisec = log_config_get_int(config, "deduplicate_interval_ms", 1);
 
+       const char *warn_quant_str = log_config_get(config, "deduplicate_warn_quantity");
+       if (!warn_quant_str)
+               warn_quantity = 10;
+       else if (parse_number(&warn_quant_str, &warn_quantity) < 0 || (warn_quantity < 0))
+               warn_quantity = 0;
+
+       warning_size = snprintf(warning_content, sizeof warning_content, WARNING_STRING, warn_quantity);
+       assert(warning_size < (sizeof warning_content));
+       if (warning_size < 0)
+               return;
+
        if (!value) {
                return;
        } else if (strcmp(value, "only_identical_neighbours") == 0) {
                deduplicate_func = basic_deduplicate;
        } else if (strcmp(value, "all_identical_logs") == 0) {
                known_hashes_capacity = 4;
-               known_hashes_vector = (uint32_t *) calloc(known_hashes_capacity, sizeof *known_hashes_vector);
+               known_hashes_vector = (deduplicate_log *) calloc(known_hashes_capacity, sizeof *known_hashes_vector);
                if (!known_hashes_vector)
                        return;
                deduplicate_func = advanced_deduplicate;
index e356dd8..d66af3d 100644 (file)
@@ -371,8 +371,11 @@ static int __write_to_log_critical_section(log_id_t log_id, int prio, const char
        struct timespec tp;
        int r;
        if (deduplicate_func && !clock_gettime(CLOCK_MONOTONIC, &tp)) {
-               if (deduplicate_func(buf, len, &tp))
+               dlog_deduplicate_e ret = deduplicate_func(buf, len, &tp);
+               if (ret == DLOG_DEDUPLICATE)
                        return DLOG_ERROR_NONE;
+               else if (ret == DLOG_DO_NOT_DEDUPLICATE_BUT_WARN)
+                       deduplicate_warn(buf, sizeof buf, len);
                r = write_to_log(log_id, prio, tag, buf, &tp);
        } else
                r = write_to_log(log_id, prio, tag, buf, NULL);
index 2e3591b..2c2a5cd 100644 (file)
 #include "libdlog.h"
 #include "logconfig.h"
 
+#define DEDUPLICATE 0
+#define WARN 0xBA5EBALL
+#define PRINT 0xC0FFEE
+
 long milliseconds;
 const char *local_advanced;
 const char *local_time_ms;
+const char *local_warn_quantity;
+bool deduplicate_warning = false;
+
+static int use_real_deduplicate_warn = false;
+void __real_deduplicate_warn(char *buf, size_t size, size_t len);
+void __wrap_deduplicate_warn(char *buf, size_t size, size_t len)
+{
+       if (use_real_deduplicate_warn)
+               __real_deduplicate_warn(buf, size, len);
+       else
+               deduplicate_warning = true;
+}
 
 int __wrap_clock_gettime(clockid_t clk_id, struct timespec *tp)
 {
@@ -43,7 +59,12 @@ int __wrap_clock_gettime(clockid_t clk_id, struct timespec *tp)
 
 int log_handler(log_id_t buf_id, log_priority pri, const char *tag, const char *msg, struct timespec *tp)
 {
-       return 0xC0FFEE;
+       if (deduplicate_warning) {
+               deduplicate_warning = false;
+               return WARN;
+       }
+
+       return PRINT;
 }
 
 void __dlog_init_pipe(const struct log_config *conf)
@@ -64,6 +85,7 @@ int __wrap_log_config_read(struct log_config *config)
        log_config_set(config, "debugmode", "1");
        log_config_set(config, "deduplicate_method", local_advanced);
        log_config_set(config, "deduplicate_interval_ms", local_time_ms);
+       log_config_set(config, "deduplicate_warn_quantity", local_warn_quantity);
        return 0;
 }
 
@@ -76,21 +98,22 @@ void test_basic_1ms_interval()
 {
        local_advanced = "only_identical_neighbours";
        local_time_ms = "1";
+       local_warn_quantity = "0";
        milliseconds = 123;
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("B", 0);
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("C", 0xC0FFEE);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("C", PRINT);
 
        milliseconds = 124;
-       check_assertion("C", 0xC0FFEE);
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("C", 0xC0FFEE);
-       check_assertion("C", 0);
-       check_assertion("C", 0);
+       check_assertion("C", PRINT);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("C", PRINT);
+       check_assertion("C", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
 
        __dlog_fini();
 }
@@ -99,29 +122,52 @@ void test_basic_10ms_interval()
 {
        local_advanced = "only_identical_neighbours";
        local_time_ms = "10";
+       local_warn_quantity = "0";
        milliseconds = 123;
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("B", 0);
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("C", 0xC0FFEE);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("C", PRINT);
 
        milliseconds = 124;
-       check_assertion("C", 0);
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("C", 0xC0FFEE);
-       check_assertion("C", 0);
-       check_assertion("C", 0);
+       check_assertion("C", DEDUPLICATE);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("C", PRINT);
+       check_assertion("C", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
 
        milliseconds = 133;
-       check_assertion("C", 0xC0FFEE);
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("C", 0xC0FFEE);
-       check_assertion("C", 0);
-       check_assertion("C", 0);
+       check_assertion("C", PRINT);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("C", PRINT);
+       check_assertion("C", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
+
+       __dlog_fini();
+}
+
+void test_basic_1ms_interval_warning()
+{
+       local_advanced = "only_identical_neighbours";
+       local_time_ms = "10";
+       local_warn_quantity = "10";
+       milliseconds = 123;
+       check_assertion("A", PRINT);
+       for (int i = 0; i < 29; ++i) {
+               if (i == 0)
+                       check_assertion("B", PRINT);
+               else if ((i + 1) % atoi(local_warn_quantity) == 0)
+                       check_assertion("B", WARN);
+               else
+                       check_assertion("B", DEDUPLICATE);
+       }
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("C", PRINT);
 
        __dlog_fini();
 }
@@ -130,21 +176,22 @@ void test_advanced_1ms_interval()
 {
        local_advanced = "all_identical_logs";
        local_time_ms = "1";
+       local_warn_quantity = "0";
        milliseconds = 123;
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("B", 0);
-       check_assertion("A", 0);
-       check_assertion("B", 0);
-       check_assertion("C", 0xC0FFEE);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("C", PRINT);
 
        milliseconds = 124;
-       check_assertion("C", 0xC0FFEE);
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("A", 0);
-       check_assertion("C", 0);
-       check_assertion("C", 0);
+       check_assertion("C", PRINT);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
 
        __dlog_fini();
 }
@@ -153,37 +200,96 @@ void test_advanced_10ms_interval()
 {
        local_advanced = "all_identical_logs";
        local_time_ms = "10";
+       local_warn_quantity = "0";
+       milliseconds = 123;
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("C", PRINT);
+
+       milliseconds = 124;
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
+
+       milliseconds = 132;
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
+
+       milliseconds = 133;
+       check_assertion("C", PRINT);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
+
+       __dlog_fini();
+}
+
+void test_advanced_10ms_interval_warning()
+{
+       local_advanced = "all_identical_logs";
+       local_time_ms = "10";
+       local_warn_quantity = "5";
        milliseconds = 123;
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("B", 0);
-       check_assertion("A", 0);
-       check_assertion("B", 0);
-       check_assertion("C", 0xC0FFEE);
+       check_assertion("A", PRINT);
+       check_assertion("B", PRINT);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("C", PRINT);
 
        milliseconds = 124;
-       check_assertion("A", 0);
-       check_assertion("B", 0);
-       check_assertion("B", 0);
-       check_assertion("A", 0);
-       check_assertion("B", 0);
-       check_assertion("C", 0);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", WARN);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
 
        milliseconds = 132;
-       check_assertion("A", 0);
-       check_assertion("B", 0);
-       check_assertion("B", 0);
-       check_assertion("A", 0);
-       check_assertion("B", 0);
-       check_assertion("C", 0);
+       check_assertion("A", WARN);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", WARN);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", WARN);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
 
        milliseconds = 133;
-       check_assertion("C", 0xC0FFEE);
-       check_assertion("A", 0xC0FFEE);
-       check_assertion("B", 0xC0FFEE);
-       check_assertion("A", 0);
-       check_assertion("C", 0);
-       check_assertion("C", 0);
+       check_assertion("B", PRINT);
+       check_assertion("A", PRINT);
+       check_assertion("C", PRINT);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", WARN);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("B", DEDUPLICATE);
+       check_assertion("A", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
+       check_assertion("C", DEDUPLICATE);
 
        __dlog_fini();
 }
@@ -192,13 +298,14 @@ void test_advanced_many_hashes()
 {
        local_advanced = "all_identical_logs";
        local_time_ms = "1";
+       local_warn_quantity = "0";
        milliseconds = 123;
        char word[3] = {'\0'};
        for (char first = 'A'; first <= 'Z'; ++first) {
                word[0] = first;
                for (char second = 'A'; second <= 'Z'; ++second) {
                        word[1] = second;
-                       check_assertion(word, 0xC0FFEE);
+                       check_assertion(word, PRINT);
                }
        }
 
@@ -210,6 +317,7 @@ void test_advanced_many_millisec()
 {
        local_advanced = "all_identical_logs";
        local_time_ms = "1";
+       local_warn_quantity = "0";
        char msg[4];
 
        for (milliseconds = 500; milliseconds < 900; milliseconds += 50) {
@@ -217,21 +325,117 @@ void test_advanced_many_millisec()
                for (int i = 0; i < 1500; ++i) {
                        int index = random() % 1000;
                        snprintf(msg, sizeof msg, "%d", index);
-                       check_assertion(msg, already_used[index] ? 0 : 0xC0FFEE);
+                       check_assertion(msg, already_used[index] ? 0 : PRINT);
                        already_used[index] = true;
                }
        }
        __dlog_fini();
 }
 
+void test_deduplicate_warn()
+{
+       use_real_deduplicate_warn = true;
+       local_warn_quantity = "11";
+       __configure();
+       char basic_log[25] = "This is a log,";
+       deduplicate_warn(basic_log, sizeof basic_log, strlen(basic_log));
+       assert(strcmp(basic_log, " LOG DUPLICATED 11 TIMES") == 0);
+       __dlog_fini();
+
+       local_warn_quantity = "17";
+       __configure();
+       char basic_log2[37] = "A completely different message,";
+       deduplicate_warn(basic_log2, sizeof basic_log2, strlen(basic_log2));
+       assert(strcmp(basic_log2, "A completely LOG DUPLICATED 17 TIMES") == 0);
+       __dlog_fini();
+
+       local_warn_quantity = "7";
+       __configure();
+       char basic_log3[31] = "This is a very long log,";
+       deduplicate_warn(basic_log3, sizeof basic_log3, strlen(basic_log3));
+       assert(strcmp(basic_log3, "This is LOG DUPLICATED 7 TIMES") == 0);
+       __dlog_fini();
+
+       local_warn_quantity = "14";
+       __configure();
+       char basic_log4[100] = "This is a log,";
+       deduplicate_warn(basic_log4, sizeof basic_log4, strlen(basic_log4));
+       assert(strcmp(basic_log4, "This is a log, LOG DUPLICATED 14 TIMES") == 0);
+
+       local_warn_quantity = "xyz";
+       __configure();
+       for (int i = 0; i < 12; ++i) {
+               if (i == 0)
+                       check_assertion("B", PRINT);
+               else
+                       check_assertion("B", DEDUPLICATE);
+       }
+
+       local_warn_quantity = "-1";
+       __configure();
+       for (int i = 0; i < 12; ++i) {
+               if (i == 0)
+                       check_assertion("B", PRINT);
+               else
+                       check_assertion("B", DEDUPLICATE);
+       }
+
+       local_warn_quantity = "";
+       __configure();
+       for (int i = 0; i < 12; ++i) {
+               if (i == 0)
+                       check_assertion("B", PRINT);
+               else
+                       check_assertion("B", DEDUPLICATE);
+       }
+
+       use_real_deduplicate_warn = false;
+       __dlog_fini();
+}
+
+void test_deduplicate_warn_random()
+{
+       use_real_deduplicate_warn = false;
+       local_advanced = "only_identical_neighbours";
+       local_time_ms = "10";
+       local_warn_quantity = "10";
+       milliseconds = 123;
+
+       srand(time(NULL));
+
+       for (int i = 0; i < 10; ++i) {
+               milliseconds++;
+               for (char c = 'A'; c <= 'Z'; ++c) {
+                       int limit = rand() % 34 + 2;
+                       for (int j = 0; j < limit; ++j) {
+                               char log_text[2];
+                               log_text[0] = c;
+                               log_text[1] = '\0';
+                               if (j == 0)
+                                       check_assertion(log_text, PRINT);
+                               else if ((j + 1) % atoi(local_warn_quantity) == 0)
+                                       check_assertion(log_text, WARN);
+                               else
+                                       check_assertion(log_text, DEDUPLICATE);
+                       }
+               }
+       }
+
+       __dlog_fini();
+}
+
 int main()
 {
        test_basic_1ms_interval();
        test_basic_10ms_interval();
+       test_basic_1ms_interval_warning();
        test_advanced_1ms_interval();
        test_advanced_10ms_interval();
+       test_advanced_10ms_interval_warning();
        test_advanced_many_hashes();
        test_advanced_many_millisec();
+       test_deduplicate_warn();
+       test_deduplicate_warn_random();
 
        return 0;
 }
index c5f8f10..9da1a17 100644 (file)
@@ -882,6 +882,50 @@ if [ "$TEST_DYNAMIC_FILTERS" = "true" ]; then
        fi
 fi
 
+dlogutil -c
+echo "deduplicate_method=only_identical_neighbours" > "$RUNTIME_FILTERS_DIR/30-deduplicate.conf"
+echo "deduplicate_interval_ms=10" >> "$RUNTIME_FILTERS_DIR/30-deduplicate.conf"
+
+dlogsend -p Info -b main -c 9 -t DLOG_DEDUP_TEST "Basic deduplication, default warn_quantity"
+LOG_DETAILS="testing if deduplication with warnings works properly (1/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Basic deduplication, default warn_quantity')" -eq 1 ] && ok || fail
+LOG_DETAILS="testing if deduplication with warnings works properly (2/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Basic deduplication, default warn_quantity LOG DUPLICATED')" -eq 0 ] && ok || fail
+
+dlogsend -p Info -b main -c 12 -t DLOG_DEDUP_TEST "Basic deduplication, default warn_quantity"
+LOG_DETAILS="testing if deduplication with warnings works properly (3/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Basic deduplication, default warn_quantity')" -eq 3 ] && ok || fail
+LOG_DETAILS="testing if deduplication with warnings works properly (4/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Basic deduplication, default warn_quantity LOG DUPLICATED')" -eq 1 ] && ok || fail
+
+echo "deduplicate_warn_quantity=8" >> "$RUNTIME_FILTERS_DIR/30-deduplicate.conf"
+
+dlogsend -p Info -b main -c 24 -t DLOG_DEDUP_TEST Message
+LOG_DETAILS="testing if deduplication with warnings works properly (5/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c Message)" -eq 4 ] && ok || fail
+LOG_DETAILS="testing if deduplication with warnings works properly (6/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Message LOG DUPLICATED')" -eq 3 ] && ok || fail
+
+dlogsend -p Info -b main -c 8 -t DLOG_DEDUP_TEST longerMessage
+LOG_DETAILS="testing if deduplication with warnings works properly (7/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c longerMessage)" -eq 2 ] && ok || fail
+LOG_DETAILS="testing if deduplication with warnings works properly (8/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c Message)" -eq 6 ] && ok || fail
+LOG_DETAILS="testing if deduplication with warnings works properly (9/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'longerMessage LOG DUPLICATED')" -eq 1 ] && ok || fail
+
+echo "deduplicate_warn_quantity=-1" >> "$RUNTIME_FILTERS_DIR/30-deduplicate.conf"
+
+dlogsend -p Info -b main -c 12 -t DLOG_DEDUP_TEST "Basic deduplication, no warning"
+LOG_DETAILS="testing if deduplication with warnings works properly (10/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Basic deduplication, no warning')" -eq 1 ] && ok || fail
+LOG_DETAILS="testing if deduplication with warnings works properly (11/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Basic deduplication')" -eq 4 ] && ok || fail
+LOG_DETAILS="testing if deduplication with warnings works properly (12/12)"
+[ "$(dlogutil -d DLOG_DEDUP_TEST | grep -c 'Basic deduplication, no warning LOG DUPLICATED')" -eq 0 ] && ok || fail
+
+rm "$RUNTIME_FILTERS_DIR/30-deduplicate.conf"
+
 LOG_DETAILS="testing if libdlogutil clears the buffer correctly"
 test_libdlogutil clear $LIBDLOGUTIL_CORRECT_PID $type && ok || fail