summaryrefslogtreecommitdiffstats
path: root/src/test/msgr/test_userspace_event.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/msgr/test_userspace_event.cc')
-rw-r--r--src/test/msgr/test_userspace_event.cc174
1 files changed, 174 insertions, 0 deletions
diff --git a/src/test/msgr/test_userspace_event.cc b/src/test/msgr/test_userspace_event.cc
new file mode 100644
index 000000000..067d81545
--- /dev/null
+++ b/src/test/msgr/test_userspace_event.cc
@@ -0,0 +1,174 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2016 XSky <haomai@xsky.com>
+ *
+ * Author: Haomai Wang <haomaiwang@gmail.com>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <map>
+#include <random>
+#include <gtest/gtest.h>
+
+#include "msg/async/dpdk/UserspaceEvent.h"
+#include "global/global_context.h"
+
+class UserspaceManagerTest : public ::testing::Test {
+ public:
+ UserspaceEventManager *manager;
+
+ UserspaceManagerTest() {}
+ virtual void SetUp() {
+ manager = new UserspaceEventManager(g_ceph_context);
+ }
+ virtual void TearDown() {
+ delete manager;
+ }
+};
+
+TEST_F(UserspaceManagerTest, BasicTest) {
+ int events[10];
+ int masks[10];
+ int fd = manager->get_eventfd();
+ ASSERT_EQ(fd, 1);
+ ASSERT_EQ(0, manager->listen(fd, 1));
+ ASSERT_EQ(0, manager->notify(fd, 1));
+ ASSERT_EQ(1, manager->poll(events, masks, 10, nullptr));
+ ASSERT_EQ(fd, events[0]);
+ ASSERT_EQ(1, masks[0]);
+ ASSERT_EQ(0, manager->notify(fd, 2));
+ ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
+ ASSERT_EQ(0, manager->unlisten(fd, 1));
+ ASSERT_EQ(0, manager->notify(fd, 1));
+ ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
+ manager->close(fd);
+ fd = manager->get_eventfd();
+ ASSERT_EQ(fd, 1);
+ ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
+}
+
+TEST_F(UserspaceManagerTest, FailTest) {
+ int events[10];
+ int masks[10];
+ int fd = manager->get_eventfd();
+ ASSERT_EQ(fd, 1);
+ ASSERT_EQ(-ENOENT, manager->listen(fd+1, 1));
+ ASSERT_EQ(-ENOENT, manager->notify(fd+1, 1));
+ ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
+ ASSERT_EQ(-ENOENT, manager->unlisten(fd+1, 1));
+ manager->close(fd);
+}
+
+TEST_F(UserspaceManagerTest, StressTest) {
+ std::vector<std::pair<int, int> > mappings;
+ int events[10];
+ int masks[10];
+ std::random_device rd;
+ std::default_random_engine rng(rd());
+ std::uniform_int_distribution<> dist(0, 100);
+
+ mappings.resize(1001);
+ mappings[0] = std::make_pair(-1, -1);
+ for (int i = 0; i < 1000; ++i) {
+ int fd = manager->get_eventfd();
+ ASSERT_TRUE(fd > 0);
+ mappings[fd] = std::make_pair(0, 0);
+ }
+ int r = 0;
+ int fd = manager->get_eventfd();
+ auto get_activate_count = [](std::vector<std::pair<int, int> > &m) {
+ std::vector<int> fds;
+ int mask = 0;
+ size_t idx = 0;
+ for (auto &&p : m) {
+ mask = p.first & p.second;
+ if (p.first != -1 && mask) {
+ p.second &= (~mask);
+ fds.push_back(idx);
+ std::cerr << " activate " << idx << " mask " << mask << std::endl;
+ }
+ ++idx;
+ }
+ return fds;
+ };
+ for (int i = 0; i < 10000; ++i) {
+ int value = dist(rng);
+ fd = dist(rng) % mappings.size();
+ auto &p = mappings[fd];
+ int mask = dist(rng) % 2 + 1;
+ if (value > 55) {
+ r = manager->notify(fd, mask);
+ if (p.first == -1) {
+ ASSERT_EQ(p.second, -1);
+ ASSERT_EQ(r, -ENOENT);
+ } else {
+ p.second |= mask;
+ ASSERT_EQ(r, 0);
+ }
+ std::cerr << " notify fd " << fd << " mask " << mask << " r " << r << std::endl;
+ } else if (value > 45) {
+ r = manager->listen(fd, mask);
+ std::cerr << " listen fd " << fd << " mask " << mask << " r " << r << std::endl;
+ if (p.first == -1) {
+ ASSERT_EQ(p.second, -1);
+ ASSERT_EQ(r, -ENOENT);
+ } else {
+ p.first |= mask;
+ ASSERT_EQ(r, 0);
+ }
+ } else if (value > 35) {
+ r = manager->unlisten(fd, mask);
+ std::cerr << " unlisten fd " << fd << " mask " << mask << " r " << r << std::endl;
+ if (p.first == -1) {
+ ASSERT_EQ(p.second, -1);
+ ASSERT_EQ(r, -ENOENT);
+ } else {
+ p.first &= ~mask;
+ ASSERT_EQ(r, 0);
+ }
+ } else if (value > 20) {
+ std::set<int> actual, expected;
+ do {
+ r = manager->poll(events, masks, 3, nullptr);
+ std::cerr << " poll " << r;
+ for (int k = 0; k < r; ++k) {
+ std::cerr << events[k] << " ";
+ actual.insert(events[k]);
+ }
+ } while (r == 3);
+ std::cerr << std::endl;
+ auto fds = get_activate_count(mappings);
+ for (auto &&d : fds)
+ expected.insert(d);
+ ASSERT_EQ(expected, actual);
+ } else if (value > 10) {
+ r = manager->get_eventfd();
+ std::cerr << " open fd " << r << std::endl;
+ ASSERT_TRUE(r > 0);
+ if ((size_t)r >= mappings.size())
+ mappings.resize(r+1);
+ mappings[r] = std::make_pair(0, 0);
+ } else {
+ manager->close(fd);
+ std::cerr << " close fd " << fd << std::endl;
+ mappings[fd] = std::make_pair(-1, -1);
+ }
+ ASSERT_TRUE(manager->check());
+ }
+}
+
+/*
+ * Local Variables:
+ * compile-command: "cd ../.. ; make ceph_test_userspace_event &&
+ * ./ceph_test_userspace_event.cc
+ *
+ * End:
+ */