Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / msgr / test_userspace_event.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2016 XSky <haomai@xsky.com>
7  *
8  * Author: Haomai Wang <haomaiwang@gmail.com>
9  *
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.
14  *
15  */
16
17 #include <map>
18 #include <random>
19 #include <gtest/gtest.h>
20
21 #include "msg/async/dpdk/UserspaceEvent.h"
22 #include "global/global_context.h"
23
24 class UserspaceManagerTest : public ::testing::Test {
25  public:
26   UserspaceEventManager *manager;
27
28   UserspaceManagerTest() {}
29   virtual void SetUp() {
30     manager = new UserspaceEventManager(g_ceph_context);
31   }
32   virtual void TearDown() {
33     delete manager;
34   }
35 };
36
37 TEST_F(UserspaceManagerTest, BasicTest) {
38   int events[10];
39   int masks[10];
40   int fd = manager->get_eventfd();
41   ASSERT_EQ(fd, 1);
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));
52   manager->close(fd);
53   fd = manager->get_eventfd();
54   ASSERT_EQ(fd, 1);
55   ASSERT_EQ(0, manager->poll(events, masks, 10, nullptr));
56 }
57
58 TEST_F(UserspaceManagerTest, FailTest) {
59   int events[10];
60   int masks[10];
61   int fd = manager->get_eventfd();
62   ASSERT_EQ(fd, 1);
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));
67   manager->close(fd);
68 }
69
70 TEST_F(UserspaceManagerTest, StressTest) {
71   std::vector<std::pair<int, int> > mappings;
72   int events[10];
73   int masks[10];
74   std::random_device rd;
75   std::default_random_engine rng(rd());
76   std::uniform_int_distribution<> dist(0, 100);
77
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();
82     ASSERT_TRUE(fd > 0);
83     mappings[fd] = std::make_pair(0, 0);
84   }
85   int r = 0;
86   int fd = manager->get_eventfd();
87   auto get_activate_count = [](std::vector<std::pair<int, int> > &m) {
88     std::vector<int> fds;
89     int mask = 0;
90     size_t idx = 0;
91     for (auto &&p : m) {
92       mask = p.first & p.second;
93       if (p.first != -1 && mask) {
94         p.second &= (~mask);
95         fds.push_back(idx);
96         std::cerr << " activate " << idx << " mask " << mask << std::endl;
97       }
98       ++idx;
99     }
100     return fds;
101   };
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;
107     if (value > 55) {
108       r = manager->notify(fd, mask);
109       if (p.first == -1) {
110         ASSERT_EQ(p.second, -1);
111         ASSERT_EQ(r, -ENOENT);
112       } else {
113         p.second |= mask;
114         ASSERT_EQ(r, 0);
115       }
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;
120       if (p.first == -1) {
121         ASSERT_EQ(p.second, -1);
122         ASSERT_EQ(r, -ENOENT);
123       } else {
124         p.first |= mask;
125         ASSERT_EQ(r, 0);
126       }
127     } else if (value > 35) {
128       r = manager->unlisten(fd, mask);
129       std::cerr << " unlisten fd " << fd << " mask " << mask << " r " << r << std::endl;
130       if (p.first == -1) {
131         ASSERT_EQ(p.second, -1);
132         ASSERT_EQ(r, -ENOENT);
133       } else {
134         p.first &= ~mask;
135         ASSERT_EQ(r, 0);
136       }
137     } else if (value > 20) {
138       std::set<int> actual, expected;
139       do {
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]);
145         }
146       } while (r == 3);
147       std::cerr << std::endl;
148       auto fds = get_activate_count(mappings);
149       for (auto &&d : fds)
150         expected.insert(d);
151       ASSERT_EQ(expected, actual);
152     } else if (value > 10) {
153       r = manager->get_eventfd();
154       std::cerr << " open fd " << r << std::endl;
155       ASSERT_TRUE(r > 0);
156       if ((size_t)r >= mappings.size())
157         mappings.resize(r+1);
158       mappings[r] = std::make_pair(0, 0);
159     } else {
160       manager->close(fd);
161       std::cerr << " close fd " << fd << std::endl;
162       mappings[fd] = std::make_pair(-1, -1);
163     }
164     ASSERT_TRUE(manager->check());
165   }
166 }
167
168 /*
169  * Local Variables:
170  * compile-command: "cd ../.. ; make ceph_test_userspace_event &&
171  *    ./ceph_test_userspace_event.cc
172  *
173  * End:
174  */