summaryrefslogtreecommitdiff
path: root/CRDT/ftbt_gtest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CRDT/ftbt_gtest.cpp')
-rw-r--r--CRDT/ftbt_gtest.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/CRDT/ftbt_gtest.cpp b/CRDT/ftbt_gtest.cpp
new file mode 100644
index 0000000..4c536bd
--- /dev/null
+++ b/CRDT/ftbt_gtest.cpp
@@ -0,0 +1,249 @@
+#include "ftb_throttler.h"
+#include "crdt_utils.h"
+#include "ransampl.h"
+#include <cstddef>
+#include <cstdio>
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+#include <math.h>
+#include "util/flow_tokens.h"
+#include "util/fair_index.h"
+
+void ftbt_throttle_sync(struct ftb_throttler *list[], size_t n)
+{
+ char *blob=NULL;
+ size_t blob_sz=0;
+ for(size_t i=0; i<n; i++)
+ {
+ ftb_throttler_serialize(list[i], &blob, &blob_sz);
+ for(size_t j=0; j<n; j++)
+ {
+ if(j==i) continue;
+ ftb_throttler_merge_blob(list[j], blob, blob_sz);
+ }
+ free(blob);
+ blob=NULL;
+ }
+}
+
+TEST(FTBT, Basic)
+{
+ uuid_t uuid;
+ uuid_generate(uuid);
+
+ struct ftb_throttler *bucket=NULL;
+ struct ftb_throttler_info *info = ALLOC(struct ftb_throttler_info, 1);
+ long long CIR=100;
+ long long CBS=200;
+ struct timeval now;
+ gettimeofday(&now, NULL);
+
+ bucket=ftb_throttler_new(uuid, now, CIR, CBS, CIR/10);
+ long long rtn = 0;
+
+ rtn=ftb_throttler_control(bucket, now, FTBT_CMD_CONSUME_NORMAL, 60, "1", 1);
+ ftb_throttler_info(bucket, info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 200);
+
+ rtn=ftb_throttler_control(bucket, now, FTBT_CMD_CONSUME_FLEXIBLE, 200, "1", 1);
+ ftb_throttler_info(bucket, info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 200);
+
+ rtn=ftb_throttler_control(bucket, now, FTBT_CMD_CONSUME_NORMAL, 60, "1", 1);
+ ftb_throttler_info(bucket, info);
+ EXPECT_EQ(rtn, 0);
+ EXPECT_EQ(info->available, 200);
+
+ ftb_throttler_free(bucket);
+}
+
+TEST(FTBT, BasicWeighted)
+{
+ uuid_t uuid;
+ uuid_generate(uuid);
+
+ struct ftb_throttler *bucket=NULL;
+ struct ftb_throttler_info *info = ALLOC(struct ftb_throttler_info, 1);
+ long long CIR=100*1000; //100*1000 bps
+ long long CBS=200;
+ struct timeval now, step;
+ gettimeofday(&now, NULL);
+
+ step.tv_sec=0;
+ step.tv_usec=(suseconds_t)1000;
+
+ bucket=ftb_throttler_new(uuid, now, CIR, CBS, CIR/10);
+ long long rtn = 0;
+
+ rtn=ftb_throttler_control(bucket, now, FTBT_CMD_CONSUME_NORMAL, 200, "1", 1); //active list : 200
+ ftb_throttler_info(bucket, info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 200);
+
+ rtn=ftb_throttler_control(bucket, now, FTBT_CMD_CONSUME_NORMAL, 160, "2", 2);//active list : 200 160
+ ftb_throttler_info(bucket, info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 200);
+
+ timeradd(&now, &step, &now);
+ rtn=ftb_throttler_control(bucket, now, FTBT_CMD_CONSUME_NORMAL, 20, "1", 1);//active list : 130 30
+ ftb_throttler_info(bucket, info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 100);
+
+ ftb_throttler_free(bucket);
+}
+
+TEST(FTBT, Merge)
+{
+ uuid_t uuid;
+
+ struct ftb_throttler *bucket[2];
+ struct ftb_throttler_info *info = ALLOC(struct ftb_throttler_info, 1);
+ long long CIR=100*1000; //100*1000 bps
+ long long CBS=200;
+ long long rtn = 0;
+ struct timeval now, step;
+ gettimeofday(&now, NULL);
+
+ step.tv_sec=0;
+ step.tv_usec=(suseconds_t)1000;
+
+ uuid_generate(uuid);
+ bucket[0]=ftb_throttler_new(uuid, now, CIR, CBS, CIR/10);
+ uuid_generate(uuid);
+ bucket[1]=ftb_throttler_new(uuid, now, CIR, CBS, CIR/10);
+
+ rtn=ftb_throttler_control(bucket[0], now, FTBT_CMD_CONSUME_NORMAL, 200, "1", 1);
+ ftb_throttler_info(bucket[0], info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 200);
+
+ rtn=ftb_throttler_control(bucket[1], now, FTBT_CMD_CONSUME_NORMAL, 50, "2", 1);
+ ftb_throttler_info(bucket[1], info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 200);
+
+ timeradd(&now, &step, &now);
+ rtn=ftb_throttler_control(bucket[0], now, FTBT_CMD_CONSUME_NORMAL, 0, "1", 1); //300-200=100
+ ftb_throttler_info(bucket[0], info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 100);
+ rtn=ftb_throttler_control(bucket[1], now, FTBT_CMD_CONSUME_NORMAL, 0, "2", 1);//300-50=250(200)
+ ftb_throttler_info(bucket[1], info);
+ EXPECT_EQ(rtn, 1);
+ EXPECT_EQ(info->available, 200);
+
+ ftbt_throttle_sync(bucket, 2);
+
+ ftb_throttler_info(bucket[0], info);
+ EXPECT_EQ(info->available, 50);
+ ftb_throttler_info(bucket[1], info);
+ EXPECT_EQ(info->available, 50);
+
+ ftb_throttler_free(bucket[0]);
+ ftb_throttler_free(bucket[1]);
+}
+
+#define FAIR_INDEX_CIR 1*1024*1000 //1024 bit/ms
+#define FAIR_INDEX_CBS 10*1024
+#define FAIR_INDEX_REQ FAIR_INDEX_CIR/1000
+#define FAIR_INDEX_MIMIC_DURATION_US 1*1000*1000
+
+TEST(FTBT, Pareto)
+{
+ int class_num = 24;
+ enum flow_type ftype = PARETO;
+ uuid_t uuid;
+ uuid_generate(uuid);
+ struct timeval start;
+ gettimeofday(&start, NULL);
+ struct ftb_throttler_info *info = ALLOC(struct ftb_throttler_info, 1);
+ struct ftb_throttler *bucket=NULL;
+ bucket=ftb_throttler_new(uuid, start, FAIR_INDEX_CIR, FAIR_INDEX_CBS, FAIR_INDEX_CIR/1000/10);
+ size_t i,j,k;
+ long long tokens=0;
+ long long consumed_class[class_num];
+ long long consumed=0, requested=0, upper_limit=0, refilled=0;
+ struct timeval step, now;
+ memcpy(&now, &start, sizeof(now));
+ step.tv_sec=0;
+ step.tv_usec=(suseconds_t)1000;
+ memset(consumed_class, 0, sizeof(consumed_class));
+ char str[20];
+
+ struct test_records ftbf_class_results[class_num], ftbf_result;
+ unsigned char class_weight[class_num];
+ double prob[class_num];
+ memset(&ftbf_result, 0, sizeof(ftbf_result));
+ memset(ftbf_class_results, 0, sizeof(ftbf_class_results));
+ memset(class_weight, 0, sizeof(class_weight));
+ memset(prob, 0, sizeof(prob));
+
+ for(int i = 0; i < class_num; i++)
+ {
+ class_weight[i] = 1;
+ }
+ set_flow_prob(prob, class_num, ftype);
+ ransampl_ws *ws = ransampl_init(prob, class_num);
+ int round = FAIR_INDEX_MIMIC_DURATION_US/1000;
+ srandom(17);
+ for(i=0; i<(size_t)round; i++)
+ {
+ timeradd(&now, &step, &now);
+ for(k = 0; k < (size_t)class_num; ++k)
+ {
+ j = ransampl_draw(ws); //并发但未限定每个classid最多请求一次,待修改
+ tokens = 0.2*FAIR_INDEX_REQ+rand()%5;
+ requested += tokens;
+ sprintf(str, "%zu", j);
+ int rtn = ftb_throttler_control(bucket, now, FTBT_CMD_CONSUME_FLEXIBLE, tokens, str, class_weight[j]);
+ ftbf_result.cnt++;
+ ftbf_class_results[j].cnt++;
+ if(rtn > 0)
+ {
+ ftbf_result.succ_cnt++;
+ ftbf_class_results[j].succ_cnt++;
+ }else
+ {
+ ftbf_result.fail_cnt++;
+ ftbf_class_results[j].fail_cnt++;
+ }
+ }
+ }
+
+ upper_limit=FAIR_INDEX_CBS+FAIR_INDEX_CIR/1000*timeval_delta_ms(start, now);
+ ftb_throttler_info(bucket, info);
+ refilled=info->refilled;
+ for(i=0; i<(size_t)class_num; ++i)
+ {
+ consumed += consumed_class[i];
+ // printf("rate[%zu]=%.2lld\n", i, consumed_class[i]);
+ }
+ EXPECT_LE(consumed, requested);
+ double accuracy=(double)consumed/MIN(refilled, requested);
+
+ float jain_fair_index = calculate_jain_fair_index(&ftbf_result, ftbf_class_results, class_weight, class_num);
+ printf("accuracy:%f, upper_limit:%lld, refilled:%lld, requested:%lld, consumed:%lld, jain_fair_index:%f\n",
+ accuracy,
+ upper_limit,
+ refilled,
+ requested,
+ consumed,
+ jain_fair_index);
+ ransampl_free(ws);
+ ftb_throttler_free(bucket);
+ EXPECT_NEAR(jain_fair_index, 1, 0.01);
+}
+
+
+int main(int argc, char ** argv)
+{
+ int ret=0;
+ ::testing::InitGoogleTest(&argc, argv);
+ ret=RUN_ALL_TESTS();
+ return ret;
+}