This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
stellar-stellar/test/monitor/gtest_ringbuf.cpp
2024-11-07 18:30:58 +08:00

194 lines
5.1 KiB
C++

#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;
}