1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 XSky <haomai@xsky.com>
8 * Author: Haomai Wang <haomaiwang@gmail.com>
10 * This is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License version 2.1, as published by the Free Software
13 * Foundation. See file COPYING.
19 #include <gtest/gtest.h>
21 #include "msg/async/dpdk/UserspaceEvent.h"
22 #include "global/global_context.h"
24 class UserspaceManagerTest : public ::testing::Test {
26 UserspaceEventManager *manager;
28 UserspaceManagerTest() {}
29 virtual void SetUp() {
30 manager = new UserspaceEventManager(g_ceph_context);
32 virtual void TearDown() {
37 TEST_F(UserspaceManagerTest, BasicTest) {
40 int fd = manager->get_eventfd();
42 ASSERT_EQ(0, manager->listen(fd, 1));
43 ASSERT_EQ(0, manager->notify(fd, 1));
44 ASSERT_EQ(1, manager->poll(events, masks, 10, nullptr));
45 ASSERT_EQ(fd, events[0]);
46 ASSERT_EQ(1, masks[0]);
47 ASSERT_EQ(0, manager->notify(fd, 2));
48 ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
49 ASSERT_EQ(0, manager->unlisten(fd, 1));
50 ASSERT_EQ(0, manager->notify(fd, 1));
51 ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
53 fd = manager->get_eventfd();
55 ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
58 TEST_F(UserspaceManagerTest, FailTest) {
61 int fd = manager->get_eventfd();
63 ASSERT_EQ(-ENOENT, manager->listen(fd+1, 1));
64 ASSERT_EQ(-ENOENT, manager->notify(fd+1, 1));
65 ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
66 ASSERT_EQ(-ENOENT, manager->unlisten(fd+1, 1));
70 TEST_F(UserspaceManagerTest, StressTest) {
71 std::vector<std::pair<int, int> > mappings;
74 std::random_device rd;
75 std::default_random_engine rng(rd());
76 std::uniform_int_distribution<> dist(0, 100);
78 mappings.resize(1001);
79 mappings[0] = std::make_pair(-1, -1);
80 for (int i = 0; i < 1000; ++i) {
81 int fd = manager->get_eventfd();
83 mappings[fd] = std::make_pair(0, 0);
86 int fd = manager->get_eventfd();
87 auto get_activate_count = [](std::vector<std::pair<int, int> > &m) {
92 mask = p.first & p.second;
93 if (p.first != -1 && mask) {
96 std::cerr << " activate " << idx << " mask " << mask << std::endl;
102 for (int i = 0; i < 10000; ++i) {
103 int value = dist(rng);
104 fd = dist(rng) % mappings.size();
105 auto &p = mappings[fd];
106 int mask = dist(rng) % 2 + 1;
108 r = manager->notify(fd, mask);
110 ASSERT_EQ(p.second, -1);
111 ASSERT_EQ(r, -ENOENT);
116 std::cerr << " notify fd " << fd << " mask " << mask << " r " << r << std::endl;
117 } else if (value > 45) {
118 r = manager->listen(fd, mask);
119 std::cerr << " listen fd " << fd << " mask " << mask << " r " << r << std::endl;
121 ASSERT_EQ(p.second, -1);
122 ASSERT_EQ(r, -ENOENT);
127 } else if (value > 35) {
128 r = manager->unlisten(fd, mask);
129 std::cerr << " unlisten fd " << fd << " mask " << mask << " r " << r << std::endl;
131 ASSERT_EQ(p.second, -1);
132 ASSERT_EQ(r, -ENOENT);
137 } else if (value > 20) {
138 std::set<int> actual, expected;
140 r = manager->poll(events, masks, 3, nullptr);
141 std::cerr << " poll " << r;
142 for (int k = 0; k < r; ++k) {
143 std::cerr << events[k] << " ";
144 actual.insert(events[k]);
147 std::cerr << std::endl;
148 auto fds = get_activate_count(mappings);
151 ASSERT_EQ(expected, actual);
152 } else if (value > 10) {
153 r = manager->get_eventfd();
154 std::cerr << " open fd " << r << std::endl;
156 if ((size_t)r >= mappings.size())
157 mappings.resize(r+1);
158 mappings[r] = std::make_pair(0, 0);
161 std::cerr << " close fd " << fd << std::endl;
162 mappings[fd] = std::make_pair(-1, -1);
164 ASSERT_TRUE(manager->check());
170 * compile-command: "cd ../.. ; make ceph_test_userspace_event &&
171 * ./ceph_test_userspace_event.cc