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