rebase onto develop-2.0
This commit is contained in:
194
test/monitor/gtest_ringbuf.cpp
Normal file
194
test/monitor/gtest_ringbuf.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <getopt.h>
|
||||
#include <pthread.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "stellar/monitor.h"
|
||||
#include "monitor_ringbuf.h"
|
||||
|
||||
#define TOTAL_TEST_NUM 100000
|
||||
#define BATCH_NUM 10
|
||||
#define MAX_PAYLOAD_LEN 2048
|
||||
#define MAGIC_NUM 0x1234ABCD
|
||||
static struct monitor_ringbuf_wrap *rbf_ctop;
|
||||
static struct monitor_ringbuf_wrap *rbf_ptoc;
|
||||
static const size_t ringbuf_size = MAX_PAYLOAD_LEN * 1024;
|
||||
|
||||
static unsigned long long ctop_producer_len = 0, ctop_consumer_len = 0;
|
||||
static unsigned long long ptoc_producer_len = 0, ptoc_consumer_len = 0;
|
||||
|
||||
struct test_ringbuf_data
|
||||
{
|
||||
long long magic;
|
||||
long long block_len; /* total length, include this header and paylaod */
|
||||
char payload[MAX_PAYLOAD_LEN];
|
||||
};
|
||||
|
||||
static int test_ringbuf_push_mode = 0; /* 0: easy push, 1: push by offset */
|
||||
|
||||
static int ringbuf_push(int tid, struct monitor_ringbuf_wrap *rbf, struct test_ringbuf_data *payload)
|
||||
{
|
||||
int ret = 0;
|
||||
if (0 == test_ringbuf_push_mode)
|
||||
{
|
||||
ret = stm_ringbuf_easy_push(tid, rbf, payload, payload->block_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssize_t offset = stm_ringbuf_stream_start(tid, rbf, payload->block_len);
|
||||
if (offset < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
stm_ringbuf_stream_append(tid, rbf, offset++, payload++, 1);
|
||||
usleep(1);
|
||||
stm_ringbuf_stream_append(tid, rbf, offset++, payload++, 1);
|
||||
usleep(10);
|
||||
stm_ringbuf_stream_append(tid, rbf, offset++, payload++, 1);
|
||||
usleep(100);
|
||||
stm_ringbuf_stream_append(tid, rbf, offset, payload, payload->block_len - 3);
|
||||
stm_ringbuf_stream_finish(tid, rbf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ringbuf_producer(int tid, struct monitor_ringbuf_wrap *rbf, int batch)
|
||||
{
|
||||
struct test_ringbuf_data t;
|
||||
for (int i = 0; i < batch; i++)
|
||||
{
|
||||
t.magic = MAGIC_NUM;
|
||||
t.block_len = rand() % (MAX_PAYLOAD_LEN - sizeof(long long) * 2) + sizeof(long long) * 2; /* variable-length */
|
||||
while (ringbuf_push(tid, rbf, &t) < 0)
|
||||
{
|
||||
usleep(1);
|
||||
}
|
||||
if (rbf == rbf_ctop)
|
||||
{
|
||||
ctop_producer_len += t.block_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptoc_producer_len += t.block_len;
|
||||
}
|
||||
}
|
||||
return batch;
|
||||
}
|
||||
|
||||
static int ringbuf_customer(int tid, struct monitor_ringbuf_wrap *rbf, int batch)
|
||||
{
|
||||
(void)tid;
|
||||
void *data;
|
||||
size_t pop_len;
|
||||
for (int i = 0; i < batch; i++)
|
||||
{
|
||||
while ((data = stm_ringbuf_pop(rbf, &pop_len)) == NULL)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
struct test_ringbuf_data *td = (struct test_ringbuf_data *)data;
|
||||
if (td->magic != MAGIC_NUM)
|
||||
{
|
||||
stm_ringbuf_release(rbf, pop_len); /* maybe lost many messages */
|
||||
return 0;
|
||||
}
|
||||
td->magic = random();
|
||||
size_t rel_len = td->block_len;
|
||||
if (rbf == rbf_ctop)
|
||||
{
|
||||
ctop_consumer_len += td->block_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptoc_consumer_len += td->block_len;
|
||||
}
|
||||
td->block_len = 0;
|
||||
stm_ringbuf_release(rbf, rel_len);
|
||||
}
|
||||
return batch;
|
||||
}
|
||||
|
||||
static void *producer_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ctop_num = 0;
|
||||
int ptoc_num = 0;
|
||||
for (int i = 0; i < TOTAL_TEST_NUM; i++)
|
||||
{
|
||||
/* only two threads, use fake fix thread id */
|
||||
ctop_num += ringbuf_producer(0, rbf_ctop, BATCH_NUM);
|
||||
ptoc_num += ringbuf_customer(0, rbf_ptoc, BATCH_NUM);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *consumer_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int ctop_num = 0;
|
||||
int ptoc_num = 0;
|
||||
for (int i = 0; i < TOTAL_TEST_NUM; i++)
|
||||
{
|
||||
/* only two threads, use fake fix thread id */
|
||||
ptoc_num += ringbuf_producer(1, rbf_ptoc, BATCH_NUM);
|
||||
ctop_num += ringbuf_customer(1, rbf_ctop, BATCH_NUM);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int gtest_ringbuf(int mode)
|
||||
{
|
||||
pthread_t pid[2];
|
||||
test_ringbuf_push_mode = mode;
|
||||
rbf_ctop = stm_ringbuf_wrap_new(2, ringbuf_size);
|
||||
rbf_ptoc = stm_ringbuf_wrap_new(2, ringbuf_size);
|
||||
|
||||
pthread_create(&pid[0], NULL, producer_thread, NULL);
|
||||
pthread_create(&pid[1], NULL, consumer_thread, NULL);
|
||||
|
||||
pthread_join(pid[0], NULL);
|
||||
pthread_join(pid[1], NULL);
|
||||
|
||||
stm_ringbuf_get_statistics(rbf_ctop, NULL, &ctop_producer_len, NULL, &ctop_consumer_len);
|
||||
stm_ringbuf_get_statistics(rbf_ptoc, NULL, &ptoc_producer_len, NULL, &ptoc_consumer_len);
|
||||
|
||||
printf("ctop push len:%llu, ctop pop len:%llu\n", ctop_producer_len, ctop_consumer_len);
|
||||
printf("ptoc push len:%llu, ctop pop len:%llu\n", ptoc_producer_len, ptoc_consumer_len);
|
||||
if (ctop_producer_len != ctop_consumer_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (ptoc_producer_len != ptoc_consumer_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
stm_ringbuf_wrap_free(rbf_ptoc);
|
||||
stm_ringbuf_wrap_free(rbf_ctop);
|
||||
pthread_cancel(pid[0]);
|
||||
pthread_cancel(pid[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(MONITOR_RINGBUF, easy)
|
||||
{
|
||||
ASSERT_EQ(0, gtest_ringbuf(0));
|
||||
}
|
||||
|
||||
TEST(MONITOR_RINGBUF, stream)
|
||||
{
|
||||
ASSERT_EQ(0, gtest_ringbuf(0));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
srand(time(NULL));
|
||||
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
int ret = RUN_ALL_TESTS();
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user