diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | test/profiling/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | test/profiling/main.c | 30 | ||||
| -rw-r--r-- | test/test_easy_fs.cpp | 75 | ||||
| -rw-r--r-- | test/test_empty_tags.cpp | 83 | ||||
| -rw-r--r-- | test/test_exporter_json.cpp | 457 | ||||
| -rw-r--r-- | test/test_fieldstat_exporter.py | 5 | ||||
| -rw-r--r-- | test/test_fuzz_test.cpp | 360 | ||||
| -rw-r--r-- | test/test_merge.cpp | 538 | ||||
| -rw-r--r-- | test/test_metric_counter.cpp | 220 | ||||
| -rw-r--r-- | test/test_metric_histogram.cpp | 87 | ||||
| -rw-r--r-- | test/test_metric_hll.cpp | 177 | ||||
| -rw-r--r-- | test/test_performance.cpp | 208 | ||||
| -rw-r--r-- | test/test_register_and_reset.cpp | 657 | ||||
| -rw-r--r-- | test/test_write_json_file.cpp | 109 | ||||
| -rw-r--r-- | test/unit_test_cell_manager.cpp | 733 | ||||
| -rw-r--r-- | test/utils.cpp | 295 | ||||
| -rw-r--r-- | test/utils.hpp | 48 |
18 files changed, 2124 insertions, 1963 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 61c6b75..a6c1403 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -16,7 +16,7 @@ set(DEBUG_FLAGS "-O3") include_directories(${PROJECT_SOURCE_DIR}/test)
include_directories(${PROJECT_SOURCE_DIR}/test/deps)
include_directories(${PROJECT_SOURCE_DIR}/src)
-include_directories(${PROJECT_SOURCE_DIR}/src/tags)
+include_directories(${PROJECT_SOURCE_DIR}/src/cells)
include_directories(${PROJECT_SOURCE_DIR}/src/metrics)
include_directories(${PROJECT_SOURCE_DIR}/include/fieldstat)
@@ -57,5 +57,4 @@ add_unit_test(test_metric_histogram) add_unit_test(test_metric_hll)
add_unit_test(test_performance)
add_unit_test(test_register_and_reset)
-add_unit_test(unit_test_cell_manager)
add_unit_test(test_write_json_file)
\ No newline at end of file diff --git a/test/profiling/CMakeLists.txt b/test/profiling/CMakeLists.txt index 5c8e99c..f06242f 100644 --- a/test/profiling/CMakeLists.txt +++ b/test/profiling/CMakeLists.txt @@ -16,7 +16,7 @@ include_directories(${PROJECT_SOURCE_DIR}/src/utils) file(GLOB SRC
"${PROJECT_SOURCE_DIR}/src/*.c"
"${PROJECT_SOURCE_DIR}/src/metrics/*.c"
- "${PROJECT_SOURCE_DIR}/src/tags/*.c"
+ "${PROJECT_SOURCE_DIR}/src/cells/*.c"
"${PROJECT_SOURCE_DIR}/src/exporter/*.c"
"${PROJECT_SOURCE_DIR}/src/utils/*.c"
"${PROJECT_SOURCE_DIR}/vendors/cjson/*.c"
diff --git a/test/profiling/main.c b/test/profiling/main.c index caf6542..9719579 100644 --- a/test/profiling/main.c +++ b/test/profiling/main.c @@ -4,36 +4,34 @@ #include <string.h> #include "fieldstat.h" -#include "tags/my_ut_hash.h" -#include "tags/my_ut_hash_inner.h" +#include "fields/my_ut_hash.h" +#include "fields/my_ut_hash_inner.h" #define ADD_OPER_NUM 5000000ULL // #define ADD_OPER_NUM 1 #define MAX_STRING_KEY_LEN 10 -const struct fieldstat_tag TEST_TAG_INT = {"INT key_", TAG_INTEGER, {.value_longlong = 100}}; +const struct field TEST_FIELD_INT = {"INT key_", FIELD_VALUE_INTEGER, {.value_longlong = 100}}; -// todo: 问一下贺岚风,tag是什么样子的 - int main () { printf("Start profiling...\n"); clock_t start, end; - // struct fieldstat_tag TAG[4] = { - // {"INT key_", TAG_INTEGER, {.value_longlong = 100}}, - // {"STRING key_", TAG_CSTRING, {.value_str = "10012312312312"}}, - // {"STRING key_", TAG_CSTRING, {.value_str = "100adsffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}}, - // {"FLOAT key_", TAG_INTEGER, {.value_double = 100.0}}, + // struct field TAG[4] = { + // {"INT key_", FIELD_VALUE_INTEGER, {.value_longlong = 100}}, + // {"STRING key_", FIELD_VALUE_CSTRING, {.value_str = "10012312312312"}}, + // {"STRING key_", FIELD_VALUE_CSTRING, {.value_str = "100adsffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}}, + // {"FLOAT key_", FIELD_VALUE_INTEGER, {.value_double = 100.0}}, // }; - struct fieldstat_tag TAG[4] = { - {"object_id", TAG_INTEGER, {.value_longlong = 20}}, - {"item_id", TAG_INTEGER, {.value_longlong = 16916397}}, - {"chart_id", TAG_INTEGER, {.value_longlong = 1}}, - {"version", TAG_INTEGER, {.value_longlong = 1}}, + struct field TAG[4] = { + {"object_id", FIELD_VALUE_INTEGER, {.value_longlong = 20}}, + {"item_id", FIELD_VALUE_INTEGER, {.value_longlong = 16916397}}, + {"chart_id", FIELD_VALUE_INTEGER, {.value_longlong = 1}}, + {"version", FIELD_VALUE_INTEGER, {.value_longlong = 1}}, }; struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); + fieldstat_cube_create(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); fieldstat_register_counter(instance, "counter"); start = clock(); diff --git a/test/test_easy_fs.cpp b/test/test_easy_fs.cpp index d3f45b7..a0e507d 100644 --- a/test/test_easy_fs.cpp +++ b/test/test_easy_fs.cpp @@ -13,54 +13,25 @@ TEST(test_easy_fieldstat, new_and_free) { - struct fieldstat_easy *fse = fieldstat_easy_new(10, "instance name1231231231", &TEST_TAG_STRING, 1); + struct fieldstat_easy *fse = fieldstat_easy_new(10, "instance name1231231231", &TEST_FIELD_STRING, 1); fieldstat_easy_free(fse); } TEST(test_easy_fieldstat, output_to_buff) { - struct fieldstat_easy *fse = fieldstat_easy_new(10, NULL, &TEST_TAG_STRING, 1); + struct fieldstat_easy *fse = fieldstat_easy_new(10, NULL, &TEST_FIELD_STRING, 1); fieldstat_easy_register_counter(fse, "metric counter"); - fieldstat_easy_counter_incrby(fse, 0, 0, &TEST_TAG_INT, 1, 1); + fieldstat_easy_counter_incrby(fse, 0, 0, &TEST_FIELD_INT, 1, 1); // read file, should be empty char *buff = NULL; size_t buff_len = 0; fieldstat_easy_output(fse, &buff, &buff_len); cJSON *root = cJSON_Parse(buff); cJSON *cell = cJSON_GetArrayItem(root, 0); - cJSON *metric = cJSON_GetObjectItem(cell, "fields"); - long long value = cJSON_GetObjectItem(metric, "metric counter")->valueint; + long long value = cJSON_GetObjectItem(cell, "metric counter")->valueint; EXPECT_EQ(value, 1); - cJSON *tags = cJSON_GetObjectItem(cell, "tags"); - EXPECT_EQ(cJSON_GetObjectItem(tags, TEST_TAG_INT.key)->valueint, TEST_TAG_INT.value_longlong); - EXPECT_STREQ(cJSON_GetObjectItem(tags, TEST_TAG_STRING.key)->valuestring, TEST_TAG_STRING.value_str); - - cJSON_Delete(root); - free(buff); - fieldstat_easy_free(fse); -} - -TEST(test_easy_fieldstat, output_to_buff_with_delta) -{ - struct fieldstat_easy *fse = fieldstat_easy_new(1, NULL, NULL, 0); - fieldstat_easy_enable_delta_in_active_output(fse); - fieldstat_easy_register_counter(fse, "metric counter"); - fieldstat_easy_counter_incrby(fse, 0, 0, NULL, 0, 1); - char *buff = NULL; - size_t buff_len = 0; - fieldstat_easy_output(fse, &buff, &buff_len); - free(buff); - fieldstat_easy_counter_incrby(fse, 0, 0, NULL, 0, 1); - fieldstat_easy_output(fse, &buff, &buff_len); - - cJSON *root = cJSON_Parse(buff); - cJSON *cell = cJSON_GetArrayItem(root, 0); - cJSON *metric = cJSON_GetObjectItem(cell, "fields"); - long long value = cJSON_GetObjectItem(metric, "metric counter")->valueint; - EXPECT_EQ(value, 2); - cJSON *metric_delta = cJSON_GetObjectItem(cell, "fields_delta"); - long long value_delta = cJSON_GetObjectItem(metric_delta, "metric counter")->valueint; - EXPECT_EQ(value_delta, 1); + EXPECT_EQ(cJSON_GetObjectItem(cell, TEST_FIELD_INT.key)->valueint, TEST_FIELD_INT.value_longlong); + EXPECT_STREQ(cJSON_GetObjectItem(cell, TEST_FIELD_STRING.key)->valuestring, TEST_FIELD_STRING.value_str); cJSON_Delete(root); free(buff); @@ -92,9 +63,9 @@ TEST(test_easy_fieldstat, output_to_file) EXPECT_EQ(cJSON_GetArraySize(root), 0); // is empty and valid cJSON_Delete(root); - fieldstat_easy_counter_incrby(fse, 0, counter_id, &TEST_TAG_INT, 1, 1); - fieldstat_easy_counter_incrby(fse, 1, counter_id, &TEST_TAG_INT, 1, 10); - fieldstat_easy_counter_incrby(fse, 2, counter_id, &TEST_TAG_INT, 1, 100); + fieldstat_easy_counter_incrby(fse, 0, counter_id, &TEST_FIELD_INT, 1, 1); + fieldstat_easy_counter_incrby(fse, 1, counter_id, &TEST_FIELD_INT, 1, 10); + fieldstat_easy_counter_incrby(fse, 2, counter_id, &TEST_FIELD_INT, 1, 100); sleep(2); // 2nd interval: merge 3 thread's data, and output @@ -123,7 +94,7 @@ TEST(test_easy_fieldstat, output_to_file) cJSON_Delete(root); // 4th interval: new data, output again - fieldstat_easy_counter_incrby(fse, 0, counter_id, &TEST_TAG_DOUBLE, 1, 10086); + fieldstat_easy_counter_incrby(fse, 0, counter_id, &TEST_FIELD_DOUBLE, 1, 10086); sleep(2); printf("4th interval\n"); root = read_file(); @@ -182,9 +153,9 @@ TEST(test_easy_fieldstat, output_interval_ok) struct fieldstat_easy *fse = fieldstat_easy_new(10, NULL, NULL, 0); fieldstat_easy_register_histogram(fse, "metric histogram", 1, 10000, 3); // a pretty time consuming metric - fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_INT, 1, 1); - fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_DOUBLE, 1, 10); - fieldstat_easy_histogram_record(fse, 0, 0, &TEST_TAG_STRING, 1, 110); + fieldstat_easy_histogram_record(fse, 0, 0, &TEST_FIELD_INT, 1, 1); + fieldstat_easy_histogram_record(fse, 0, 0, &TEST_FIELD_DOUBLE, 1, 10); + fieldstat_easy_histogram_record(fse, 0, 0, &TEST_FIELD_STRING, 1, 110); fieldstat_easy_enable_auto_output(fse, FILENAME, 1); @@ -197,10 +168,10 @@ TEST(test_easy_fieldstat, output_interval_ok) TEST(test_easy_fieldstat, ensure_data_racing_of_two_output_and_of_incyby) { const int N_THREADS = 3; - struct fieldstat_tag global_tags[1]; - struct fieldstat_tag tmptag; + struct field global_tags[1]; + struct field tmptag; tmptag.key = "app id"; - tmptag.type = TAG_INTEGER; + tmptag.type = FIELD_VALUE_INTEGER; tmptag.value_longlong = 1; global_tags[0] = tmptag; @@ -213,8 +184,8 @@ TEST(test_easy_fieldstat, ensure_data_racing_of_two_output_and_of_incyby) for (int thread_id = 0; thread_id < N_THREADS; thread_id++) { threads[thread_id] = std::thread([fse, counter_id, hdr_id, thread_id]() { for (int i = 0; i < 1000000; i++) { // loop million times to ensure no core dump - fieldstat_easy_counter_incrby(fse, thread_id, counter_id, &TEST_TAG_INT, 1, 1); - fieldstat_easy_histogram_record(fse, thread_id, hdr_id, &TEST_TAG_INT, 1, rand() % 10000); + fieldstat_easy_counter_incrby(fse, thread_id, counter_id, &TEST_FIELD_INT, 1, 1); + fieldstat_easy_histogram_record(fse, thread_id, hdr_id, &TEST_FIELD_INT, 1, rand() % 10000); usleep(1); // 1us * 1000000 = 1s, just long enough to output } }); @@ -231,8 +202,8 @@ TEST(test_easy_fieldstat, reset) { struct fieldstat_easy *fse = fieldstat_easy_new(3, NULL, NULL, 0); int counter_id = fieldstat_easy_register_counter(fse, "metric counter"); - fieldstat_easy_counter_incrby(fse, 0, counter_id, &TEST_TAG_INT, 1, 1); - fieldstat_easy_counter_incrby(fse, 1, counter_id, &TEST_TAG_INT, 1, 1); + fieldstat_easy_counter_incrby(fse, 0, counter_id, &TEST_FIELD_INT, 1, 1); + fieldstat_easy_counter_incrby(fse, 1, counter_id, &TEST_FIELD_INT, 1, 1); char **objects = NULL; size_t n_objects = 0; @@ -250,8 +221,7 @@ TEST(test_easy_fieldstat, reset) long long get_value(const char *input, const char *key) { cJSON *root = cJSON_Parse(input); - cJSON *metric = cJSON_GetObjectItem(root, "fields"); - long long value = cJSON_GetObjectItem(metric, key)->valueint; + long long value = cJSON_GetObjectItem(root, key)->valueint; cJSON_Delete(root); return value; } @@ -268,7 +238,7 @@ TEST(test_easy_fieldstat, accuracy_in_multithread) for (int thread_id = 0; thread_id < N_THREADS; thread_id++) { threads[thread_id] = std::thread([fse, counter_id, thread_id]() { for (size_t i = 0; i < 2000000ULL; i++) { // 1 million times - fieldstat_easy_counter_incrby(fse, thread_id, counter_id, &TEST_TAG_INT, 1, 1); + fieldstat_easy_counter_incrby(fse, thread_id, counter_id, &TEST_FIELD_INT, 1, 1); } }); } @@ -305,5 +275,6 @@ TEST(test_easy_fieldstat, accuracy_in_multithread) int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); + // testing::GTEST_FLAG(filter) = "test_easy_fieldstat.accuracy_in_multithread"; return RUN_ALL_TESTS(); }
\ No newline at end of file diff --git a/test/test_empty_tags.cpp b/test/test_empty_tags.cpp index 4f500bd..9cbaead 100644 --- a/test/test_empty_tags.cpp +++ b/test/test_empty_tags.cpp @@ -8,25 +8,25 @@ void assert_cell_null(const struct fieldstat *instance, int cube_id, long long expected_count) { - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_cube(instance, cube_id, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); - EXPECT_EQ(tag_list[0].n_tag, 0); - EXPECT_TRUE(tag_list[0].tag == NULL); + EXPECT_EQ(tag_list[0].n_field, 0); + EXPECT_TRUE(tag_list[0].field == NULL); long long value; - fieldstat_counter_get(instance, cube_id, 0, &tag_list[0], &value); + fieldstat_counter_get(instance, cube_id, &tag_list[0], 0, &value); EXPECT_EQ(value, expected_count); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); } - TEST(test_empty_tag, add_many_times) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 1); + int cube_id = fieldstat_cube_create(instance, NULL, 0); + int metric_id = fieldstat_register_counter(instance, cube_id, "metric"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_COMPREHENSIVE, 1, 0); - int metric_id = fieldstat_register_counter(instance, "metric"); fieldstat_counter_incrby(instance, cube_id, metric_id, NULL, 0, 1); fieldstat_counter_incrby(instance, cube_id, metric_id, NULL, 0, 1); @@ -38,8 +38,10 @@ TEST(test_empty_tag, add_many_times) struct fieldstat *test_empty_my_init(enum sampling_mode mode = SAMPLING_MODE_COMPREHENSIVE) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, NULL, 0, mode, 1); - int metric_id = fieldstat_register_counter(instance, "metric"); + int cube_id = fieldstat_cube_create(instance, NULL, 0); + int metric_id = fieldstat_register_counter(instance, cube_id, "metric"); + fieldstat_cube_set_sampling(instance, cube_id, mode, 1, 0); + fieldstat_counter_incrby(instance, cube_id, metric_id, NULL, 0, 1); return instance; @@ -57,10 +59,10 @@ TEST(test_empty_tag, merge) int n_cube = 0; fieldstat_get_cubes(instance_dst, &ret_cube_id_arr, &n_cube); int ret_cell_id = ret_cube_id_arr[0]; - struct fieldstat_tag_list *shared_tag = fieldstat_get_shared_tags(instance_dst, ret_cell_id); - EXPECT_EQ(shared_tag->n_tag, 0); - EXPECT_TRUE(shared_tag->tag == NULL); - fieldstat_tag_list_arr_free(shared_tag, 1); + struct field_list *shared_tag = fieldstat_cube_get_dimensions(instance_dst, ret_cell_id); + EXPECT_EQ(shared_tag->n_field, 0); + EXPECT_TRUE(shared_tag->field == NULL); + fieldstat_field_list_arr_free(shared_tag, 1); free(ret_cube_id_arr); assert_cell_null(instance_dst, ret_cell_id, 2); @@ -81,10 +83,10 @@ TEST(test_empty_tag, merge_topk) int n_cube = 0; fieldstat_get_cubes(instance_dst, &ret_cube_id_arr, &n_cube); int ret_cell_id = ret_cube_id_arr[0]; - struct fieldstat_tag_list *shared_tag = fieldstat_get_shared_tags(instance_dst, ret_cell_id); - EXPECT_EQ(shared_tag->n_tag, 0); - EXPECT_TRUE(shared_tag->tag == NULL); - fieldstat_tag_list_arr_free(shared_tag, 1); + struct field_list *shared_tag = fieldstat_cube_get_dimensions(instance_dst, ret_cell_id); + EXPECT_EQ(shared_tag->n_field, 0); + EXPECT_TRUE(shared_tag->field == NULL); + fieldstat_field_list_arr_free(shared_tag, 1); free(ret_cube_id_arr); assert_cell_null(instance_dst, ret_cell_id, 2); @@ -94,6 +96,43 @@ TEST(test_empty_tag, merge_topk) fieldstat_free(instance_src); } +TEST(test_empty_tag, merge_spreadsketch) +{ + struct fieldstat *instance_src = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance_src, NULL, 0); + int metric_id = fieldstat_register_hll(instance_src, cube_id, "metric", 4); + fieldstat_cube_set_sampling(instance_src, cube_id, SAMPLING_MODE_TOP_CARDINALITY, 1, 0); + fieldstat_hll_add(instance_src, cube_id, metric_id, NULL, 0, "1", 1); + struct fieldstat *instance_dst = fieldstat_new(); + + fieldstat_merge(instance_dst, instance_src); + fieldstat_merge(instance_dst, instance_src); + + int *ret_cube_id_arr = NULL; + int n_cube = 0; + fieldstat_get_cubes(instance_dst, &ret_cube_id_arr, &n_cube); + int ret_cell_id = ret_cube_id_arr[0]; + struct field_list *shared_tag = fieldstat_cube_get_dimensions(instance_dst, ret_cell_id); + EXPECT_EQ(shared_tag->n_field, 0); + EXPECT_TRUE(shared_tag->field == NULL); + fieldstat_field_list_arr_free(shared_tag, 1); + free(ret_cube_id_arr); + + struct field_list *tag_list = NULL; + size_t n_cell = 0; + fieldstat_cube_get_cells(instance_dst, cube_id, &tag_list, &n_cell); + EXPECT_EQ(n_cell, 1); + EXPECT_EQ(tag_list[0].n_field, 0); + EXPECT_TRUE(tag_list[0].field == NULL); + double value; + fieldstat_hll_get(instance_dst, cube_id, &tag_list[0], 0, &value); + EXPECT_NEAR(value, 1, 0.4); + fieldstat_field_list_arr_free(tag_list, n_cell); + + fieldstat_free(instance_dst); + fieldstat_free(instance_src); +} + TEST(test_empty_tag, export) { struct fieldstat *instance = test_empty_my_init(); @@ -107,9 +146,9 @@ TEST(test_empty_tag, export) fieldstat_free(instance); cJSON *root = cJSON_GetArrayItem(root_arr, 0); - // check tag - cJSON *tag = cJSON_GetObjectItem(root, "tags"); - EXPECT_EQ(cJSON_GetArraySize(tag), 0); + // check field + cJSON *field = cJSON_GetObjectItem(root, "tags"); + EXPECT_EQ(cJSON_GetArraySize(field), 0); cJSON *metrics = cJSON_GetObjectItem(root, "fields"); EXPECT_NE(metrics, nullptr); diff --git a/test/test_exporter_json.cpp b/test/test_exporter_json.cpp index 09aa579..f405b7f 100644 --- a/test/test_exporter_json.cpp +++ b/test/test_exporter_json.cpp @@ -1,6 +1,7 @@ #include <gtest/gtest.h> #include <random> +#include <unordered_set> #include "cjson/cJSON.h" #include "base64/b64.h" @@ -10,35 +11,35 @@ #include "utils.hpp" #include "hdr/hdr_histogram.h" #include "hdr/hdr_histogram_log.h" -#include "st_hyperloglog.h" +#include "hyperloglog.h" #include "histogram_encoder.h" #include "very_fast_json_writer.h" const size_t OPER_NUM = 10000; std::string g_hll_standard_oper[OPER_NUM]; long long g_histogram_standard_oper[OPER_NUM]; -struct ST_hyperloglog *g_hll_standard; +struct hyperloglog *g_hll_standard; struct hdr_histogram *g_histogram_standard; #define TEST_TOPK_STANDARD_K 5 #define TEST_METRIC_NUM 2 -const struct fieldstat_tag TEST_TAG_GLOBAL1 = {"test_tag_global 1", .type = TAG_INTEGER, {.value_longlong = 1}}; -const struct fieldstat_tag TEST_TAG_GLOBAL2 = {"test_tag_global 2", .type = TAG_DOUBLE, {.value_double = 2.2}}; -const struct fieldstat_tag TEST_TAG_GLOBAL3 = {"test_tag_global 3", .type = TAG_CSTRING, {.value_str = "string3"}}; -const struct fieldstat_tag TEST_TAG_GLOBAL[3] = {TEST_TAG_GLOBAL1, TEST_TAG_GLOBAL2, TEST_TAG_GLOBAL3}; +const struct field TEST_TAG_GLOBAL1 = {"test_tag_global 1", .type = FIELD_VALUE_INTEGER, {.value_longlong = 1}}; +const struct field TEST_TAG_GLOBAL2 = {"test_tag_global 2", .type = FIELD_VALUE_DOUBLE, {.value_double = 2.2}}; +const struct field TEST_TAG_GLOBAL3 = {"test_tag_global 3", .type = FIELD_VALUE_CSTRING, {.value_str = "string3"}}; +const struct field TEST_TAG_GLOBAL[3] = {TEST_TAG_GLOBAL1, TEST_TAG_GLOBAL2, TEST_TAG_GLOBAL3}; -const struct fieldstat_tag TEST_TAG_SHARED1_1 = {"test_tag_shared 1", .type = TAG_INTEGER, {.value_longlong = 3}}; -const struct fieldstat_tag TEST_TAG_SHARED1_2 = {"test_tag_shared 2", .type = TAG_DOUBLE, {.value_double = 0.2}}; -const struct fieldstat_tag TEST_TAG_SHARED1_3 = {"test_tag_shared 3", .type = TAG_CSTRING, {.value_str = "1string"}}; -const struct fieldstat_tag TEST_TAG_SHARED1[3] = {TEST_TAG_SHARED1_1, TEST_TAG_SHARED1_2, TEST_TAG_SHARED1_3}; +const struct field TEST_TAG_SHARED1_1 = {"test_tag_shared 1", .type = FIELD_VALUE_INTEGER, {.value_longlong = 3}}; +const struct field TEST_TAG_SHARED1_2 = {"test_tag_shared 2", .type = FIELD_VALUE_DOUBLE, {.value_double = 0.2}}; +const struct field TEST_TAG_SHARED1_3 = {"test_tag_shared 3", .type = FIELD_VALUE_CSTRING, {.value_str = "1string"}}; +const struct field TEST_TAG_SHARED1[3] = {TEST_TAG_SHARED1_1, TEST_TAG_SHARED1_2, TEST_TAG_SHARED1_3}; -const struct fieldstat_tag TEST_TAG_SHARED2_1 = {"test_tag_shared 11", .type = TAG_INTEGER, {.value_longlong = 4}}; -const struct fieldstat_tag TEST_TAG_SHARED2_2 = {"test_tag_shared 22", .type = TAG_DOUBLE, {.value_double = 0.3}}; -const struct fieldstat_tag TEST_TAG_SHARED2_3 = {"test_tag_shared 33", .type = TAG_CSTRING, {.value_str = "2string"}}; -const struct fieldstat_tag TEST_TAG_SHARED2[3] = {TEST_TAG_SHARED2_1, TEST_TAG_SHARED2_2, TEST_TAG_SHARED2_3}; +const struct field TEST_TAG_SHARED2_1 = {"test_tag_shared 11", .type = FIELD_VALUE_INTEGER, {.value_longlong = 4}}; +const struct field TEST_TAG_SHARED2_2 = {"test_tag_shared 22", .type = FIELD_VALUE_DOUBLE, {.value_double = 0.3}}; +const struct field TEST_TAG_SHARED2_3 = {"test_tag_shared 33", .type = FIELD_VALUE_CSTRING, {.value_str = "2string"}}; +const struct field TEST_TAG_SHARED2[3] = {TEST_TAG_SHARED2_1, TEST_TAG_SHARED2_2, TEST_TAG_SHARED2_3}; -const struct fieldstat_tag TEST_TAG_SHARED3_1 = {"test_tag_shared 3", .type = TAG_INTEGER, {.value_longlong = 5}}; -const struct fieldstat_tag TEST_TAG_SHARED3[1] = {TEST_TAG_SHARED3_1}; +const struct field TEST_TAG_SHARED3_1 = {"test_tag_shared 3", .type = FIELD_VALUE_INTEGER, {.value_longlong = 5}}; +const struct field TEST_TAG_SHARED3[1] = {TEST_TAG_SHARED3_1}; void test_check_if_tag_list_is_in_json(cJSON *tag_obj, const Fieldstat_tag_list_wrapper *benchmark) { @@ -48,7 +49,7 @@ void test_check_if_tag_list_is_in_json(cJSON *tag_obj, const Fieldstat_tag_list_ if (tag_val->type == cJSON_String) { EXPECT_STREQ(tag_val->valuestring, benchmark->get_tag()[tag_id].value_str); } else { - if (benchmark->get_tag()[tag_id].type == TAG_INTEGER) { + if (benchmark->get_tag()[tag_id].type == FIELD_VALUE_INTEGER) { EXPECT_EQ(tag_val->valueint, benchmark->get_tag()[tag_id].value_longlong); } else { EXPECT_NEAR(tag_val->valuedouble, benchmark->get_tag()[tag_id].value_double, 0.0001); @@ -59,7 +60,7 @@ void test_check_if_tag_list_is_in_json(cJSON *tag_obj, const Fieldstat_tag_list_ void test_check_if_global_tag_is_in_json(cJSON *tag_obj) { - struct fieldstat_tag_list tag_list = {.tag = (struct fieldstat_tag *)TEST_TAG_GLOBAL, .n_tag = 3}; + struct field_list tag_list = {.field = (struct field *)TEST_TAG_GLOBAL, .n_field = 3}; const Fieldstat_tag_list_wrapper benchmark(&tag_list); test_check_if_tag_list_is_in_json(tag_obj, &benchmark); } @@ -83,7 +84,7 @@ void test_check_if_metric_gauge_correct(cJSON *metric_obj, const char *name) { char *blob_gauge_benchmark = NULL; size_t size_dummy = 0; - ST_hyperloglog_serialize_for_networking(g_hll_standard, &blob_gauge_benchmark, &size_dummy); + hyperloglog_serialize_into_base64(g_hll_standard, &blob_gauge_benchmark, &size_dummy); cJSON *gauge_obj = cJSON_GetObjectItem(metric_obj, name); EXPECT_NE(gauge_obj, nullptr); @@ -104,7 +105,7 @@ void test_check_if_metric_topk_correct(cJSON *metric_obj, const char **name, uns } } -void fill_random_tag(Fieldstat_tag_list_wrapper *tags[], int tag_list_num) +void fill_random_tag(Fieldstat_tag_list_wrapper *fields[], int tag_list_num) { std::uniform_int_distribution<int> dist(1,100); std::mt19937 rng(); @@ -112,7 +113,7 @@ void fill_random_tag(Fieldstat_tag_list_wrapper *tags[], int tag_list_num) for (int i = 0; i < tag_list_num; i++) { Fieldstat_tag_list_wrapper *tmp = new Fieldstat_tag_list_wrapper(dist, i + 1); - tags[i] = tmp; + fields[i] = tmp; } } @@ -166,9 +167,10 @@ void topk_standard_oper(const std::function<void(Fieldstat_tag_list_wrapper *, u void topk_init(struct fieldstat *instance, unsigned int test_expected_big_count) { const char *metric_name[TEST_METRIC_NUM] = {"topk1", "topk2"}; - int cube_id = fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_TOPK, TEST_TOPK_STANDARD_K); - int m1 = fieldstat_register_counter(instance, metric_name[0]); - int m2 = fieldstat_register_counter(instance, metric_name[1]); + int cube_id = fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3); + int m1 = fieldstat_register_counter(instance, cube_id, metric_name[0]); + int m2 = fieldstat_register_counter(instance, cube_id, metric_name[1]); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, TEST_TOPK_STANDARD_K, 0); std::function<void(Fieldstat_tag_list_wrapper *, unsigned int *)> topk_add = [instance, cube_id, m1, m2](const Fieldstat_tag_list_wrapper *my_tags, unsigned int counts[TEST_METRIC_NUM]) { @@ -185,23 +187,25 @@ TEST(export_test, cjson_export_with_fixed_tag_and_many_metrics_on_one_cube_of_co // new instance struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, tag_list_num); - int id_counter = fieldstat_register_counter(instance, "counter"); - int id_gauge = fieldstat_register_hll(instance, "gauge", g_hll_standard->cfg.precision); - int id_histogram = fieldstat_register_hist(instance, "histogram", + int cube_id = fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3); + int id_counter = fieldstat_register_counter(instance, cube_id, "counter"); + int id_gauge = fieldstat_register_hll(instance, cube_id, "gauge", g_hll_standard->cfg.precision); + int id_histogram = fieldstat_register_histogram(instance, cube_id, "histogram", g_histogram_standard->lowest_discernible_value, g_histogram_standard->highest_trackable_value, g_histogram_standard->significant_figures); - Fieldstat_tag_list_wrapper *tags[tag_list_num]; - fill_random_tag(tags, tag_list_num); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_COMPREHENSIVE, tag_list_num, 0); + + Fieldstat_tag_list_wrapper *fields[tag_list_num]; + fill_random_tag(fields, tag_list_num); for (int j = 0; j < tag_list_num; j++) { - const struct fieldstat_tag *tag_tmp = tags[j]->get_tag(); - size_t tag_count = tags[j]->get_tag_count(); + const struct field *tag_tmp = fields[j]->get_tag(); + size_t tag_count = fields[j]->get_tag_count(); fieldstat_counter_incrby(instance, cube_id, id_counter, tag_tmp, tag_count, 1); for (size_t i = 0; i < OPER_NUM; i++){ fieldstat_hll_add(instance, cube_id, id_gauge, tag_tmp, tag_count, g_hll_standard_oper[i].c_str(), g_hll_standard_oper[i].length()); - fieldstat_hist_record(instance, cube_id, id_histogram, tag_tmp, tag_count, g_histogram_standard_oper[i]); + fieldstat_histogram_record(instance, cube_id, id_histogram, tag_tmp, tag_count, g_histogram_standard_oper[i]); } } @@ -214,10 +218,10 @@ TEST(export_test, cjson_export_with_fixed_tag_and_many_metrics_on_one_cube_of_co { cJSON *root = cJSON_GetArrayItem(root_arr, i); - // check tag - cJSON *tag = cJSON_GetObjectItem(root, "tags"); - EXPECT_NE(tag, nullptr); - test_check_if_tag_list_is_in_json(tag, tags[i]); + // check field + cJSON *field = cJSON_GetObjectItem(root, "tags"); + EXPECT_NE(field, nullptr); + test_check_if_tag_list_is_in_json(field, fields[i]); // check metrics cJSON *metrics = cJSON_GetObjectItem(root, "fields"); @@ -229,7 +233,7 @@ TEST(export_test, cjson_export_with_fixed_tag_and_many_metrics_on_one_cube_of_co } for (int i = 0; i < 3; i++) { - delete tags[i]; + delete fields[i]; } fieldstat_free(instance); @@ -247,6 +251,7 @@ TEST(export_test, cjson_export_on_one_cube_of_topk_sampling) int arr_num = cJSON_GetArraySize(root_arr); EXPECT_EQ(arr_num, TEST_TOPK_STANDARD_K); + std::unordered_set<long long> topk_tag_value_set; for (int i = 0; i < arr_num; i++) { cJSON *root = cJSON_GetArrayItem(root_arr, i); @@ -255,11 +260,12 @@ TEST(export_test, cjson_export_on_one_cube_of_topk_sampling) cJSON *tag = cJSON_GetObjectItem(root, "tags"); EXPECT_NE(tag, nullptr); - Fieldstat_tag_list_wrapper *added_tmp = new Fieldstat_tag_list_wrapper("flow id key", i); - test_check_if_tag_list_is_in_json(tag, added_tmp); - delete added_tmp; + cJSON *tag_val = cJSON_GetObjectItem(tag, "flow id key"); + EXPECT_NE(tag_val, nullptr); + EXPECT_EQ(tag_val->type, cJSON_Number); + topk_tag_value_set.insert(tag_val->valueint); - struct fieldstat_tag_list tmp_tag = {(struct fieldstat_tag *)&TEST_TAG_SHARED1, 3}; + struct field_list tmp_tag = {(struct field *)&TEST_TAG_SHARED1, 3}; Fieldstat_tag_list_wrapper shared_wrapper = Fieldstat_tag_list_wrapper(&tmp_tag); test_check_if_tag_list_is_in_json(tag, &shared_wrapper); @@ -269,11 +275,71 @@ TEST(export_test, cjson_export_on_one_cube_of_topk_sampling) const char *metric_name[TEST_METRIC_NUM] = {"topk1", "topk2"}; test_check_if_metric_topk_correct(metrics, (const char **)metric_name, test_expected_big_count, TEST_METRIC_NUM); } + + EXPECT_EQ(topk_tag_value_set.size(), TEST_TOPK_STANDARD_K); + for (int i = 0; i < TEST_TOPK_STANDARD_K; i++) { // the top k flow id is [0, TEST_TOPK_STANDARD_K - 1] + EXPECT_NE(topk_tag_value_set.find(i), topk_tag_value_set.end()); + } + cJSON_Delete(root_arr); fieldstat_free(instance); } +extern "C" { + double fieldstat_hll_base64_to_count(char *buf); +} +TEST(export_test, cjson_export_on_one_cube_of_spreadsketch_sampling) { + int K = 10; + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance, cube_id, "metric", 7); + int metric_count = fieldstat_register_counter(instance, cube_id, "oper cnt"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, K, 0); + + SpreadSketchZipfGenerator flow_generator(1.0, K * 10); + + for (int i = 0; i < 100000; i++) { + Flow flow = flow_generator.next(); + Fieldstat_tag_list_wrapper dimension = Fieldstat_tag_list_wrapper("bigger fanouts", flow.src_ip.c_str()); + Fieldstat_tag_list_wrapper item = Fieldstat_tag_list_wrapper("dummy", flow.dst_ip.c_str()); + fieldstat_hll_add_field(instance, cube_id, metric_id, dimension.get_tag(), dimension.get_tag_count(), item.get_tag(), item.get_tag_count()); + fieldstat_counter_incrby(instance, cube_id, metric_count, dimension.get_tag(), dimension.get_tag_count(), 1); + } + for (int i = 0; i < 100; i++) { + Flow flow = flow_generator.next(); + Fieldstat_tag_list_wrapper dimension = Fieldstat_tag_list_wrapper("smaller fanouts", flow.src_ip.c_str()); + Fieldstat_tag_list_wrapper item = Fieldstat_tag_list_wrapper("dummy", flow.dst_ip.c_str()); + fieldstat_hll_add_field(instance, cube_id, metric_id, dimension.get_tag(), dimension.get_tag_count(), item.get_tag(), item.get_tag_count()); + fieldstat_counter_incrby(instance, cube_id, metric_count, dimension.get_tag(), dimension.get_tag_count(), 1); + } + + cJSON *root_arr = test_exporter_extract_results(instance); + int arr_num = cJSON_GetArraySize(root_arr); + EXPECT_EQ(arr_num, K); + + for (int i = 0; i < arr_num; i++) { + cJSON *root = cJSON_GetArrayItem(root_arr, i); + + // check tag + cJSON *tag = cJSON_GetObjectItem(root, "tags"); + EXPECT_NE(tag, nullptr); + cJSON *tag_val = cJSON_GetObjectItem(tag, "bigger fanouts"); + EXPECT_NE(tag_val, nullptr); + + // check metrics + cJSON *metrics = cJSON_GetObjectItem(root, "fields"); + EXPECT_NE(metrics, nullptr); + cJSON *metric = cJSON_GetObjectItem(metrics, "metric"); + cJSON *metric_count = cJSON_GetObjectItem(metrics, "oper cnt"); + double hll_value = fieldstat_hll_base64_to_count(metric->valuestring); + EXPECT_NEAR(hll_value, metric_count->valueint, metric_count->valueint * 0.2); + } + + cJSON_Delete(root_arr); + fieldstat_free(instance); +} + TEST(export_test, empty_fieldstat_export_null) { struct fieldstat *instance = fieldstat_new(); cJSON *root_arr = test_exporter_extract_results_with_standard_global(instance); @@ -281,17 +347,25 @@ TEST(export_test, empty_fieldstat_export_null) { fieldstat_free(instance); } +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *dimensions, size_t n_dimensions, enum sampling_mode mode, int k, int primary_metric_id=0) +{ + assert(mode == SAMPLING_MODE_COMPREHENSIVE); + int ret = fieldstat_cube_create(instance, dimensions, n_dimensions); + fieldstat_cube_set_sampling(instance, ret, mode, k, primary_metric_id); + return ret; +} + TEST(export_test, only_registered_but_not_added_export_null_with_global_tag) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); - fieldstat_register_counter(instance, "counter"); - fieldstat_register_hll(instance, "gauge", g_hll_standard->cfg.precision); - fieldstat_register_hist(instance, "histogram", + int cube_id = test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); + fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_register_hll(instance, cube_id, "gauge", g_hll_standard->cfg.precision); + fieldstat_register_histogram(instance, cube_id, "histogram", g_histogram_standard->lowest_discernible_value, g_histogram_standard->highest_trackable_value, g_histogram_standard->significant_figures); - // add global tag + // add global field cJSON *root_arr = test_exporter_extract_results_with_standard_global(instance); EXPECT_EQ(root_arr, nullptr); @@ -301,20 +375,20 @@ TEST(export_test, only_registered_but_not_added_export_null_with_global_tag) TEST(export_test, skip_two_empty_cube_and_export_last_one_with_global_tag) { struct fieldstat *instance = fieldstat_new(); - (void)fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); - (void)fieldstat_create_cube(instance, TEST_TAG_SHARED2, 3, SAMPLING_MODE_COMPREHENSIVE, 3); - int cube_id_3 = fieldstat_create_cube(instance, TEST_TAG_SHARED3, 1, SAMPLING_MODE_COMPREHENSIVE, 3); - (void)fieldstat_register_counter(instance, "counter"); - (void)fieldstat_register_hll(instance, "gauge", g_hll_standard->cfg.precision); - int id_histogram = fieldstat_register_hist(instance, "histogram", + (void)test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); + (void)test_fieldstat_cube_create(instance, TEST_TAG_SHARED2, 3, SAMPLING_MODE_COMPREHENSIVE, 3); + int cube_id_3 = test_fieldstat_cube_create(instance, TEST_TAG_SHARED3, 1, SAMPLING_MODE_COMPREHENSIVE, 3); + (void)fieldstat_register_counter(instance, cube_id_3, "counter"); + (void)fieldstat_register_hll(instance, cube_id_3, "gauge", g_hll_standard->cfg.precision); + int id_histogram = fieldstat_register_histogram(instance, cube_id_3, "histogram", g_histogram_standard->lowest_discernible_value, g_histogram_standard->highest_trackable_value, g_histogram_standard->significant_figures); const int tag_num = 1; - Fieldstat_tag_list_wrapper *tags[tag_num]; - fill_random_tag(tags, tag_num); - const Fieldstat_tag_list_wrapper *the_tag = tags[0]; + Fieldstat_tag_list_wrapper *fields[tag_num]; + fill_random_tag(fields, tag_num); + const Fieldstat_tag_list_wrapper *the_tag = fields[0]; for (size_t i = 0; i < OPER_NUM; i++){ - fieldstat_hist_record(instance, cube_id_3, id_histogram, the_tag->get_tag(), the_tag->get_tag_count(), g_histogram_standard_oper[i]); + fieldstat_histogram_record(instance, cube_id_3, id_histogram, the_tag->get_tag(), the_tag->get_tag_count(), g_histogram_standard_oper[i]); } // export test @@ -328,7 +402,7 @@ TEST(export_test, skip_two_empty_cube_and_export_last_one_with_global_tag) // check tag cJSON *tag = cJSON_GetObjectItem(root, "tags"); - test_check_if_tag_list_is_in_json(tag, tags[0]); + test_check_if_tag_list_is_in_json(tag, fields[0]); test_check_if_global_tag_is_in_json(tag); cJSON *metrics = cJSON_GetObjectItem(root, "fields"); @@ -341,7 +415,7 @@ TEST(export_test, skip_two_empty_cube_and_export_last_one_with_global_tag) FAIL(); } - delete tags[0]; + delete fields[0]; fieldstat_free(instance); cJSON_Delete(root_arr); @@ -349,18 +423,18 @@ TEST(export_test, skip_two_empty_cube_and_export_last_one_with_global_tag) TEST(export_test, skip_empty_metrics_given_cube_deleted) { struct fieldstat *instance = fieldstat_new(); - int cube_id_del = fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); - int cube_id = fieldstat_create_cube(instance, TEST_TAG_SHARED2, 3, SAMPLING_MODE_COMPREHENSIVE, 3); - fieldstat_destroy_cube(instance, cube_id_del); - (void)fieldstat_register_counter(instance, "counter"); - (void)fieldstat_register_counter(instance, "counter2"); - int metric_id = fieldstat_register_counter(instance, "counter3"); - (void)fieldstat_register_counter(instance, "counter4"); + int cube_id_del = test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); + int cube_id = test_fieldstat_cube_create(instance, TEST_TAG_SHARED2, 3, SAMPLING_MODE_COMPREHENSIVE, 3); + fieldstat_cube_destroy(instance, cube_id_del); + (void)fieldstat_register_counter(instance, cube_id, "counter"); + (void)fieldstat_register_counter(instance, cube_id, "counter2"); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter3"); + (void)fieldstat_register_counter(instance, cube_id, "counter4"); const int tag_num = 1; - Fieldstat_tag_list_wrapper *tags[tag_num]; - fill_random_tag(tags, tag_num); - const Fieldstat_tag_list_wrapper *the_tag = tags[0]; + Fieldstat_tag_list_wrapper *fields[tag_num]; + fill_random_tag(fields, tag_num); + const Fieldstat_tag_list_wrapper *the_tag = fields[0]; fieldstat_counter_incrby(instance, cube_id, metric_id, the_tag->get_tag(), the_tag->get_tag_count(), 1234); @@ -371,13 +445,13 @@ TEST(export_test, skip_empty_metrics_given_cube_deleted) { for (int i = 0; i < arr_num; i++) { cJSON *root = cJSON_GetArrayItem(root_arr, i); - // check tag - cJSON *tag = cJSON_GetObjectItem(root, "tags"); - test_check_if_tag_list_is_in_json(tag, tags[0]); - test_check_if_global_tag_is_in_json(tag); - struct fieldstat_tag_list tmp_tag = {(struct fieldstat_tag *)&TEST_TAG_SHARED2, 3}; + // check field + cJSON *field = cJSON_GetObjectItem(root, "tags"); + test_check_if_tag_list_is_in_json(field, fields[0]); + test_check_if_global_tag_is_in_json(field); + struct field_list tmp_tag = {(struct field *)&TEST_TAG_SHARED2, 3}; Fieldstat_tag_list_wrapper shared_wrapper = Fieldstat_tag_list_wrapper(&tmp_tag); - test_check_if_tag_list_is_in_json(tag, &shared_wrapper); + test_check_if_tag_list_is_in_json(field, &shared_wrapper); cJSON *metrics = cJSON_GetObjectItem(root, "fields"); EXPECT_NE(metrics, nullptr); @@ -390,7 +464,7 @@ TEST(export_test, skip_empty_metrics_given_cube_deleted) { FAIL(); } - delete tags[0]; + delete fields[0]; fieldstat_free(instance); cJSON_Delete(root_arr); } @@ -398,9 +472,9 @@ TEST(export_test, skip_empty_metrics_given_cube_deleted) { TEST(export_test, enable_delta_and_export_twice_without_new_metric) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); - int id_counter = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_TAG_INT, 1, 1); + int cube_id = test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); + int id_counter = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_FIELD_INT, 1, 1); // export test struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); @@ -467,12 +541,12 @@ TEST(export_test, enable_delta_and_export_twice_without_new_metric) TEST(export_test, enable_delta_and_export_twice_with_new_metric_and_omit_histogram) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); - int id_counter = fieldstat_register_counter(instance, "counter"); - int id_histogram = fieldstat_register_hist(instance, "histogram", + int cube_id = test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); + int id_counter = fieldstat_register_counter(instance, cube_id, "counter"); + int id_histogram = fieldstat_register_histogram(instance, cube_id, "histogram", g_histogram_standard->lowest_discernible_value, g_histogram_standard->highest_trackable_value, g_histogram_standard->significant_figures); - fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_TAG_INT, 1, 1); - fieldstat_hist_record(instance, cube_id, id_histogram, &TEST_TAG_INT, 1, 123); + fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_FIELD_INT, 1, 1); + fieldstat_histogram_record(instance, cube_id, id_histogram, &TEST_FIELD_INT, 1, 123); // export test struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); @@ -507,9 +581,9 @@ TEST(export_test, enable_delta_and_export_twice_with_new_metric_and_omit_histogr struct timeval new_ts = TEST_TIMEVAL; new_ts.tv_sec += 1; - int id_counter2 = fieldstat_register_counter(instance, "counter2"); - fieldstat_counter_incrby(instance, cube_id, id_counter2, &TEST_TAG_INT, 1, 1); - fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_TAG_INT, 1, 10); + int id_counter2 = fieldstat_register_counter(instance, cube_id, "counter2"); + fieldstat_counter_incrby(instance, cube_id, id_counter2, &TEST_FIELD_INT, 1, 1); + fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_FIELD_INT, 1, 10); json_string = fieldstat_json_exporter_export(fieldstat_json_exporter, instance, &new_ts); root_arr = cJSON_Parse(json_string); @@ -549,12 +623,12 @@ TEST(export_test, enable_delta_and_export_twice_with_new_metric_and_omit_histogr TEST(export_test, enable_delta_and_export_three_times_skipping_cube_with_no_counter) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); - int id_counter = fieldstat_register_counter(instance, "counter"); - int id_histogram = fieldstat_register_hist(instance, "histogram", + int cube_id = test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); + int id_counter = fieldstat_register_counter(instance, cube_id, "counter"); + int id_histogram = fieldstat_register_histogram(instance, cube_id, "histogram", g_histogram_standard->lowest_discernible_value, g_histogram_standard->highest_trackable_value, g_histogram_standard->significant_figures); - fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_TAG_INT, 1, 1); - fieldstat_hist_record(instance, cube_id, id_histogram, &TEST_TAG_STRING, 1, 123); + fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_FIELD_INT, 1, 1); + fieldstat_histogram_record(instance, cube_id, id_histogram, &TEST_FIELD_STRING, 1, 123); /* -------------------------- export test, 1st time ------------------------- */ struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); @@ -609,8 +683,8 @@ TEST(export_test, enable_delta_and_export_three_times_skipping_cube_with_no_coun /* -------------------------------- 3rd time -------------------------------- */ // add some new recs - fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_TAG_INT, 1, 10); - fieldstat_hist_record(instance, cube_id, id_histogram, &TEST_TAG_STRING, 1, 1234); + fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_FIELD_INT, 1, 10); + fieldstat_histogram_record(instance, cube_id, id_histogram, &TEST_FIELD_STRING, 1, 1234); json_string = fieldstat_json_exporter_export(fieldstat_json_exporter, instance, &TEST_TIMEVAL); root_arr = cJSON_Parse(json_string); free(json_string); @@ -636,15 +710,15 @@ TEST(export_test, enable_delta_and_export_three_times_skipping_cube_with_no_coun fieldstat_free(instance); } -void test_check_delta_for_one_json(const struct fieldstat_tag_list *expect_cell_tag, const struct fieldstat_tag_list *expect_shared_tag, long long expect_value, long long expect_delta, cJSON *root) +void test_check_delta_for_one_json(const struct field_list *expect_cell_tag, const struct field_list *expect_shared_tag, long long expect_value, long long expect_delta, cJSON *root) { - // check tag - cJSON *tag = cJSON_GetObjectItem(root, "tags"); + // check field + cJSON *field = cJSON_GetObjectItem(root, "tags"); Fieldstat_tag_list_wrapper cell_wrapper = Fieldstat_tag_list_wrapper(expect_cell_tag); - test_check_if_tag_list_is_in_json(tag, &cell_wrapper); + test_check_if_tag_list_is_in_json(field, &cell_wrapper); Fieldstat_tag_list_wrapper shared_wrapper = Fieldstat_tag_list_wrapper(expect_shared_tag); - test_check_if_tag_list_is_in_json(tag, &shared_wrapper); - test_check_if_global_tag_is_in_json(tag); + test_check_if_tag_list_is_in_json(field, &shared_wrapper); + test_check_if_global_tag_is_in_json(field); // check metrics cJSON *metrics = cJSON_GetObjectItem(root, "fields"); @@ -658,14 +732,15 @@ void test_check_delta_for_one_json(const struct fieldstat_tag_list *expect_cell_ TEST(export_test, enable_delta_and_export_instance_with_many_cells_with_global_tags) { struct fieldstat *instance = fieldstat_new(); - int cube_id1 = fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); - int id_counter1 = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_TAG_INT, 1, 11); - fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_TAG_STRING, 1, 12); + int cube_id1 = test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 10); + int id_counter1 = fieldstat_register_counter(instance, cube_id1, "counter"); + fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_FIELD_INT, 1, 11); + fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_FIELD_STRING, 1, 12); - int cube_id2 = fieldstat_create_cube(instance, TEST_TAG_SHARED3, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_counter_incrby(instance, cube_id2, id_counter1, &TEST_TAG_INT, 1, 21); - fieldstat_counter_incrby(instance, cube_id2, id_counter1, &TEST_TAG_DOUBLE, 1, 22); + int cube_id2 = test_fieldstat_cube_create(instance, TEST_TAG_SHARED3, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int id_counter2 = fieldstat_register_counter(instance, cube_id2, "counter"); + fieldstat_counter_incrby(instance, cube_id2, id_counter2, &TEST_FIELD_INT, 1, 21); + fieldstat_counter_incrby(instance, cube_id2, id_counter2, &TEST_FIELD_DOUBLE, 1, 22); // export test struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); @@ -681,28 +756,28 @@ TEST(export_test, enable_delta_and_export_instance_with_many_cells_with_global_t /* ------------------------------ cube 0 cell 0 ----------------------------- */ cJSON *root = cJSON_GetArrayItem(root_arr, 0); - struct fieldstat_tag_list tmp_tag_cell = {(struct fieldstat_tag *)&TEST_TAG_INT, 1}; - struct fieldstat_tag_list tmp_tag_shared = {(struct fieldstat_tag *)&TEST_TAG_SHARED1, 3}; + struct field_list tmp_tag_cell = {(struct field *)&TEST_FIELD_INT, 1}; + struct field_list tmp_tag_shared = {(struct field *)&TEST_TAG_SHARED1, 3}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 11, 11, root); /* ------------------------------ cube 0 cell 1 ----------------------------- */ root = cJSON_GetArrayItem(root_arr, 1); - tmp_tag_cell = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_STRING, 1}; + tmp_tag_cell = (struct field_list){(struct field *)&TEST_FIELD_STRING, 1}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 12, 12, root); /* ------------------------------ cube 1 cell 0 ----------------------------- */ root = cJSON_GetArrayItem(root_arr, 2); - tmp_tag_cell = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_INT, 1}; - tmp_tag_shared = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_SHARED3, 1}; + tmp_tag_cell = (struct field_list){(struct field *)&TEST_FIELD_INT, 1}; + tmp_tag_shared = (struct field_list){(struct field *)&TEST_TAG_SHARED3, 1}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 21, 21, root); /* ------------------------------ cube 1 cell 1 ----------------------------- */ root = cJSON_GetArrayItem(root_arr, 3); - tmp_tag_cell = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_DOUBLE, 1}; + tmp_tag_cell = (struct field_list){(struct field *)&TEST_FIELD_DOUBLE, 1}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 22, 22, root); // new turn - fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_TAG_INT, 1, 100); - fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_TAG_STRING, 1, 200); - fieldstat_counter_incrby(instance, cube_id2, id_counter1, &TEST_TAG_INT, 1, 300); - fieldstat_counter_incrby(instance, cube_id2, id_counter1, &TEST_TAG_DOUBLE, 1, 400); + fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_FIELD_INT, 1, 100); + fieldstat_counter_incrby(instance, cube_id1, id_counter1, &TEST_FIELD_STRING, 1, 200); + fieldstat_counter_incrby(instance, cube_id2, id_counter1, &TEST_FIELD_INT, 1, 300); + fieldstat_counter_incrby(instance, cube_id2, id_counter1, &TEST_FIELD_DOUBLE, 1, 400); cJSON_Delete(root_arr); @@ -717,21 +792,21 @@ TEST(export_test, enable_delta_and_export_instance_with_many_cells_with_global_t /* ------------------------------ cube 0 cell 0 ----------------------------- */ root = cJSON_GetArrayItem(root_arr, 0); - tmp_tag_cell = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_INT, 1}; - tmp_tag_shared = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_SHARED1, 3}; + tmp_tag_cell = (struct field_list){(struct field *)&TEST_FIELD_INT, 1}; + tmp_tag_shared = (struct field_list){(struct field *)&TEST_TAG_SHARED1, 3}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 111, 100, root); /* ------------------------------ cube 0 cell 1 ----------------------------- */ root = cJSON_GetArrayItem(root_arr, 1); - tmp_tag_cell = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_STRING, 1}; + tmp_tag_cell = (struct field_list){(struct field *)&TEST_FIELD_STRING, 1}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 212, 200, root); /* ------------------------------ cube 1 cell 0 ----------------------------- */ root = cJSON_GetArrayItem(root_arr, 2); - tmp_tag_cell = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_INT, 1}; - tmp_tag_shared = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_SHARED3, 1}; + tmp_tag_cell = (struct field_list){(struct field *)&TEST_FIELD_INT, 1}; + tmp_tag_shared = (struct field_list){(struct field *)&TEST_TAG_SHARED3, 1}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 321, 300, root); /* ------------------------------ cube 1 cell 1 ----------------------------- */ root = cJSON_GetArrayItem(root_arr, 3); - tmp_tag_cell = (struct fieldstat_tag_list){(struct fieldstat_tag *)&TEST_TAG_DOUBLE, 1}; + tmp_tag_cell = (struct field_list){(struct field *)&TEST_FIELD_DOUBLE, 1}; test_check_delta_for_one_json(&tmp_tag_cell, &tmp_tag_shared, 422, 400, root); cJSON_Delete(root_arr); @@ -743,9 +818,9 @@ TEST(export_test, enable_delta_and_export_instance_with_many_cells_with_global_t void test_reset_one_round(std::function<void(struct fieldstat *, struct fieldstat_json_exporter *)> trigger_reset) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 1); - int id_counter = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_TAG_INT, 1, 11); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 1); + int id_counter = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, cube_id, id_counter, &TEST_FIELD_INT, 1, 11); // export test struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); @@ -767,9 +842,10 @@ void test_reset_one_round(std::function<void(struct fieldstat *, struct fieldsta trigger_reset(instance, fieldstat_json_exporter); - fieldstat_counter_set(instance, cube_id, id_counter, &TEST_TAG_INT, 1, 123); + fieldstat_counter_set(instance, cube_id, id_counter, &TEST_FIELD_INT, 1, 123); json_string = fieldstat_json_exporter_export(fieldstat_json_exporter, instance, &TEST_TIMEVAL); + printf("test_reset_one_round :\n%s\n", json_string); root_arr = cJSON_Parse(json_string); free(json_string); @@ -804,18 +880,11 @@ TEST(export_test, enable_delta_and_reset_on_change_exporter_tag) { test_reset_one_round(trigger); } -TEST(export_test, enable_delta_and_reset_on_reset_instance) { - auto trigger = [](struct fieldstat *instance, struct fieldstat_json_exporter *fieldstat_json_exporter) { - fieldstat_reset(instance); - }; - - test_reset_one_round(trigger); -} - TEST(export_test, enable_delta_and_reset_on_delete_cube) { auto trigger = [](struct fieldstat *instance, struct fieldstat_json_exporter *fieldstat_json_exporter) { - fieldstat_destroy_cube(instance, 0); - fieldstat_create_cube(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); + fieldstat_cube_destroy(instance, 0); + test_fieldstat_cube_create(instance, TEST_TAG_SHARED1, 3, SAMPLING_MODE_COMPREHENSIVE, 3); + fieldstat_register_counter(instance, 0, "counter"); }; test_reset_one_round(trigger); @@ -824,15 +893,15 @@ TEST(export_test, enable_delta_and_reset_on_delete_cube) { TEST(export_test, delta_with_two_instance_same_config) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); - int id_counter = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, 0, id_counter, &TEST_TAG_INT, 1, 123); - int id_hist = fieldstat_register_hist(instance, "histogram", 1, 1000, 3); - fieldstat_hist_record(instance, 0, id_hist, &TEST_TAG_INT, 1, 5); + int cube_id = test_fieldstat_cube_create(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); + int id_counter = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, 0, id_counter, &TEST_FIELD_INT, 1, 123); + int id_hist = fieldstat_register_histogram(instance, cube_id, "histogram", 1, 1000, 3); + fieldstat_histogram_record(instance, cube_id, id_hist, &TEST_FIELD_INT, 1, 5); struct fieldstat *acc = fieldstat_new(); fieldstat_merge(acc, instance); - fieldstat_counter_incrby(acc, 0, id_counter, &TEST_TAG_INT, 1, 1000); + fieldstat_counter_incrby(acc, 0, id_counter, &TEST_FIELD_INT, 1, 1000); // export test struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); @@ -864,18 +933,17 @@ TEST(export_test, delta_with_two_instance_same_config) TEST(export_test, delta_with_two_instance_one_empty) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); - int id_counter = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, 0, id_counter, &TEST_TAG_INT, 1, 123); - int id_hist = fieldstat_register_hist(instance, "histogram", 1, 1000, 3); - fieldstat_hist_record(instance, 0, id_hist, &TEST_TAG_INT, 1, 5); + int cube_id = test_fieldstat_cube_create(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); + int id_counter = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, 0, id_counter, &TEST_FIELD_INT, 1, 123); + int id_hist = fieldstat_register_histogram(instance, cube_id, "histogram", 1, 1000, 3); + fieldstat_histogram_record(instance, 0, id_hist, &TEST_FIELD_INT, 1, 5); struct fieldstat *delta = fieldstat_fork(instance); // export test struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); char *json = fieldstat_json_exporter_export_with_delta(fieldstat_json_exporter, instance, delta, &TEST_TIMEVAL, &TEST_TIMEVAL); - printf("delta_with_two_instance_one_empty :\n%s\n", json); cJSON *root_arr = cJSON_Parse(json); free(json); @@ -904,12 +972,12 @@ TEST(export_test, delta_with_two_instance_one_empty) TEST(export_test, delta_with_two_instance_different_cell) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); - int id_counter = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, 0, id_counter, &TEST_TAG_INT, 1, 123); + test_fieldstat_cube_create(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); + int id_counter = fieldstat_register_counter(instance, 0, "counter"); + fieldstat_counter_incrby(instance, 0, id_counter, &TEST_FIELD_INT, 1, 123); struct fieldstat *delta = fieldstat_fork(instance); - fieldstat_counter_incrby(delta, 0, id_counter, &TEST_TAG_DOUBLE, 1, 1); + fieldstat_counter_incrby(delta, 0, id_counter, &TEST_FIELD_DOUBLE, 1, 1); fieldstat_merge(instance, delta); // export test @@ -949,27 +1017,66 @@ TEST(export_test, delta_with_two_instance_different_cell) fieldstat_free(delta); } -// TEST(export_test, sort_tag) { -// const struct fieldstat_tag tag1[3] = {TEST_TAG_INT, TEST_TAG_STRING, TEST_TAG_DOUBLE}; -// const struct fieldstat_tag tag2[3] = {TEST_TAG_STRING, TEST_TAG_DOUBLE, TEST_TAG_INT}; +TEST(export_test, export_flat_null_with_only_global_tag) { + struct fieldstat *instance = fieldstat_new(); + struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); + fieldstat_json_exporter_set_global_tag(fieldstat_json_exporter, TEST_TAG_GLOBAL, 3); + + char **out_array = NULL; + size_t out_array_len = 0; + fieldstat_json_exporter_export_flat_array(fieldstat_json_exporter, instance, &TEST_TIMEVAL, &out_array, &out_array_len); + EXPECT_EQ(out_array_len, 0); + EXPECT_EQ(out_array, nullptr); + + fieldstat_json_exporter_free(fieldstat_json_exporter); + free(out_array); + fieldstat_free(instance); +} + +TEST(export_test, export_flat_many_tags_many_cell) { + struct fieldstat *instance = fieldstat_new(); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 3); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter metric"); -// struct fieldstat *instance = fieldstat_new(); -// fieldstat_create_cube(instance, NULL, 0, SAMPLING_MODE_COMPREHENSIVE, 0); -// int id_counter = fieldstat_register_counter(instance, "counter"); -// fieldstat_counter_incrby(instance, 0, id_counter, tag1, 3, 1); -// fieldstat_counter_incrby(instance, 0, id_counter, tag2, 3, 10); -// // export test -// cJSON *root_arr = test_exporter_extract_results(instance); -// EXPECT_EQ(cJSON_GetArraySize(root_arr), 1); -// cJSON *root = cJSON_GetArrayItem(root_arr, 0); -// cJSON *metrics = cJSON_GetObjectItem(root, "fields"); -// cJSON *counter = cJSON_GetObjectItem(metrics, "counter"); -// EXPECT_EQ(counter->valueint, 11); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 123); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, 321); -// cJSON_Delete(root_arr); -// fieldstat_free(instance); -// } + struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(); + fieldstat_json_exporter_set_global_tag(fieldstat_json_exporter, TEST_TAG_GLOBAL, 3); + + char **out_array = NULL; + size_t out_array_len = 0; + fieldstat_json_exporter_export_flat_array(fieldstat_json_exporter, instance, &TEST_TIMEVAL, &out_array, &out_array_len); + EXPECT_EQ(out_array_len, 2); + + cJSON *root = cJSON_Parse(out_array[0]); + Fieldstat_tag_list_wrapper cell_dimension = Fieldstat_tag_list_wrapper(&TEST_FIELD_LIST_INT); + Fieldstat_tag_list_wrapper cube_dimension = Fieldstat_tag_list_wrapper(&TEST_FIELD_LIST_STRING); + Fieldstat_tag_list_wrapper cell_dimension2 = Fieldstat_tag_list_wrapper(&TEST_FIELD_LIST_DOUBLE); + + test_check_if_tag_list_is_in_json(root, &cell_dimension); + test_check_if_global_tag_is_in_json(root); + test_check_if_tag_list_is_in_json(root, &cube_dimension); + cJSON *metrics = cJSON_GetObjectItem(root, "counter metric"); + EXPECT_EQ(metrics->valueint, 123); + + cJSON_Delete(root); + root = cJSON_Parse(out_array[1]); + test_check_if_tag_list_is_in_json(root, &cell_dimension2); + test_check_if_global_tag_is_in_json(root); + test_check_if_tag_list_is_in_json(root, &cube_dimension); + metrics = cJSON_GetObjectItem(root, "counter metric"); + EXPECT_EQ(metrics->valueint, 321); + + cJSON_Delete(root); + fieldstat_free(instance); + fieldstat_json_exporter_free(fieldstat_json_exporter); + for (size_t i = 0; i < out_array_len; i++) { + free(out_array[i]); + } + free(out_array); +} extern "C" { extern int add_object_to_json_array_start(char *buf, int buf_len); @@ -1056,11 +1163,11 @@ TEST(export_unit_test, json_writer_length_is_on_margin_4096_string) void init_hll_standard_oper() { - g_hll_standard = ST_hyperloglog_new(12); + g_hll_standard = hyperloglog_new(12); for (size_t i = 0; i < OPER_NUM; i++) { std::string added_tmp = std::to_string(i); g_hll_standard_oper[i] = added_tmp; - ST_hyperloglog_add(g_hll_standard, added_tmp.c_str(), added_tmp.size()); + hyperloglog_add(g_hll_standard, added_tmp.c_str(), added_tmp.size()); } } @@ -1079,10 +1186,12 @@ int main(int argc, char *argv[]) { init_hll_standard_oper(); init_histogram_standard_oper(); + testing::InitGoogleTest(&argc, argv); + // testing::GTEST_FLAG(filter) = "*flat*"; int ret = RUN_ALL_TESTS(); - ST_hyperloglog_free(g_hll_standard); + hyperloglog_free(g_hll_standard); hdr_close(g_histogram_standard); return ret; } diff --git a/test/test_fieldstat_exporter.py b/test/test_fieldstat_exporter.py index aaafb16..4f82f1a 100644 --- a/test/test_fieldstat_exporter.py +++ b/test/test_fieldstat_exporter.py @@ -17,6 +17,7 @@ from prettytable import PrettyTable,NONE,HEADER import os current_path = os.path.dirname(os.path.abspath(__file__)) sys.path.append(current_path + '/../../src/exporter') +sys.path.append('/home/chenzizhan/heavykeeperczz/FieldStat/src/exporter') from fieldstat_exporter import FieldstatAPI @@ -153,7 +154,7 @@ class TestPrometheusExporter(unittest.TestCase): metric = self.prom._PrometheusExporter__build_type_hll(name, tags, value) - self.assertEqual(metric, "tsg_master_log{policy_id=\"1\",app_name=\"-\"} 62.61\n") + self.assertEqual(metric, "tsg_master_log{policy_id=\"1\",app_name=\"-\"} 93.61\n") def test__build_metrics(self): @@ -186,7 +187,7 @@ class TestPrometheusExporter(unittest.TestCase): "timestamp_ms_delta": 100010 } metrics = self.prom._PrometheusExporter__build_metrics(hll_dict) - self.assertEqual(metrics, "external_ip{rule_id=\"1\",app_name=\"-\"} 62.61\n") + self.assertEqual(metrics, "external_ip{rule_id=\"1\",app_name=\"-\"} 93.61\n") hist_dict = {"name": "-", "tags": { diff --git a/test/test_fuzz_test.cpp b/test/test_fuzz_test.cpp index 2083b89..46f60e4 100644 --- a/test/test_fuzz_test.cpp +++ b/test/test_fuzz_test.cpp @@ -10,7 +10,7 @@ using namespace std; -void fill_random_tag_of_length_1_to_3(Fieldstat_tag_list_wrapper *tags[], int tag_list_num) +void fill_random_tag_of_length_1_to_3(Fieldstat_tag_list_wrapper *fields[], int tag_list_num) { std::uniform_int_distribution<int> dist(1,100); std::mt19937 rng(); @@ -19,39 +19,39 @@ void fill_random_tag_of_length_1_to_3(Fieldstat_tag_list_wrapper *tags[], int ta { Fieldstat_tag_list_wrapper *tmp = new Fieldstat_tag_list_wrapper(dist, rand() % 3 + 1); tmp->sort_tag_list(); - tags[i] = tmp; + fields[i] = tmp; } } -void fill_with_elephant_flows(Fieldstat_tag_list_wrapper *tags[], int tag_list_num) +void fill_with_elephant_flows(Fieldstat_tag_list_wrapper *fields[], int tag_list_num) { for (int i = 0; i < tag_list_num; i++) { Fieldstat_tag_list_wrapper *tmp; - int rand_ret = rand() % 3; - if (rand_ret == 0) { - tmp = new Fieldstat_tag_list_wrapper("mouse", rand() % 1000); - } else if (rand_ret == 1) { - tmp = new Fieldstat_tag_list_wrapper("elephant", rand() % 200); - } else { + int rand_ret = rand() % 10; + if (rand_ret < 5) { tmp = new Fieldstat_tag_list_wrapper("elephant", rand() % 50); // most hit + } else if (rand_ret == 6 || rand_ret == 7) { + tmp = new Fieldstat_tag_list_wrapper("mid", rand() % 200); + } else { + tmp = new Fieldstat_tag_list_wrapper("mouse", rand() % 10000); } - tags[i] = tmp; + fields[i] = tmp; } } -long long fuzz_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag_list *tag_list) +long long fuzz_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct field_list *tag_list) { long long value = 0; - int ret = fieldstat_counter_get(instance, cube_id, metric_id, tag_list, &value); + int ret = fieldstat_counter_get(instance, cube_id, tag_list, metric_id, &value); EXPECT_EQ(ret, 0); return value; } -double fuzz_fieldstat_hll_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag_list *tag_list) +double fuzz_fieldstat_hll_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct field_list *tag_list) { double value = 0; - int ret = fieldstat_hll_get(instance, cube_id, metric_id, tag_list, &value); + int ret = fieldstat_hll_get(instance, cube_id, tag_list, metric_id, &value); EXPECT_EQ(ret, 0); return value; } @@ -77,13 +77,15 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ // init cube for (int i = 0; i < CUBE_NUM; i++) { shared_tags[i] = new Fieldstat_tag_list_wrapper("shared_tag", i); - int cube_id = fieldstat_create_cube(master, shared_tags[i]->get_tag(), shared_tags[i]->get_tag_count(), SAMPLING_MODE_COMPREHENSIVE, CELL_MAX); + int cube_id = fieldstat_cube_create(master, shared_tags[i]->get_tag(), shared_tags[i]->get_tag_count()); EXPECT_EQ(cube_id, i); + + fieldstat_register_counter(master, cube_id, metric_name[METRIC_ID_COUNTER]); + fieldstat_register_hll(master, cube_id, metric_name[METRIC_ID_HLL], 6); + fieldstat_cube_set_sampling(master, cube_id, SAMPLING_MODE_COMPREHENSIVE, CELL_MAX, 0); } - // init metric - fieldstat_register_counter(master, metric_name[METRIC_ID_COUNTER]); - fieldstat_register_hll(master, metric_name[METRIC_ID_HLL], 6); - // all the possible tags + + // all the possible fields Fieldstat_tag_list_wrapper *tag_list_wrapper[FLOW_NUM]; fill_random_tag_of_length_1_to_3(tag_list_wrapper, FLOW_NUM); //all the possible operations @@ -119,8 +121,12 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ Fieldstat_tag_list_wrapper *new_tag = new Fieldstat_tag_list_wrapper("shared_tag", next_shared_tag_value++); delete shared_tags[cube_id_to_change]; shared_tags[cube_id_to_change] = new_tag; - fieldstat_destroy_cube(master, cube_id_to_change); - int cube_id_new = fieldstat_create_cube(master, new_tag->get_tag(), new_tag->get_tag_count(), SAMPLING_MODE_COMPREHENSIVE, CELL_MAX); + fieldstat_cube_destroy(master, cube_id_to_change); + int cube_id_new = fieldstat_cube_create(master, new_tag->get_tag(), new_tag->get_tag_count()); + fieldstat_register_counter(master, cube_id_new, metric_name[METRIC_ID_COUNTER]); + fieldstat_register_hll(master, cube_id_new, metric_name[METRIC_ID_HLL], 6); + fieldstat_cube_set_sampling(master, cube_id_new, SAMPLING_MODE_COMPREHENSIVE, CELL_MAX, 0); + EXPECT_EQ(cube_id_new, cube_id_to_change); // should new the cube in the hole leaved by the destroyed cube // calibrate for (int j = 0; j < INSTANCE_NUM; j++) { @@ -133,19 +139,19 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ } } struct fieldstat *instance = replica[rand() % INSTANCE_NUM]; // the flow randomly goes to one of the instance - const Fieldstat_tag_list_wrapper * tag = tag_list_wrapper[rand() % FLOW_NUM]; + const Fieldstat_tag_list_wrapper * field = tag_list_wrapper[rand() % FLOW_NUM]; int cube_id = rand() % CUBE_NUM; const Fieldstat_tag_list_wrapper *shared_tag = shared_tags[cube_id]; - int ret_add = fieldstat_counter_incrby(instance, cube_id, METRIC_ID_COUNTER, tag->get_tag(), tag->get_tag_count(), rand_nums[i]); + int ret_add = fieldstat_counter_incrby(instance, cube_id, METRIC_ID_COUNTER, field->get_tag(), field->get_tag_count(), rand_nums[i]); if (ret_add == FS_ERR_TOO_MANY_CELLS) { continue; } EXPECT_EQ(ret_add, FS_OK); string *val = rand_strs[i]; - ret_add = fieldstat_hll_add(instance, cube_id, METRIC_ID_HLL, tag->get_tag(), tag->get_tag_count(), val->c_str(), val->size()); + ret_add = fieldstat_hll_add(instance, cube_id, METRIC_ID_HLL, field->get_tag(), field->get_tag_count(), val->c_str(), val->size()); EXPECT_EQ(ret_add, FS_OK); - string cell_key = shared_tag->to_string() + tag->to_string(); + string cell_key = shared_tag->to_string() + field->to_string(); comp_count[cell_key] += rand_nums[i]; comp_hll[cell_key].insert(*val); } @@ -163,23 +169,22 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ delete shared_tags[i]; } + long long dummy_ll; + double dummy_d; int *cube_ids; int cube_num; struct fieldstat *instance_in_focus = dest; fieldstat_get_cubes(instance_in_focus, &cube_ids, &cube_num); for (int i = 0; i < cube_num; i++) { - struct fieldstat_tag_list *shared_tag_out = fieldstat_get_shared_tags(instance_in_focus, cube_ids[i]); + struct field_list *shared_tag_out = fieldstat_cube_get_dimensions(instance_in_focus, cube_ids[i]); size_t cell_num0; - struct fieldstat_tag_list *tags0; - fieldstat_get_cells_used_by_metric(instance_in_focus, cube_ids[i], METRIC_ID_COUNTER, &tags0, &cell_num0); - size_t cell_num1; - struct fieldstat_tag_list *tags1; - fieldstat_get_cells_used_by_metric(instance_in_focus, cube_ids[i], METRIC_ID_HLL, &tags1, &cell_num1); + struct field_list *tags0; + fieldstat_cube_get_cells(instance_in_focus, cube_ids[i], &tags0, &cell_num0); - EXPECT_EQ(cell_num0, cell_num1); for (size_t j = 0; j < cell_num0; j++) { - EXPECT_TRUE(Fieldstat_tag_list_wrapper(&tags0[j]) == Fieldstat_tag_list_wrapper(&tags1[j])); + EXPECT_EQ(fieldstat_counter_get(instance_in_focus, cube_ids[i], &tags0[j], METRIC_ID_COUNTER, &dummy_ll), FS_OK); + EXPECT_EQ(fieldstat_hll_get(instance_in_focus, cube_ids[i], &tags0[j], METRIC_ID_HLL, &dummy_d), FS_OK); } for (size_t j = 0; j < cell_num0; j++) { @@ -189,9 +194,8 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ EXPECT_EQ(comp_count[cell_key], fuzz_fieldstat_counter_get(instance_in_focus, cube_ids[i], 0, &tags0[j])); } - fieldstat_tag_list_arr_free(tags0, cell_num0); - fieldstat_tag_list_arr_free(tags1, cell_num1); - fieldstat_tag_list_arr_free(shared_tag_out, 1); + fieldstat_field_list_arr_free(tags0, cell_num0); + fieldstat_field_list_arr_free(shared_tag_out, 1); } free(cube_ids); @@ -219,12 +223,13 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ // init cube for (int i = 0; i < CUBE_NUM; i++) { shared_tags[i] = new Fieldstat_tag_list_wrapper("shared_tag", i); - int cube_id = fieldstat_create_cube(master, shared_tags[i]->get_tag(), shared_tags[i]->get_tag_count(), SAMPLING_MODE_TOPK, CELL_MAX); + int cube_id = fieldstat_cube_create(master, shared_tags[i]->get_tag(), shared_tags[i]->get_tag_count()); EXPECT_EQ(cube_id, i); + fieldstat_register_counter(master, cube_id, "topk"); + fieldstat_cube_set_sampling(master, cube_id, SAMPLING_MODE_TOPK, CELL_MAX, 0); } - // init metric - fieldstat_register_counter(master, "topk"); - // all the possible tags + + // all the possible fields Fieldstat_tag_list_wrapper *tag_list_wrapper[FLOW_NUM]; fill_with_elephant_flows(tag_list_wrapper, FLOW_NUM); //all the possible operations @@ -237,7 +242,7 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ replica[i] = fieldstat_fork(master); } // for benchmark - unordered_map<string, unordered_map<string, int>> count_map; // hte first key is shared tag, second key is tag + unordered_map<string, unordered_map<string, int>> count_map; // hte first key is shared field, second key is field clock_t start = clock(); int next_shared_tag_value = CUBE_NUM; @@ -257,8 +262,11 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ Fieldstat_tag_list_wrapper *new_tag = new Fieldstat_tag_list_wrapper("shared_tag", next_shared_tag_value++); delete shared_tags[cube_id_to_change]; shared_tags[cube_id_to_change] = new_tag; - fieldstat_destroy_cube(master, cube_id_to_change); - int cube_id_new = fieldstat_create_cube(master, new_tag->get_tag(), new_tag->get_tag_count(), SAMPLING_MODE_TOPK, CELL_MAX); + fieldstat_cube_destroy(master, cube_id_to_change); + int cube_id_new = fieldstat_cube_create(master, new_tag->get_tag(), new_tag->get_tag_count()); + fieldstat_register_counter(master, cube_id_new, "topk"); + fieldstat_cube_set_sampling(master, cube_id_new, SAMPLING_MODE_TOPK, CELL_MAX, 0); + EXPECT_EQ(cube_id_new, cube_id_to_change); // should new the cube in the hole leaved by the destroyed cube // calibrate for (int j = 0; j < INSTANCE_NUM; j++) { @@ -271,16 +279,16 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ } } struct fieldstat *instance = replica[rand() % INSTANCE_NUM]; // the flow randomly goes to one of the instance - const Fieldstat_tag_list_wrapper * tag = tag_list_wrapper[rand() % FLOW_NUM]; + const Fieldstat_tag_list_wrapper * field = tag_list_wrapper[rand() % FLOW_NUM]; int cube_id = rand() % CUBE_NUM; const Fieldstat_tag_list_wrapper *shared_tag = shared_tags[cube_id]; - int ret_add = fieldstat_counter_incrby(instance, cube_id, 0, tag->get_tag(), tag->get_tag_count(), rand_nums[i]); + int ret_add = fieldstat_counter_incrby(instance, cube_id, 0, field->get_tag(), field->get_tag_count(), rand_nums[i]); if (ret_add == FS_ERR_TOO_MANY_CELLS) { continue; } EXPECT_EQ(ret_add, FS_OK); - count_map[shared_tag->to_string()][tag->to_string()] += rand_nums[i]; + count_map[shared_tag->to_string()][field->to_string()] += rand_nums[i]; } clock_t end = clock(); @@ -298,25 +306,41 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ struct fieldstat *instance_in_focus = dest; fieldstat_get_cubes(instance_in_focus, &cube_ids, &cube_num); for (int i = 0; i < cube_num; i++) { - struct fieldstat_tag_list *shared_tag_out = fieldstat_get_shared_tags(instance_in_focus, cube_ids[i]); + struct field_list *shared_tag_out = fieldstat_cube_get_dimensions(instance_in_focus, cube_ids[i]); size_t cell_num; - struct fieldstat_tag_list *tags; - fieldstat_get_cells_used_by_metric(instance_in_focus, cube_ids[i], 0, &tags, &cell_num); + struct field_list *fields; + fieldstat_cube_get_cells(instance_in_focus, cube_ids[i], &fields, &cell_num); std::vector<struct Fieldstat_tag_list_wrapper *> test_result; for (size_t j = 0; j < cell_num; j++) { - test_result.push_back(new Fieldstat_tag_list_wrapper(&tags[j])); + test_result.push_back(new Fieldstat_tag_list_wrapper(&fields[j])); } - EXPECT_GE(test_cal_topk_accuracy(test_result, count_map[Fieldstat_tag_list_wrapper(shared_tag_out).to_string()]), 0.9); + double accuracy = test_cal_topk_accuracy(test_result, count_map[Fieldstat_tag_list_wrapper(shared_tag_out).to_string()]); + EXPECT_GE(accuracy, 0.95); + // printf("topk accuracy: %lf\n", accuracy); + + // mre + double mre = 0; + for (size_t j = 0; j < cell_num; j++) { + Fieldstat_tag_list_wrapper cell_dimension = Fieldstat_tag_list_wrapper(&fields[j]); + long long value_true = count_map[Fieldstat_tag_list_wrapper(shared_tag_out).to_string()][cell_dimension.to_string()]; + long long value_est; + fieldstat_counter_get(instance_in_focus, cube_ids[i], &fields[j], 0, &value_est); + + mre += (double)(abs(value_true - value_est)) / (double)value_true; + } + mre = mre / cell_num; + // printf("topk_add_and_test_accuracy Mean ratio e: %f\n", mre); + EXPECT_LE(mre, 0.25); for (size_t j = 0; j < cell_num; j++) { delete test_result[j]; } - fieldstat_tag_list_arr_free(tags, cell_num); - fieldstat_tag_list_arr_free(shared_tag_out, 1); + fieldstat_field_list_arr_free(fields, cell_num); + fieldstat_field_list_arr_free(shared_tag_out, 1); } free(cube_ids); @@ -327,6 +351,154 @@ TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_ } } +TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_spreadsketch) +{ + const int CUBE_NUM = 5; + const int INSTANCE_NUM = 10; + const int CELL_MAX = 10; + const int TEST_ROUND = 100000; + const int OUT_GAP = 10000; + struct fieldstat *master = fieldstat_new(); + struct fieldstat *replica[INSTANCE_NUM]; + struct fieldstat *dest = fieldstat_new(); + + Fieldstat_tag_list_wrapper *shared_tags[CUBE_NUM]; + + // init cube + for (int i = 0; i < CUBE_NUM; i++) { + shared_tags[i] = new Fieldstat_tag_list_wrapper("shared_tag", i); + int cube_id = fieldstat_cube_create(master, shared_tags[i]->get_tag(), shared_tags[i]->get_tag_count()); + EXPECT_EQ(cube_id, i); + fieldstat_register_hll(master, cube_id, "hll", 6); + fieldstat_cube_set_sampling(master, cube_id, SAMPLING_MODE_TOP_CARDINALITY, CELL_MAX, 0); + } + + //init instance + for (int i = 0; i < INSTANCE_NUM; i++) { + replica[i] = fieldstat_fork(master); + } + + SpreadSketchZipfGenerator generator(1.0, CELL_MAX * 10); + unordered_map<string, unordered_map<string, int>> count_map; // the first key is cube dimension, second key is cell dimension. value is the fanout(hll return value) + + clock_t start = clock(); + int next_shared_tag_value = CUBE_NUM; + + for (int i = 0; i < TEST_ROUND; i++) { + if (i != 0 && i % OUT_GAP == 0) { + // merge + for (int j = 0; j < INSTANCE_NUM; j++) { + fieldstat_merge(dest, replica[j]); + } + for (int j = 0; j < INSTANCE_NUM; j++) { + fieldstat_reset(replica[j]); + } + + // modify master and calibrate + int cube_id_to_change = rand() % CUBE_NUM; + Fieldstat_tag_list_wrapper *new_tag = new Fieldstat_tag_list_wrapper("shared_tag", next_shared_tag_value++); + delete shared_tags[cube_id_to_change]; + shared_tags[cube_id_to_change] = new_tag; + fieldstat_cube_destroy(master, cube_id_to_change); + int cube_id_new = fieldstat_cube_create(master, new_tag->get_tag(), new_tag->get_tag_count()); + fieldstat_register_hll(master, cube_id_new, "hll", 6); + EXPECT_EQ(cube_id_new, cube_id_to_change); // should new the cube in the hole leaved by the destroyed cube + fieldstat_cube_set_sampling(master, cube_id_new, SAMPLING_MODE_TOP_CARDINALITY, CELL_MAX, 0); + + // calibrate + for (int j = 0; j < INSTANCE_NUM; j++) { + fieldstat_calibrate(master, replica[j]); + } + + // let merge happens last(no add operation is missed) + if (i + OUT_GAP >= TEST_ROUND) { + break; + } + } + + // add + Flow flow = generator.next(); + + struct fieldstat *instance = replica[rand() % INSTANCE_NUM]; + const Fieldstat_tag_list_wrapper cell_dimension("src_ip", flow.src_ip.c_str()); + const Fieldstat_tag_list_wrapper item("dst_ip", flow.dst_ip.c_str()); + int cube_id = rand() % CUBE_NUM; + const Fieldstat_tag_list_wrapper *shared_tag = shared_tags[cube_id]; + + int ret_add = fieldstat_hll_add_field(instance, cube_id, 0, cell_dimension.get_tag(), cell_dimension.get_tag_count(), item.get_tag(), item.get_tag_count()); + if (ret_add == FS_ERR_TOO_MANY_CELLS) { + continue; + } + EXPECT_EQ(ret_add, FS_OK); + count_map[shared_tag->to_string()][cell_dimension.to_string()] += 1; + } + + clock_t end = clock(); + printf("time: %lf\n", (double)(end - start) / CLOCKS_PER_SEC); + + for (int i = 0; i < CUBE_NUM; i++) { + delete shared_tags[i]; + } + + int *cube_ids; + int cube_num; + struct fieldstat *instance_in_focus = dest; + fieldstat_get_cubes(instance_in_focus, &cube_ids, &cube_num); + double sum_accuracy = 0; + for (int i = 0; i < cube_num; i++) { + struct field_list *shared_tag_out = fieldstat_cube_get_dimensions(instance_in_focus, cube_ids[i]); + + size_t cell_num; + struct field_list *cells; + fieldstat_cube_get_cells(instance_in_focus, cube_ids[i], &cells, &cell_num); + + std::vector<struct Fieldstat_tag_list_wrapper *> test_result; + for (size_t j = 0; j < cell_num; j++) { + test_result.push_back(new Fieldstat_tag_list_wrapper(&cells[j])); + } + + Fieldstat_tag_list_wrapper cube_dimension = Fieldstat_tag_list_wrapper(shared_tag_out); + double accuracy = test_cal_topk_accuracy(test_result, count_map[cube_dimension.to_string()]); + // printf("spreadsketch accuracy: %lf\n", accuracy); + sum_accuracy += accuracy; + + // CM sketch error + double est_total = 0; + double true_total = 0; + for (size_t j = 0; j < cell_num; j++) { + Fieldstat_tag_list_wrapper cell_dimension = Fieldstat_tag_list_wrapper(&cells[j]); + double value_true = count_map[cube_dimension.to_string()][cell_dimension.to_string()]; + double value_est = 0; + fieldstat_hll_get(instance_in_focus, cube_ids[i], &cells[j], 0, &value_est); + // printf("cube:%s, cell:%s, true:%lf, est:%lf\n", cube_dimension.to_string().c_str(), cell_dimension.to_string().c_str(), value_true, value_est); + + est_total += value_est; + true_total += value_true; + } + EXPECT_LE(abs(est_total - true_total) / true_total, 0.2); + // printf("spreadsketch Mean ratio e: %f\n", abs(est_total - true_total) / true_total); + + for (size_t j = 0; j < cell_num; j++) { + delete test_result[j]; + } + + fieldstat_field_list_arr_free(cells, cell_num); + fieldstat_field_list_arr_free(shared_tag_out, 1); + } + double mean_accuracy = sum_accuracy / cube_num; + EXPECT_GE(mean_accuracy, 0.7); + + free(cube_ids); + + fieldstat_free(master); + fieldstat_free(dest); + for (int i = 0; i < INSTANCE_NUM; i++) { + fieldstat_free(replica[i]); + } +} + +// issue: https://jira.geedge.net/browse/TSG-21192 +// 在reset后,所有项都是dying 状态,此时添加count = 0 的项,不能正常把dying pop掉,误以为sorted set 已满,出现添加失败(FS_ERR_TOO_MANY_CELLS)但是查不到任何cell 的情况。 TEST(Fuzz_test, add_and_reset_with_randomly_generated_flows_and_randomly_chosen_metric) { const int FLOW_NUM = 50000; @@ -335,40 +507,48 @@ TEST(Fuzz_test, add_and_reset_with_randomly_generated_flows_and_randomly_chosen_ fill_with_elephant_flows(tag_list_wrapper, FLOW_NUM); struct fieldstat *instance = fieldstat_new(); - int primary_metric_id = fieldstat_register_counter(instance, "counter"); - int counter2_id = fieldstat_register_counter(instance, "counter2"); - int cube_id = fieldstat_create_cube(instance,NULL,0,SAMPLING_MODE_TOPK, 1); // K = 1, just to increase the possibility of FS_ERR_TOO_MANY_CELLS + + int cube_id = fieldstat_cube_create(instance,NULL,0); + int primary_metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + int counter2_id = fieldstat_register_counter(instance, cube_id, "counter2"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 1, 0); // K = 1, just to increase the possibility of FS_ERR_TOO_MANY_CELLS + fieldstat_counter_incrby(instance, cube_id, primary_metric_id, tag_list_wrapper[0]->get_tag(), tag_list_wrapper[0]->get_tag_count(), 1); fieldstat_counter_incrby(instance, cube_id, counter2_id, tag_list_wrapper[0]->get_tag(), tag_list_wrapper[0]->get_tag_count(), 1); - struct fieldstat_tag_list tag_list_tmp = {NULL, 0}; + struct field_list tag_list_tmp = {NULL, 0}; for(int i = 0; i < FLOW_NUM; i++) { int using_id = rand() % 2 == 0 ? primary_metric_id : counter2_id; int ret = fieldstat_counter_incrby(instance, cube_id, using_id, tag_list_wrapper[i]->get_tag(), tag_list_wrapper[i]->get_tag_count(), 1); if (ret == FS_ERR_TOO_MANY_CELLS) { - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_cube(instance, cube_id, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); ASSERT_EQ(n_cell, 1); long long value; - tag_list_tmp.tag = (struct fieldstat_tag *)tag_list_wrapper[i]->get_tag(); - tag_list_tmp.n_tag = tag_list_wrapper[i]->get_tag_count(); - int counter_exist = fieldstat_counter_get(instance, cube_id, using_id, &tag_list_tmp, &value); - ASSERT_EQ(counter_exist, FS_ERR_INVALID_TAG); // the tag is not added to the cube - fieldstat_tag_list_arr_free(tag_list, n_cell); + tag_list_tmp.field = (struct field *)tag_list_wrapper[i]->get_tag(); + tag_list_tmp.n_field = tag_list_wrapper[i]->get_tag_count(); + int counter_exist = fieldstat_counter_get(instance, cube_id, &tag_list_tmp, using_id, &value); + ASSERT_EQ(counter_exist, FS_ERR_INVALID_DIMENSION); // the field is not added to the cube + fieldstat_field_list_arr_free(tag_list, n_cell); } if (i % 1000 == 0) { fieldstat_reset(instance); } } + + for (int i = 0; i < FLOW_NUM; i++) { + delete tag_list_wrapper[i]; + } + fieldstat_free(instance); } -TEST(Fuzz_test, simple_one_for_perf) +TEST(perf, simple_one_for_perf_topk) { const int CUBE_NUM = 5; const int FLOW_NUM = 50000; @@ -381,12 +561,14 @@ TEST(Fuzz_test, simple_one_for_perf) // init cube for (int i = 0; i < CUBE_NUM; i++) { shared_tags[i] = new Fieldstat_tag_list_wrapper("shared_tag", i); - int cube_id = fieldstat_create_cube(master, shared_tags[i]->get_tag(), shared_tags[i]->get_tag_count(), SAMPLING_MODE_TOPK, CELL_MAX); + int cube_id = fieldstat_cube_create(master, shared_tags[i]->get_tag(), shared_tags[i]->get_tag_count()); EXPECT_EQ(cube_id, i); + fieldstat_register_counter(master, cube_id, "topk"); + fieldstat_cube_set_sampling(master, cube_id, SAMPLING_MODE_TOPK, CELL_MAX, 0); } // init metric - fieldstat_register_counter(master, "topk"); - // all the possible tags + + // all the possible fields Fieldstat_tag_list_wrapper *tag_list_wrapper[FLOW_NUM]; fill_with_elephant_flows(tag_list_wrapper, FLOW_NUM); //all the possible operations @@ -398,15 +580,15 @@ TEST(Fuzz_test, simple_one_for_perf) struct fieldstat *instance = master; clock_t start = clock(); - printf("press any key to start\n"); + printf("press any key to start v46\n"); getchar(); for (int i = 0; i < TEST_ROUND; i++) { - const Fieldstat_tag_list_wrapper * tag = tag_list_wrapper[rand() % FLOW_NUM]; + const Fieldstat_tag_list_wrapper * field = tag_list_wrapper[rand() % FLOW_NUM]; int cube_id = rand() % CUBE_NUM; - (void)fieldstat_counter_incrby(instance, cube_id, 0, tag->get_tag(), tag->get_tag_count(), rand_nums[i]); + (void)fieldstat_counter_incrby(instance, cube_id, 0, field->get_tag(), field->get_tag_count(), rand_nums[i]); } clock_t end = clock(); @@ -422,10 +604,44 @@ TEST(Fuzz_test, simple_one_for_perf) fieldstat_free(master); } +TEST(perf, simple_one_for_perf_spreadsketch) +{ + const int CELL_MAX = 100; + const int TEST_ROUND = 500000; + struct fieldstat *instance = fieldstat_new(); + + int cube_id = fieldstat_cube_create(instance, &TEST_FIELD_STRING, 1); + fieldstat_register_hll(instance, cube_id, "hll", 6); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, CELL_MAX, 0); + + SpreadSketchZipfGenerator generator(1.0, CELL_MAX * 10); + Fieldstat_tag_list_wrapper *cell_dimension[TEST_ROUND]; + Fieldstat_tag_list_wrapper *items[TEST_ROUND]; + for (int i = 0; i < TEST_ROUND; i++) { + Flow flow = generator.next(); + cell_dimension[i] = new Fieldstat_tag_list_wrapper("src_ip", flow.src_ip.c_str()); + items[i] = new Fieldstat_tag_list_wrapper("dst_ip", flow.dst_ip.c_str()); + } + + clock_t start = clock(); + printf("press any key to start \n"); + getchar(); + + for (int i = 0; i < TEST_ROUND; i++) { + fieldstat_hll_add_field(instance, cube_id, 0, cell_dimension[i]->get_tag(), cell_dimension[i]->get_tag_count(), items[i]->get_tag(), items[i]->get_tag_count()); + } + + clock_t end = clock(); + printf("time: %lf second\n", (double)(end - start) / CLOCKS_PER_SEC); + + fieldstat_free(instance); +} int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); - testing::GTEST_FLAG(filter) = "-Fuzz_test.simple_one_for_perf"; + // testing::GTEST_FLAG(filter) = "*many_instance_random_flow_unregister_calibrate_reset_fork_merge_spreadsketch"; + testing::GTEST_FLAG(filter) = "-perf.*"; + return RUN_ALL_TESTS(); }
\ No newline at end of file diff --git a/test/test_merge.cpp b/test/test_merge.cpp index a37dff9..46583d1 100644 --- a/test/test_merge.cpp +++ b/test/test_merge.cpp @@ -2,6 +2,7 @@ #include <gtest/gtest.h> #include <set> #include <unordered_map> +#include <unordered_set> #include "fieldstat.h" #include "utils.hpp" @@ -31,64 +32,37 @@ double test_cal_accuracy_given_expected_key(vector<struct Fieldstat_tag_list_wra return test_cal_topk_accuracy(test_result, countMap); } -long long merge_test_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag_list *tag_list = &TEST_TAG_LIST_STRING) +long long merge_test_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct field_list *tag_list = &TEST_FIELD_LIST_STRING) { long long ret = 0; - fieldstat_counter_get(instance, cube_id, metric_id, tag_list, &ret); + fieldstat_counter_get(instance, cube_id, tag_list, metric_id, &ret); return ret; } -TEST(unit_test_merge, test_metric_name_mapping_with_new_metric_on_existing_cube) +double merge_test_fieldstat_hll_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct field_list *tag_list = &TEST_FIELD_LIST_STRING) { - struct fieldstat *instance = fieldstat_new(); - - int cube_id1 = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id_1_0 = fieldstat_register_counter(instance, "metric_name cube1 cube2"); - int metric_id_1_1 = fieldstat_register_counter(instance, "shared name"); - fieldstat_counter_incrby(instance, cube_id1, metric_id_1_0, &TEST_TAG_STRING, 1, 1); - fieldstat_counter_incrby(instance, cube_id1, metric_id_1_1, &TEST_TAG_STRING, 1, 2); - int cube_id2 = fieldstat_create_cube(instance, &TEST_TAG_INT, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_counter_incrby(instance, cube_id2, metric_id_1_0, &TEST_TAG_STRING, 1, 3); - - struct fieldstat *instance_dest = fieldstat_new(); - int cube_id_dest = fieldstat_create_cube(instance_dest, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - (void)fieldstat_register_counter(instance_dest, "shared name"); - // shared name metric is not operated on cube_id_dest - - EXPECT_EQ(fieldstat_merge(instance_dest, instance), FS_OK); - - int *cube_id; - int n_cube; - fieldstat_get_cubes(instance_dest, &cube_id, &n_cube); - EXPECT_TRUE(n_cube == 2); - EXPECT_TRUE(cube_id[0] == cube_id_dest); - - int *metric_ids; - size_t n_metrics; - fieldstat_get_metrics_used_by_cube(instance_dest, cube_id_dest, &metric_ids, &n_metrics); - EXPECT_EQ(n_metrics, 2); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, metric_ids[0]), "shared name"); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, metric_ids[1]), "metric_name cube1 cube2"); - - EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, cube_id_dest, 0), 2); // shared name - EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, cube_id_dest, 1), 1); // metric_name cube1 cube2 on cube1 - EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, cube_id[1], 1), 3); // metric_name cube1 cube2 on cube2 + double ret = 0; + fieldstat_hll_get(instance, cube_id, tag_list, metric_id, &ret); + return ret; +} - fieldstat_free(instance); - fieldstat_free(instance_dest); - free(cube_id); - free(metric_ids); +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *dimensions, size_t n_dimensions, enum sampling_mode mode, int k, int primary_metric_id=0) +{ + assert(mode == SAMPLING_MODE_COMPREHENSIVE); + int ret = fieldstat_cube_create(instance, dimensions, n_dimensions); + fieldstat_cube_set_sampling(instance, ret, mode, k, primary_metric_id); + return ret; } TEST(unit_test_merge, cube_shared_tag_mapping_with_new_cube) { struct fieldstat *instance = fieldstat_new(); - (void)fieldstat_create_cube(instance, &TEST_TAG_DOUBLE, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int cube_id2 = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_counter(instance, "metric in cube 2"); - fieldstat_counter_incrby(instance, cube_id2, metric_id, &TEST_TAG_STRING, 1, 1); + (void)test_fieldstat_cube_create(instance, &TEST_FIELD_DOUBLE, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id2 = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance,cube_id2,"metric in cube 2"); + fieldstat_counter_incrby(instance, cube_id2, metric_id, &TEST_FIELD_STRING, 1, 1); struct fieldstat *instance_dest = fieldstat_new(); - int cube_id_dest = fieldstat_create_cube(instance_dest, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id_dest = test_fieldstat_cube_create(instance_dest, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); fieldstat_merge(instance_dest, instance); @@ -121,8 +95,8 @@ TEST(unit_test_merge, empty_instance) TEST(unit_test_merge, new_cube_and_metric_to_empty_comprehensive) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_counter(instance, "metric_name"); + test_fieldstat_cube_create(instance, &TEST_FIELD_INT, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_counter(instance, 0, "metric_name"); struct fieldstat *instance_dest = fieldstat_new(); @@ -132,7 +106,7 @@ TEST(unit_test_merge, new_cube_and_metric_to_empty_comprehensive) int n_cube; fieldstat_get_cubes(instance_dest, &cube_id_dest, &n_cube); EXPECT_TRUE(n_cube == 1); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0), "metric_name"); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, cube_id_dest[0], 0), "metric_name"); fieldstat_free(instance); fieldstat_free(instance_dest); @@ -142,47 +116,47 @@ TEST(unit_test_merge, new_cube_and_metric_to_empty_comprehensive) TEST(unit_test_merge, new_cell_on_existing_cube_and_metric_comprehensive) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_counter(instance, "metric_name"); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance, 0, "metric_name"); struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 10086); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 10086); fieldstat_merge(instance_dest, instance); int *cube_id_dest; int n_cube; fieldstat_get_cubes(instance_dest, &cube_id_dest, &n_cube); EXPECT_TRUE(n_cube == 1); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, cube_id_dest[0], 0), "metric_name"); free(cube_id_dest); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0), "metric_name"); long long measure = merge_test_fieldstat_counter_get(instance, cube_id, metric_id); EXPECT_EQ(measure, 10086); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance, cube_id, metric_id, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); - EXPECT_EQ(tag_list->n_tag, 1); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_STRING.key); + EXPECT_EQ(tag_list->n_field, 1); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_STRING.key); fieldstat_free(instance); fieldstat_free(instance_dest); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); } TEST(unit_test_merge, merge_existing_cell_on_existing_cube_and_metric_comprehensive) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_counter(instance, "metric_name"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 5); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance, cube_id, "metric_name"); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 5); struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); fieldstat_merge(instance_dest, instance); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0), "metric_name"); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, cube_id, 0), "metric_name"); long long measure = merge_test_fieldstat_counter_get(instance_dest, cube_id, metric_id); EXPECT_EQ(measure, 10); @@ -193,61 +167,61 @@ TEST(unit_test_merge, merge_existing_cell_on_existing_cube_and_metric_comprehens TEST(unit_test_merge, new_too_many_cells_on_one_metric_given_source_cube_reset_and_get_different_cube_comprehensive) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 2); // limit is 2 - int metric_id = fieldstat_register_counter(instance, "metric name"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 1); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 2); // limit is 2 + int metric_id = fieldstat_register_counter(instance, cube_id, "metric name"); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 1); struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); fieldstat_reset(instance); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 2); // 2nd cell - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_DOUBLE, 1, 3); // 3rd cell, exceeding the limit 2 + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 2); // 2nd cell + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, 3); // 3rd cell, exceeding the limit 2 fieldstat_merge(instance_dest, instance); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); EXPECT_EQ(n_cell, 2); EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, 0, 0, &tag_list[0]), 1); EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, 0, 0, &tag_list[1]), 2); fieldstat_free(instance); fieldstat_free(instance_dest); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); } TEST(unit_test_merge, new_too_many_cells_on_multiple_metric_given_source_cube_reset_and_get_different_cube_comprehensive) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 2); - int metric_id1 = fieldstat_register_counter(instance, "metric name1"); - int metric_id2 = fieldstat_register_counter(instance, "metric name2"); - fieldstat_counter_incrby(instance, cube_id, metric_id1, &TEST_TAG_STRING, 1, 1); // 1st cell on metric name1 + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 2); + int metric_id1 = fieldstat_register_counter(instance, cube_id, "metric name1"); + int metric_id2 = fieldstat_register_counter(instance, cube_id, "metric name2"); + fieldstat_counter_incrby(instance, cube_id, metric_id1, &TEST_FIELD_STRING, 1, 1); // 1st cell on metric name1 struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); fieldstat_reset(instance); - int metric_id3 = fieldstat_register_counter(instance, "metric name3"); - fieldstat_counter_incrby(instance, cube_id, metric_id3, &TEST_TAG_INT, 1, 2); // 2nd cell on metric name3, this is a metric dest dont have - fieldstat_counter_incrby(instance, cube_id, metric_id2, &TEST_TAG_DOUBLE, 1, 3); // 3nd cell on metric name2 + int metric_id3 = fieldstat_register_counter(instance, cube_id, "metric name3"); + fieldstat_counter_incrby(instance, cube_id, metric_id3, &TEST_FIELD_INT, 1, 2); // 2nd cell on metric name3, this is a metric dest dont have + fieldstat_counter_incrby(instance, cube_id, metric_id2, &TEST_FIELD_DOUBLE, 1, 3); // 3nd cell on metric name2 fieldstat_merge(instance_dest, instance); - struct fieldstat_tag_list *tag_list = NULL; - size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, 0, metric_id1, &tag_list, &n_cell); - EXPECT_EQ(n_cell, 1); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_STRING.key); - fieldstat_tag_list_arr_free(tag_list, n_cell); - - fieldstat_get_cells_used_by_metric(instance_dest, 0, metric_id2, &tag_list, &n_cell); // 3nd cell failed to merge - EXPECT_EQ(n_cell, 0); + int *metric_ids = NULL; + size_t n_metrics = 0; + fieldstat_get_metric_in_cell(instance_dest, 0, &TEST_FIELD_LIST_STRING, &metric_ids, &n_metrics); + EXPECT_EQ(n_metrics, 1); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0, metric_ids[0]), "metric name1"); + free(metric_ids); - fieldstat_get_cells_used_by_metric(instance_dest, 0, metric_id3, &tag_list, &n_cell); - EXPECT_EQ(n_cell, 1); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_INT.key); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_get_metric_in_cell(instance_dest, 0, &TEST_FIELD_LIST_INT, &metric_ids, &n_metrics); + EXPECT_EQ(n_metrics, 1); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0, metric_ids[0]), "metric name3"); + free(metric_ids); + // 3nd cell failed to merge, because max sampling is 2 + fieldstat_get_metric_in_cell(instance_dest, 0, &TEST_FIELD_LIST_DOUBLE, &metric_ids, &n_metrics); + EXPECT_EQ(n_metrics, 0); fieldstat_free(instance); fieldstat_free(instance_dest); @@ -256,8 +230,9 @@ TEST(unit_test_merge, new_too_many_cells_on_multiple_metric_given_source_cube_re TEST(unit_test_merge, new_cube_and_metric_to_empty_topk) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT, 1, SAMPLING_MODE_TOPK, 10); - fieldstat_register_counter(instance, "metric_name"); + fieldstat_cube_create(instance, &TEST_FIELD_INT, 1); + fieldstat_register_counter(instance, 0, "metric_name"); + fieldstat_cube_set_sampling(instance, 0, SAMPLING_MODE_TOPK, 10, 0); struct fieldstat *instance_dest = fieldstat_new(); @@ -267,7 +242,7 @@ TEST(unit_test_merge, new_cube_and_metric_to_empty_topk) int n_cube; fieldstat_get_cubes(instance_dest, &cube_id_dest, &n_cube); EXPECT_TRUE(n_cube == 1); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0), "metric_name"); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, cube_id_dest[0], 0), "metric_name"); fieldstat_free(instance); fieldstat_free(instance_dest); @@ -277,41 +252,43 @@ TEST(unit_test_merge, new_cube_and_metric_to_empty_topk) TEST(unit_test_merge, new_cell_on_existing_cube_and_metric_topk) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - int metric_id = fieldstat_register_counter(instance, "metric_name"); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "metric_name"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, 0); struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 10086); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 10086); fieldstat_merge(instance_dest, instance); int *cube_id_dest; int n_cube; fieldstat_get_cubes(instance_dest, &cube_id_dest, &n_cube); EXPECT_TRUE(n_cube == 1); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest,cube_id_dest[0], 0), "metric_name"); free(cube_id_dest); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0), "metric_name"); long long measure = merge_test_fieldstat_counter_get(instance, cube_id, metric_id); EXPECT_EQ(measure, 10086); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance, cube_id, metric_id, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); - EXPECT_EQ(tag_list->n_tag, 1); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_STRING.key); + EXPECT_EQ(tag_list->n_field, 1); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_STRING.key); fieldstat_free(instance); fieldstat_free(instance_dest); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); } TEST(unit_test_merge, merge_existing_cell_on_existing_cube_and_metric_topk) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - int metric_id = fieldstat_register_counter(instance, "metric_name"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 5); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "metric_name"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, 0); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 5); struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); @@ -322,17 +299,17 @@ TEST(unit_test_merge, merge_existing_cell_on_existing_cube_and_metric_topk) fieldstat_get_cubes(instance_dest, &cube_id_dest, &n_cube); EXPECT_TRUE(n_cube == 1); int ret_cube_id = cube_id_dest[0]; + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest,cube_id_dest[0], 0), "metric_name"); free(cube_id_dest); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, 0), "metric_name"); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, ret_cube_id, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_dest, ret_cube_id, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); long long measure = merge_test_fieldstat_counter_get(instance_dest, cube_id, metric_id, &tag_list[0]); EXPECT_EQ(measure, 10); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); fieldstat_free(instance); fieldstat_free(instance_dest); } @@ -340,36 +317,38 @@ TEST(unit_test_merge, merge_existing_cell_on_existing_cube_and_metric_topk) TEST(unit_test_merge, new_too_many_cells_on_one_metric_given_source_cube_reset_and_get_different_cube_topk) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 2); - int metric_id = fieldstat_register_counter(instance, "metric name"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 1); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "metric name"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 2, 0); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 1); struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); fieldstat_reset(instance); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 2); // 2nd cell - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_DOUBLE, 1, 3); // 3rd cell,bigger than the others, so keep it + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 2); // 2nd cell + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, 3); // 3rd cell,bigger than the others, so keep it fieldstat_merge(instance_dest, instance); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); EXPECT_EQ(n_cell, 2); EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, 0, 0, &tag_list[0]), 3); EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, 0, 0, &tag_list[1]), 2); fieldstat_free(instance); fieldstat_free(instance_dest); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); } -struct fieldstat *test_push_flows(vector<Fieldstat_tag_list_wrapper *> &flows_in_test, int K, long long count = 1) +struct fieldstat *topk_test_push_flows(vector<Fieldstat_tag_list_wrapper *> &flows_in_test, int K, long long count = 1) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, K); - int metric_id = fieldstat_register_counter(instance, "metric name"); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "metric name"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, K, 0); for (size_t i = 0; i < flows_in_test.size(); i++) { fieldstat_counter_incrby(instance, cube_id, metric_id, flows_in_test[i]->get_tag(), flows_in_test[i]->get_tag_count(), count); } @@ -380,14 +359,14 @@ TEST(unit_test_merge, merge_accuracy_test_with_K_large_enough_topk) { int K = 100; vector<Fieldstat_tag_list_wrapper *> flows_in_src = test_gen_topk_flows(K, K); - struct fieldstat *instance_src = test_push_flows(flows_in_src, K); + struct fieldstat *instance_src = topk_test_push_flows(flows_in_src, K); vector<Fieldstat_tag_list_wrapper *> flows_in_dest = test_gen_topk_flows(K, K); - struct fieldstat *instance_dest = test_push_flows(flows_in_dest, K); + struct fieldstat *instance_dest = topk_test_push_flows(flows_in_dest, K); fieldstat_merge(instance_dest, instance_src); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); vector<Fieldstat_tag_list_wrapper *> flows_in_merged; for (size_t i = 0; i < n_cell; i++) { @@ -400,7 +379,7 @@ TEST(unit_test_merge, merge_accuracy_test_with_K_large_enough_topk) fieldstat_free(instance_src); fieldstat_free(instance_dest); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); for (size_t i = 0; i < flows_in_merged.size(); i++) { delete flows_in_merged[i]; } @@ -409,23 +388,23 @@ TEST(unit_test_merge, merge_accuracy_test_with_K_large_enough_topk) } } -TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_all_inserted_given_src_flows_larger) +TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_all_inserted_given_src_flows_larger_topk) { int K = 1000; vector<Fieldstat_tag_list_wrapper *> flows_in_src = test_gen_topk_flows(10000, K); - struct fieldstat *instance_src = test_push_flows(flows_in_src, K, 1000); // 1000 times larger than dest 1 + struct fieldstat *instance_src = topk_test_push_flows(flows_in_src, K, 1000); // 1000 times larger than dest 1 vector<Fieldstat_tag_list_wrapper *> flows_in_dest; for (int i = 0; i < K; i++) { Fieldstat_tag_list_wrapper *tmp = new Fieldstat_tag_list_wrapper("flows in dest", to_string(i).c_str()); flows_in_dest.push_back(tmp); } - struct fieldstat *instance_dest = test_push_flows(flows_in_dest, K, 1); + struct fieldstat *instance_dest = topk_test_push_flows(flows_in_dest, K, 1); fieldstat_merge(instance_dest, instance_src); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); vector<Fieldstat_tag_list_wrapper *> flows_in_merged; for (size_t i = 0; i < n_cell; i++) { flows_in_merged.push_back(new Fieldstat_tag_list_wrapper(&tag_list[i])); @@ -438,7 +417,7 @@ TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_all_inserted_given_src_f fieldstat_free(instance_src); fieldstat_free(instance_dest); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); for (size_t i = 0; i < flows_in_merged.size(); i++) { delete flows_in_merged[i]; } @@ -447,18 +426,18 @@ TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_all_inserted_given_src_f } } -TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_some_inserted_and_some_merged_and_some_fail_to_add) +TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_some_inserted_and_some_merged_and_some_fail_to_add_topk) { int K = 100; - vector<Fieldstat_tag_list_wrapper *> flows_in_src = test_gen_topk_flows(10000, K + 50); // let elephant flows in src and dest different - struct fieldstat *instance_src = test_push_flows(flows_in_src, K); - vector<Fieldstat_tag_list_wrapper *> flows_in_dest = test_gen_topk_flows(10000, K + 50); - struct fieldstat *instance_dest = test_push_flows(flows_in_dest, K); + vector<Fieldstat_tag_list_wrapper *> flows_in_src = test_gen_topk_flows(30000, K + 50); // let elephant flows in src and dest different + struct fieldstat *instance_src = topk_test_push_flows(flows_in_src, K); + vector<Fieldstat_tag_list_wrapper *> flows_in_dest = test_gen_topk_flows(30000, K + 50); + struct fieldstat *instance_dest = topk_test_push_flows(flows_in_dest, K); fieldstat_merge(instance_dest, instance_src); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); vector<Fieldstat_tag_list_wrapper *> flows_in_merged; for (size_t i = 0; i < n_cell; i++) { flows_in_merged.push_back(new Fieldstat_tag_list_wrapper(&tag_list[i])); @@ -466,12 +445,12 @@ TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_some_inserted_and_some_m flows_in_dest.insert(flows_in_dest.end(), std::make_move_iterator(flows_in_src.begin()), std::make_move_iterator(flows_in_src.end())); double accuracy = test_cal_accuracy_given_expected_key(flows_in_dest, flows_in_merged); - EXPECT_GE(accuracy, 0.87); // by heavy keeper benchmark, with K = 100, merging result should be about 0.96, for adding the flows will also cause some inaccuracy, so here we set 0.93 + EXPECT_GE(accuracy, 0.87); printf("merge_accuracy_test_gen_dest_full_some_inserted_and_some_merged_and_some_fail_to_add accuracy is %lf\n", accuracy); fieldstat_free(instance_src); fieldstat_free(instance_dest); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); for (size_t i = 0; i < flows_in_merged.size(); i++) { delete flows_in_merged[i]; } @@ -483,23 +462,24 @@ TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_some_inserted_and_some_m TEST(unit_test_merge, primary_metric_has_no_value) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 2); - int metric_primary = fieldstat_register_counter(instance, "primary"); - int metric_operated = fieldstat_register_counter(instance, "operated"); - fieldstat_counter_incrby(instance, cube_id, metric_operated, &TEST_TAG_STRING, 1, 1); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_primary = fieldstat_register_counter(instance, cube_id, "primary"); + int metric_operated = fieldstat_register_counter(instance, cube_id, "operated"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 2, metric_primary); + fieldstat_counter_incrby(instance, cube_id, metric_operated, &TEST_FIELD_STRING, 1, 1); struct fieldstat *instance_dest = fieldstat_new(); fieldstat_merge(instance_dest, instance); fieldstat_merge(instance_dest, instance); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dest, 0, metric_primary, &tag_list, &n_cell); - EXPECT_EQ(n_cell, 0); - - fieldstat_get_cells_used_by_metric(instance_dest, 0, metric_operated, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); + EXPECT_STREQ(tag_list[0].field[0].key, TEST_FIELD_STRING.key); + EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, 0, metric_operated, &tag_list[0]), 2); - fieldstat_tag_list_arr_free(tag_list, n_cell); + EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dest, 0, metric_primary, &tag_list[0]), 0); + fieldstat_field_list_arr_free(tag_list, n_cell); fieldstat_free(instance); fieldstat_free(instance_dest); @@ -508,42 +488,254 @@ TEST(unit_test_merge, primary_metric_has_no_value) TEST(unit_test_merge, primary_metric_id_different) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 2); - int metric_primary = fieldstat_register_counter(instance, "primary"); - int metric_2 = fieldstat_register_counter(instance, "2"); - fieldstat_counter_incrby(instance, cube_id, metric_primary, &TEST_TAG_STRING, 1, 100); - fieldstat_counter_incrby(instance, cube_id, metric_2, &TEST_TAG_STRING, 1, 1); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_primary = fieldstat_register_counter(instance, cube_id, "primary"); + int metric_2 = fieldstat_register_counter(instance, cube_id, "2"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 2, metric_primary); + + fieldstat_counter_incrby(instance, cube_id, metric_primary, &TEST_FIELD_STRING, 1, 100); + fieldstat_counter_incrby(instance, cube_id, metric_2, &TEST_FIELD_STRING, 1, 1); struct fieldstat *instance_dst = fieldstat_new(); - int cube_id_dst = fieldstat_create_cube(instance_dst, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 2); - fieldstat_register_counter(instance_dst, "2"); - int metric_primary_dst = fieldstat_register_counter(instance_dst, "primary"); - fieldstat_cube_set_primary_metric(instance_dst, cube_id_dst, metric_primary_dst); + int cube_id_dst = fieldstat_cube_create(instance_dst, &TEST_SHARED_TAG, 1); + fieldstat_register_counter(instance_dst, cube_id_dst, "2"); + int metric_primary_dst = fieldstat_register_counter(instance_dst, cube_id_dst, "primary"); + fieldstat_cube_set_sampling(instance_dst, cube_id_dst, SAMPLING_MODE_TOPK, 2, metric_primary_dst); + + EXPECT_EQ(fieldstat_merge(instance_dst, instance), FS_ERR_DIFFERENT_CONFIGURATION_FOR_SAME_CUBE); + + fieldstat_free(instance); + fieldstat_free(instance_dst); +} + +TEST(unit_test_merge, new_cube_and_metric_to_empty_spreadsketch) { + struct fieldstat *instance = fieldstat_new(); + fieldstat_cube_create(instance, &TEST_FIELD_INT, 1); + fieldstat_register_hll(instance, 0, "metric", 6); + fieldstat_cube_set_sampling(instance, 0, SAMPLING_MODE_TOP_CARDINALITY, 10, 0); + + struct fieldstat *instance_dest = fieldstat_new(); + fieldstat_merge(instance_dest, instance); + + int *cube_id_dest; + int n_cube; + fieldstat_get_cubes(instance_dest, &cube_id_dest, &n_cube); + EXPECT_TRUE(n_cube == 1); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, cube_id_dest[0], 0), "metric"); + + free(cube_id_dest); + fieldstat_free(instance); + fieldstat_free(instance_dest); +} + +TEST(unit_test_merge, new_cell_on_existing_cube_and_metric_spreadsketch) { + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance, cube_id, "metric", 6); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, 10, 0); + struct fieldstat *instance_dest = fieldstat_new(); + fieldstat_merge(instance_dest, instance); + + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, "1", 1); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, "2", 1); + fieldstat_merge(instance_dest, instance); - fieldstat_merge(instance_dst, instance); + int *cube_id_dest; + int n_cube; + fieldstat_get_cubes(instance_dest, &cube_id_dest, &n_cube); + EXPECT_TRUE(n_cube == 1); + EXPECT_STREQ(fieldstat_get_metric_name(instance_dest, cube_id_dest[0], 0), "metric"); + long long measure = merge_test_fieldstat_hll_get(instance, cube_id, metric_id); + EXPECT_NEAR(measure, 2, 0.3); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance_dst, 0, metric_primary, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); - int *metric_ids; - size_t n_metrics; - fieldstat_get_metrics(instance_dst, &metric_ids, &n_metrics); - EXPECT_EQ(n_metrics, 2); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dst, metric_ids[0]), "2"); - EXPECT_STREQ(fieldstat_get_metric_name(instance_dst, metric_ids[1]), "primary"); - - EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dst, 0, metric_ids[1], &tag_list[0]), 100); - EXPECT_EQ(merge_test_fieldstat_counter_get(instance_dst, 0, metric_ids[0], &tag_list[0]), 1); - fieldstat_tag_list_arr_free(tag_list, n_cell); - free(metric_ids); + EXPECT_EQ(tag_list->n_field, 1); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_STRING.key); + + free(cube_id_dest); fieldstat_free(instance); - fieldstat_free(instance_dst); + fieldstat_free(instance_dest); + fieldstat_field_list_arr_free(tag_list, n_cell); } +TEST(unit_test_merge, merge_existing_cell_on_existing_cube_and_metric_spreadsketch) { + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance, cube_id, "metric", 6); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, 10, 0); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, "1", 1); + struct fieldstat *instance_dest = fieldstat_new(); + + fieldstat_merge(instance_dest, instance); + fieldstat_merge(instance_dest, instance); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, "2", 1); + fieldstat_merge(instance_dest, instance); + + struct field_list *tag_list = NULL; + size_t n_cell = 0; + fieldstat_cube_get_cells(instance_dest, cube_id, &tag_list, &n_cell); + EXPECT_EQ(n_cell, 1); + double value = merge_test_fieldstat_hll_get(instance_dest, cube_id, metric_id, &tag_list[0]); + EXPECT_NEAR(value, 2, 0.3); + + fieldstat_free(instance); + fieldstat_free(instance_dest); + fieldstat_field_list_arr_free(tag_list, n_cell); +} + +TEST(unit_test_merge, new_too_many_cells_on_one_metric_given_source_cube_reset_and_get_different_cube_spreadsketch) { + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance, cube_id, "metric", 6); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, 2, 0); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, "1", 1); + struct fieldstat *instance_dest = fieldstat_new(); + fieldstat_merge(instance_dest, instance); + + fieldstat_reset(instance); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, "21", 2); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, "22", 2); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, "31", 2); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, "32", 2); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, "33", 2); + fieldstat_merge(instance_dest, instance); + + struct field_list *tag_list = NULL; + size_t n_cell = 0; + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); + EXPECT_EQ(n_cell, 2); + EXPECT_NEAR(merge_test_fieldstat_hll_get(instance_dest, 0, 0, &tag_list[0]), 3, 0.3); + EXPECT_NEAR(merge_test_fieldstat_hll_get(instance_dest, 0, 0, &tag_list[1]), 2, 0.3); + EXPECT_STREQ(tag_list[0].field[0].key, TEST_FIELD_DOUBLE.key); + EXPECT_STREQ(tag_list[1].field[0].key, TEST_FIELD_INT.key); + + fieldstat_free(instance); + fieldstat_free(instance_dest); + fieldstat_field_list_arr_free(tag_list, n_cell); +} + + +TEST(unit_test_merge, gen_dest_full_all_src_inserted_given_src_flows_larger_spreadsketch) { + int K = 100; + SpreadSketchZipfGenerator flow_generator(1.0, K); // exactly the number of cells, so there will be almost all(in case of hash collision happen) cells added successfully + struct fieldstat *instance_src = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance_src, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance_src, cube_id, "metric", 6); + fieldstat_cube_set_sampling(instance_src, cube_id, SAMPLING_MODE_TOP_CARDINALITY, K, 0); + struct fieldstat *instance_dest = fieldstat_fork(instance_src); + const char dest_key[] = "key of dest"; + const char src_key[] = "key of src"; + + std::unordered_map<std::string, std::unordered_set<std::string>> flow_cnt; + for (int i = 0; i < 500000; i++) { // add more, so the fanout of any flow to src instance is more than dest + Flow flow = flow_generator.next(); + Fieldstat_tag_list_wrapper dimension = Fieldstat_tag_list_wrapper(src_key, flow.src_ip.c_str()); + Fieldstat_tag_list_wrapper item = Fieldstat_tag_list_wrapper("dummy", flow.dst_ip.c_str()); + fieldstat_hll_add_field(instance_src, cube_id, metric_id, dimension.get_tag(), dimension.get_tag_count(), item.get_tag(), item.get_tag_count()); + + flow_cnt[dimension.to_string()].insert(item.to_string()); + } + + for (int i = 0; i < 1000; i++) { + Flow flow = flow_generator.next(); + Fieldstat_tag_list_wrapper dimension = Fieldstat_tag_list_wrapper(dest_key, flow.src_ip.c_str()); + Fieldstat_tag_list_wrapper item = Fieldstat_tag_list_wrapper("dummy", flow.dst_ip.c_str()); + fieldstat_hll_add_field(instance_dest, cube_id, metric_id, dimension.get_tag(), dimension.get_tag_count(), item.get_tag(), item.get_tag_count()); + + flow_cnt[dimension.to_string()].insert(item.to_string()); + } + + fieldstat_merge(instance_dest, instance_src); + + struct field_list *tag_list = NULL; + struct field_list *tag_list_src = NULL; + size_t n_cell = 0; + size_t n_cell_src = 0; + std::vector<struct Fieldstat_tag_list_wrapper *> test_result; + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance_src, 0, &tag_list_src, &n_cell_src); + for (size_t i = 0; i < n_cell; i++) { + test_result.push_back(new Fieldstat_tag_list_wrapper(&tag_list[i])); + } + std::unordered_map<std::string, int> expected_unique_cnt; + for (auto &kv : flow_cnt) { + expected_unique_cnt[kv.first] = kv.second.size(); + } + + double recall = test_cal_topk_accuracy(test_result, expected_unique_cnt); + EXPECT_NEAR(recall, n_cell_src * 1.0 / n_cell, 0.0001); // the false positive is only generated because some cells in src are left because of hash collision + + fieldstat_free(instance_src); + fieldstat_free(instance_dest); + fieldstat_field_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list_src, n_cell_src); + for (size_t i = 0; i < test_result.size(); i++) { + delete test_result[i]; + } +} + +TEST(unit_test_merge, merge_accuracy_test_gen_dest_full_some_inserted_and_some_merged_and_some_fail_to_add_spreadsketch) { + int K = 10; + SpreadSketchZipfGenerator flow_generator(1.0, K * 10); + struct fieldstat *instance_src = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance_src, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance_src, cube_id, "metric", 6); + fieldstat_cube_set_sampling(instance_src, cube_id, SAMPLING_MODE_TOP_CARDINALITY, K, 0); + struct fieldstat *instance_dest = fieldstat_fork(instance_src); + + std::unordered_map<std::string, std::unordered_set<std::string>> flow_cnt; + for (int i = 0; i < 100000; i++) { + Flow flow = flow_generator.next(); + const char *use_key = rand()%2? "src":"common"; + Fieldstat_tag_list_wrapper dimension = Fieldstat_tag_list_wrapper(use_key, flow.src_ip.c_str()); + Fieldstat_tag_list_wrapper item = Fieldstat_tag_list_wrapper("dummy", flow.dst_ip.c_str()); + fieldstat_hll_add_field(instance_src, cube_id, metric_id, dimension.get_tag(), dimension.get_tag_count(), item.get_tag(), item.get_tag_count()); + + flow_cnt[dimension.to_string()].insert(item.to_string()); + } + for (int i = 0; i < 100000; i++) { + Flow flow = flow_generator.next(); + const char *use_key = rand()%2? "dest":"common"; + Fieldstat_tag_list_wrapper dimension = Fieldstat_tag_list_wrapper(use_key, flow.src_ip.c_str()); + Fieldstat_tag_list_wrapper item = Fieldstat_tag_list_wrapper("dummy", flow.dst_ip.c_str()); + fieldstat_hll_add_field(instance_src, cube_id, metric_id, dimension.get_tag(), dimension.get_tag_count(), item.get_tag(), item.get_tag_count()); + + flow_cnt[dimension.to_string()].insert(item.to_string()); + } + + fieldstat_merge(instance_dest, instance_src); + + struct field_list *tag_list = NULL; + size_t n_cell = 0; + std::vector<struct Fieldstat_tag_list_wrapper *> test_result; + fieldstat_cube_get_cells(instance_dest, 0, &tag_list, &n_cell); + for (size_t i = 0; i < n_cell; i++) { + test_result.push_back(new Fieldstat_tag_list_wrapper(&tag_list[i])); + } + + std::unordered_map<std::string, int> expected_unique_cnt; + for (auto &kv : flow_cnt) { + expected_unique_cnt[kv.first] = kv.second.size(); + } + double recall = test_cal_topk_accuracy(test_result, expected_unique_cnt); + EXPECT_GE(recall, 0.7); + printf("gen_dest_full_all_src_inserted_given_src_flows_larger_spreadsketch recall is %lf\n", recall); + + fieldstat_free(instance_src); + fieldstat_free(instance_dest); + fieldstat_field_list_arr_free(tag_list, n_cell); + for (size_t i = 0; i < test_result.size(); i++) { + delete test_result[i]; + } +} int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); + // testing::GTEST_FLAG(filter) = "*gen_dest_full_all_src_inserted_given_src_flows_larger_spreadsketch"; + return RUN_ALL_TESTS(); }
\ No newline at end of file diff --git a/test/test_metric_counter.cpp b/test/test_metric_counter.cpp index de0f42b..98b52dd 100644 --- a/test/test_metric_counter.cpp +++ b/test/test_metric_counter.cpp @@ -7,22 +7,33 @@ using namespace std; + struct fieldstat *test_init_standard_instance() { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); EXPECT_EQ(cube_id, 0); - int metric_id = fieldstat_register_counter(instance, "czz_test counter metric"); + int metric_id = fieldstat_register_counter(instance, cube_id, "czz_test counter metric"); EXPECT_EQ(metric_id, 0); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_COMPREHENSIVE, 10, 0); + return instance; } -long long my_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag_list *tag_list = &TEST_TAG_LIST_INT) +long long my_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, const struct field_list *tag_list = &TEST_FIELD_LIST_INT) { long long ret = 0; - fieldstat_counter_get(instance, cube_id, metric_id, tag_list, &ret); + fieldstat_counter_get(instance, cube_id, tag_list, metric_id, &ret); + return ret; +} + +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *dimensions, size_t n_dimensions, enum sampling_mode mode, int k, int primary_metric_id=0) +{ + assert(mode == SAMPLING_MODE_COMPREHENSIVE); + int ret = fieldstat_cube_create(instance, dimensions, n_dimensions); + fieldstat_cube_set_sampling(instance, ret, mode, k, primary_metric_id); return ret; } @@ -35,25 +46,32 @@ void test_assert_standard_instance(const struct fieldstat *instance) int ret_cell_id = ret_cube_id_arr[0]; free(ret_cube_id_arr); EXPECT_EQ(ret_cell_id, 0); - const char *name = fieldstat_get_metric_name(instance, 0); + const char *name = fieldstat_get_metric_name(instance, ret_cell_id, 0); EXPECT_STREQ(name, "czz_test counter metric"); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, 0, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); - EXPECT_EQ(tag_list->n_tag, 1); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_INT.key); + EXPECT_EQ(tag_list->n_field, 1); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_INT.key); - fieldstat_tag_list_arr_free(tag_list, n_cell); + int *metric_id = NULL; + size_t n_metric = 0; + fieldstat_get_metric_in_cell(instance, 0, &tag_list[0], &metric_id, &n_metric); + EXPECT_EQ(n_metric, 1); + EXPECT_EQ(metric_id[0], 0); + free(metric_id); + + fieldstat_field_list_arr_free(tag_list, n_cell); } TEST(metric_test_counter, simple_register_and_query_counter) { struct fieldstat *instance = test_init_standard_instance(); - fieldstat_counter_incrby(instance, 0, 0, &TEST_TAG_INT, 1, 10000); - fieldstat_counter_incrby(instance, 0, 0, &TEST_TAG_INT, 1, 86); + fieldstat_counter_incrby(instance, 0, 0, &TEST_FIELD_INT, 1, 10000); + fieldstat_counter_incrby(instance, 0, 0, &TEST_FIELD_INT, 1, 86); test_assert_standard_instance(instance); EXPECT_EQ(my_fieldstat_counter_get(instance, 0, 0), 10086); @@ -64,8 +82,8 @@ TEST(metric_test_counter, simple_register_and_query_counter) TEST(metric_test_counter, merge_counter) { struct fieldstat *instance = test_init_standard_instance(); - fieldstat_counter_incrby(instance, 0, 0, &TEST_TAG_INT, 1, 100); - fieldstat_counter_incrby(instance, 0, 0, &TEST_TAG_INT, 1, -10000); + fieldstat_counter_incrby(instance, 0, 0, &TEST_FIELD_INT, 1, 100); + fieldstat_counter_incrby(instance, 0, 0, &TEST_FIELD_INT, 1, -10000); struct fieldstat *instance_total = fieldstat_new(); fieldstat_merge(instance_total, instance); @@ -80,16 +98,16 @@ TEST(metric_test_counter, merge_counter) fieldstat_free(instance_total); } -TEST(metric_test_counter, serialization_and_merge_counter_twice_with_reset) +TEST(metric_test_counter, merge_counter_twice_with_reset) { struct fieldstat *instance = test_init_standard_instance(); - fieldstat_counter_incrby(instance, 0, 0, &TEST_TAG_INT, 1, 10086); + fieldstat_counter_incrby(instance, 0, 0, &TEST_FIELD_INT, 1, 10086); struct fieldstat *instance_total = fieldstat_new(); fieldstat_merge(instance_total, instance); fieldstat_reset(instance); - fieldstat_counter_incrby(instance, 0, 0, &TEST_TAG_INT, 1, 4); + fieldstat_counter_incrby(instance, 0, 0, &TEST_FIELD_INT, 1, 4); fieldstat_merge(instance_total, instance); test_assert_standard_instance(instance_total); @@ -103,11 +121,12 @@ TEST(metric_test_counter, serialization_and_merge_counter_twice_with_reset) TEST(metric_test_counter, topk_add_and_test_accuracy) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_TOPK, 10); - fieldstat_register_counter(instance, "test"); + fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1); + fieldstat_register_counter(instance, 0, "test"); + fieldstat_cube_set_sampling(instance, 0, SAMPLING_MODE_TOPK, 10, 0); int tag_list_num = 10000; - Fieldstat_tag_list_wrapper *tags[tag_list_num]; + Fieldstat_tag_list_wrapper *fields[tag_list_num]; map<string, int> flow_cnt; for (int i = 0; i < tag_list_num; i++) { @@ -120,18 +139,18 @@ TEST(metric_test_counter, topk_add_and_test_accuracy) flow_k = "mouse"; flow_v = std::to_string(rand() % 1000); } - tags[i] = new Fieldstat_tag_list_wrapper(flow_k, flow_v.c_str()); + fields[i] = new Fieldstat_tag_list_wrapper(flow_k, flow_v.c_str()); flow_cnt[flow_k + flow_v]++; } for (int i = 0; i < tag_list_num; i++) { - fieldstat_counter_incrby(instance, 0, 0, tags[i]->get_tag(), tags[i]->get_tag_count(), 1); + fieldstat_counter_incrby(instance, 0, 0, fields[i]->get_tag(), fields[i]->get_tag_count(), 1); } - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, 0, &tag_list, &n_cell); EXPECT_EQ(n_cell, 10); long long error = 0; for (size_t i = 0; i < n_cell; i++) { @@ -148,49 +167,21 @@ TEST(metric_test_counter, topk_add_and_test_accuracy) printf("topk_add_and_test_accuracy Mean ratio e: %lld\n", error); EXPECT_LT(error, tag_list_num * 0.005); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); fieldstat_free(instance); for (int i = 0; i < tag_list_num; i++) - delete tags[i]; -} - -TEST(metric_test_counter, topk_add_with_monotonically_increasing_flow_expecting_add_fail) -{ - struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_TOPK, 10); - fieldstat_register_counter(instance, "test"); - - const int end_cell_id = 10 * 8; - const int tag_list_num = 100; - Fieldstat_tag_list_wrapper *tags[tag_list_num]; - for (int i = 0; i < tag_list_num; i++) - { - tags[i] = new Fieldstat_tag_list_wrapper("elephant", std::to_string(i).c_str()); - } - - for (int i = 0; i < tag_list_num; i++) { - int ret = fieldstat_counter_incrby(instance, 0, 0, tags[i]->get_tag(), tags[i]->get_tag_count(), i + 1); - if (ret < 0) { - EXPECT_EQ(i, end_cell_id); - EXPECT_EQ(ret, FS_ERR_TOO_MANY_CELLS); - break; - } - } - - fieldstat_free(instance); - for (int i = 0; i < tag_list_num; i++) - delete tags[i]; + delete fields[i]; } TEST(metric_test_counter, add_with_wrong_cube_id_expecting_fail) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_TOPK, 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int ret = fieldstat_counter_incrby(instance, cube_id + 1, 0, &TEST_TAG_INT, 1, 1); + int ret = fieldstat_counter_incrby(instance, cube_id + 1, 0, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_CUBE_ID); - ret = fieldstat_counter_incrby(instance, -1, 0, &TEST_TAG_INT, 1, 1); + ret = fieldstat_counter_incrby(instance, -1, 0, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_CUBE_ID); fieldstat_free(instance); @@ -199,12 +190,12 @@ TEST(metric_test_counter, add_with_wrong_cube_id_expecting_fail) TEST(metric_test_counter, add_with_wrong_metric_id_expecting_fail) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_TOPK, 10); - int metric_id = fieldstat_register_counter(instance, "test"); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance, 0, "test"); - int ret = fieldstat_counter_incrby(instance, cube_id, metric_id + 1, &TEST_TAG_INT, 1, 1); + int ret = fieldstat_counter_incrby(instance, cube_id, metric_id + 1, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_ID); - ret = fieldstat_counter_incrby(instance, cube_id, -1, &TEST_TAG_INT, 1, 1); + ret = fieldstat_counter_incrby(instance, cube_id, -1, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_ID); fieldstat_free(instance); @@ -213,57 +204,16 @@ TEST(metric_test_counter, add_with_wrong_metric_id_expecting_fail) TEST(metric_test_counter, add_and_query_on_dummy_cell_of_topk) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - fieldstat_register_counter(instance, "primary"); // also the dummy one - int metric_id = fieldstat_register_counter(instance, "using"); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + fieldstat_register_counter(instance, cube_id, "primary"); // also the dummy one + int metric_id = fieldstat_register_counter(instance, cube_id, "using"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, 0); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 1); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); // add success long long measure = my_fieldstat_counter_get(instance, cube_id, metric_id); EXPECT_EQ(measure, 1); - // cannot query dummy - int *metric_ids = NULL; - size_t n_metric = 0; - fieldstat_get_metrics_used_by_cube(instance, cube_id, &metric_ids, &n_metric); - EXPECT_EQ(n_metric, 1); - EXPECT_EQ(metric_ids[0], 1); - free(metric_ids); - - struct fieldstat_tag_list *tag_list = NULL; - size_t n_cell; - fieldstat_get_cells_used_by_metric(instance, cube_id, 0, &tag_list, &n_cell); - EXPECT_EQ(n_cell, 0); - - fieldstat_free(instance); -} - -TEST(metric_test_counter, set_on_primary_metric_going_smaller) -{ - struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - int metric_id = fieldstat_register_counter(instance, "primary"); - - int ret = fieldstat_counter_set(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 10); - EXPECT_EQ(ret, FS_OK); - ret = fieldstat_counter_set(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 2); - EXPECT_EQ(ret, FS_ERR_INVALID_PARAM); - - fieldstat_free(instance); -} - -TEST(metric_test_counter, set_on_primary_metric_going_bigger) -{ - struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - int metric_id = fieldstat_register_counter(instance, "primary"); - - int ret = fieldstat_counter_set(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 10); - EXPECT_EQ(ret, FS_OK); - ret = fieldstat_counter_set(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 20); - EXPECT_EQ(ret, FS_OK); - - EXPECT_EQ(my_fieldstat_counter_get(instance, cube_id, metric_id), 20); fieldstat_free(instance); } @@ -271,68 +221,34 @@ TEST(metric_test_counter, set_on_primary_metric_going_bigger) TEST(metric_test_counter, primary_counter_add_after_first) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - int metric_id_primary = fieldstat_register_counter(instance, "primary"); - int metric_id2 = fieldstat_register_counter(instance, "using"); - fieldstat_cube_set_primary_metric(instance, cube_id, metric_id_primary); - + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id_primary = fieldstat_register_counter(instance, cube_id, "primary"); + int metric_id2 = fieldstat_register_counter(instance, cube_id, "using"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, metric_id_primary); - int ret = fieldstat_counter_incrby(instance, cube_id, metric_id2, &TEST_TAG_INT, 1, 10); + int ret = fieldstat_counter_incrby(instance, cube_id, metric_id2, &TEST_FIELD_INT, 1, 10); EXPECT_EQ(ret, FS_OK); - ret = fieldstat_counter_incrby(instance, cube_id, metric_id_primary, &TEST_TAG_INT, 1, 20); + ret = fieldstat_counter_incrby(instance, cube_id, metric_id_primary, &TEST_FIELD_INT, 1, 20); EXPECT_EQ(ret, FS_OK); EXPECT_EQ(my_fieldstat_counter_get(instance, cube_id, metric_id_primary), 20); EXPECT_EQ(my_fieldstat_counter_get(instance, cube_id, metric_id2), 10); // TOPK functions well - struct fieldstat_tag tag = TEST_TAG_INT; + struct field field = TEST_FIELD_INT; for (int i = 0; i < 9; i++) { - tag.value_longlong = i + 123; - ret = fieldstat_counter_incrby(instance, cube_id, metric_id_primary, &tag, 1, 1 + i); + field.value_longlong = i + 123; + ret = fieldstat_counter_incrby(instance, cube_id, metric_id_primary, &field, 1, 1 + i); EXPECT_EQ(ret, FS_OK); } // now the TOPK is full, add a new one - tag.value_longlong = 321; - ret = fieldstat_counter_incrby(instance, cube_id, metric_id_primary, &tag, 1, 1); + field.value_longlong = 321; + ret = fieldstat_counter_incrby(instance, cube_id, metric_id_primary, &field, 1, 1); EXPECT_EQ(ret, FS_ERR_TOO_MANY_CELLS); fieldstat_free(instance); } -TEST(metric_test_counter, topk_set_and_test_accuracy) -{ - struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_TOPK, 6); - fieldstat_register_counter(instance, "test"); - - struct fieldstat_tag tag = TEST_TAG_INT; - // tag : [0, 1, 2, 3, 4 ,5] - // value: [0, 1, 2, 3, 4 ,5] - for (int i = 0; i < 6; i++) { - tag.value_longlong = i; - EXPECT_EQ(fieldstat_counter_set(instance, 0, 0, &tag, 1, i), FS_OK); - } - // tag : [0, 1, 2, 3, 4 ,5, 6, 7, 8] - // value: [0, 1, 2, 100, 100, 100, 100, 100, 100] - for (int i = 0; i < 6; i++) { - tag.value_longlong = i + 3; - EXPECT_EQ(fieldstat_counter_set(instance, 0, 0, &tag, 1, 100), FS_OK); - } - - struct fieldstat_tag_list *tag_list = NULL; - size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance, 0, 0, &tag_list, &n_cell); - EXPECT_EQ(n_cell, 6); - for (size_t i = 0; i < n_cell; i++) { - EXPECT_EQ(tag_list[i].tag[0].value_longlong, i + 3); - EXPECT_EQ(my_fieldstat_counter_get(instance, 0, 0, &tag_list[i]), 100); - } - - fieldstat_tag_list_arr_free(tag_list, n_cell); - fieldstat_free(instance); -} - int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); diff --git a/test/test_metric_histogram.cpp b/test/test_metric_histogram.cpp index 6983d02..c99a565 100644 --- a/test/test_metric_histogram.cpp +++ b/test/test_metric_histogram.cpp @@ -6,13 +6,21 @@ #include "hdr/hdr_histogram.h" #include "histogram_encoder.h" +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *dimensions, size_t n_dimensions, enum sampling_mode mode, int k) +{ + assert(mode == SAMPLING_MODE_COMPREHENSIVE); + int ret = fieldstat_cube_create(instance, dimensions, n_dimensions); + fieldstat_cube_set_sampling(instance, ret, mode, k, 0); + return ret; +} + struct fieldstat *test_init_standard_instance_one_cube_one_metric_one_cell_hdr() { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); EXPECT_EQ(cube_id, 0); - int metric_id = fieldstat_register_hist(instance, "czz_test hdr metric", 1, 600000, 3); + int metric_id = fieldstat_register_histogram(instance, cube_id, "czz_test hdr metric", 1, 600000, 3); EXPECT_EQ(metric_id, 0); return instance; @@ -27,31 +35,38 @@ void test_assert_standard_instance(const struct fieldstat *instance) int ret_cell_id = ret_cube_id_arr[0]; free(ret_cube_id_arr); EXPECT_EQ(ret_cell_id, 0); - const char *name = fieldstat_get_metric_name(instance, 0); + const char *name = fieldstat_get_metric_name(instance, ret_cell_id, 0); EXPECT_STREQ(name, "czz_test hdr metric"); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, 0, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); - EXPECT_EQ(tag_list->n_tag, 1); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_STRING.key); + EXPECT_EQ(tag_list->n_field, 1); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_STRING.key); + + int *metric_id = NULL; + size_t n_metric = 0; + fieldstat_get_metric_in_cell(instance, 0, &tag_list[0], &metric_id, &n_metric); + EXPECT_EQ(n_metric, 1); + EXPECT_EQ(metric_id[0], 0); + free(metric_id); - fieldstat_tag_list_arr_free(tag_list, n_cell); + fieldstat_field_list_arr_free(tag_list, n_cell); } TEST(metric_test_histogram, simple_register_and_query) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hdr(); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 1234); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 1234); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 123); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 1234); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 1234); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 123); test_assert_standard_instance(instance); - EXPECT_EQ(fieldstat_hist_value_at_percentile(instance, 0, 0, &TEST_TAG_LIST_STRING, 50.0), 1234); - EXPECT_EQ(fieldstat_hist_count_le_value(instance, 0, 0, &TEST_TAG_LIST_STRING, 1000), 1); + EXPECT_EQ(fieldstat_histogram_value_at_percentile(instance, 0, &TEST_FIELD_LIST_STRING, 0, 50.0), 1234); + EXPECT_EQ(fieldstat_histogram_count_le_value(instance, 0, &TEST_FIELD_LIST_STRING, 0, 1000), 1); fieldstat_free(instance); } @@ -59,9 +74,9 @@ TEST(metric_test_histogram, simple_register_and_query) TEST(metric_test_histogram, merge) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hdr(); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 1234); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 1234); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 123); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 1234); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 1234); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 123); struct fieldstat *instance_total = fieldstat_new(); fieldstat_merge(instance_total, instance); @@ -69,8 +84,8 @@ TEST(metric_test_histogram, merge) // query test_assert_standard_instance(instance_total); - EXPECT_EQ(fieldstat_hist_value_at_percentile(instance_total, 0, 0, &TEST_TAG_LIST_STRING, 50.0), 1234); - EXPECT_EQ(fieldstat_hist_count_le_value(instance, 0, 0, &TEST_TAG_LIST_STRING, 1000), 1); + EXPECT_EQ(fieldstat_histogram_value_at_percentile(instance_total, 0, &TEST_FIELD_LIST_STRING, 0, 50.0), 1234); + EXPECT_EQ(fieldstat_histogram_count_le_value(instance, 0, &TEST_FIELD_LIST_STRING, 0, 1000), 1); fieldstat_free(instance); fieldstat_free(instance_total); @@ -79,19 +94,19 @@ TEST(metric_test_histogram, merge) TEST(metric_test_histogram, merge_twice_with_reset) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hdr(); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 1234); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 123); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 1234); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 123); struct fieldstat *instance_total = fieldstat_new(); fieldstat_merge(instance_total, instance); fieldstat_reset(instance); - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_STRING, 1, 1234); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_STRING, 1, 1234); fieldstat_merge(instance_total, instance); test_assert_standard_instance(instance_total); - EXPECT_EQ(fieldstat_hist_value_at_percentile(instance_total, 0, 0, &TEST_TAG_LIST_STRING, 50.0), 1234); - EXPECT_EQ(fieldstat_hist_count_le_value(instance_total, 0, 0, &TEST_TAG_LIST_STRING, 1000), 1); + EXPECT_EQ(fieldstat_histogram_value_at_percentile(instance_total, 0, &TEST_FIELD_LIST_STRING, 0, 50.0), 1234); + EXPECT_EQ(fieldstat_histogram_count_le_value(instance_total, 0, &TEST_FIELD_LIST_STRING, 0, 1000), 1); fieldstat_free(instance); fieldstat_free(instance_total); @@ -100,11 +115,11 @@ TEST(metric_test_histogram, merge_twice_with_reset) TEST(metric_test_histogram, add_with_wrong_cube_id_expecting_fail) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int ret = fieldstat_hist_record(instance, cube_id + 1, 0, &TEST_TAG_INT, 1, 1); + int ret = fieldstat_histogram_record(instance, cube_id + 1, 0, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_CUBE_ID); - ret = fieldstat_hist_record(instance, -1, 0, &TEST_TAG_INT, 1, 1); + ret = fieldstat_histogram_record(instance, -1, 0, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_CUBE_ID); fieldstat_free(instance); @@ -113,12 +128,12 @@ TEST(metric_test_histogram, add_with_wrong_cube_id_expecting_fail) TEST(metric_test_histogram, add_with_wrong_metric_id_expecting_fail) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_hist(instance, "czz_test", 1, 600000, 3); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_histogram(instance, cube_id, "czz_test", 1, 600000, 3); - int ret = fieldstat_hist_record(instance, cube_id, metric_id + 1, &TEST_TAG_INT, 1, 1); + int ret = fieldstat_histogram_record(instance, cube_id, metric_id + 1, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_ID); - ret = fieldstat_hist_record(instance, cube_id, -1, &TEST_TAG_INT, 1, 1); + ret = fieldstat_histogram_record(instance, cube_id, -1, &TEST_FIELD_INT, 1, 1); EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_ID); fieldstat_free(instance); @@ -162,16 +177,16 @@ TEST(metric_test_histogram, encode_decode_b64) TEST(metric_test_histogram, can_add_0value) // histogram only allow min_val > 0, but it can accept value == 0 { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_hist(instance, "czz_test", 1, 600000, 3); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_histogram(instance, cube_id, "czz_test", 1, 600000, 3); - int ret = fieldstat_hist_record(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 0); + int ret = fieldstat_histogram_record(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 0); EXPECT_EQ(ret, 0); - ret = fieldstat_hist_record(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 0); + ret = fieldstat_histogram_record(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 0); EXPECT_EQ(ret, 0); - ret = fieldstat_hist_record(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 500); + ret = fieldstat_histogram_record(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 500); - EXPECT_EQ(fieldstat_hist_value_at_percentile(instance, cube_id, metric_id, &TEST_TAG_LIST_INT, 60.0), 0); + EXPECT_EQ(fieldstat_histogram_value_at_percentile(instance, cube_id, &TEST_FIELD_LIST_INT, metric_id, 60.0), 0); fieldstat_free(instance); } diff --git a/test/test_metric_hll.cpp b/test/test_metric_hll.cpp index 4f7f9d2..bbfc36a 100644 --- a/test/test_metric_hll.cpp +++ b/test/test_metric_hll.cpp @@ -1,14 +1,28 @@ #include <gtest/gtest.h> +#include <string> +#include <vector> +#include <unordered_map> +#include <unordered_set> +#include <math.h> + #include "fieldstat.h" #include "utils.hpp" +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *dimensions, size_t n_dimensions, enum sampling_mode mode, int k) +{ + assert(mode == SAMPLING_MODE_COMPREHENSIVE); + int ret = fieldstat_cube_create(instance, dimensions, n_dimensions); + fieldstat_cube_set_sampling(instance, ret, mode, k, 0); + return ret; +} + struct fieldstat *test_init_standard_instance_one_cube_one_metric_one_cell_hll(bool is_gauge = false) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); EXPECT_EQ(cube_id, 0); - int metric_id = fieldstat_register_hll(instance, "czz_test hll metric", 10); + int metric_id = fieldstat_register_hll(instance, cube_id, "czz_test hll metric", 10); EXPECT_EQ(metric_id, 0); return instance; @@ -23,23 +37,30 @@ void test_assert_standard_instance(const struct fieldstat *instance) int ret_cell_id = ret_cube_id_arr[0]; free(ret_cube_id_arr); EXPECT_EQ(ret_cell_id, 0); - const char *name = fieldstat_get_metric_name(instance, 0); + const char *name = fieldstat_get_metric_name(instance, ret_cell_id, 0); EXPECT_STREQ(name, "czz_test hll metric"); - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(instance, 0, 0, &tag_list, &n_cell); + fieldstat_cube_get_cells(instance, 0, &tag_list, &n_cell); EXPECT_EQ(n_cell, 1); - EXPECT_EQ(tag_list->n_tag, 1); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_INT.key); - - fieldstat_tag_list_arr_free(tag_list, n_cell); + EXPECT_EQ(tag_list->n_field, 1); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_INT.key); + + int *metric_id = NULL; + size_t n_metric = 0; + fieldstat_get_metric_in_cell(instance, 0, &tag_list[0], &metric_id, &n_metric); + EXPECT_EQ(n_metric, 1); + EXPECT_EQ(metric_id[0], 0); + free(metric_id); + + fieldstat_field_list_arr_free(tag_list, n_cell); } double my_fieldstat_hll_get(const struct fieldstat *instance, int cube_id, int metric_id) { double ret = 0; - fieldstat_hll_get(instance, cube_id, metric_id, &TEST_TAG_LIST_INT, &ret); + fieldstat_hll_get(instance, cube_id, &TEST_FIELD_LIST_INT, metric_id, &ret); return ret; } @@ -47,10 +68,23 @@ TEST(metric_test_hll, simple_register_and_query) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hll(); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "hello", 5); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "wor", 3); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "world", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "hello", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "wor", 3); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "world", 5); + + test_assert_standard_instance(instance); + EXPECT_NEAR(my_fieldstat_hll_get(instance, 0, 0), 3, 0.5); + + fieldstat_free(instance); +} + +TEST(metric_test_hll, add_with_tags) { + struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hll(); + fieldstat_hll_add_field(instance, 0, 0, &TEST_FIELD_INT, 1, &TEST_FIELD_INT, 1); + fieldstat_hll_add_field(instance, 0, 0, &TEST_FIELD_INT, 1, &TEST_FIELD_DOUBLE, 1); + fieldstat_hll_add_field(instance, 0, 0, &TEST_FIELD_INT, 1, &TEST_FIELD_STRING, 1); + test_assert_standard_instance(instance); EXPECT_NEAR(my_fieldstat_hll_get(instance, 0, 0), 3, 0.5); @@ -60,9 +94,9 @@ TEST(metric_test_hll, simple_register_and_query) TEST(metric_test_hll, merge) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hll(); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "hello", 5); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "wor", 3); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "world", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "hello", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "wor", 3); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "world", 5); struct fieldstat *instance_total = fieldstat_new(); fieldstat_merge(instance_total, instance); @@ -79,14 +113,14 @@ TEST(metric_test_hll, merge) TEST(metric_test_hll, merge_twice_with_reset) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hll(); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "hello", 5); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "wor", 3); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "hello", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "wor", 3); struct fieldstat *instance_total = fieldstat_new(); fieldstat_merge(instance_total, instance); fieldstat_reset(instance); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "world", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "world", 5); fieldstat_merge(instance_total, instance); test_assert_standard_instance(instance_total); @@ -102,17 +136,17 @@ TEST(metric_test_hll, merge_twice_with_reset) (((uint32_t)(A) & 0x0000ff00) << 8) | \ (((uint32_t)(A) & 0x000000ff) << 24)) #include "base64/b64.h" -#include "st_hyperloglog.h" +#include "hyperloglog.h" TEST(metric_test_hll, serialize_with_b64_and_query) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hll(); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "hello", 5); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "wor", 3); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "world", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "hello", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "wor", 3); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "world", 5); char *blob = NULL; size_t blob_len = 0; - fieldstat_get_serialized_blob(instance, 0, 0, &TEST_TAG_LIST_INT, &blob, &blob_len); + fieldstat_metric_get_serialization_as_base64(instance, 0, 0, &TEST_FIELD_LIST_INT, &blob, &blob_len); size_t dec_size = 0; unsigned char *dec = b64_decode_ex(blob, blob_len, &dec_size); @@ -123,7 +157,7 @@ TEST(metric_test_hll, serialize_with_b64_and_query) memcpy(&precision, dec + sizeof(unsigned char), sizeof(unsigned char)); EXPECT_EQ(precision, 10); // the one initialized in test_init_standard_instance_one_cube_one_metric_one_cell_hll - struct ST_hyperloglog *hll_from_blob = ST_hyperloglog_new(precision); + struct hyperloglog *hll_from_blob = hyperloglog_new(precision); int num_reg = NUM_REG(precision); int words = INT_CEIL(num_reg, REG_PER_WORD); size_t reg_size = words * sizeof(uint32_t); @@ -136,11 +170,11 @@ TEST(metric_test_hll, serialize_with_b64_and_query) memcpy(hll_from_blob->registers, registers, reg_size); free(registers); - EXPECT_NEAR(ST_hyperloglog_count(hll_from_blob), 3, 0.5); + EXPECT_NEAR(hyperloglog_count(hll_from_blob), 3, 0.5); free(blob); free(dec); fieldstat_free(instance); - ST_hyperloglog_free(hll_from_blob); + hyperloglog_free(hll_from_blob); } @@ -151,32 +185,32 @@ extern "C" { TEST(metric_test_hll, serialize_with_b64_and_query_with_python_api) { struct fieldstat *instance = test_init_standard_instance_one_cube_one_metric_one_cell_hll(); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "hello", 5); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "wor", 3); - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, "world", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "hello", 5); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "wor", 3); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, "world", 5); char *blob = NULL; size_t blob_len = 0; - fieldstat_get_serialized_blob(instance, 0, 0, &TEST_TAG_LIST_INT, &blob, &blob_len); + fieldstat_metric_get_serialization_as_base64(instance, 0, 0, &TEST_FIELD_LIST_INT, &blob, &blob_len); bool flag = fieldstat_is_hll(blob); EXPECT_EQ(flag, true); void *hll_from_blob = hll_base64_decode(blob); - EXPECT_NEAR(ST_hyperloglog_count((struct ST_hyperloglog *)hll_from_blob), 3, 0.5); + EXPECT_NEAR(hyperloglog_count((struct hyperloglog *)hll_from_blob), 3, 0.5); free(blob); fieldstat_free(instance); - ST_hyperloglog_free((struct ST_hyperloglog *)hll_from_blob); + hyperloglog_free((struct hyperloglog *)hll_from_blob); } TEST(metric_test_hll, add_with_wrong_cube_id_expecting_fail) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int ret = fieldstat_hll_add(instance, cube_id + 1, 0, &TEST_TAG_INT, 1, "hello", 5); + int ret = fieldstat_hll_add(instance, cube_id + 1, 0, &TEST_FIELD_INT, 1, "hello", 5); EXPECT_EQ(ret, FS_ERR_INVALID_CUBE_ID); - ret = fieldstat_hll_add(instance, -1, 0, &TEST_TAG_INT, 1, "hello", 5); + ret = fieldstat_hll_add(instance, -1, 0, &TEST_FIELD_INT, 1, "hello", 5); EXPECT_EQ(ret, FS_ERR_INVALID_CUBE_ID); fieldstat_free(instance); @@ -185,20 +219,83 @@ TEST(metric_test_hll, add_with_wrong_cube_id_expecting_fail) TEST(metric_test_hll, add_with_wrong_metric_id_expecting_fail) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_hll(instance, "czz_test hll metric", 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_hll(instance, cube_id, "czz_test hll metric", 10); - int ret = fieldstat_hll_add(instance, cube_id, metric_id + 1, &TEST_TAG_INT, 1, "hello", 5); + int ret = fieldstat_hll_add(instance, cube_id, metric_id + 1, &TEST_FIELD_INT, 1, "hello", 5); EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_ID); - ret = fieldstat_hll_add(instance, cube_id, -1, &TEST_TAG_INT, 1, "hello", 5); + ret = fieldstat_hll_add(instance, cube_id, -1, &TEST_FIELD_INT, 1, "hello", 5); EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_ID); fieldstat_free(instance); } +TEST(metric_test_hll, spread_sketch_add_and_test_accuracy) +{ + struct fieldstat *instance = fieldstat_new(); + int K = 10; + fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1); + fieldstat_register_hll(instance, 0, "testss", 6); + fieldstat_cube_set_sampling(instance, 0, SAMPLING_MODE_TOP_CARDINALITY, K, 0); + + int n_flows = 100000; + std::unordered_map<std::string, std::unordered_set<std::string>> flow_cnt; + SpreadSketchZipfGenerator generator(1.0, K * 10); // give much bigger distribution, so that we can test the accuracy + for (int i = 0; i < n_flows; i++) + { + Flow f = generator.next(); + Fieldstat_tag_list_wrapper dimension("src ip", f.src_ip.c_str()); + Fieldstat_tag_list_wrapper counted("dst ip", f.dst_ip.c_str()); + + fieldstat_hll_add_field(instance, 0, 0, dimension.get_tag(), dimension.get_tag_count(), counted.get_tag(), counted.get_tag_count()); + + flow_cnt[dimension.to_string()].insert(counted.to_string()); + } + + // recall + std::unordered_map<std::string, int> expected_unique_cnt; + std::vector<struct Fieldstat_tag_list_wrapper *> test_result; + for (auto &kv : flow_cnt) { + expected_unique_cnt[kv.first] = kv.second.size(); + } + + struct field_list *tag_list = NULL; + size_t n_cell = 0; + fieldstat_cube_get_cells(instance, 0, &tag_list, &n_cell); + EXPECT_EQ(n_cell, K); + for (size_t i = 0; i < n_cell; i++) { + Fieldstat_tag_list_wrapper tmp = Fieldstat_tag_list_wrapper(&tag_list[i]); + test_result.push_back(new Fieldstat_tag_list_wrapper(tmp)); + } + double recall = test_cal_topk_accuracy(test_result, expected_unique_cnt); + printf("spread_sketch_add_and_test_accuracy recall: %f\n", recall); + EXPECT_GE(recall, 0.8); + + // MRE + double mre = 0; + for (size_t i = 0; i < n_cell; i++) { + Fieldstat_tag_list_wrapper tmp = Fieldstat_tag_list_wrapper(&tag_list[i]); + double value_true = expected_unique_cnt[tmp.to_string()]; + double value_est; + fieldstat_hll_get(instance, 0, &tag_list[i], 0, &value_est); + // printf("the estimated value for %s is %f, the true value is %f\n", tmp.to_string().c_str(), value_est, value_true); + + mre += fabs(value_true - value_est) / value_true; + } + mre = mre / n_cell; + printf("topk_add_and_test_accuracy Mean ratio e: %f\n", mre); + EXPECT_LE(mre, 0.2); + + fieldstat_field_list_arr_free(tag_list, n_cell); + fieldstat_free(instance); + for (auto &ptr : test_result) { + delete ptr; + } +} int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); + // testing::GTEST_FLAG(filter) = "metric_test_hll.spread_sketch_add_and_test_accuracy"; return RUN_ALL_TESTS(); } diff --git a/test/test_performance.cpp b/test/test_performance.cpp index 11c05ce..48d3859 100644 --- a/test/test_performance.cpp +++ b/test/test_performance.cpp @@ -6,22 +6,32 @@ #include "fieldstat_exporter.h" #include "utils.hpp" + +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *tag, size_t tag_count, enum sampling_mode mode, int k, int primary_metric_id=0) +{ + int ret = fieldstat_cube_create(instance, tag, tag_count); + fieldstat_cube_set_sampling(instance, ret, mode, k, primary_metric_id); + return ret; +} + + // /* -------------------------------------------------------------------------- */ // /* merge */ // /* -------------------------------------------------------------------------- */ -double perform_merge_test(std::function<void (struct fieldstat*, int, int, const struct fieldstat_tag *, int)> metric_add_func, +double perform_merge_test(std::function<void (struct fieldstat*, int, int, const struct field *, int)> metric_add_func, std::function<int(struct fieldstat*)> metric_register_func, enum sampling_mode mode, bool merge_empty_dest) { const int MAX_CELL_NUM = 1000; - Fieldstat_tag_list_wrapper *tags[MAX_CELL_NUM]; + Fieldstat_tag_list_wrapper *fields[MAX_CELL_NUM]; for (int i = 0; i < MAX_CELL_NUM; i++) { - tags[i] = new Fieldstat_tag_list_wrapper("my key", i); + fields[i] = new Fieldstat_tag_list_wrapper("my key", i); } struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, mode, MAX_CELL_NUM); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); int metric_id = metric_register_func(instance); + fieldstat_cube_set_sampling(instance, cube_id, mode, MAX_CELL_NUM, metric_id); for (int j = 0; j < MAX_CELL_NUM; j++) { - metric_add_func(instance, cube_id, metric_id, tags[j]->get_tag(), 1); + metric_add_func(instance, cube_id, metric_id, fields[j]->get_tag(), 1); } struct fieldstat *instance_dest = fieldstat_new(); @@ -36,7 +46,7 @@ double perform_merge_test(std::function<void (struct fieldstat*, int, int, const fieldstat_free(instance_dest); fieldstat_free(instance); for (int i = 0; i < MAX_CELL_NUM; i++) { - delete tags[i]; + delete fields[i]; } return (end - start) / 1000.0; @@ -44,11 +54,11 @@ double perform_merge_test(std::function<void (struct fieldstat*, int, int, const TEST(test_performance, merge_performance_one_instance_comprehensive_counter_empty_dest) { - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_counter_incrby(instance, cube_id, metric_id, tags, n_tag, 1); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_counter_incrby(instance, cube_id, metric_id, fields, n_field, 1); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_counter(instance, "metric name"); + return fieldstat_register_counter(instance, 0, "metric name"); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_COMPREHENSIVE, true); @@ -61,11 +71,11 @@ TEST(test_performance, merge_performance_one_instance_comprehensive_hll_empty_de // int metric_id = fieldstat_register_hll(instance, cube_id, "czz_test hll metric", 10); // int ret = fieldstat_hll_add(instance, cube_id, metric_id, cell_id, "hello", 5); - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_hll_add(instance, cube_id, metric_id, tags, n_tag, "hello", 5); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_hll_add(instance, cube_id, metric_id, fields, n_field, "hello", 5); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_hll(instance, "hll metric", 6); + return fieldstat_register_hll(instance, 0, "hll metric", 6); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_COMPREHENSIVE, true); @@ -75,14 +85,11 @@ TEST(test_performance, merge_performance_one_instance_comprehensive_hll_empty_de TEST(test_performance, merge_performance_one_instance_comprehensive_histogram_empty_dest) { - // int metric_id = fieldstat_register_hist(instance, cube_id, "czz_test", 1, 100000, 1); - // int ret = fieldstat_hist_record(instance, cube_id, metric_id, cell_id, 1234); - - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_hist_record(instance, cube_id, metric_id, tags, n_tag, 1234); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_histogram_record(instance, cube_id, metric_id, fields, n_field, 1234); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_hist(instance, "histogram metric", 1, 100000, 1); + return fieldstat_register_histogram(instance, 0, "histogram metric", 1, 100000, 1); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_COMPREHENSIVE, true); @@ -92,11 +99,11 @@ TEST(test_performance, merge_performance_one_instance_comprehensive_histogram_em TEST(test_performance, merge_performance_one_instance_topk_counter_empty_dest) { - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_counter_incrby(instance, cube_id, metric_id, tags, n_tag, rand() % 1000); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_counter_incrby(instance, cube_id, metric_id, fields, n_field, rand() % 1000); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_counter(instance, "metric name"); + return fieldstat_register_counter(instance, 0, "metric name"); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_TOPK, true); @@ -106,11 +113,11 @@ TEST(test_performance, merge_performance_one_instance_topk_counter_empty_dest) TEST(test_performance, merge_performance_one_instance_comprehensive_counter_full_dest) { - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_counter_incrby(instance, cube_id, metric_id, tags, n_tag, 1); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_counter_incrby(instance, cube_id, metric_id, fields, n_field, 1); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_counter(instance, "metric name"); + return fieldstat_register_counter(instance, 0, "metric name"); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_COMPREHENSIVE, false); @@ -120,11 +127,11 @@ TEST(test_performance, merge_performance_one_instance_comprehensive_counter_full TEST(test_performance, merge_performance_one_instance_comprehensive_hll_full_dest) { - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_hll_add(instance, cube_id, metric_id, tags, n_tag, "hello", 5); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_hll_add(instance, cube_id, metric_id, fields, n_field, "hello", 5); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_hll(instance, "hll metric", 6); + return fieldstat_register_hll(instance, 0, "hll metric", 6); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_COMPREHENSIVE, false); @@ -134,11 +141,11 @@ TEST(test_performance, merge_performance_one_instance_comprehensive_hll_full_des TEST(test_performance, merge_performance_one_instance_comprehensive_histogram_full_dest) { - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_hist_record(instance, cube_id, metric_id, tags, n_tag, 1234); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_histogram_record(instance, cube_id, metric_id, fields, n_field, 1234); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_hist(instance, "histogram metric", 1, 100000, 1); + return fieldstat_register_histogram(instance, 0, "histogram metric", 1, 100000, 1); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_COMPREHENSIVE, false); @@ -148,11 +155,11 @@ TEST(test_performance, merge_performance_one_instance_comprehensive_histogram_fu TEST(test_performance, merge_performance_one_instance_topk_counter_full_dest) { - auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, int n_tag) { - fieldstat_counter_incrby(instance, cube_id, metric_id, tags, n_tag, rand() % 1000); + auto metric_add_func = [](struct fieldstat *instance, int cube_id, int metric_id, const struct field *fields, int n_field) { + fieldstat_counter_incrby(instance, cube_id, metric_id, fields, n_field, rand() % 1000); }; auto metric_register_func = [](struct fieldstat *instance) { - return fieldstat_register_counter(instance, "metric name"); + return fieldstat_register_counter(instance,0, "metric name"); }; double elapsed = perform_merge_test(metric_add_func, metric_register_func, SAMPLING_MODE_TOPK, false); @@ -163,14 +170,16 @@ TEST(test_performance, merge_performance_one_instance_topk_counter_full_dest) struct fieldstat *construct_fs_with_many_empty_cubes(int cube_num, int metric_num, enum sampling_mode mode) { struct fieldstat *instance = fieldstat_new(); - struct fieldstat_tag tmp_tag = TEST_TAG_INT; + struct field tmp_tag = TEST_FIELD_INT; for (int i = 0; i < cube_num; i++) { tmp_tag.value_longlong = i; - fieldstat_create_cube(instance, &tmp_tag, 1, mode, 1000); + int cube_id = fieldstat_cube_create(instance, &tmp_tag, 1); for (int j = 0; j < metric_num; j++) { - fieldstat_register_counter(instance, std::to_string(j).c_str()); + fieldstat_register_counter(instance, cube_id, std::to_string(j).c_str()); } + + fieldstat_cube_set_sampling(instance, cube_id, mode, 1000, 0); } return instance; } @@ -215,19 +224,19 @@ TEST(test_performance, merge_empty_cubes_topk) TEST(test_performance, performance_test_add_cells_comprehensive) { size_t cell_count = 100000; - struct fieldstat_tag tags[cell_count]; + struct field fields[cell_count]; for (size_t i = 0; i < cell_count; i++) { - tags[i] = TEST_TAG_INT; - tags[i].value_longlong = i; + fields[i] = TEST_FIELD_INT; + fields[i].value_longlong = i; } // getchar(); struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, cell_count); - fieldstat_register_counter(instance, "test"); + test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, cell_count); + fieldstat_register_counter(instance, 0, "test"); clock_t start = clock(); for (size_t i = 0; i < cell_count; i++) { - fieldstat_counter_incrby(instance, 0, 0, &tags[i % cell_count], 1, 1); + fieldstat_counter_incrby(instance, 0, 0, &fields[i % cell_count], 1, 1); } clock_t end = clock(); double seconds = (double)(end - start) / cell_count; @@ -239,23 +248,24 @@ TEST(test_performance, performance_test_add_cells_comprehensive) TEST(test_performance, performance_test_add_cells_topk) { size_t cell_count = 100000; - struct fieldstat_tag tags[cell_count]; + struct field fields[cell_count]; for (size_t i = 0; i < cell_count; i++) { - tags[i] = TEST_TAG_INT; - // tags[i].value_longlong = rand() % 10000; + fields[i] = TEST_FIELD_INT; + // fields[i].value_longlong = rand() % 10000; if (rand()%2) - tags[i].value_longlong = i; + fields[i].value_longlong = i; else - tags[i].value_longlong = rand() % 1000; + fields[i].value_longlong = rand() % 1000; } struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_TOPK, 1000); - fieldstat_register_counter(instance, "test"); + fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1); + fieldstat_register_counter(instance, 0, "test"); + fieldstat_cube_set_sampling(instance, 0, SAMPLING_MODE_TOPK, 1000, 0); // getchar(); clock_t start = clock(); for (size_t i = 0; i < cell_count; i++) { - fieldstat_counter_incrby(instance, 0, 0, &tags[i % cell_count], 1, 1); + fieldstat_counter_incrby(instance, 0, 0, &fields[i % cell_count], 1, 1); } clock_t end = clock(); double seconds = (double)(end - start) / cell_count; @@ -270,8 +280,8 @@ TEST(test_performance, performance_test_add_cells_topk) TEST(test_performance, performance_test_add_cells_histogram_record) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_hist(instance, "test", 1, 100000, 3); + test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_histogram(instance, 0, "test", 1, 100000, 3); size_t test_num = 100000; long long vals[test_num]; for (size_t i = 0; i < test_num; i++) { @@ -279,7 +289,7 @@ TEST(test_performance, performance_test_add_cells_histogram_record) } clock_t start = clock(); for (size_t i = 0; i < test_num; i++) { - fieldstat_hist_record(instance, 0, 0, &TEST_TAG_INT, 1, vals[i]); + fieldstat_histogram_record(instance, 0, 0, &TEST_FIELD_INT, 1, vals[i]); } clock_t end = clock(); double seconds = (double)(end - start) / test_num; @@ -291,8 +301,8 @@ TEST(test_performance, performance_test_add_cells_histogram_record) TEST(test_performance, performance_test_add_cells_hll_add) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_hll(instance, "test", 6); + test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_hll(instance, 0, "test", 6); size_t test_num = 100000; std::string vals[test_num]; for (size_t i = 0; i < test_num; i++) { @@ -301,7 +311,7 @@ TEST(test_performance, performance_test_add_cells_hll_add) clock_t start = clock(); for (size_t i = 0; i < test_num; i++) { - fieldstat_hll_add(instance, 0, 0, &TEST_TAG_INT, 1, vals[i].c_str(), vals[i].length()); + fieldstat_hll_add(instance, 0, 0, &TEST_FIELD_INT, 1, vals[i].c_str(), vals[i].length()); } clock_t end = clock(); double seconds = (double)(end - start) / test_num; @@ -313,23 +323,23 @@ TEST(test_performance, performance_test_add_cells_hll_add) TEST(test_performance, performance_test_add_cells_comprehensive_5_tags) { size_t cell_count = 100000; - struct fieldstat_tag *tag_v[cell_count]; + struct field *tag_v[cell_count]; for (size_t i = 0; i < cell_count; i++) { - struct fieldstat_tag *tags = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag) * 5); + struct field *fields = (struct field *)malloc(sizeof(struct field) * 5); - tags[0] = TEST_TAG_INT; - tags[1] = TEST_TAG_INT; - tags[2] = TEST_TAG_INT; - tags[3] = TEST_TAG_INT; - tags[4] = TEST_TAG_INT; - tags[0].value_longlong = i; + fields[0] = TEST_FIELD_INT; + fields[1] = TEST_FIELD_INT; + fields[2] = TEST_FIELD_INT; + fields[3] = TEST_FIELD_INT; + fields[4] = TEST_FIELD_INT; + fields[0].value_longlong = i; - tag_v[i] = tags; + tag_v[i] = fields; } // getchar(); struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, cell_count); - fieldstat_register_counter(instance, "test"); + test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, cell_count); + fieldstat_register_counter(instance, 0, "test"); clock_t start = clock(); for (size_t i = 0; i < cell_count; i++) { @@ -337,7 +347,7 @@ TEST(test_performance, performance_test_add_cells_comprehensive_5_tags) } clock_t end = clock(); double seconds = (double)(end - start) / cell_count; - printf("performance_test_add_cells_comprehensive time 5 tags cost: %f\n", seconds); + printf("performance_test_add_cells_comprehensive time 5 fields cost: %f\n", seconds); EXPECT_TRUE(seconds < 2); fieldstat_free(instance); @@ -349,27 +359,27 @@ TEST(test_performance, performance_test_add_cells_comprehensive_5_tags) TEST(test_performance, performance_test_add_cells_histogram_record_5tags) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_hist(instance, "test", 1, 100000, 3); + test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_histogram(instance, 0, "test", 1, 100000, 3); size_t test_num = 100000; long long vals[test_num]; for (size_t i = 0; i < test_num; i++) { vals[i] = rand() % 100000 + 1; } - struct fieldstat_tag tags[5]; - tags[0] = TEST_TAG_INT; - tags[1] = TEST_TAG_STRING; - tags[2] = TEST_TAG_DOUBLE; - tags[3] = TEST_TAG_INT; - tags[4] = TEST_TAG_INT; + struct field fields[5]; + fields[0] = TEST_FIELD_INT; + fields[1] = TEST_FIELD_STRING; + fields[2] = TEST_FIELD_DOUBLE; + fields[3] = TEST_FIELD_INT; + fields[4] = TEST_FIELD_INT; clock_t start = clock(); for (size_t i = 0; i < test_num; i++) { - fieldstat_hist_record(instance, 0, 0, tags, 5, vals[i]); + fieldstat_histogram_record(instance, 0, 0, fields, 5, vals[i]); } clock_t end = clock(); double seconds = (double)(end - start) / test_num; - printf("performance_test_add_cells_histogram_record time 5 tags cost: %f\n", seconds); + printf("performance_test_add_cells_histogram_record time 5 fields cost: %f\n", seconds); EXPECT_TRUE(seconds < 1); fieldstat_free(instance); } @@ -377,27 +387,27 @@ TEST(test_performance, performance_test_add_cells_histogram_record_5tags) TEST(test_performance, performance_test_add_cells_hll_add_5tags) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_hll(instance, "test", 6); + test_fieldstat_cube_create(instance, &TEST_FIELD_INT_2, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_hll(instance, 0, "test", 6); size_t test_num = 100000; std::string vals[test_num]; for (size_t i = 0; i < test_num; i++) { vals[i] = std::to_string(rand() % 1000000 + 1); } - struct fieldstat_tag tags[5]; - tags[0] = TEST_TAG_INT; - tags[1] = TEST_TAG_STRING; - tags[2] = TEST_TAG_DOUBLE; - tags[3] = TEST_TAG_INT; - tags[4] = TEST_TAG_INT; + struct field fields[5]; + fields[0] = TEST_FIELD_INT; + fields[1] = TEST_FIELD_STRING; + fields[2] = TEST_FIELD_DOUBLE; + fields[3] = TEST_FIELD_INT; + fields[4] = TEST_FIELD_INT; clock_t start = clock(); for (size_t i = 0; i < test_num; i++) { - fieldstat_hll_add(instance, 0, 0, tags, 5, vals[i].c_str(), vals[i].length()); + fieldstat_hll_add(instance, 0, 0, fields, 5, vals[i].c_str(), vals[i].length()); } clock_t end = clock(); double seconds = (double)(end - start) / test_num; - printf("performance_test_add_cells_hll_add time 5 tags cost: %f\n", seconds); + printf("performance_test_add_cells_hll_add time 5 fields cost: %f\n", seconds); EXPECT_TRUE(seconds < 1); fieldstat_free(instance); } @@ -414,22 +424,22 @@ TEST(test_performance, export_many_cells) const int CUBE_NUM = 10; const int METRIC_NUM = 10; - Fieldstat_tag_list_wrapper *tags[TAG_NUM]; + Fieldstat_tag_list_wrapper *fields[TAG_NUM]; for (int i = 0; i < TAG_NUM; i++) { - tags[i] = new Fieldstat_tag_list_wrapper("my key", i); + fields[i] = new Fieldstat_tag_list_wrapper("my key", i); } struct fieldstat *instance = fieldstat_new(); for (int i = 0; i < CUBE_NUM; i++) { Fieldstat_tag_list_wrapper cube_tag("shared key", i); - int cube_id = fieldstat_create_cube(instance, cube_tag.get_tag(), cube_tag.get_tag_count(), SAMPLING_MODE_COMPREHENSIVE, MAX_CELL_NUM); + int cube_id = test_fieldstat_cube_create(instance, cube_tag.get_tag(), cube_tag.get_tag_count(), SAMPLING_MODE_COMPREHENSIVE, MAX_CELL_NUM); for (int j = 0; j < METRIC_NUM; j++) { string metric_name = "metric name" + to_string(i) + to_string(j); - int metric_id = fieldstat_register_counter(instance, metric_name.c_str()); + int metric_id = fieldstat_register_counter(instance, cube_id, metric_name.c_str()); for (int k = 0; k < MAX_CELL_NUM; k++) { - fieldstat_counter_incrby(instance, cube_id, metric_id, tags[rand() % TAG_NUM]->get_tag(), 1, 1); + fieldstat_counter_incrby(instance, cube_id, metric_id, fields[rand() % TAG_NUM]->get_tag(), 1, 1); } } } @@ -447,7 +457,7 @@ TEST(test_performance, export_many_cells) fieldstat_free(instance); for (int i = 0; i < TAG_NUM; i++) { - delete tags[i]; + delete fields[i]; } } @@ -496,12 +506,12 @@ TEST(test_performance, callibrate_unchanged) fieldstat_free(instance_dest); } -struct fieldstat *construct_fs_with_many_cells(int cell_num, enum sampling_mode mode) +struct fieldstat *construct_fs_with_many_cells(int cell_num) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_TAG_INT, 1, mode, cell_num); - fieldstat_register_counter(instance, "test"); - struct fieldstat_tag tmp_tag = TEST_TAG_INT; + test_fieldstat_cube_create(instance, &TEST_FIELD_INT, 1, SAMPLING_MODE_COMPREHENSIVE, cell_num); + fieldstat_register_counter(instance, 0, "test"); + struct field tmp_tag = TEST_FIELD_INT; for (int i = 0; i < cell_num; i++) { tmp_tag.value_longlong = i; fieldstat_counter_incrby(instance, 0, 0, &tmp_tag, 1, 1); @@ -512,7 +522,7 @@ struct fieldstat *construct_fs_with_many_cells(int cell_num, enum sampling_mode TEST(test_performance, reset_many_cells) { - struct fieldstat *instance = construct_fs_with_many_cells(1000, SAMPLING_MODE_COMPREHENSIVE); // many empty cubes, 10 metrics is a common case + struct fieldstat *instance = construct_fs_with_many_cells(1000); // many empty cubes, 10 metrics is a common case clock_t start = clock(); fieldstat_reset(instance); clock_t end = clock(); diff --git a/test/test_register_and_reset.cpp b/test/test_register_and_reset.cpp index 57c947e..b79da54 100644 --- a/test/test_register_and_reset.cpp +++ b/test/test_register_and_reset.cpp @@ -3,137 +3,345 @@ #include "fieldstat.h" #include "utils.hpp" +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *dimensions, size_t n_dimensions, enum sampling_mode mode, int k) +{ + assert(mode == SAMPLING_MODE_COMPREHENSIVE); + int ret = fieldstat_cube_create(instance, dimensions, n_dimensions); + fieldstat_cube_set_sampling(instance, ret, mode, k, 0); + return ret; +} -TEST(test_register, reset_and_version) +TEST(test_register, delete_cube_and_register_and_origin_position) { struct fieldstat *instance = fieldstat_new(); - EXPECT_EQ(fieldstat_get_version(instance), 0); - fieldstat_reset(instance); - EXPECT_EQ(fieldstat_get_version(instance), 1); - fieldstat_reset(instance); - fieldstat_reset(instance); - EXPECT_EQ(fieldstat_get_version(instance), 3); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_cube_destroy(instance, cube_id); + cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + EXPECT_EQ(cube_id, 0); + EXPECT_EQ(fieldstat_find_cube(instance, &TEST_SHARED_TAG, 1) , 0); + fieldstat_free(instance); +} + +TEST(test_register, delete_comprehensive_cube_with_cells_and_metrics) +{ + struct fieldstat *instance = fieldstat_new(); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); + + fieldstat_cube_destroy(instance, cube_id); + + struct field_list *tag_list = fieldstat_cube_get_dimensions(instance, cube_id); + EXPECT_EQ(tag_list, nullptr); + int cube_id_ret = fieldstat_find_cube(instance, &TEST_SHARED_TAG, 1); + EXPECT_EQ(cube_id_ret, FS_ERR_INVALID_DIMENSION); fieldstat_free(instance); } -TEST(test_register, delete_cube_and_version_increase) +TEST(test_register, delete_topk_cube_with_cells_and_metrics) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - EXPECT_EQ(fieldstat_get_cube_version(instance, cube_id), 0); - int ret = fieldstat_destroy_cube(instance, cube_id); - EXPECT_EQ(ret, 0); - EXPECT_EQ(fieldstat_get_cube_version(instance, cube_id), FS_ERR_INVALID_CUBE_ID); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, metric_id); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); - cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - EXPECT_EQ(fieldstat_get_cube_version(instance, cube_id), 1); + fieldstat_cube_destroy(instance, cube_id); + struct field_list *tag_list = fieldstat_cube_get_dimensions(instance, cube_id); + EXPECT_EQ(tag_list, nullptr); + int cube_id_ret = fieldstat_find_cube(instance, &TEST_SHARED_TAG, 1); + EXPECT_EQ(cube_id_ret, FS_ERR_INVALID_DIMENSION); fieldstat_free(instance); } -TEST(test_register, query_on_wrong_version) +TEST(test_register, delete_spreadsketch_cube_with_cells_and_metrics) { - EXPECT_EQ(fieldstat_get_cube_version(NULL, 1), FS_ERR_NULL_HANDLER); struct fieldstat *instance = fieldstat_new(); - EXPECT_EQ(fieldstat_get_cube_version(instance, 1), FS_ERR_INVALID_CUBE_ID); - EXPECT_EQ(fieldstat_get_cube_version(instance, -1), FS_ERR_INVALID_CUBE_ID); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id1 = fieldstat_register_counter(instance, cube_id, "counter"); + int metric_primary = fieldstat_register_hll(instance, cube_id, "hll_primary", 5); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, 10, metric_primary); + + fieldstat_counter_incrby(instance, cube_id, metric_id1, &TEST_FIELD_INT, 1, 1); + fieldstat_hll_add_field(instance, cube_id, metric_primary, &TEST_FIELD_INT, 1, &TEST_FIELD_DOUBLE, 1); + + fieldstat_cube_destroy(instance, cube_id); + struct field_list *tag_list = fieldstat_cube_get_dimensions(instance, cube_id); + EXPECT_EQ(tag_list, nullptr); + int cube_id_ret = fieldstat_find_cube(instance, &TEST_SHARED_TAG, 1); + EXPECT_EQ(cube_id_ret, FS_ERR_INVALID_DIMENSION); + fieldstat_free(instance); } -TEST(test_register, delete_cube_and_register_and_origin_position) +int test_get_max_metric_id(const struct fieldstat *instance) +{ + int *metric_id_out; + size_t n_metric; + (void)fieldstat_cube_get_metrics(instance, 0, &metric_id_out, &n_metric); + free(metric_id_out); + return n_metric - 1; +} + +TEST(test_register, reset_and_try_to_query_cell_comprehensive) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_destroy_cube(instance, cube_id); - cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - EXPECT_EQ(cube_id, 0); - EXPECT_EQ(fieldstat_find_cube(instance, &TEST_SHARED_TAG, 1) , 0); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); + + fieldstat_reset(instance); + long long value; + EXPECT_EQ(fieldstat_counter_get(instance, cube_id, &TEST_FIELD_LIST_INT, metric_id, &value), FS_ERR_INVALID_DIMENSION); + + size_t n_cell; + struct field_list *tag_list; + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); + EXPECT_EQ(n_cell, 0); + fieldstat_free(instance); } -TEST(test_register, delete_comprehensive_cube_with_cells_and_metrics) +TEST(test_register, reset_and_try_to_query_metric) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 1); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_counter = fieldstat_register_counter(instance, cube_id, "counter"); + int metric_hll = fieldstat_register_hll(instance, cube_id, "hll", 5); + int metric_hist = fieldstat_register_histogram(instance, cube_id, "hist", 0, 10000, 5); + int metric_operated_after_reset = fieldstat_register_counter(instance, cube_id, "counter_after_reset"); + + fieldstat_counter_incrby(instance, cube_id, metric_counter, &TEST_FIELD_INT, 1, 1); + fieldstat_hll_add(instance, cube_id, metric_counter, &TEST_FIELD_INT, 1, "1", 1); + fieldstat_histogram_record(instance, cube_id, metric_hist, &TEST_FIELD_INT, 1, 1000); + + fieldstat_reset(instance); + fieldstat_counter_incrby(instance, cube_id, metric_operated_after_reset, &TEST_FIELD_INT, 1, 1); + + long long value; + double value_hll; + EXPECT_EQ(fieldstat_counter_get(instance, cube_id, &TEST_FIELD_LIST_INT, metric_counter, &value), FS_ERR_INVALID_METRIC_ID); + EXPECT_EQ(fieldstat_hll_get(instance, cube_id, &TEST_FIELD_LIST_INT, metric_hll, &value_hll), FS_ERR_INVALID_METRIC_ID); + EXPECT_EQ(fieldstat_histogram_value_at_percentile(instance, cube_id, &TEST_FIELD_LIST_INT, metric_hist, 0.5), FS_ERR_INVALID_METRIC_ID); + EXPECT_EQ(fieldstat_counter_get(instance, cube_id, &TEST_FIELD_LIST_INT, metric_operated_after_reset, &value), FS_OK); - fieldstat_destroy_cube(instance, cube_id); fieldstat_free(instance); } -TEST(test_register, delete_topk_cube_with_cells_and_metrics) +TEST(test_register, reset_and_try_to_query_cell_topk) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - int metric_id = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 1); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, metric_id); + + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); + + fieldstat_reset(instance); + long long value; + EXPECT_EQ(fieldstat_counter_get(instance, cube_id, &TEST_FIELD_LIST_INT, metric_id, &value), FS_ERR_INVALID_DIMENSION); + + size_t n_cell; + struct field_list *tag_list; + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); + EXPECT_EQ(n_cell, 0); - fieldstat_destroy_cube(instance, cube_id); fieldstat_free(instance); } -int test_get_max_metric_id(const struct fieldstat *instance) +TEST(test_register, reset_and_try_to_query_cell_spreadsketch) { - int *metric_id_out; - size_t n_metric; - (void)fieldstat_get_metrics(instance, &metric_id_out, &n_metric); - free(metric_id_out); - return n_metric - 1; + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance, cube_id, "hll", 5); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, 10, metric_id); + fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, "12abc", 5); + + fieldstat_reset(instance); + double value; + EXPECT_EQ(fieldstat_hll_get(instance, cube_id, &TEST_FIELD_LIST_INT, metric_id, &value), FS_ERR_INVALID_DIMENSION); + + size_t n_cell; + struct field_list *tag_list; + fieldstat_cube_get_cells(instance, cube_id, &tag_list, &n_cell); + EXPECT_EQ(n_cell, 0); + + fieldstat_free(instance); } -TEST(test_register, reset_and_try_to_query_cell) +TEST(test_register, reset_and_new_cell_comprehensive) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 1); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 2); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, 1); + int ret = fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 1); + EXPECT_EQ(ret, FS_ERR_TOO_MANY_CELLS); fieldstat_reset(instance); - EXPECT_EQ(test_get_max_metric_id(instance), 0); - long long value; - EXPECT_EQ(fieldstat_counter_get(instance, cube_id, metric_id, &TEST_TAG_LIST_INT, &value), FS_ERR_INVALID_TAG); + ret = fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_STRING, 1, 1); + EXPECT_EQ(ret, FS_OK); + + fieldstat_free(instance); +} + +TEST(test_register, reset_and_new_cell_topk) +{ + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 1, metric_id); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 100);//100: bigger value + int ret = fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, 1); + EXPECT_EQ(ret, FS_ERR_TOO_MANY_CELLS); + + fieldstat_reset(instance); + ret = fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, 1); + EXPECT_EQ(ret, FS_OK); fieldstat_free(instance); } -TEST(test_register, reset_and_new_cell) +TEST(test_register, reset_and_new_cell_spreadsketch) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 2); - int metric_id = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 1); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_DOUBLE, 1, 1); - int ret = fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 1); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance, cube_id, "hll", 5); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, 1, metric_id); + // spread sketch will store more data than expected cell number 1. So loop for many cells first to trigger the error + struct field test_tag_long = TEST_FIELD_INT; + for (int i = 0; i < 10000; i++) { + test_tag_long.value_longlong = i; + fieldstat_hll_add(instance, cube_id, metric_id, &test_tag_long, 1, "12abc", 5); + } + int ret = fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, "12abc", 5); EXPECT_EQ(ret, FS_ERR_TOO_MANY_CELLS); fieldstat_reset(instance); - ret = fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_STRING, 1, 1); + ret = fieldstat_hll_add(instance, cube_id, metric_id, &TEST_FIELD_DOUBLE, 1, "12abc", 5); EXPECT_EQ(ret, FS_OK); fieldstat_free(instance); } +TEST(test_register, ensure_recovery_more_faster_comprehensive) { + struct fieldstat *instance = fieldstat_new(); + int cell_num = 1000; + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, cell_num); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + struct field test_tag_long = TEST_FIELD_INT; + + clock_t start = clock(); + for (int i = 0; i < cell_num; i++) { + test_tag_long.value_longlong = i; + fieldstat_counter_incrby(instance, cube_id, metric_id, &test_tag_long, 1, 1); + } + clock_t end = clock(); + clock_t duration_initialize = end - start; + + fieldstat_reset(instance); + + start = clock(); + for (int i = 0; i < cell_num; i++) { + test_tag_long.value_longlong = i; + fieldstat_counter_incrby(instance, cube_id, metric_id, &test_tag_long, 1, 1); + } + end = clock(); + clock_t duration_reset = end - start; + + EXPECT_LT(duration_reset, duration_initialize); + + fieldstat_free(instance); +} + +TEST(test_register, ensure_recovery_more_faster_topk) { + struct fieldstat *instance = fieldstat_new(); + int cell_num = 1000; + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, cell_num, metric_id); + + struct field test_tag_long = TEST_FIELD_INT; + + clock_t start = clock(); + for (int i = 0; i < cell_num; i++) { + test_tag_long.value_longlong = i; + fieldstat_counter_incrby(instance, cube_id, metric_id, &test_tag_long, 1, 1); + } + clock_t end = clock(); + clock_t duration_initialize = end - start; + + fieldstat_reset(instance); + + start = clock(); + for (int i = 0; i < cell_num; i++) { + test_tag_long.value_longlong = i; + fieldstat_counter_incrby(instance, cube_id, metric_id, &test_tag_long, 1, 1); + } + end = clock(); + clock_t duration_reset = end - start; + + EXPECT_LT(duration_reset, duration_initialize); + + fieldstat_free(instance); +} + +TEST(test_register, ensure_recovery_more_faster_spreadsketch) { + struct fieldstat *instance = fieldstat_new(); + int cell_num = 1000; + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_hll(instance, cube_id, "counter", 6); + fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOP_CARDINALITY, cell_num, metric_id); + char long_string[1000]; + memset(long_string, 'a', 1000); + long_string[999] = '\0'; + struct field test_tag_long = {long_string, FIELD_VALUE_INTEGER, {.value_longlong = 0}}; + + clock_t start = clock(); + for (int i = 0; i < cell_num; i++) { + test_tag_long.value_longlong = i; + fieldstat_hll_add(instance, cube_id, metric_id, &test_tag_long, 1, "1", 1); + } + clock_t end = clock(); + clock_t duration_initialize = end - start; + + fieldstat_reset(instance); + + start = clock(); + for (int i = 0; i < cell_num; i++) { + test_tag_long.value_longlong = i; + fieldstat_hll_add(instance, cube_id, metric_id, &test_tag_long, 1, "1", 1); + } + end = clock(); + clock_t duration_reset = end - start; + + EXPECT_LT(duration_reset, duration_initialize); + + fieldstat_free(instance); +} + TEST(test_register, register_many_cubes) { struct fieldstat *instance = fieldstat_new(); int registered_cube = 10000; // will trigger realloc many times - struct fieldstat_tag shared_tag = TEST_SHARED_TAG; + struct field shared_tag = TEST_SHARED_TAG; for (int i = 0; i < registered_cube; i++) { shared_tag.value_longlong = i; - int cube_id = fieldstat_create_cube(instance, &shared_tag, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(instance, &shared_tag, 1, SAMPLING_MODE_COMPREHENSIVE, 10); EXPECT_EQ(cube_id, i); + fieldstat_register_counter(instance, cube_id, "counter"); } // try to use the cube - int metric_id = fieldstat_register_counter(instance, "counter"); for (int i = 0; i < registered_cube; i++) { - fieldstat_counter_incrby(instance, i, metric_id, &TEST_TAG_INT, 1, i); + fieldstat_counter_incrby(instance, i, 0, &TEST_FIELD_INT, 1, i); } for (int i = 0; i < registered_cube; i++) { long long result; - fieldstat_counter_get(instance, i, 0, &TEST_TAG_LIST_INT, &result); + fieldstat_counter_get(instance, i, &TEST_FIELD_LIST_INT, 0, &result); EXPECT_EQ(result, i); } @@ -143,18 +351,19 @@ TEST(test_register, register_many_cubes) TEST(test_register, add_many_tagged_cells) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - struct fieldstat_tag test_tag_long[100]; - for (int i = 0; i < 100; i++) { - test_tag_long[i] = TEST_TAG_INT; // will trigger realloc + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + size_t n_field = 1000; + struct field test_tag_long[n_field]; + for (size_t i = 0; i < n_field; i++) { + test_tag_long[i] = TEST_FIELD_INT; // will trigger realloc } - int metric_id = fieldstat_register_counter(instance, "counter"); - fieldstat_counter_incrby(instance, cube_id, metric_id, test_tag_long, 100, 10086); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + fieldstat_counter_incrby(instance, cube_id, metric_id, test_tag_long, n_field, 10086); long long result; - struct fieldstat_tag_list tag_list = {test_tag_long, 100}; - fieldstat_counter_get(instance, cube_id, metric_id, &tag_list, &result); + struct field_list tag_list = {test_tag_long, n_field}; + fieldstat_counter_get(instance, cube_id, &tag_list, metric_id, &result); EXPECT_EQ(result, 10086); fieldstat_free(instance); @@ -163,19 +372,19 @@ TEST(test_register, add_many_tagged_cells) TEST(test_register, add_long_tagged_cells) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - struct fieldstat_tag test_tag_long = TEST_TAG_STRING; + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + struct field test_tag_long = TEST_FIELD_STRING; char *long_string = (char *)malloc(5001); memset(long_string, 'a', 5001); long_string[5000] = '\0'; test_tag_long.value_str = long_string; - int metric_id = fieldstat_register_counter(instance, "counter"); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); fieldstat_counter_incrby(instance, cube_id, metric_id, &test_tag_long, 1, 10086); long long result; - struct fieldstat_tag_list tag_list = {&test_tag_long, 1}; - fieldstat_counter_get(instance, cube_id, metric_id, &tag_list, &result); + struct field_list tag_list = {&test_tag_long, 1}; + fieldstat_counter_get(instance, cube_id, &tag_list, metric_id, &result); EXPECT_EQ(result, 10086); fieldstat_free(instance); @@ -185,21 +394,21 @@ TEST(test_register, add_long_tagged_cells) TEST(test_register, register_many_metrics) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); int metric_id = 0; for (int i = 0; i < 200; i++) { - metric_id = fieldstat_register_counter(instance, (std::string("counter ") + std::to_string(i)).c_str()); + metric_id = fieldstat_register_counter(instance, cube_id, (std::string("counter ") + std::to_string(i)).c_str()); EXPECT_EQ(metric_id, i); } for (int i = 0; i < 200; i++) { - EXPECT_EQ(fieldstat_counter_incrby(instance, cube_id, i, &TEST_TAG_INT, 1, 1), 0); + EXPECT_EQ(fieldstat_counter_incrby(instance, cube_id, i, &TEST_FIELD_INT, 1, 1), 0); } fieldstat_free(instance); } -TEST(test_register, dup_registered_info_from_empty_one) +TEST(test_register, fork_registered_info_from_empty_one) { struct fieldstat *instance = fieldstat_new(); @@ -214,16 +423,16 @@ TEST(test_register, dup_registered_info_from_empty_one) fieldstat_free(instance); } -TEST(test_register, dup_registered_info_with_cube_and_metric_without_cell) +TEST(test_register, fork_registered_info_with_cube_and_metric) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_counter(instance, "counter"); - int metric_id2 = fieldstat_register_counter(instance, "counter2"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 1); - int cube_id_del = fieldstat_create_cube(instance, &TEST_TAG_DOUBLE_collided, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int cube_id2 = fieldstat_create_cube(instance, &TEST_TAG_DOUBLE, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_destroy_cube(instance, cube_id_del); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + int metric_id2 = fieldstat_register_counter(instance, cube_id, "counter2"); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); + int cube_id_del = test_fieldstat_cube_create(instance, &TEST_FIELD_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + test_fieldstat_cube_create(instance, &TEST_FIELD_DOUBLE, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_cube_destroy(instance, cube_id_del); struct fieldstat *dup = fieldstat_fork(instance); @@ -231,18 +440,25 @@ TEST(test_register, dup_registered_info_with_cube_and_metric_without_cell) int cube_num; fieldstat_get_cubes(dup, &cube_ids, &cube_num); EXPECT_EQ(cube_num, 2); - EXPECT_EQ(cube_ids[0], cube_id); - EXPECT_EQ(cube_ids[1], cube_id2); - free(cube_ids); - - EXPECT_STREQ(fieldstat_get_metric_name(dup, metric_id), "counter"); - EXPECT_STREQ(fieldstat_get_metric_name(dup, metric_id2), "counter2"); - - struct fieldstat_tag_list *tag_list = NULL; + struct field_list *tag_list = NULL; + + tag_list = fieldstat_cube_get_dimensions(dup, cube_ids[0]); + EXPECT_STREQ(tag_list->field[0].key, TEST_SHARED_TAG.key); + fieldstat_field_list_arr_free(tag_list, 1); size_t n_cell = 0; - fieldstat_get_cells_used_by_metric(dup, cube_id, metric_id, &tag_list, &n_cell); + fieldstat_cube_get_cells(dup, cube_ids[0], &tag_list, &n_cell); EXPECT_EQ(n_cell, 0); + tag_list = fieldstat_cube_get_dimensions(dup, cube_ids[1]); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_DOUBLE.key); + + fieldstat_field_list_arr_free(tag_list, 1); + + EXPECT_STREQ(fieldstat_get_metric_name(dup, cube_ids[0], metric_id), "counter"); + EXPECT_STREQ(fieldstat_get_metric_name(dup, cube_ids[0], metric_id2), "counter2"); + EXPECT_EQ(fieldstat_get_metric_name(dup, cube_ids[1], metric_id), nullptr); + + free(cube_ids); fieldstat_free(dup); fieldstat_free(instance); } @@ -252,16 +468,16 @@ TEST(test_register, unregister_cube_on_wrong_instance) struct fieldstat *instance = fieldstat_new(); struct fieldstat *instance_dst = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int cube_id2 = fieldstat_create_cube(instance, &TEST_TAG_DOUBLE, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - int metric_id = fieldstat_register_counter(instance, "counter"); - int metric_id2 = fieldstat_register_counter(instance, "counter2"); - fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_TAG_INT, 1, 1); - fieldstat_counter_incrby(instance, cube_id2, metric_id2, &TEST_TAG_INT, 1, 1); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id2 = test_fieldstat_cube_create(instance, &TEST_FIELD_DOUBLE, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + int metric_id2 = fieldstat_register_counter(instance, cube_id2, "counter2"); + fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); + fieldstat_counter_incrby(instance, cube_id2, metric_id2, &TEST_FIELD_INT, 1, 1); fieldstat_merge(instance_dst, instance); - fieldstat_destroy_cube(instance_dst, 0); + fieldstat_cube_destroy(instance_dst, 0); int *cube_ids; int cube_num; @@ -272,10 +488,10 @@ TEST(test_register, unregister_cube_on_wrong_instance) fieldstat_merge(instance_dst, instance); long long val_deleted_once; - fieldstat_counter_get(instance_dst, cube_id, metric_id, &TEST_TAG_LIST_INT, &val_deleted_once); + fieldstat_counter_get(instance_dst, cube_id, &TEST_FIELD_LIST_INT,metric_id, &val_deleted_once); EXPECT_EQ(val_deleted_once, 1); - long long val_merged_twice; - fieldstat_counter_get(instance_dst, cube_id2, metric_id2, &TEST_TAG_LIST_INT, &val_merged_twice); + long long val_merged_twice = -1; + fieldstat_counter_get(instance_dst, cube_id2, &TEST_FIELD_LIST_INT, metric_id2, &val_merged_twice); EXPECT_EQ(val_merged_twice, 2); fieldstat_free(instance); @@ -286,9 +502,9 @@ TEST(test_register, unregister_cube_on_wrong_instance) TEST(test_register, register_many_cells_on_unlimited_sized_cube) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 0); - int metric_id = fieldstat_register_counter(instance, "counter"); - struct fieldstat_tag test_tag = {"abc", TAG_INTEGER, {.value_longlong = 0}}; + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 0); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + struct field test_tag = {"abc", FIELD_VALUE_INTEGER, {.value_longlong = 0}}; for (int i = 0; i < 10000; i++) { test_tag.value_longlong = i; fieldstat_counter_incrby(instance, cube_id, metric_id, &test_tag, 1, 1); @@ -296,9 +512,9 @@ TEST(test_register, register_many_cells_on_unlimited_sized_cube) for (int i = 0; i < 10000; i++) { test_tag.value_longlong = i; - struct fieldstat_tag_list tag_list = {&test_tag, 1}; + struct field_list tag_list = {&test_tag, 1}; long long value; - fieldstat_counter_get(instance, cube_id, metric_id, &tag_list, &value); + fieldstat_counter_get(instance, cube_id, &tag_list, metric_id, &value); EXPECT_EQ(value, 1); } @@ -307,105 +523,129 @@ TEST(test_register, register_many_cells_on_unlimited_sized_cube) TEST(test_register, register_cube_twice) { struct fieldstat *instance = fieldstat_new(); - fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - int cube_id2 = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - EXPECT_EQ(cube_id2, FS_ERR_INVALID_KEY); + test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id2 = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + EXPECT_EQ(cube_id2, FS_ERR_DIMENSION_ALREADY_EXISTS); fieldstat_free(instance); } TEST(test_register, find_cube) { struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); int find_cube_id = fieldstat_find_cube(instance, &TEST_SHARED_TAG, 1); EXPECT_EQ(cube_id, find_cube_id); - int find_cube_id2 = fieldstat_find_cube(instance, &TEST_TAG_DOUBLE, 1); - EXPECT_EQ(find_cube_id2, FS_ERR_INVALID_KEY); + int find_cube_id2 = fieldstat_find_cube(instance, &TEST_FIELD_DOUBLE, 1); + EXPECT_EQ(find_cube_id2, FS_ERR_INVALID_DIMENSION); + + fieldstat_free(instance); +} + +TEST(test_register, set_sampling_error) { + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int ret = fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, 0); + EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_ID); + int metric_id = fieldstat_register_hll(instance, cube_id, "hll", 5); + ret = fieldstat_cube_set_sampling(instance, cube_id, SAMPLING_MODE_TOPK, 10, metric_id); + EXPECT_EQ(ret, FS_ERR_INVALID_METRIC_TYPE); fieldstat_free(instance); } TEST(test_register, register_metric_twice) { struct fieldstat *instance = fieldstat_new(); - fieldstat_register_counter(instance, "counter"); - int metric_id2 = fieldstat_register_counter(instance, "counter"); - EXPECT_EQ(metric_id2, FS_ERR_INVALID_KEY); + int cube_id = test_fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + + fieldstat_register_counter(instance, cube_id, "counter"); + int metric_id2 = fieldstat_register_counter(instance, cube_id, "counter"); + EXPECT_EQ(metric_id2, FS_ERR_METRIC_NAME_ALREADY_EXISTS); + fieldstat_free(instance); +} + +TEST(test_register, add_on_uninitialized_cube) { + struct fieldstat *instance = fieldstat_new(); + int cube_id = fieldstat_cube_create(instance, &TEST_SHARED_TAG, 1); + int metric_id = fieldstat_register_counter(instance, cube_id, "counter"); + // fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1); + EXPECT_EQ(fieldstat_counter_incrby(instance, cube_id, metric_id, &TEST_FIELD_INT, 1, 1), FS_ERR_CUBE_SAMPLING_NOT_INITIALIZED); + fieldstat_free(instance); } TEST(calibrate, target_one_more_metric) { struct fieldstat *master = fieldstat_new(); - int cube_id = fieldstat_create_cube(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_counter(master, "counter"); + int cube_id = test_fieldstat_cube_create(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_counter(master, cube_id, "counter"); struct fieldstat *target = fieldstat_fork(master); - EXPECT_EQ(fieldstat_register_counter(target, "counter2"), 1); + EXPECT_EQ(fieldstat_register_counter(target, cube_id, "counter2"), 1); fieldstat_calibrate(master, target); EXPECT_EQ(test_get_max_metric_id(target), 0); - EXPECT_STREQ(fieldstat_get_metric_name(target, 0), "counter"); - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, cube_id); - EXPECT_STREQ(tag_list->tag[0].key, TEST_SHARED_TAG.key); + EXPECT_STREQ(fieldstat_get_metric_name(target, cube_id, 0), "counter"); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, cube_id); + EXPECT_STREQ(tag_list->field[0].key, TEST_SHARED_TAG.key); fieldstat_free(master); fieldstat_free(target); - fieldstat_tag_list_arr_free(tag_list, 1); + fieldstat_field_list_arr_free(tag_list, 1); } TEST(calibrate, master_one_more_metric) { struct fieldstat *master = fieldstat_new(); - int cube_id = fieldstat_create_cube(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_counter(master, "counter"); + int cube_id = test_fieldstat_cube_create(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_counter(master, cube_id, "counter"); struct fieldstat *target = fieldstat_fork(master); - EXPECT_EQ(fieldstat_register_counter(master, "counter2"), 1); + EXPECT_EQ(fieldstat_register_counter(master, cube_id, "counter2"), 1); fieldstat_calibrate(master, target); EXPECT_EQ(test_get_max_metric_id(target), 1); - EXPECT_STREQ(fieldstat_get_metric_name(target, 0), "counter"); - EXPECT_STREQ(fieldstat_get_metric_name(target, 1), "counter2"); - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, cube_id); - EXPECT_STREQ(tag_list->tag[0].key, TEST_SHARED_TAG.key); + EXPECT_STREQ(fieldstat_get_metric_name(target, cube_id,0), "counter"); + EXPECT_STREQ(fieldstat_get_metric_name(target, cube_id,1), "counter2"); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, cube_id); + EXPECT_STREQ(tag_list->field[0].key, TEST_SHARED_TAG.key); fieldstat_free(master); fieldstat_free(target); - fieldstat_tag_list_arr_free(tag_list, 1); + fieldstat_field_list_arr_free(tag_list, 1); } // different metric on same cube TEST(calibrate, different_metric) { struct fieldstat *master = fieldstat_new(); - int cube_id = fieldstat_create_cube(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_counter(master, "counter"); + int cube_id = test_fieldstat_cube_create(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_counter(master, cube_id, "counter"); struct fieldstat *target = fieldstat_fork(master); - EXPECT_EQ(fieldstat_register_counter(target, "counter2"), 1); - EXPECT_EQ(fieldstat_register_counter(master, "hi i am master new"), 1); + EXPECT_EQ(fieldstat_register_counter(target, cube_id, "counter2"), 1); + EXPECT_EQ(fieldstat_register_counter(master, cube_id, "hi i am master new"), 1); fieldstat_calibrate(master, target); EXPECT_EQ(test_get_max_metric_id(target), 1); - EXPECT_STREQ(fieldstat_get_metric_name(target, 0), "counter"); - EXPECT_STREQ(fieldstat_get_metric_name(target, 1), "hi i am master new"); - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, cube_id); - EXPECT_STREQ(tag_list->tag[0].key, TEST_SHARED_TAG.key); + EXPECT_STREQ(fieldstat_get_metric_name(target, cube_id, 0), "counter"); + EXPECT_STREQ(fieldstat_get_metric_name(target, cube_id, 1), "hi i am master new"); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, cube_id); + EXPECT_STREQ(tag_list->field[0].key, TEST_SHARED_TAG.key); fieldstat_free(master); fieldstat_free(target); - fieldstat_tag_list_arr_free(tag_list, 1); + fieldstat_field_list_arr_free(tag_list, 1); } TEST(calibrate, target_more_cube) { struct fieldstat *master = fieldstat_new(); - int cube_id = fieldstat_create_cube(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_counter(master, "counter"); + int cube_id = test_fieldstat_cube_create(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_register_counter(master, cube_id, "counter"); struct fieldstat *target = fieldstat_fork(master); - int cube_id2 = fieldstat_create_cube(target, &TEST_TAG_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id2 = test_fieldstat_cube_create(target, &TEST_FIELD_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 10); EXPECT_EQ(cube_id2, 1); - fieldstat_register_counter(target, "counter2"); + fieldstat_register_counter(target, cube_id, "counter2"); fieldstat_calibrate(master, target); @@ -417,24 +657,24 @@ TEST(calibrate, target_more_cube) free(cube_ids); EXPECT_EQ(test_get_max_metric_id(target), 0); - EXPECT_STREQ(fieldstat_get_metric_name(target, 0), "counter"); - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, cube_id); - EXPECT_STREQ(tag_list->tag[0].key, TEST_SHARED_TAG.key); + EXPECT_STREQ(fieldstat_get_metric_name(target, cube_id, 0), "counter"); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, cube_id); + EXPECT_STREQ(tag_list->field[0].key, TEST_SHARED_TAG.key); EXPECT_EQ(fieldstat_find_cube(target, &TEST_SHARED_TAG, 1), 0); - EXPECT_EQ(fieldstat_find_cube(target, &TEST_TAG_STRING, 1), FS_ERR_INVALID_KEY); + EXPECT_EQ(fieldstat_find_cube(target, &TEST_FIELD_STRING, 1), FS_ERR_INVALID_DIMENSION); fieldstat_free(master); fieldstat_free(target); - fieldstat_tag_list_arr_free(tag_list, 1); + fieldstat_field_list_arr_free(tag_list, 1); } TEST(calibrate, master_more_cube) { struct fieldstat *master = fieldstat_new(); - int cube_id = fieldstat_create_cube(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); struct fieldstat *target = fieldstat_fork(master); - int cube_id2 = fieldstat_create_cube(master, &TEST_TAG_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id2 = test_fieldstat_cube_create(master, &TEST_FIELD_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 10); fieldstat_calibrate(master, target); @@ -446,57 +686,55 @@ TEST(calibrate, master_more_cube) EXPECT_EQ(cube_ids[1], cube_id2); free(cube_ids); - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, cube_id); - EXPECT_STREQ(tag_list->tag[0].key, TEST_SHARED_TAG.key); - struct fieldstat_tag_list *tag_list2 = fieldstat_get_shared_tags(target, cube_id2); - EXPECT_STREQ(tag_list2->tag[0].key, TEST_TAG_STRING.key); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, cube_id); + EXPECT_STREQ(tag_list->field[0].key, TEST_SHARED_TAG.key); + struct field_list *tag_list2 = fieldstat_cube_get_dimensions(target, cube_id2); + EXPECT_STREQ(tag_list2->field[0].key, TEST_FIELD_STRING.key); - EXPECT_EQ(fieldstat_find_cube(target, &TEST_TAG_STRING, 1), 1); + EXPECT_EQ(fieldstat_find_cube(target, &TEST_FIELD_STRING, 1), 1); EXPECT_EQ(fieldstat_find_cube(target, &TEST_SHARED_TAG, 1), 0); fieldstat_free(master); fieldstat_free(target); - fieldstat_tag_list_arr_free(tag_list, 1); - fieldstat_tag_list_arr_free(tag_list2, 1); + fieldstat_field_list_arr_free(tag_list, 1); + fieldstat_field_list_arr_free(tag_list2, 1); } TEST(calibrate, master_change_cube) { struct fieldstat *master = fieldstat_new(); - int cube_id = fieldstat_create_cube(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - fieldstat_register_counter(master, "counter"); + int cube_id = test_fieldstat_cube_create(master, &TEST_SHARED_TAG, 1, SAMPLING_MODE_COMPREHENSIVE, 10); struct fieldstat *target = fieldstat_fork(master); - fieldstat_destroy_cube(master, cube_id); - fieldstat_create_cube(master, &TEST_TAG_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + fieldstat_cube_destroy(master, cube_id); + test_fieldstat_cube_create(master, &TEST_FIELD_STRING, 1, SAMPLING_MODE_COMPREHENSIVE, 10); fieldstat_calibrate(master, target); - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, cube_id); - EXPECT_STREQ(tag_list->tag[0].key, TEST_TAG_STRING.key); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, cube_id); + EXPECT_STREQ(tag_list->field[0].key, TEST_FIELD_STRING.key); - EXPECT_EQ(fieldstat_find_cube(target, &TEST_TAG_STRING, 1), 0); - EXPECT_EQ(fieldstat_get_cube_version(target, cube_id), 1); + EXPECT_EQ(fieldstat_find_cube(target, &TEST_FIELD_STRING, 1), 0); fieldstat_free(master); fieldstat_free(target); - fieldstat_tag_list_arr_free(tag_list, 1); + fieldstat_field_list_arr_free(tag_list, 1); } TEST(calibrate, master_many_cube) { struct fieldstat *master = fieldstat_new(); int registered_cube = 3000; // will trigger realloc 1 times - struct fieldstat_tag shared_tag = TEST_SHARED_TAG; + struct field shared_tag = TEST_SHARED_TAG; for (int i = 0; i < registered_cube; i++) { shared_tag.value_longlong = i; - int cube_id = fieldstat_create_cube(master, &shared_tag, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(master, &shared_tag, 1, SAMPLING_MODE_COMPREHENSIVE, 10); EXPECT_EQ(cube_id, i); } struct fieldstat *target = fieldstat_fork(master); int new_registered = 5000; for (int i = 0; i < new_registered; i++) { shared_tag.value_longlong = i + registered_cube; - int cube_id = fieldstat_create_cube(master, &shared_tag, 1, SAMPLING_MODE_COMPREHENSIVE, 10); + int cube_id = test_fieldstat_cube_create(master, &shared_tag, 1, SAMPLING_MODE_COMPREHENSIVE, 10); EXPECT_EQ(cube_id, i + registered_cube); } @@ -517,32 +755,6 @@ TEST(calibrate, master_many_cube) fieldstat_free(target); } -TEST(test_register, get_cube_mode) -{ - // int fieldstat_get_cube_mode(const struct fieldstat *instance, int cube_id, enum sampling_mode *mode, int *primary_metric_id) - - struct fieldstat *instance = fieldstat_new(); - int cube_id = fieldstat_create_cube(instance, &TEST_SHARED_TAG, 1, SAMPLING_MODE_TOPK, 10); - fieldstat_register_counter(instance, "counter"); - fieldstat_register_counter(instance, "counter2"); - fieldstat_cube_set_primary_metric(instance, cube_id, 1); - int cube_id2 = fieldstat_create_cube(instance, &TEST_TAG_INT, 1, SAMPLING_MODE_COMPREHENSIVE, 10); - - enum sampling_mode mode; - int primary_metric_id; - EXPECT_EQ(fieldstat_get_cube_mode(instance, cube_id, &mode, &primary_metric_id), 0); - EXPECT_EQ(mode, SAMPLING_MODE_TOPK); - EXPECT_EQ(primary_metric_id, 1); - - EXPECT_EQ(fieldstat_get_cube_mode(instance, cube_id2, &mode, &primary_metric_id), 0); - EXPECT_EQ(mode, SAMPLING_MODE_COMPREHENSIVE); - EXPECT_EQ(primary_metric_id, -1); - - EXPECT_EQ(fieldstat_get_cube_mode(instance, 100, &mode, &primary_metric_id), FS_ERR_INVALID_CUBE_ID); - - fieldstat_free(instance); -} - // issue: https://jira.geedge.net/browse/TSG-20140 // 流程: // calibrate调用前: @@ -552,7 +764,7 @@ TEST(test_register, get_cube_mode) // calibrate调用时,依次比较每个cube id,id:0时,将master[0] 同步,同步时,会先删除A,然后添加B' // replica:B' B (B' B) -// calibrate 继续,同步master[1],replica[1]不存在,创建新的cube。此时,不仅从id->cube 的数组中删除掉B,且从cube tag->id 的字典中删除掉B。可能会错误的删除掉B',导致两个map的对应不一致。 +// calibrate 继续,同步master[1],replica[1]不存在,创建新的cube。此时,不仅从id->cube 的数组中删除掉B,且从cube field->id 的字典中删除掉B。可能会错误的删除掉B',导致两个map的对应不一致。 // replica:B' / (B ) // 例如:find_cube(B)-> 返回1。 @@ -560,15 +772,15 @@ TEST(test_register, get_cube_mode) TEST(calibrate, issue_calibrate_wrong) { struct fieldstat *master = fieldstat_new(); - const struct fieldstat_tag *tag_A = &TEST_SHARED_TAG; - const struct fieldstat_tag *tag_B = &TEST_TAG_INT; - int cube_idA = fieldstat_create_cube(master, tag_A, 1, SAMPLING_MODE_COMPREHENSIVE, 1); - int cube_idB = fieldstat_create_cube(master, tag_B, 1, SAMPLING_MODE_COMPREHENSIVE, 1); + const struct field *tag_A = &TEST_SHARED_TAG; + const struct field *tag_B = &TEST_FIELD_INT; + int cube_idA = test_fieldstat_cube_create(master, tag_A, 1, SAMPLING_MODE_COMPREHENSIVE, 1); + int cube_idB = test_fieldstat_cube_create(master, tag_B, 1, SAMPLING_MODE_COMPREHENSIVE, 1); struct fieldstat *target = fieldstat_fork(master); - EXPECT_EQ(fieldstat_destroy_cube(master, cube_idA), FS_OK); - EXPECT_EQ(fieldstat_destroy_cube(master, cube_idB), FS_OK); - int cube_idBa = fieldstat_create_cube(master, tag_B, 1, SAMPLING_MODE_COMPREHENSIVE, 1); + EXPECT_EQ(fieldstat_cube_destroy(master, cube_idA), FS_OK); + EXPECT_EQ(fieldstat_cube_destroy(master, cube_idB), FS_OK); + int cube_idBa = test_fieldstat_cube_create(master, tag_B, 1, SAMPLING_MODE_COMPREHENSIVE, 1); EXPECT_EQ(cube_idBa, 0); fieldstat_calibrate(master, target); @@ -577,30 +789,28 @@ TEST(calibrate, issue_calibrate_wrong) int n_cubes = 0; fieldstat_get_cubes(target, &cubes_id_ret, &n_cubes); EXPECT_EQ(n_cubes, 1); - EXPECT_EQ(cubes_id_ret[0], 0); - free(cubes_id_ret); + EXPECT_EQ(fieldstat_find_cube(target, tag_A, 1), FS_ERR_INVALID_DIMENSION); + EXPECT_EQ(fieldstat_find_cube(target, tag_B, 1), cubes_id_ret[0]); - EXPECT_EQ(fieldstat_find_cube(target, tag_A, 1), FS_ERR_INVALID_KEY); - EXPECT_EQ(fieldstat_find_cube(target, tag_B, 1), 0); - - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, 0); - EXPECT_STREQ(tag_list->tag[0].key, tag_B->key); - fieldstat_tag_list_arr_free(tag_list, 1); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, cubes_id_ret[0]); + EXPECT_STREQ(tag_list->field[0].key, tag_B->key); + fieldstat_field_list_arr_free(tag_list, 1); fieldstat_free(master); fieldstat_free(target); + free(cubes_id_ret); } TEST(calibrate, delete_first_cube) { struct fieldstat *master = fieldstat_new(); - const struct fieldstat_tag *tag_A = &TEST_SHARED_TAG; - const struct fieldstat_tag *tag_B = &TEST_TAG_INT; - int cube_idA = fieldstat_create_cube(master, tag_A, 1, SAMPLING_MODE_COMPREHENSIVE, 1); - int cube_idB = fieldstat_create_cube(master, tag_B, 1, SAMPLING_MODE_COMPREHENSIVE, 1); + const struct field *tag_A = &TEST_SHARED_TAG; + const struct field *tag_B = &TEST_FIELD_INT; + int cube_idA = test_fieldstat_cube_create(master, tag_A, 1, SAMPLING_MODE_COMPREHENSIVE, 1); + int cube_idB = test_fieldstat_cube_create(master, tag_B, 1, SAMPLING_MODE_COMPREHENSIVE, 1); struct fieldstat *target = fieldstat_fork(master); - fieldstat_destroy_cube(master, cube_idA); + fieldstat_cube_destroy(master, cube_idA); fieldstat_calibrate(master, target); @@ -611,12 +821,12 @@ TEST(calibrate, delete_first_cube) EXPECT_EQ(cubes_id_ret[0], cube_idB); free(cubes_id_ret); - EXPECT_EQ(fieldstat_find_cube(target, tag_A, 1), FS_ERR_INVALID_KEY); + EXPECT_EQ(fieldstat_find_cube(target, tag_A, 1), FS_ERR_INVALID_DIMENSION); EXPECT_EQ(fieldstat_find_cube(target, tag_B, 1), 1); - struct fieldstat_tag_list *tag_list = fieldstat_get_shared_tags(target, 1); - EXPECT_STREQ(tag_list->tag[0].key, tag_B->key); - fieldstat_tag_list_arr_free(tag_list, 1); + struct field_list *tag_list = fieldstat_cube_get_dimensions(target, 1); + EXPECT_STREQ(tag_list->field[0].key, tag_B->key); + fieldstat_field_list_arr_free(tag_list, 1); fieldstat_free(master); fieldstat_free(target); @@ -625,5 +835,6 @@ TEST(calibrate, delete_first_cube) int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); + // testing::GTEST_FLAG(filter) = "test_register.reset_and_new_cell_spreadsketch"; return RUN_ALL_TESTS(); }
\ No newline at end of file diff --git a/test/test_write_json_file.cpp b/test/test_write_json_file.cpp index 6d6131c..1dba94b 100644 --- a/test/test_write_json_file.cpp +++ b/test/test_write_json_file.cpp @@ -22,23 +22,23 @@ extern "C" { extern char *fs_easy_output_to_json(struct fieldstat_easy *fs, const struct timeval *timestamp, const struct timeval *timestamp_delta); } -static struct fieldstat_easy *get_hist_fieldstat_easy() +[[gnu::unused]] static struct fieldstat_easy *get_hist_fieldstat_easy() { - struct fieldstat_tag global_tags[2]; - struct fieldstat_tag cell_tags[2]; + struct field global_tags[2]; + struct field cell_tags[2]; global_tags[0].key = "rule_id"; - global_tags[0].type = TAG_INTEGER; + global_tags[0].type = FIELD_VALUE_INTEGER; global_tags[0].value_longlong = 1; global_tags[1].key = "action"; - global_tags[1].type = TAG_CSTRING; + global_tags[1].type = FIELD_VALUE_CSTRING; global_tags[1].value_str = "deny"; cell_tags[0].key = "thread_id"; - cell_tags[0].type = TAG_INTEGER; + cell_tags[0].type = FIELD_VALUE_INTEGER; cell_tags[0].value_longlong = 1; cell_tags[1].key = "hit_rate"; - cell_tags[1].type = TAG_DOUBLE; + cell_tags[1].type = FIELD_VALUE_DOUBLE; cell_tags[1].value_double = 1.1; const char *hist_names[] = {"list_num", "max_wt_ms", "ivt_nx_itv_ms", @@ -58,24 +58,28 @@ static struct fieldstat_easy *get_hist_fieldstat_easy() return fse; } -static struct fieldstat *get_hll_fieldsstat() +int test_fieldstat_cube_create(struct fieldstat *instance, const struct field *dimensions, size_t n_dimensions, enum sampling_mode mode, int k) { - struct fieldstat_tag shared_tags[1]; + assert(mode == SAMPLING_MODE_COMPREHENSIVE); + int ret = fieldstat_cube_create(instance, dimensions, n_dimensions); + fieldstat_cube_set_sampling(instance, ret, mode, k, 0); + return ret; +} + +static void write_hll(struct fieldstat *instance) { + struct field shared_tags[1]; shared_tags[0].key = "rule_id"; - shared_tags[0].type = TAG_INTEGER; + shared_tags[0].type = FIELD_VALUE_INTEGER; shared_tags[0].value_longlong = 1; const char *hll_name[] = {"external_ip", "internal_ip", "acc_ip"}; - - struct fieldstat *instance = fieldstat_new(); - EXPECT_NE(nullptr, instance); - int cube_id = fieldstat_create_cube(instance, shared_tags, 1, + int cube_id = test_fieldstat_cube_create(instance, shared_tags, 1, SAMPLING_MODE_COMPREHENSIVE, 100); for(unsigned int i = 0; i < sizeof(hll_name) / sizeof(hll_name[0]); i++) { - int hll_id = fieldstat_register_hll(instance, hll_name[i], 5); + int hll_id = fieldstat_register_hll(instance, cube_id, hll_name[i], 5); for(int j = 0; j < 100; j++) { @@ -85,30 +89,25 @@ static struct fieldstat *get_hll_fieldsstat() int ret = fieldstat_hll_add(instance, cube_id, hll_id, NULL, 0, ip_str, strlen(ip_str)); EXPECT_EQ(0, ret); } - } - - return instance; } - -static struct fieldstat *get_hist_fieldstat() -{ - struct fieldstat_tag shared_tags[2]; - struct fieldstat_tag cell_tags[2]; +void write_histogram(struct fieldstat *instance) { + struct field shared_tags[2]; + struct field cell_tags[2]; shared_tags[0].key = "rule_id"; - shared_tags[0].type = TAG_INTEGER; + shared_tags[0].type = FIELD_VALUE_INTEGER; shared_tags[0].value_longlong = 1; shared_tags[1].key = "action"; - shared_tags[1].type = TAG_CSTRING; + shared_tags[1].type = FIELD_VALUE_CSTRING; shared_tags[1].value_str = "deny"; cell_tags[0].key = "thread_id"; - cell_tags[0].type = TAG_INTEGER; + cell_tags[0].type = FIELD_VALUE_INTEGER; cell_tags[0].value_longlong = 1; cell_tags[1].key = "hit_rate"; - cell_tags[1].type = TAG_DOUBLE; + cell_tags[1].type = FIELD_VALUE_DOUBLE; cell_tags[1].value_double = 1.1; const char *hist_names[] = {"list_num", "max_wt_ms", "ivt_nx_itv_ms", @@ -116,35 +115,30 @@ static struct fieldstat *get_hist_fieldstat() "bye/udp", "oth_mtd/udp"}; - struct fieldstat *instance = fieldstat_new(); - EXPECT_NE(nullptr, instance); - int cube_id = fieldstat_create_cube(instance, shared_tags, 2, + int cube_id = test_fieldstat_cube_create(instance, shared_tags, 2, SAMPLING_MODE_COMPREHENSIVE, 100); - EXPECT_EQ(0, cube_id); for(unsigned int i = 0; i < sizeof(hist_names)/sizeof(hist_names[0]); i++) { - int hist_id = fieldstat_register_hist(instance, hist_names[i], 1, 600000, 3); + int hist_id = fieldstat_register_histogram(instance, cube_id, hist_names[i], 1, 600000, 3); for(int j = 0; j < 100; j++) { - fieldstat_hist_record(instance, cube_id, hist_id, cell_tags, 2, i*100 + j); + fieldstat_histogram_record(instance, cube_id, hist_id, cell_tags, 2, i*100 + j); } } - - return instance; } // static struct fieldstat_easy *get_table_fieldstat_easy() // { -// struct fieldstat_tag global_tags[2]; -// struct fieldstat_tag cell_tags; +// struct field global_tags[2]; +// struct field cell_tags; // global_tags[0].key = "policy_id"; -// global_tags[0].type = TAG_INTEGER; +// global_tags[0].type = FIELD_VALUE_INTEGER; // global_tags[0].value_longlong = 1; // global_tags[1].key = "quanlity"; -// global_tags[1].type = TAG_DOUBLE; +// global_tags[1].type = FIELD_VALUE_DOUBLE; // global_tags[1].value_double = 0.5; // const char *cell_tag_value[] = { @@ -154,7 +148,7 @@ static struct fieldstat *get_hist_fieldstat() // "STATISTICS-RULE-METRIC", "OBJECT-STATISTICS-METRIC"}; // cell_tags.key = "send_log"; -// cell_tags.type = TAG_CSTRING; +// cell_tags.type = FIELD_VALUE_CSTRING; // cell_tags.value_str = "true"; // struct fieldstat_easy *fse = fieldstat_easy_new(N_THREAD, NULL, global_tags, 2); @@ -179,14 +173,13 @@ void fieldstat_easy_to_file(struct fieldstat_easy *fse, const char *file_path) fieldstat_easy_free(fse); // only by free to stop exporting } -static struct fieldstat *get_table_fieldstat() -{ - struct fieldstat_tag shared_tags[2]; +void write_table(struct fieldstat *instance) { + struct field shared_tags[2]; shared_tags[0].key = "policy_id"; - shared_tags[0].type = TAG_INTEGER; + shared_tags[0].type = FIELD_VALUE_INTEGER; shared_tags[0].value_longlong = 1; shared_tags[1].key = "quanlity"; - shared_tags[1].type = TAG_DOUBLE; + shared_tags[1].type = FIELD_VALUE_DOUBLE; shared_tags[1].value_double = 0.5; const char *cell_tag_value[] = { @@ -195,21 +188,17 @@ static struct fieldstat *get_table_fieldstat() "GTPC-RECORD", "BGP-RECORD", "PROXY-EVENT", "DOS-SKETCH-RECORD", "STATISTICS-RULE-METRIC", "OBJECT-STATISTICS-METRIC"}; - struct fieldstat_tag cell_tags; + struct field cell_tags; cell_tags.key = "send_log"; - cell_tags.type = TAG_CSTRING; + cell_tags.type = FIELD_VALUE_CSTRING; cell_tags.value_str = "true"; - struct fieldstat *instance = fieldstat_new(); - EXPECT_NE(nullptr, instance); - - int cube_id = fieldstat_create_cube(instance, shared_tags, 2, + int cube_id = test_fieldstat_cube_create(instance, shared_tags, 2, SAMPLING_MODE_COMPREHENSIVE, 100); - EXPECT_EQ(0, cube_id); - int counter_id_0 = fieldstat_register_counter(instance, "T_success_log"); + int counter_id_0 = fieldstat_register_counter(instance, cube_id, "T_success_log"); - int counter_id_1 = fieldstat_register_counter(instance, "T_fail_log"); + int counter_id_1 = fieldstat_register_counter(instance, cube_id, "T_fail_log"); for(unsigned int i = 0; i < sizeof(cell_tag_value)/sizeof(cell_tag_value[0]); i++) { @@ -218,8 +207,6 @@ static struct fieldstat *get_table_fieldstat() if(i < 5) fieldstat_counter_incrby(instance, cube_id, counter_id_1, &cell_tags, 1, 2); } - - return instance; } static int write_json_to_file(const char *filename, char *json_str) @@ -239,13 +226,11 @@ TEST(ExporterLocal, TableBuild) { struct timeval current = {100, 10000}; struct fieldstat *merger = fieldstat_new(); - struct fieldstat *hll = get_hll_fieldsstat(); - struct fieldstat *hist = get_hist_fieldstat(); - struct fieldstat *table = get_table_fieldstat(); - fieldstat_merge(merger, hll); - fieldstat_merge(merger, hist); - fieldstat_merge(merger, table); + write_hll(merger); + write_histogram(merger); + write_table(merger); + struct fieldstat_json_exporter *exporter = fieldstat_json_exporter_new(); fieldstat_json_exporter_enable_delta(exporter); char *str_json = fieldstat_json_exporter_export(exporter, merger, ¤t); diff --git a/test/unit_test_cell_manager.cpp b/test/unit_test_cell_manager.cpp deleted file mode 100644 index 67c1033..0000000 --- a/test/unit_test_cell_manager.cpp +++ /dev/null @@ -1,733 +0,0 @@ - -#include <gtest/gtest.h> -#include <map> -#include <set> -#include <string> -#include <vector> -#include <algorithm> - - -#include "fieldstat.h" -#include "tags/cell_manager.h" -#include "utils.hpp" -#include "tags/my_ut_hash.h" - -using namespace std; - -struct tag_hash_key *test_gen_tag_key(const char *key, int value) -{ - struct fieldstat_tag tag = { - .key = key, - .type = TAG_CSTRING, - {.value_str = strdup(to_string(value).c_str())}, - }; - - struct tag_hash_key *tag_key = (struct tag_hash_key *)malloc(sizeof(struct tag_hash_key)); - tag_hash_key_init_with_fieldstat_tag(tag_key, &tag, 1, true); - - free((void *)tag.value_str); - - return tag_key; -} - -struct Fieldstat_tag_list_wrapper *test_key_tag_to_wrapper(const struct tag_hash_key *key) -{ - struct fieldstat_tag *tag; - size_t n_out; - tag_hash_key_convert_to_fieldstat_tag(key, &tag, &n_out); - struct fieldstat_tag_list tag_list; - tag_list.tag = tag; - tag_list.n_tag = n_out; - struct Fieldstat_tag_list_wrapper *wrapper = new Fieldstat_tag_list_wrapper(&tag_list); - - for (size_t i = 0; i < n_out; i++) - { - if (tag[i].type == TAG_CSTRING) - free((void *)tag[i].value_str); - free((void *)tag[i].key); - } - free(tag); - - return wrapper; -} - -double cal_accuracy_with_tags(const vector<struct tag_hash_key *> &expected_keys, const vector<struct tag_hash_key *> &test_result) { - unordered_map<string, int> countMap; - for (size_t i = 0; i < expected_keys.size(); i++) { - struct Fieldstat_tag_list_wrapper *wrapper = test_key_tag_to_wrapper(expected_keys[i]); - string key = wrapper->to_string(); - countMap[key]++; - delete wrapper; - } - vector<struct Fieldstat_tag_list_wrapper *> test_result_wrapper; - - for (size_t i = 0; i < test_result.size(); i++) { - struct Fieldstat_tag_list_wrapper *wrapper = test_key_tag_to_wrapper(test_result[i]); - test_result_wrapper.push_back(wrapper); - } - - double ret = test_cal_topk_accuracy(test_result_wrapper, countMap); - - for (size_t i = 0; i < test_result.size(); i++) { - delete test_result_wrapper[i]; - } - return ret; -} - -vector<tag_hash_key *> test_query_cell_manager_content(const struct cell_manager *cm) -{ - int ret_len; - const struct tag_hash_key **dump_ret = cell_manager_dump(cm, &ret_len); - vector<tag_hash_key *> test_result; - for (int i = 0; i < ret_len; i++) { - if (dump_ret[i] == NULL) { - continue; - } - - test_result.push_back((struct tag_hash_key *)dump_ret[i]); - } - - return test_result; -} - -TEST(unit_test_cell_manager, topk_simple_add) -{ - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - const int TEST_ROUND = 10; - - vector<struct tag_hash_key *> keys; - for (int i = 0; i < TEST_ROUND; i++) - { - struct tag_hash_key *key = test_gen_tag_key("key", i); - keys.push_back(key); - } - - int pop_dummy; - - for (int i = 0; i < TEST_ROUND; i++) { - cell_manager_add_cell_topk(cm, keys[i], 1, &pop_dummy); - } - - vector<tag_hash_key *> test_result = test_query_cell_manager_content(cm); - EXPECT_EQ(test_result.size(), 10); - double accuracy = cal_accuracy_with_tags(keys, test_result); - EXPECT_NEAR(accuracy, 1.0, 0.01); - - cell_manager_free(cm); - for (int i = 0; i < TEST_ROUND; i++) { - tag_hash_key_free(keys[i]); - } -} - -TEST(unit_test_cell_manager, topk_add_pop) -{ - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - const int TEST_ROUND = 11; - - vector<struct tag_hash_key *> keys; - for (int i = 0; i < TEST_ROUND; i++) - { - struct tag_hash_key *key = test_gen_tag_key("key", i); - keys.push_back(key); - } - - int pop_dummy; - for (int i = 0; i < TEST_ROUND - 1; i++) { - cell_manager_add_cell_topk(cm, keys[i], 1, &pop_dummy); - } - cell_manager_add_cell_topk(cm, keys[TEST_ROUND - 1], 100, &pop_dummy); - - vector<tag_hash_key *> test_result = test_query_cell_manager_content(cm); - EXPECT_EQ(test_result.size(), 10); - double accuracy = cal_accuracy_with_tags(keys, test_result); - EXPECT_NEAR(accuracy, 1.0, 0.01); - - EXPECT_EQ(cell_manager_get_count_by_tag(cm, keys[TEST_ROUND - 1]), 100); - - cell_manager_free(cm); - for (int i = 0; i < TEST_ROUND; i++) { - tag_hash_key_free(keys[i]); - } -} - -TEST(unit_test_cell_manager, topk_add_twice) -{ - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - const int TEST_ROUND = 10; - - vector<struct tag_hash_key *> keys; - for (int i = 0; i < TEST_ROUND; i++) - { - struct tag_hash_key *key = test_gen_tag_key("key", i); - keys.push_back(key); - } - - int pop_dummy; - for (int i = 0; i < TEST_ROUND; i++) { - cell_manager_add_cell_topk(cm, keys[i], 1, &pop_dummy); - } - cell_manager_add_cell_topk(cm, keys[TEST_ROUND - 1], 100, &pop_dummy); - - vector<tag_hash_key *> test_result = test_query_cell_manager_content(cm); - EXPECT_EQ(test_result.size(), 10); - double accuracy = cal_accuracy_with_tags(keys, test_result); - EXPECT_NEAR(accuracy, 1.0, 0.01); - - cell_manager_free(cm); - for (int i = 0; i < TEST_ROUND; i++) { - tag_hash_key_free(keys[i]); - } -} - -TEST(unit_test_cell_manager, topk_add_and_query_accuracy) -{ - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - const int TEST_ROUND = 10000; - - vector<struct tag_hash_key *> keys; - for (int i = 0; i < TEST_ROUND; i++) - { - if (rand()) { - struct tag_hash_key *key = test_gen_tag_key("key", rand() % 10); - keys.push_back(key); - } else { - struct tag_hash_key *key = test_gen_tag_key("key", rand() % 1000); - keys.push_back(key); - } - } - - int pop_dummy; - for (int i = 0; i < TEST_ROUND; i++) { - cell_manager_add_cell_topk(cm, keys[i], 1, &pop_dummy); - } - - vector<tag_hash_key *> test_result = test_query_cell_manager_content(cm); - EXPECT_EQ(test_result.size(), 10); - double accuracy = cal_accuracy_with_tags(keys, test_result); - EXPECT_NEAR(accuracy, 1.0, 0.01); - - cell_manager_free(cm); - for (int i = 0; i < TEST_ROUND; i++) { - tag_hash_key_free(keys[i]); - } -} - -TEST(unit_test_cell_manager, merge_topk_given_K_large_enough) -{ - struct cell_manager *cm1 = cell_manager_new(SAMPLING_MODE_TOPK, 10); - struct cell_manager *cm2 = cell_manager_new(SAMPLING_MODE_TOPK, 10); - - vector<struct tag_hash_key *> keys; - keys.push_back(test_gen_tag_key("key_share", 1)); - keys.push_back(test_gen_tag_key("key_1", 1)); - keys.push_back(test_gen_tag_key("key_1", 2)); - keys.push_back(test_gen_tag_key("key_share", 1)); - keys.push_back(test_gen_tag_key("key_2", 1)); - - int pop_dummy; - int cell_id_1[3]; - int cell_id_2[2]; - - for (size_t i = 0; i < 3; i++) { - cell_id_1[i] = cell_manager_add_cell_topk(cm1, keys[i], 1, &pop_dummy); - } - for (size_t i = 3; i < 5; i++) { - cell_id_2[i - 3] = cell_manager_add_cell_topk(cm2, keys[i], 1, &pop_dummy); - } - int *cell_id_popped; - int n_cell_id_popped; - int *cell_id_old; - int *cell_id_added; - int n_cell_id_added; - - cell_manager_merge_topk(cm1, cm2, &cell_id_popped, &n_cell_id_popped, &cell_id_old, &cell_id_added, &n_cell_id_added); - EXPECT_EQ(n_cell_id_popped, 0); - EXPECT_EQ(n_cell_id_added, 2); - EXPECT_EQ(cell_id_added[0], cell_id_1[0]); // key_share in cm1 - EXPECT_EQ(cell_id_old[0], cell_id_2[0]); // key_share in cm2 - EXPECT_EQ(cell_id_added[1], 3); // key_2, new cell - EXPECT_EQ(cell_id_old[1], cell_id_2[1]); // key_2 in cm2 - - auto test_result = test_query_cell_manager_content(cm1); - double accuracy = cal_accuracy_with_tags(keys, test_result); - EXPECT_NEAR(accuracy, 1.0, 0.01); - - EXPECT_EQ(cell_manager_get_count_by_tag(cm1, keys[0]), 2); // key_share merged once - - free(cell_id_popped); - free(cell_id_old); - free(cell_id_added); - cell_manager_free(cm1); - cell_manager_free(cm2); - - for (size_t i = 0; i < keys.size(); i++) { - tag_hash_key_free(keys[i]); - } -} - -TEST(unit_test_cell_manager, merge_topk_to_empty) -{ - struct cell_manager *cm1 = cell_manager_new(SAMPLING_MODE_TOPK, 10); - struct cell_manager *cm2 = cell_manager_new(SAMPLING_MODE_TOPK, 10); - - vector<struct tag_hash_key *> keys; - keys.push_back(test_gen_tag_key("key_1", 1)); - keys.push_back(test_gen_tag_key("key_1", 1)); - keys.push_back(test_gen_tag_key("key_1", 2)); - - int pop_dummy; - int cell_id_1[3]; - - for (size_t i = 0; i < 3; i++) { - cell_id_1[i] = cell_manager_add_cell_topk(cm1, keys[i], 1, &pop_dummy); - printf("cell id: %d\n", cell_id_1[i]); - } - - int *cell_id_popped; - int n_cell_id_popped; - int *cell_id_old; - int *cell_id_added; - int n_cell_id_added; - - cell_manager_merge_topk(cm2, cm1, &cell_id_popped, &n_cell_id_popped, &cell_id_old, &cell_id_added, &n_cell_id_added); - EXPECT_EQ(n_cell_id_popped, 0); - EXPECT_EQ(n_cell_id_added, 2); - EXPECT_EQ(cell_id_added[0], 0); // new added - EXPECT_EQ(cell_id_old[0], cell_id_1[0]); // key_11 in cm1 - EXPECT_EQ(cell_id_added[1], 1); // new added - EXPECT_EQ(cell_id_old[1], cell_id_1[2]); // key_12 in cm1 - EXPECT_EQ(cell_manager_get_count_by_tag(cm2, keys[0]), 2); // key_11 added twice - EXPECT_EQ(cell_manager_get_count_by_tag(cm2, keys[2]), 1); // key_12 - - free(cell_id_popped); - free(cell_id_old); - free(cell_id_added); - cell_manager_free(cm1); - cell_manager_free(cm2); - - for (size_t i = 0; i < keys.size(); i++) { - tag_hash_key_free(keys[i]); - } -} - -TEST(unit_test_cell_manager, merge_topk_to_full_one) -{ - struct cell_manager *cm1 = cell_manager_new(SAMPLING_MODE_TOPK, 10); - struct cell_manager *cm2 = cell_manager_new(SAMPLING_MODE_TOPK, 10); - - vector<struct tag_hash_key *> keys1; - keys1.push_back(test_gen_tag_key("key_1", 1)); - keys1.push_back(test_gen_tag_key("key_1", 2)); - keys1.push_back(test_gen_tag_key("key_shared", 1)); - - vector<struct tag_hash_key *> keys2; - for (int i = 0; i < 9; i++) { - keys2.push_back(test_gen_tag_key("key_2", i)); - } - keys2.push_back(test_gen_tag_key("key_shared", 1)); - - int pop_dummy; - int cell_id_1[3]; - int cell_id_2[10]; - for (size_t i = 0; i < 3; i++) { - cell_id_1[i] = cell_manager_add_cell_topk(cm1, keys1[i], 10, &pop_dummy); - } - for (size_t i = 0; i < 10; i++) { - unsigned int count = i < 2 ? i : 5; // the first 2 keys have count 1 and 2(less), the rest have count 5 - cell_id_2[i] = cell_manager_add_cell_topk(cm2, keys2[i], count, &pop_dummy); - } - - int *cell_id_popped; - int n_cell_id_popped; - int *cell_id_old; - int *cell_id_added; - int n_cell_id_added; - cell_manager_merge_topk(cm2, cm1, &cell_id_popped, &n_cell_id_popped, &cell_id_old, &cell_id_added, &n_cell_id_added); - - EXPECT_EQ(n_cell_id_popped, 2); // 2 "key_1" added, should pop 2 cells - EXPECT_EQ(cell_id_popped[0], cell_id_2[0]); // key2 which has count of 1 - EXPECT_EQ(cell_id_popped[1], cell_id_2[1]); // key2 which has count of 2 - EXPECT_EQ(n_cell_id_added, 3); // 2 "key_1", "key_shared" added, should add 3 cells - EXPECT_EQ(cell_id_added[0], 10); // newly added - EXPECT_EQ(cell_id_added[1], 11); // newly added - EXPECT_EQ(cell_id_added[2], cell_id_2[9]); // shared key - EXPECT_EQ(cell_id_old[0], cell_id_1[0]); // key_1 in cm1 - EXPECT_EQ(cell_id_old[1], cell_id_1[1]); // key_1 in cm1 - EXPECT_EQ(cell_id_old[2], cell_id_1[2]); // key_shared in cm1 - - auto test_result = test_query_cell_manager_content(cm2); - // join keys2 to keys1 - keys1.insert(keys1.end(), std::make_move_iterator(keys2.begin()), std::make_move_iterator(keys2.end())); - double accuracy = cal_accuracy_with_tags(keys1, test_result); - EXPECT_NEAR(accuracy, 1.0, 0.01); - - free(cell_id_popped); - free(cell_id_old); - free(cell_id_added); - cell_manager_free(cm1); - cell_manager_free(cm2); - for (size_t i = 0; i < keys1.size(); i++) { - tag_hash_key_free(keys1[i]); - } - // all keys are moved to cm1, so no need to free keys2 -} - -bool test_is_tag_equal(const struct tag_hash_key* a, const struct tag_hash_key* b) { - char *key1 = tag_hash_key_get_compound_key(a); - char *key2 = tag_hash_key_get_compound_key(b); - bool ret = strcmp(key1, key2) == 0; - free(key1); - free(key2); - return ret; -} - -void add_key_and_assert_find_result(struct cell_manager *cm, const struct tag_hash_key *key) -{ - int pop_dummy; - int cell_id = cell_manager_add_cell_topk(cm, key, 1234, &pop_dummy); - EXPECT_EQ(cell_id, 0); - EXPECT_EQ(cell_manager_get_count_by_tag(cm, key), 1234); - const struct tag_hash_key *key_get = cell_manager_get_tag_by_cell_id(cm, cell_id); - EXPECT_TRUE(test_is_tag_equal(key_get, key)); -} - -void add_key_and_assert_find_result_comprehensive(struct cell_manager *cm, const struct tag_hash_key *key) -{ - int cell_id = cell_manager_add_cell(cm, key); - EXPECT_EQ(cell_id, 0); - const struct tag_hash_key *key_get = cell_manager_get_tag_by_cell_id(cm, cell_id); - EXPECT_TRUE(test_is_tag_equal(key_get, key)); -} - -struct tag_hash_key *tag_hash_key_construct_with_fieldstat_tag(const struct fieldstat_tag *src, size_t n_src) -{ - struct tag_hash_key *ret_hash_key = (struct tag_hash_key *)malloc(sizeof(struct tag_hash_key)); - - tag_hash_key_init_with_fieldstat_tag(ret_hash_key, src, n_src, false); - - return ret_hash_key; -} - -TEST(unit_test_cell_manager, add_with_key_length_is_1_int_type_topk) -{ - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(&TEST_TAG_INT, 1); - - add_key_and_assert_find_result(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -TEST(unit_test_cell_manager, add_with_key_length_is_1_double_type_topk) -{ - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(&TEST_TAG_DOUBLE, 1); - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - - add_key_and_assert_find_result(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -TEST(unit_test_cell_manager, add_with_key_length_is_1_string_type_topk) -{ - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(&TEST_TAG_STRING, 1); - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - - add_key_and_assert_find_result(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -TEST(unit_test_cell_manager, add_with_key_length_is_3_of_diff_types_topk) -{ - const struct fieldstat_tag tags[3] = {TEST_TAG_INT, TEST_TAG_STRING, TEST_TAG_DOUBLE}; - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(tags, 3); - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, 10); - - add_key_and_assert_find_result(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -TEST(unit_test_cell_manager, add_with_key_length_is_1_int_type_comprehensive) -{ - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_COMPREHENSIVE, 10); - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(&TEST_TAG_INT, 1); - - add_key_and_assert_find_result_comprehensive(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -TEST(unit_test_cell_manager, add_with_key_length_is_1_double_type_comprehensive) -{ - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(&TEST_TAG_DOUBLE, 1); - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_COMPREHENSIVE, 10); - - add_key_and_assert_find_result_comprehensive(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -TEST(unit_test_cell_manager, add_with_key_length_is_1_string_type_comprehensive) -{ - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(&TEST_TAG_STRING, 1); - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_COMPREHENSIVE, 10); - - add_key_and_assert_find_result_comprehensive(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -TEST(unit_test_cell_manager, add_with_key_length_is_3_of_diff_types_comprehensive) -{ - const struct fieldstat_tag tags[3] = {TEST_TAG_INT, TEST_TAG_STRING, TEST_TAG_DOUBLE}; - struct tag_hash_key *key = tag_hash_key_construct_with_fieldstat_tag(tags, 3); - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_COMPREHENSIVE, 10); - - add_key_and_assert_find_result_comprehensive(cm, key); - - cell_manager_free(cm); - tag_hash_key_free(key); -} - -extern "C" -{ - int find_next_unused_cell_id(const int *sorted_pst_cell_id_arr, size_t arr_len, int last_find_result, int *next_idx); -} -TEST(unit_test_cell_manager, find_next_id_given_all_cell_id_continuous) -{ - int *arr = (int *)malloc(sizeof(int) * 10); - for (int i = 0; i < 10; i++) - { - arr[i] = i; - } - - int last_find_result = -1; - int next_idx = 0; - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 10); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 11); - - free(arr); -} - -TEST(unit_test_cell_manager, find_next_id_given_continuous_hole) -{ - int *arr = (int *)malloc(sizeof(int) * 10); - for (int i = 0; i < 3; i++) - { - arr[i] = i; - } - arr[3] = 5; // 3, 4 is hole - for (int i = 4; i < 10; i++) - { - arr[i] = i + 2; - } - - int last_find_result = -1; - int next_idx = 0; - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 3); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 4); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 12); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 13); - - free(arr); -} - -TEST(unit_test_cell_manager, find_next_id_given_holes) -{ - int *arr = (int *)malloc(sizeof(int) * 10); - for (int i = 0; i < 10; i++) - { - arr[i] = i * 2; // 0, 2, 4, ... - } - - int last_find_result = -1; - int next_idx = 0; - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 1); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 3); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 5); - - free(arr); -} - -TEST(unit_test_cell_manager, find_next_id_given_holes_at_only_start) -{ - int *arr = (int *)malloc(sizeof(int ) * 10); - for (int i = 0; i < 10; i++) - { - arr[i] = i + 2; - } - - int last_find_result = -1; - int next_idx = 0; - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 0); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 1); - last_find_result = find_next_unused_cell_id(arr, 10, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 12); - - free(arr); -} - -TEST(unit_test_cell_manager, find_next_id_given_empty_arr) -{ - int *arr = (int *)malloc(sizeof(int) * 0); - - int last_find_result = -1; - int next_idx = 0; - last_find_result = find_next_unused_cell_id(arr, 0, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 0); - last_find_result = find_next_unused_cell_id(arr, 0, last_find_result, &next_idx); - EXPECT_EQ(last_find_result, 1); - - free(arr); -} - -TEST(unit_test_cell_manager, reset_once_and_query) -{ - const int TEST_ROUND = 10; - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_COMPREHENSIVE, TEST_ROUND); - - vector<struct tag_hash_key *> keys; - for (int i = 0; i < TEST_ROUND; i++) - { - struct tag_hash_key *key = test_gen_tag_key("key", i); - keys.push_back(key); - } - for (int i = 0; i < TEST_ROUND; i++) { - int cell_id = cell_manager_add_cell(cm, keys[i]); - EXPECT_EQ(cell_id, i); - } - - cell_manager_reset(cm); - for (int i = 0; i < TEST_ROUND; i++) { - EXPECT_EQ(cell_manager_find(cm, keys[i]), -1); - EXPECT_TRUE(cell_manager_get_tag_by_cell_id(cm, i) == NULL); - } - int array_len = 0; - cell_manager_dump(cm, &array_len); - EXPECT_EQ(array_len, 0); - - // do it again, to see the effect of reset on a recovered cell_manager(instead of which just newed) - for (int i = 0; i < TEST_ROUND; i++) { - int cell_id = cell_manager_add_cell(cm, keys[i]); - EXPECT_EQ(cell_id, i); - } - cell_manager_reset(cm); - for (int i = 0; i < TEST_ROUND; i++) { - EXPECT_EQ(cell_manager_find(cm, keys[i]), -1); - EXPECT_TRUE(cell_manager_get_tag_by_cell_id(cm, i) == NULL); - } - cell_manager_dump(cm, &array_len); - EXPECT_EQ(array_len, 0); - - cell_manager_free(cm); - for (int i = 0; i < TEST_ROUND; i++) { - tag_hash_key_free(keys[i]); - } -} - -// reset once will not delete the cells, just let them be discared, so in such case, cube_add will just add to the same cell. -TEST(unit_test_cell_manager, add_after_reset_and_ensure_performance_improvement) { - clock_t start, end; - const int TEST_ROUND = 100000; - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_COMPREHENSIVE, TEST_ROUND); - vector<struct tag_hash_key *> keys; - for (int i = 0; i < TEST_ROUND; i++) - { - struct tag_hash_key *key = test_gen_tag_key("key", i); - keys.push_back(key); - } - for (int i = 0; i < TEST_ROUND; i++) { - int cell_id = cell_manager_add_cell(cm, keys[i]); - EXPECT_EQ(cell_id, i); - } - - cell_manager_reset(cm); - start = clock(); - for (int i = 0; i < TEST_ROUND; i++) - { - int cell_id = cell_manager_add_cell(cm, keys[i]); - EXPECT_EQ(cell_id, i); - } - end = clock(); - clock_t time_reset_once = end - start; - - - cell_manager_reset(cm); - cell_manager_reset(cm); - start = clock(); - for (int i = 0; i < TEST_ROUND; i++) - { - int cell_id = cell_manager_add_cell(cm, keys[i]); - EXPECT_EQ(cell_id, i); // completely new cell - } - end = clock(); - clock_t time_reset_twice = end - start; - - EXPECT_GT((double)time_reset_twice, (double)time_reset_once); - - cell_manager_free(cm); - for (int i = 0; i < TEST_ROUND; i++) { - tag_hash_key_free(keys[i]); - } -} - -TEST(unit_test_cell_manager, reset_once_and_query_topk) -{ - const int TEST_ROUND = 10; - struct cell_manager *cm = cell_manager_new(SAMPLING_MODE_TOPK, TEST_ROUND); - - vector<struct tag_hash_key *> keys; - for (int i = 0; i < TEST_ROUND; i++) - { - struct tag_hash_key *key = test_gen_tag_key("key", i); - keys.push_back(key); - } - for (int i = 0; i < TEST_ROUND; i++) { - int dummy; - int cell_id = cell_manager_add_cell_topk(cm, keys[i], 1, &dummy); - EXPECT_EQ(cell_id, i); - } - - cell_manager_reset(cm); - for (int i = 0; i < TEST_ROUND; i++) { - EXPECT_EQ(cell_manager_find(cm, keys[i]), -1); - EXPECT_TRUE(cell_manager_get_tag_by_cell_id(cm, i) == NULL); - EXPECT_EQ(cell_manager_get_count_by_tag(cm, keys[i]), -1); - } - int array_len = 0; - cell_manager_dump(cm, &array_len); - EXPECT_EQ(array_len, 0); - - cell_manager_free(cm); - for (int i = 0; i < TEST_ROUND; i++) { - tag_hash_key_free(keys[i]); - } -} - -// 速度测试 - -int main(int argc, char *argv[]) -{ - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -}
\ No newline at end of file diff --git a/test/utils.cpp b/test/utils.cpp index b53e4e4..4e41d8f 100644 --- a/test/utils.cpp +++ b/test/utils.cpp @@ -8,7 +8,10 @@ #include <random> #include <string.h> #include <algorithm> - +#include <fstream> +#include <math.h> +#include <unistd.h> +#include <sstream> #include "fieldstat.h" #include "utils.hpp" @@ -32,24 +35,24 @@ string gen_rand_string(int len) /* taglist wrapper */ /* -------------------------------------------------------------------------- */ -Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(const struct fieldstat_tag_list *tag_list) { - tag_list_c.tag = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag) * tag_list->n_tag); - tag_list_c.n_tag = tag_list->n_tag; - for (size_t i = 0; i < tag_list->n_tag; i++) +Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(const struct field_list *tag_list) { + tag_list_c.field = (struct field *)malloc(sizeof(struct field) * tag_list->n_field); + tag_list_c.n_field = tag_list->n_field; + for (size_t i = 0; i < tag_list->n_field; i++) { // copy the tag_list - tag_list_c.tag[i].key = strdup(tag_list->tag[i].key); - tag_list_c.tag[i].type = tag_list->tag[i].type; - switch (tag_list->tag[i].type) + tag_list_c.field[i].key = strdup(tag_list->field[i].key); + tag_list_c.field[i].type = tag_list->field[i].type; + switch (tag_list->field[i].type) { - case TAG_INTEGER: - tag_list_c.tag[i].value_longlong = tag_list->tag[i].value_longlong; + case FIELD_VALUE_INTEGER: + tag_list_c.field[i].value_longlong = tag_list->field[i].value_longlong; break; - case TAG_DOUBLE: - tag_list_c.tag[i].value_double = tag_list->tag[i].value_double; + case FIELD_VALUE_DOUBLE: + tag_list_c.field[i].value_double = tag_list->field[i].value_double; break; - case TAG_CSTRING: - tag_list_c.tag[i].value_str = strdup(tag_list->tag[i].value_str); + case FIELD_VALUE_CSTRING: + tag_list_c.field[i].value_str = strdup(tag_list->field[i].value_str); break; default: break; @@ -59,84 +62,84 @@ Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(const struct fieldstat_ta Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(const char * key, int value) { - tag_list_c.tag = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag)); - tag_list_c.n_tag = 1; - tag_list_c.tag[0].key = strdup(key); - tag_list_c.tag[0].type = TAG_INTEGER; - tag_list_c.tag[0].value_longlong = value; + tag_list_c.field = (struct field *)malloc(sizeof(struct field)); + tag_list_c.n_field = 1; + tag_list_c.field[0].key = strdup(key); + tag_list_c.field[0].type = FIELD_VALUE_INTEGER; + tag_list_c.field[0].value_longlong = value; } Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(const char * key, const char *value) { - tag_list_c.tag = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag)); - tag_list_c.n_tag = 1; - tag_list_c.tag[0].key = strdup(key); - tag_list_c.tag[0].type = TAG_CSTRING; - tag_list_c.tag[0].value_str = strdup(value); + tag_list_c.field = (struct field *)malloc(sizeof(struct field)); + tag_list_c.n_field = 1; + tag_list_c.field[0].key = strdup(key); + tag_list_c.field[0].type = FIELD_VALUE_CSTRING; + tag_list_c.field[0].value_str = strdup(value); } Fieldstat_tag_list_wrapper::~Fieldstat_tag_list_wrapper() { - for (size_t i = 0; i < tag_list_c.n_tag; i++) { - free((char *)tag_list_c.tag[i].key); - if (tag_list_c.tag[i].type == TAG_CSTRING) { - free((char *)tag_list_c.tag[i].value_str); + for (size_t i = 0; i < tag_list_c.n_field; i++) { + free((char *)tag_list_c.field[i].key); + if (tag_list_c.field[i].type == FIELD_VALUE_CSTRING) { + free((char *)tag_list_c.field[i].value_str); } } - free(tag_list_c.tag); + free(tag_list_c.field); } Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(std::uniform_int_distribution<int> &dist, int tag_count) { - tag_list_c.tag = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag) * tag_count); - tag_list_c.n_tag = tag_count; + tag_list_c.field = (struct field *)malloc(sizeof(struct field) * tag_count); + tag_list_c.n_field = tag_count; std::mt19937 rng(1); for (int i = 0; i < tag_count; i++) { - tag_list_c.tag[i].key = strdup(gen_rand_string(10).c_str()); + tag_list_c.field[i].key = strdup(gen_rand_string(10).c_str()); int rand_ret = rand() % 3; if (rand_ret == 0) { - tag_list_c.tag[i].type = TAG_INTEGER; - tag_list_c.tag[i].value_longlong = static_cast<long long>(dist(rng)); + tag_list_c.field[i].type = FIELD_VALUE_INTEGER; + tag_list_c.field[i].value_longlong = static_cast<long long>(dist(rng)); } else if (rand_ret == 1) { - tag_list_c.tag[i].type = TAG_DOUBLE; - tag_list_c.tag[i].value_double = static_cast<double>(dist(rng)) + 0.5; + tag_list_c.field[i].type = FIELD_VALUE_DOUBLE; + tag_list_c.field[i].value_double = static_cast<double>(dist(rng)) + 0.5; } else { - tag_list_c.tag[i].type = TAG_CSTRING; - tag_list_c.tag[i].value_str = strdup(gen_rand_string(10).c_str()); + tag_list_c.field[i].type = FIELD_VALUE_CSTRING; + tag_list_c.field[i].value_str = strdup(gen_rand_string(10).c_str()); } } } Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper() { - tag_list_c.tag = NULL; - tag_list_c.n_tag = 0; + tag_list_c.field = NULL; + tag_list_c.n_field = 0; } Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(const Fieldstat_tag_list_wrapper &tag_list_wrapper){ - const struct fieldstat_tag_list *tag_list = tag_list_wrapper.get_c_struct(); - tag_list_c.tag = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag) * tag_list->n_tag); - tag_list_c.n_tag = tag_list->n_tag; - for (size_t i = 0; i < tag_list->n_tag; i++) + const struct field_list *tag_list = tag_list_wrapper.get_c_struct(); + tag_list_c.field = (struct field *)malloc(sizeof(struct field) * tag_list->n_field); + tag_list_c.n_field = tag_list->n_field; + for (size_t i = 0; i < tag_list->n_field; i++) { // copy the tag_list - tag_list_c.tag[i].key = strdup(tag_list->tag[i].key); - tag_list_c.tag[i].type = tag_list->tag[i].type; - switch (tag_list->tag[i].type) + tag_list_c.field[i].key = strdup(tag_list->field[i].key); + tag_list_c.field[i].type = tag_list->field[i].type; + switch (tag_list->field[i].type) { - case TAG_INTEGER: - tag_list_c.tag[i].value_longlong = tag_list->tag[i].value_longlong; + case FIELD_VALUE_INTEGER: + tag_list_c.field[i].value_longlong = tag_list->field[i].value_longlong; break; - case TAG_DOUBLE: - tag_list_c.tag[i].value_double = tag_list->tag[i].value_double; + case FIELD_VALUE_DOUBLE: + tag_list_c.field[i].value_double = tag_list->field[i].value_double; break; - case TAG_CSTRING: - tag_list_c.tag[i].value_str = strdup(tag_list->tag[i].value_str); + case FIELD_VALUE_CSTRING: + tag_list_c.field[i].value_str = strdup(tag_list->field[i].value_str); break; default: break; @@ -144,38 +147,38 @@ Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(const Fieldstat_tag_list_ } } -const struct fieldstat_tag *Fieldstat_tag_list_wrapper::get_tag() const +const struct field *Fieldstat_tag_list_wrapper::get_tag() const { - return tag_list_c.tag; + return tag_list_c.field; } size_t Fieldstat_tag_list_wrapper::get_tag_count() const { - return tag_list_c.n_tag; + return tag_list_c.n_field; } -const struct fieldstat_tag_list *Fieldstat_tag_list_wrapper::get_c_struct() const +const struct field_list *Fieldstat_tag_list_wrapper::get_c_struct() const { return &tag_list_c; } void Fieldstat_tag_list_wrapper::print_tag_list() const { - printf("tag_list_c.n_tag: %zu\n", tag_list_c.n_tag); - for (size_t i = 0; i < tag_list_c.n_tag; i++) + printf("tag_list_c.n_field: %zu\n", tag_list_c.n_field); + for (size_t i = 0; i < tag_list_c.n_field; i++) { - printf("tag_list_c.tag[%zu].key: %s\n", i, tag_list_c.tag[i].key); - printf("tag_list_c.tag[%zu].type: %d\n", i, (int)tag_list_c.tag[i].type); - switch (tag_list_c.tag[i].type) + printf("tag_list_c.field[%zu].key: %s\n", i, tag_list_c.field[i].key); + printf("tag_list_c.field[%zu].type: %d\n", i, (int)tag_list_c.field[i].type); + switch (tag_list_c.field[i].type) { - case TAG_INTEGER: - printf("tag_list_c.tag[%zu].value_longlong: %lld\n", i, tag_list_c.tag[i].value_longlong); + case FIELD_VALUE_INTEGER: + printf("tag_list_c.field[%zu].value_longlong: %lld\n", i, tag_list_c.field[i].value_longlong); break; - case TAG_DOUBLE: - printf("tag_list_c.tag[%zu].value_double: %lf\n", i, tag_list_c.tag[i].value_double); + case FIELD_VALUE_DOUBLE: + printf("tag_list_c.field[%zu].value_double: %lf\n", i, tag_list_c.field[i].value_double); break; - case TAG_CSTRING: - printf("tag_list_c.tag[%zu].value_str: %s\n", i, tag_list_c.tag[i].value_str); + case FIELD_VALUE_CSTRING: + printf("tag_list_c.field[%zu].value_str: %s\n", i, tag_list_c.field[i].value_str); break; default: break; @@ -187,20 +190,20 @@ void Fieldstat_tag_list_wrapper::print_tag_list() const string Fieldstat_tag_list_wrapper::to_string() const { string str = ""; - for (size_t i = 0; i < tag_list_c.n_tag; i++) + for (size_t i = 0; i < tag_list_c.n_field; i++) { - str += tag_list_c.tag[i].key; + str += tag_list_c.field[i].key; str += ":"; - switch (tag_list_c.tag[i].type) + switch (tag_list_c.field[i].type) { - case TAG_INTEGER: - str += std::to_string(tag_list_c.tag[i].value_longlong); + case FIELD_VALUE_INTEGER: + str += std::to_string(tag_list_c.field[i].value_longlong); break; - case TAG_DOUBLE: - str += std::to_string(tag_list_c.tag[i].value_double); + case FIELD_VALUE_DOUBLE: + str += std::to_string(tag_list_c.field[i].value_double); break; - case TAG_CSTRING: - str += tag_list_c.tag[i].value_str; + case FIELD_VALUE_CSTRING: + str += tag_list_c.field[i].value_str; break; default: break; @@ -212,30 +215,30 @@ string Fieldstat_tag_list_wrapper::to_string() const bool Fieldstat_tag_list_wrapper::operator==(const Fieldstat_tag_list_wrapper &tag_list_wrapper) const { - const struct fieldstat_tag_list *tag_list = tag_list_wrapper.get_c_struct(); - if (tag_list_c.n_tag != tag_list->n_tag) { + const struct field_list *tag_list = tag_list_wrapper.get_c_struct(); + if (tag_list_c.n_field != tag_list->n_field) { return false; } - for (size_t i = 0; i < tag_list_c.n_tag; i++) { - if (strcmp((char *)tag_list_c.tag[i].key, (char *)tag_list->tag[i].key) != 0) { + for (size_t i = 0; i < tag_list_c.n_field; i++) { + if (strcmp((char *)tag_list_c.field[i].key, (char *)tag_list->field[i].key) != 0) { return false; } - if (tag_list_c.tag[i].type != tag_list->tag[i].type) { + if (tag_list_c.field[i].type != tag_list->field[i].type) { return false; } - switch (tag_list_c.tag[i].type) { - case TAG_INTEGER: - if (tag_list_c.tag[i].value_longlong != tag_list->tag[i].value_longlong) { + switch (tag_list_c.field[i].type) { + case FIELD_VALUE_INTEGER: + if (tag_list_c.field[i].value_longlong != tag_list->field[i].value_longlong) { return false; } break; - case TAG_DOUBLE: - if (tag_list_c.tag[i].value_double != tag_list->tag[i].value_double) { + case FIELD_VALUE_DOUBLE: + if (tag_list_c.field[i].value_double != tag_list->field[i].value_double) { return false; } break; - case TAG_CSTRING: - if (strcmp((char *)tag_list_c.tag[i].value_str, (char *)tag_list->tag[i].value_str) != 0) { + case FIELD_VALUE_CSTRING: + if (strcmp((char *)tag_list_c.field[i].value_str, (char *)tag_list->field[i].value_str) != 0) { return false; } break; @@ -248,7 +251,7 @@ bool Fieldstat_tag_list_wrapper::operator==(const Fieldstat_tag_list_wrapper &ta Fieldstat_tag_list_wrapper& Fieldstat_tag_list_wrapper::sort_tag_list() { - std::sort(tag_list_c.tag, tag_list_c.tag + tag_list_c.n_tag, [](const struct fieldstat_tag &a, const struct fieldstat_tag &b) { + std::sort(tag_list_c.field, tag_list_c.field + tag_list_c.n_field, [](const struct field &a, const struct field &b) { return strcmp((char *)a.key, (char *)b.key) < 0; }); return *this; @@ -293,3 +296,115 @@ double test_cal_topk_accuracy(vector<struct Fieldstat_tag_list_wrapper *> &test_ double accuracy = (double)correct / test_result.size(); return accuracy; } + + +//=========================================================================== +//= Function to generate Zipf (power law) distributed random variables = +//= - Input: alpha and N = +//= - Output: Returns with Zipf distributed random variable = +//=========================================================================== +int zipf(double alpha, int n) +{ + static bool first = true; // Static first time flag + static double c = 0; // Normalization constant + double z; // Uniform random number (0 < z < 1) + double sum_prob; // Sum of probabilities + double zipf_value; // Computed exponential value to be returned + int i; // Loop counter + + // Compute normalization constant on first call only + if (first) + { + for (i=1; i<=n; i++) + c = c + (1.0 / pow((double) i, alpha)); + c = 1.0 / c; + first = false; + } + + // Pull a uniform random number (0 < z < 1) + do + { + z = (double)rand() / (double)RAND_MAX; + } + while ((z == 0.0) || (z == 1.0)); + + // Map z to the value + sum_prob = 0; + for (i=1; i<=n; i++) + { + sum_prob = sum_prob + c / pow((double) i, alpha); + if (sum_prob >= z) + { + zipf_value = i; + break; + } + } + + return(zipf_value); +} + +SpreadSketchZipfGenerator::SpreadSketchZipfGenerator(double alpha, int n) { + _alpha = alpha; + _n = n; + cursor = 0; + + // generate data and write them to file + std::string filename = "zipf_" + std::to_string(alpha) + "_" + std::to_string(n) + ".txt"; + + std::unordered_map<int, int> fanout_map; // src_ip_id -> fanout being used + + if (access(filename.c_str(), F_OK) != 0) { + printf("file %s not found, generating data\n", filename.c_str()); + + std::ofstream file(filename); + if (!file.is_open()) { + printf("failed to open file %s\n", filename.c_str()); + return; + } + + for (int i = 0; i < MAX_DATA; i++) { + int src_id = zipf(alpha, n); + int fanout = fanout_map.find(src_id) == fanout_map.end() ? 0 : fanout_map[src_id]; + fanout_map[src_id] = fanout + 1; + + file << "s_" << src_id << " d_" << fanout << std::endl; + } + + file.close(); + printf("data generated and saved to file %s\n", filename.c_str()); + } + + // load data + std::ifstream file(filename); + if (!file.is_open()) { + printf("failed to open file %s\n", filename.c_str()); + return; + } + + loadeds = new std::vector<std::pair<std::string, std::string>>; + std::string line; + while (std::getline(file, line)) { + std::istringstream iss(line); + std::string src_ip, dst_ip; + iss >> src_ip >> dst_ip; + loadeds->push_back(std::make_pair(src_ip, dst_ip)); + } + file.close(); + +} + +SpreadSketchZipfGenerator::~SpreadSketchZipfGenerator() { + delete loadeds; +} + +struct Flow SpreadSketchZipfGenerator::next() { + int r_cursor = cursor % loadeds->size(); + struct Flow flow; + + flow.src_ip = loadeds->at(r_cursor).first; + flow.dst_ip = loadeds->at(r_cursor).second; + + cursor++; + + return flow; +}
\ No newline at end of file diff --git a/test/utils.hpp b/test/utils.hpp index 4fe7fde..efac03a 100644 --- a/test/utils.hpp +++ b/test/utils.hpp @@ -3,15 +3,14 @@ #include <unordered_map> #include "fieldstat.h" -const struct fieldstat_tag TEST_TAG_STRING = {"STRING KEY_", TAG_CSTRING, {.value_str = "100.1"}}; -const struct fieldstat_tag_list TEST_TAG_LIST_STRING = {(struct fieldstat_tag *)&TEST_TAG_STRING, 1}; -const struct fieldstat_tag TEST_TAG_STRING_collided = {"collided", TAG_CSTRING, {.value_str = "2"}}; -const struct fieldstat_tag TEST_TAG_INT = {"INT key_", TAG_INTEGER, {.value_longlong = 100}}; -const struct fieldstat_tag_list TEST_TAG_LIST_INT = {(struct fieldstat_tag *)&TEST_TAG_INT, 1}; -const struct fieldstat_tag TEST_TAG_INT_collided = {"collided", TAG_INTEGER, {.value_longlong = 2}}; -const struct fieldstat_tag TEST_TAG_DOUBLE = {"DOUBLE key_", TAG_DOUBLE, {.value_double = 100.1}}; -const struct fieldstat_tag TEST_TAG_DOUBLE_collided = {"collided", TAG_DOUBLE, {.value_double = 2.0}}; -const struct fieldstat_tag TEST_SHARED_TAG = {"shared", TAG_INTEGER, {.value_longlong = 1}}; +const struct field TEST_FIELD_STRING = {"STRING KEY_", FIELD_VALUE_CSTRING, {.value_str = "100.1"}}; +const struct field_list TEST_FIELD_LIST_STRING = {(struct field *)&TEST_FIELD_STRING, 1}; +const struct field TEST_FIELD_INT = {"INT key_", FIELD_VALUE_INTEGER, {.value_longlong = 100}}; +const struct field_list TEST_FIELD_LIST_INT = {(struct field *)&TEST_FIELD_INT, 1}; +const struct field TEST_FIELD_INT_2 = {"collided", FIELD_VALUE_INTEGER, {.value_longlong = 2}}; +const struct field TEST_FIELD_DOUBLE = {"DOUBLE key_", FIELD_VALUE_DOUBLE, {.value_double = 100.1}}; +const struct field_list TEST_FIELD_LIST_DOUBLE = {(struct field *)&TEST_FIELD_DOUBLE, 1}; +const struct field TEST_SHARED_TAG = {"shared", FIELD_VALUE_INTEGER, {.value_longlong = 1}}; const struct timeval TEST_TIMEVAL = {100, 10000}; const long long TEST_TIMEVAL_LONG = 100010; // 100s * 1000 + 10000us / 1000 = 100010ms @@ -19,7 +18,7 @@ std::string gen_rand_string(int len); class Fieldstat_tag_list_wrapper { public: - explicit Fieldstat_tag_list_wrapper(const struct fieldstat_tag_list *tag_list_c); + explicit Fieldstat_tag_list_wrapper(const struct field_list *tag_list_c); explicit Fieldstat_tag_list_wrapper(const char * key, int value); explicit Fieldstat_tag_list_wrapper(const char * key, const char *value); explicit Fieldstat_tag_list_wrapper(std::uniform_int_distribution<int> &dist, int tag_count); @@ -30,17 +29,38 @@ public: ~Fieldstat_tag_list_wrapper(); bool operator==(const Fieldstat_tag_list_wrapper &tag_list_wrapper) const; - const struct fieldstat_tag *get_tag() const; + const struct field *get_tag() const; size_t get_tag_count() const; - const struct fieldstat_tag_list *get_c_struct() const; + const struct field_list *get_c_struct() const; void print_tag_list() const; Fieldstat_tag_list_wrapper& sort_tag_list(); private: - struct fieldstat_tag_list tag_list_c; + struct field_list tag_list_c; }; double test_cal_topk_accuracy(std::vector<struct Fieldstat_tag_list_wrapper *> &test_result, std::unordered_map<std::string, int> &expected_count); // after we change fieldstat_counter_get return a error code in, all the tests should change correspondingly, so just use a adapter aliasing the old function -long long my_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id);
\ No newline at end of file +long long my_fieldstat_counter_get(const struct fieldstat *instance, int cube_id, int metric_id, int cell_id); + + +struct Flow { + std::string src_ip; + std::string dst_ip; +}; + +class SpreadSketchZipfGenerator { +private: + const int MAX_DATA = 1000000; + std::vector<std::pair<std::string, std::string>> *loadeds; + unsigned cursor; + +public: + SpreadSketchZipfGenerator(double alpha, int n); + struct Flow next(); + ~SpreadSketchZipfGenerator(); + + double _alpha; + int _n; +};
\ No newline at end of file |
