From fcba593fc1125a48a693226f13d89de498bb00eb Mon Sep 17 00:00:00 2001 From: chenzizhan Date: Wed, 21 Jun 2023 16:06:27 +0800 Subject: test utils --- test/utils.cpp | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 321 insertions(+), 13 deletions(-) (limited to 'test/utils.cpp') diff --git a/test/utils.cpp b/test/utils.cpp index ce09dd8..6438512 100644 --- a/test/utils.cpp +++ b/test/utils.cpp @@ -4,12 +4,31 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "fieldstat.h" #include "utils.hpp" using namespace std; +static int g_tag_num = 10; + +void set_tag_num(int num) +{ + g_tag_num = num; +} + +int get_tag_num() +{ + return g_tag_num; +} + string gen_rand_string(int len) { string s; @@ -20,22 +39,311 @@ string gen_rand_string(int len) return s; } -// class Tester +// Fieldstat_tag_wrapper::Fieldstat_tag_wrapper(const char *key, long long value) { +// tag.key = key; +// tag.type = TAG_INTEGER; +// tag.value_int = value; +// } + +// Fieldstat_tag_wrapper::Fieldstat_tag_wrapper(const char *key, double value) { +// tag.key = key; +// tag.type = TAG_DOUBLE; +// tag.value_double = value; +// } + +// Fieldstat_tag_wrapper::Fieldstat_tag_wrapper(const char *key, const char *value) { +// tag.key = key; +// tag.type = TAG_CSTRING; +// tag.value_str = value; +// // TODO: 这个地方应该是strdup。说实话这个类感觉都没什么用了,就先这样吧 +// } + +// Fieldstat_tag_wrapper::Fieldstat_tag_wrapper(const struct fieldstat_tag *tag) { +// switch (tag->type) +// { +// case TAG_INTEGER: +// Fieldstat_tag_wrapper(tag->key, tag->value_int); +// break; +// case TAG_DOUBLE: +// Fieldstat_tag_wrapper(tag->key, tag->value_double); +// break; +// case TAG_CSTRING: +// Fieldstat_tag_wrapper(tag->key, tag->value_str); +// break; +// default: +// break; +// } +// } + +// Fieldstat_tag_wrapper::Fieldstat_tag_wrapper(const std::uniform_int_distribution& dist) // { -// public: -// explicit Tester(string name) +// default_random_engine e; +// tag.key = strdup(gen_rand_string(10).c_str()); +// int rand_ret = rand() % 3; +// if (rand_ret == 0) +// { +// tag.type = TAG_INTEGER; +// tag.value_int = static_cast(dist(e)); +// } +// else if (rand_ret == 1) +// { +// tag.type = TAG_DOUBLE; +// tag.value_double = static_cast(dist(e)); +// } +// else +// { +// tag.type = TAG_CSTRING; +// tag.value_str = strdup(gen_rand_string(10).c_str()); +// } +// } +// Fieldstat_tag_wrapper::~Fieldstat_tag_wrapper() { +// if (tag.type == TAG_CSTRING) +// { +// free((void *)tag.value_str); +// } +// free((void *)tag.key); +// } + +// bool Fieldstat_tag_wrapper::operator==(const Fieldstat_tag_wrapper& rhs) const { +// if (tag.type != rhs.tag.type) +// { +// return false; +// } +// if (tag.type == TAG_INTEGER) +// { +// return tag.value_int == rhs.tag.value_int; +// } +// else if (tag.type == TAG_DOUBLE) // { -// string instance_name = name; -// instance = fieldstat_new()); +// return tag.value_double == rhs.tag.value_double; // } -// ~Tester() +// else // { -// fieldstat_free(instance); +// return strcmp(tag.value_str, rhs.tag.value_str) == 0; // } -// template -// requires std::is_same_v +// if (strcmp(tag.key, rhs.tag.key) != 0) { +// return false; +// } +// return true; +// } + +// const struct fieldstat_tag& Fieldstat_tag_wrapper::get_c_struct() const +// { +// return tag; +// } + +/* -------------------------------------------------------------------------- */ +/* taglist wrapper */ +/* -------------------------------------------------------------------------- */ + +Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(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++) + { + // 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) + { + case TAG_INTEGER: + tag_list_c.tag[i].value_int = tag_list->tag[i].value_int; + break; + case TAG_DOUBLE: + tag_list_c.tag[i].value_double = tag_list->tag[i].value_double; + break; + case TAG_CSTRING: + tag_list_c.tag[i].value_str = strdup(tag_list->tag[i].value_str); + break; + default: + break; + } + } +} + +Fieldstat_tag_list_wrapper::~Fieldstat_tag_list_wrapper() { + for (size_t i = 0; i < tag_list_c.n_tag; i++) + { + free((void *)tag_list_c.tag[i].key); + if (tag_list_c.tag[i].type == TAG_CSTRING) + { + free((void *)tag_list_c.tag[i].value_str); + } + } + free((void *)tag_list_c.tag); +} + +Fieldstat_tag_list_wrapper::Fieldstat_tag_list_wrapper(std::uniform_int_distribution &dist) +{ + int tag_count = get_tag_count(); // TODO: 更多的tag数量产生方式 + tag_list_c.tag = (struct fieldstat_tag *)malloc(sizeof(struct fieldstat_tag) * tag_count); + tag_list_c.n_tag = tag_count; + std::mt19937 rng(RAND_SEED); + for (int i = 0; i < tag_count; i++) + { + tag_list_c.tag[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_int = static_cast(dist(rng)); + } + else if (rand_ret == 1) + { + tag_list_c.tag[i].type = TAG_DOUBLE; + tag_list_c.tag[i].value_double = static_cast(dist(rng)); + } + else + { + tag_list_c.tag[i].type = TAG_CSTRING; + tag_list_c.tag[i].value_str = strdup(gen_rand_string(10).c_str()); + } + } +} + +const struct fieldstat_tag *Fieldstat_tag_list_wrapper::get_tag() +{ + return tag_list_c.tag; +} + +size_t Fieldstat_tag_list_wrapper::get_tag_count() +{ + return tag_list_c.n_tag; +} + + +/* -------------------------------------------------------------------------- */ +/* Api_caller */ +/* -------------------------------------------------------------------------- */ + +template +Api_caller::Api_caller() : rng(std::random_device()()), distribution(1, 100) +{ +} + +template +void Api_caller::addApiFunction(const std::function& apiFunction) { + apiFunctions.push_back(apiFunction); +} + +template +void Api_caller::testApis() +{ + for (const auto& apiFunction : apiFunctions) { + std::vector> args = generateArguments(); + for (const auto& argSet : args) { + ReturnType result = callApiFunction(apiFunction, argSet); + recordInputOutput(apiFunction, argSet, result); + } + } +} + +template +void Api_caller::testApis(int loop_num) { + for (int i = 0; i < loop_num; i++) { + testApis(); + } +} + +template +template +Arg Api_caller::generateArgument() { + return static_cast(distribution(rng)); +} + +template +template +void Api_caller::generateArgumentsImpl(std::vector>& args, std::tuple& current) { + if constexpr (Index == sizeof...(Args)) { + args.push_back(current); + } else { + std::get(current) = generateArgument>>(); + generateArgumentsImpl(args, current); + } +} + +template +template +void Api_caller::generateArgumentsImpl(std::vector>& args) { + std::tuple current; + generateArgumentsImpl(args, current); +} + +template +std::vector> Api_caller::generateArguments() { + std::vector> args; + generateArgumentsImpl<0, Args...>(args); + return args; +} + +// Call an API function with arguments +template +ReturnType Api_caller::callApiFunction(const std::function& apiFunction, const std::tuple& args) { + return std::apply(apiFunction, args); +} + +// TODO: 看看到底有没用,没用就删了吧 +template +void printInput(const std::tuple& args) { + if constexpr (Index < sizeof...(Args)) { + std::cout << std::get(args) << " "; + printInput(args); + } +} + +// Record the input arguments and output of an API function +template +void Api_caller::recordInputOutput(Args... args, ReturnType result) +{ + arguments.emplace_back(std::make_tuple(args...)); + results.push_back(result); +} + +template +std::vector>Api_caller::getArguments() +{ + return arguments; +} + +template +Query_caller::Query_caller(const std::function& queryFunction) : queryFunction(queryFunction) +{ +} + +template +template +void Query_caller::take_args(std::vector>& args) +{ + for (auto& arg : args) + { + extract_tags(arg); + } +} + +template +std::vector Query_caller::get_results() +{ + std::vector results; + std::transform(arguments.begin(), arguments.end(), std::back_inserter(results), queryFunction); + return results; +} + +template +template +void Query_caller::extract_tags(std::tuple& args) +{ + Fieldstat_tag_list_wrapper tag_list_wrapper; + arguments.push_back(std::get(args)); +} + +template +double cal_accuracy(std::vector& results, std::vector& expected_results) +{ + int count = 0; + + for (const auto &expected_result : expected_results) { + count += std::count(results.begin(), results.end(), expected_result); + } -// private: -// string instance_name; -// struct fieldstat *instance; -// }; \ No newline at end of file + return count / results.size(); +} \ No newline at end of file -- cgit v1.2.3