diff options
| author | chenzizhan <[email protected]> | 2023-09-27 16:02:51 +0800 |
|---|---|---|
| committer | chenzizhan <[email protected]> | 2023-09-27 16:02:51 +0800 |
| commit | e938e4a19295253f004a8e6c45dac40aac305fd4 (patch) | |
| tree | 9bdcea29cc8e066a8c3545632500188d2361e049 | |
| parent | 833b336ab8279ef69fa50590bd4628368c2a2f57 (diff) | |
fuzz test comprehensive
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | include/fieldstat/fieldstat.h | 2 | ||||
| -rw-r--r-- | test/CMakeLists.txt | 16 | ||||
| -rw-r--r-- | test/test_fuzz_test.cpp | 295 |
4 files changed, 118 insertions, 197 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 340861e..4b89567 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ if (CMAKE_CXX_CPPCHECK) "--inline-suppr"
"--suppress=*:${PROJECT_SOURCE_DIR}/vendors/*"
"--suppress=*:${PROJECT_SOURCE_DIR}/test/utils.hpp"
- # "--suppress=*:${PROJECT_SOURCE_DIR}/test/test_fuzz_test.cpp"
+ "--suppress=*:${PROJECT_SOURCE_DIR}/test/test_fuzz_test.cpp"
"--suppress=*:${PROJECT_SOURCE_DIR}/test/unit_test_serialize.cpp"
"--suppress=*:${PROJECT_SOURCE_DIR}/src/logger/log_handle.c"
)
diff --git a/include/fieldstat/fieldstat.h b/include/fieldstat/fieldstat.h index 157b783..1c87e4a 100644 --- a/include/fieldstat/fieldstat.h +++ b/include/fieldstat/fieldstat.h @@ -8,8 +8,6 @@ extern "C" #include <stddef.h> #include <stdbool.h> -#define EXPORT_VER 1 // increase by 1 when the serialization format is changed. - #define FS_OK 0 #define FS_ERR_TOO_MANY_CELLS -1 #define FS_ERR_NULL_HANDLER -2 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cdd8ebe..896ccf6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -46,13 +46,13 @@ function (add_unit_test file_name) set_property(TARGET ${file_name} PROPERTY CXX_STANDARD 17)
endfunction()
-# add_unit_test(test_empty_tags)
+add_unit_test(test_empty_tags)
add_unit_test(test_exporter_json)
-# add_unit_test(test_fuzz_test)
-# add_unit_test(test_merge)
-# add_unit_test(test_metric_counter)
-# add_unit_test(test_metric_histogram)
-# add_unit_test(test_metric_hll)
+add_unit_test(test_fuzz_test)
+add_unit_test(test_merge)
+add_unit_test(test_metric_counter)
+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)
\ No newline at end of file +add_unit_test(test_register_and_reset)
+add_unit_test(unit_test_cell_manager)
\ No newline at end of file diff --git a/test/test_fuzz_test.cpp b/test/test_fuzz_test.cpp index 19cbcc6..d5a795f 100644 --- a/test/test_fuzz_test.cpp +++ b/test/test_fuzz_test.cpp @@ -23,248 +23,171 @@ void fill_random_tag_of_length_1_to_3(Fieldstat_tag_list_wrapper *tags[], int ta } } -TEST(Fuzz_test, both_comp_and_topk_cubes_with_merge_and_reset_expecting_correct_results) +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 value = 0; + int ret = fieldstat_counter_get(instance, cube_id, metric_id, tag_list, &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 value = 0; + int ret = fieldstat_hll_get(instance, cube_id, metric_id, tag_list, &value); + EXPECT_EQ(ret, 0); + return value; +} + +// cpp-check-suppress moduloofone +TEST(Fuzz_test, many_instance_random_flow_unregister_calibrate_reset_fork_merge_comprehensive) { const int METRIC_NUM = 2; - const char *metric_name_of_topk[METRIC_NUM] = {"topk1", "topk2"}; - const char *metric_name_of_comprehensive[METRIC_NUM] = {"counter_", "hll_"}; - const int CELL_NUM = 50; - const int CUBE_NUM = 10; - int cube_ids[CUBE_NUM]; - bool cube_is_topk[CUBE_NUM]; - unordered_map<string, int> topk_count_per_metric[CUBE_NUM][METRIC_NUM]; - unordered_map<string, int> comp_count[CUBE_NUM]; - unordered_map<string, set<string>> comp_hll[CUBE_NUM]; - Fieldstat_tag_list_wrapper *shared_tag[CUBE_NUM]; + const int METRIC_ID_COUNTER = 0; + const int METRIC_ID_HLL = 1; + const int CUBE_NUM = 5; + const int INSTANCE_NUM = 10; + const int FLOW_NUM = 5000; + const int CELL_MAX = 5000; // must be no less than FLOW_NUM to ensure an accurate statistics + const int TEST_ROUND = 100000; + const int OUT_GAP = 10000; + const char *metric_name[METRIC_NUM] = {"counter_", "hll_"}; + 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_tag[i] = new Fieldstat_tag_list_wrapper("shared_tag", 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); + EXPECT_EQ(cube_id, i); } - - Fieldstat_tag_list_wrapper *tag_list_wrapper[CELL_NUM]; - fill_random_tag_of_length_1_to_3(tag_list_wrapper, CELL_NUM); - - const int TEST_ROUND = 100001; - struct fieldstat *instance = fieldstat_new(); - struct fieldstat *instance_dest = fieldstat_new(); + // 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 + 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 long long rand_nums[TEST_ROUND]; string *rand_strs[TEST_ROUND] = {NULL}; for (int i = 0; i < TEST_ROUND; i++) { - rand_nums[i] = rand() % 10000; + rand_nums[i] = rand() % 1000; rand_strs[i] = new string(string("str val") + std::to_string(rand_nums[i])); } - - std::function<int(int)> metric_reg_funcs_comp[METRIC_NUM] = { - std::bind(fieldstat_register_counter, instance, std::placeholders::_1, metric_name_of_comprehensive[0]), - std::bind(fieldstat_register_hll, instance, std::placeholders::_1, metric_name_of_comprehensive[1], 10), // 4: precision - }; - std::function<int(int)> metric_reg_funcs_topk[METRIC_NUM] = { - std::bind(fieldstat_register_counter, instance, std::placeholders::_1, metric_name_of_topk[0]), - std::bind(fieldstat_register_counter, instance, std::placeholders::_1, metric_name_of_topk[1]), - }; - - for (int i = 0; i < CUBE_NUM; i++) { - bool is_topk = rand() % 2 == 0; - // bool is_topk = true; - cube_is_topk[i] = is_topk; - cube_ids[i] = fieldstat_create_cube(instance, shared_tag[i]->get_tag(), shared_tag[i]->get_tag_count(), is_topk ? SAMPLING_MODE_TOPK : SAMPLING_MODE_COMPREHENSIVE, - is_topk ? 10000 : CELL_NUM); - std::function<int(int)> *metric_reg_funcs = is_topk ? metric_reg_funcs_topk : metric_reg_funcs_comp; - for (int metric_id = 0; metric_id < METRIC_NUM; metric_id++) { - metric_reg_funcs[metric_id](cube_ids[i]); - } + //init instance + for (int i = 0; i < INSTANCE_NUM; i++) { + replica[i] = fieldstat_fork(master); } + // for benchmark + unordered_map<string, int> comp_count; + unordered_map<string, set<string>> comp_hll; clock_t start = clock(); + int next_shared_tag_value = CUBE_NUM; for (int i = 0; i < TEST_ROUND; i++) { - if (i != 0 && i % 1000 == 0) { - char *blob; - size_t blob_len; - fieldstat_serialize(instance, &blob, &blob_len); - struct fieldstat *instance_tmp = fieldstat_deserialize(blob, blob_len); - fieldstat_merge(instance_dest, instance_tmp); - fieldstat_free(instance_tmp); - fieldstat_reset(instance); - free(blob); + 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_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); + 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++) { + fieldstat_calibrate(master, replica[j]); + } // check if no merge happens in the last 100 rounds - if (i + 100 >= TEST_ROUND) { + if (i + OUT_GAP >= TEST_ROUND) { break; } } + 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]; int cube_id = rand() % CUBE_NUM; - // int cube_id = 0; + const Fieldstat_tag_list_wrapper *shared_tag = shared_tags[cube_id]; - if (cube_is_topk[cube_id]) { - const Fieldstat_tag_list_wrapper * tmp = tag_list_wrapper[rand() % CELL_NUM]; - int cell_id = fieldstat_cube_add(instance, cube_ids[cube_id], tmp->get_tag(), tmp->get_tag_count(), rand_nums[i]); - if (cell_id == -1) { - continue; - } - for (int metric_id = 0; metric_id < METRIC_NUM; metric_id++) { - long long val = rand_nums[i]; - fieldstat_counter_incrby(instance, cube_id, metric_id, cell_id, val); - topk_count_per_metric[cube_id][metric_id][tmp->to_string()] += val; - } - } else { - const Fieldstat_tag_list_wrapper * tmp = tag_list_wrapper[rand() % CELL_NUM]; - int cell_id = fieldstat_cube_add(instance, cube_ids[cube_id], tmp->get_tag(), tmp->get_tag_count(), 1); - if (cell_id == -1) { - printf("cell_id == -1\n"); - continue; - } - fieldstat_counter_incrby(instance, cube_id, 0, cell_id, rand_nums[i]); - string *val = rand_strs[i]; - fieldstat_hll_add(instance, cube_id, 1, cell_id, val->c_str(), val->size()); - string cell_key = tmp->to_string(); - comp_count[cube_id][cell_key] += rand_nums[i]; - comp_hll[cube_id][cell_key].insert(*val); + int ret_add = fieldstat_counter_incrby(instance, cube_id, METRIC_ID_COUNTER, tag->get_tag(), tag->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()); + EXPECT_EQ(ret_add, FS_OK); + string cell_key = shared_tag->to_string() + tag->to_string(); + comp_count[cell_key] += rand_nums[i]; + comp_hll[cell_key].insert(*val); } - clock_t end = clock(); printf("time: %lf\n", (double)(end - start) / CLOCKS_PER_SEC); for (int i = 0; i < TEST_ROUND; i++) { delete rand_strs[i]; } - for (int i = 0; i < CELL_NUM; i++) { + for (int i = 0; i < FLOW_NUM; i++) { delete tag_list_wrapper[i]; } for (int i = 0; i < CUBE_NUM; i++) { - delete shared_tag[i]; + delete shared_tags[i]; } - int *cubes; + int *cube_ids; int cube_num; - struct fieldstat *instance_in_focus = instance_dest; - fieldstat_get_cubes(instance_in_focus, &cubes, &cube_num); - EXPECT_EQ(cube_num, 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++) { - EXPECT_EQ(fieldstat_get_max_metric_id(instance_in_focus, cubes[i]), METRIC_NUM - 1); - int *cells0; + struct fieldstat_tag_list *shared_tag_out = fieldstat_get_shared_tags(instance_in_focus, cube_ids[i]); + size_t cell_num0; struct fieldstat_tag_list *tags0; - fieldstat_get_cells_used_by_metric(instance_in_focus, cubes[i], 0, &cells0, &tags0, &cell_num0); - int *cells1; + 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, cubes[i], 1, &cells1, &tags1, &cell_num1); + fieldstat_get_cells_used_by_metric(instance_in_focus, cube_ids[i], METRIC_ID_HLL, &tags1, &cell_num1); 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(cells0[j], cells1[j]); } - if (cube_is_topk[cubes[i]]) { - std::vector<struct Fieldstat_tag_list_wrapper *> test_result[METRIC_NUM]; - for (size_t j = 0; j < cell_num0; j++) { - test_result[0].push_back(new Fieldstat_tag_list_wrapper(&tags0[j])); - test_result[1].push_back(new Fieldstat_tag_list_wrapper(&tags1[j])); - } - EXPECT_GT(test_cal_topk_accuracy(test_result[0], topk_count_per_metric[cubes[i]][0]), 0.9); - EXPECT_GT(test_cal_topk_accuracy(test_result[1], topk_count_per_metric[cubes[i]][1]), 0.9); - - for (size_t j = 0; j < cell_num0; j++) { - delete test_result[0][j]; - delete test_result[1][j]; - } - } else { - for (size_t j = 0; j < cell_num0; j++) { - string cell_key = Fieldstat_tag_list_wrapper(&tags0[j]).to_string(); - EXPECT_EQ(comp_count[cubes[i]][cell_key], my_fieldstat_counter_get(instance_in_focus, cubes[i], 0, cells0[j])); - EXPECT_NEAR(comp_hll[cubes[i]][cell_key].size(), fieldstat_hll_get(instance_in_focus, cubes[i], 1, cells0[j]), comp_hll[cubes[i]][cell_key].size() * 0.2); - } + for (size_t j = 0; j < cell_num0; j++) { + string tag_str_out = Fieldstat_tag_list_wrapper(&tags0[j]).to_string(); + string cell_key = Fieldstat_tag_list_wrapper(shared_tag_out).to_string() + tag_str_out; + + EXPECT_EQ(comp_count[cell_key], fuzz_fieldstat_counter_get(instance_in_focus, cube_ids[i], 0, &tags0[j])); + // EXPECT_NEAR(comp_hll[cell_key].size(), fuzz_fieldstat_hll_get(instance_in_focus, cube_ids[i], 1, &tags1[j]), comp_hll[cell_key].size() * 0.2); } - free(cells0); - free(cells1); 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); } - free(cubes); + free(cube_ids); - // printf("czzzz test (json)----------------\n"); - // struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(instance_dest); - // char *json_string = fieldstat_json_exporter_export(fieldstat_json_exporter); - // EXPECT_TRUE(json_string != NULL); - // printf("%s\n", json_string); - // fieldstat_json_exporter_free(fieldstat_json_exporter); - // free(json_string); - - fieldstat_free(instance_dest); - fieldstat_free(instance); + fieldstat_free(master); + fieldstat_free(dest); + for (int i = 0; i < INSTANCE_NUM; i++) { + fieldstat_free(replica[i]); + } } -// TEST(Fuzz_test, memory_cost_test) -// { -// const int METRIC_NUM = 10; -// const char *metric_name_of_comprehensive[METRIC_NUM] = {"counter1", "counter2", "counter3", "counter4", "counter5", "counter6", "counter7", "counter8", "counter9", "counter10"}; -// const int CELL_NUM = 4000; -// const int CUBE_NUM = 1; -// int cube_ids[CUBE_NUM]; - -// Fieldstat_tag_list_wrapper *shared_tag[CUBE_NUM]; -// for (int i = 0; i < CUBE_NUM; i++) { -// shared_tag[i] = new Fieldstat_tag_list_wrapper("shared_tag", i); -// } - -// Fieldstat_tag_list_wrapper *tag_list_wrapper[CELL_NUM]; -// fill_random_tag_of_length_1_to_3(tag_list_wrapper, CELL_NUM); - -// const int TEST_ROUND = 100000; -// struct fieldstat *instance = fieldstat_new(); -// long long rand_nums[TEST_ROUND]; -// for (int i = 0; i < TEST_ROUND; i++) { -// rand_nums[i] = rand() % 10000; -// } - -// for (int i = 0; i < CUBE_NUM; i++) { -// cube_ids[i] = fieldstat_create_cube(instance, shared_tag[i]->get_tag(), shared_tag[i]->get_tag_count(), SAMPLING_MODE_COMPREHENSIVE, -// CELL_NUM); -// for (int metric_id = 0; metric_id < METRIC_NUM; metric_id++) { -// fieldstat_register_counter(instance, cube_ids[i], metric_name_of_comprehensive[metric_id], false); -// } -// } - -// for (int i = 0; i < TEST_ROUND; i++) { -// // int cube_id = i % CUBE_NUM; -// int cube_id = 0; -// // int cube_id = 0; - -// const Fieldstat_tag_list_wrapper * tmp = tag_list_wrapper[rand() % CELL_NUM]; -// int cell_id = fieldstat_cube_add(instance, cube_ids[cube_id], tmp->get_tag(), tmp->get_tag_count(), 1); -// if (cell_id == -1) { -// continue; -// } -// for (int metric_id = 0; metric_id < METRIC_NUM; metric_id++) { -// fieldstat_counter_incrby(instance, cube_ids[cube_id], metric_id, cell_id, rand_nums[i]); -// } -// } - -// for (int i = 0; i < CELL_NUM; i++) { -// delete tag_list_wrapper[i]; -// } -// for (int i = 0; i < CUBE_NUM; i++) { -// delete shared_tag[i]; -// } -// printf("czzzz test (json)----------------\n"); -// getchar(); -// struct fieldstat_json_exporter *fieldstat_json_exporter = fieldstat_json_exporter_new(instance); -// char *json_string = fieldstat_json_exporter_export(fieldstat_json_exporter); -// EXPECT_TRUE(json_string != NULL); -// // printf("%s\n", json_string); -// printf("export done\n"); -// getchar(); -// fieldstat_json_exporter_free(fieldstat_json_exporter); -// free(json_string); - -// fieldstat_free(instance); -// } - int main(int argc, char *argv[]) { testing::InitGoogleTest(&argc, argv); |
