Release 0.1.66
[platform/core/security/key-manager.git] / unit-tests / test_socket-manager.cpp
1 /*
2  *  Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16
17 #include <poll.h>
18
19 #include <cstdlib>
20 #include <ctime>
21 #include <cerrno>
22
23 #include <thread>
24 #include <mutex>
25 #include <condition_variable>
26 #include <chrono>
27 #include <utility>
28 #include <string>
29 #include <sstream>
30 #include <vector>
31 #include <algorithm>
32 #include <type_traits>
33
34 #include <boost/test/test_tools.hpp>
35 #include <boost_macros_wrapper.h>
36
37 #include <test_common.h>
38 #include <dpl/log/log.h>
39
40 #include <client-common.h>
41 #include <socket-manager.h>
42 #include <message-buffer.h>
43
44 using namespace CKM;
45
46 namespace {
47
48 size_t Random(size_t max)
49 {
50         static unsigned int seed = ::time(nullptr);
51         return ::rand_r(&seed) % max;
52 }
53
54 constexpr char SERVICE_SOCKET_TEST[] = "/tmp/.central-key-manager-test.sock";
55 constexpr CKM::InterfaceID SOCKET_ID_TEST = 42;
56 constexpr std::chrono::seconds CV_TIMEOUT(10);
57
58 struct TestSocketManager : public SocketManager {
59         size_t TimeoutQueueSize() const { return m_timeoutQueue.size(); }
60 };
61
62 #define THREAD_REQUIRE_MESSAGE(test, message)                                      \
63         do {                                                                           \
64                 if (!(test)) {                                                             \
65                         std::ostringstream os;                                                 \
66                         os << __FILE__ << ":" << __LINE__ << " " << #test << " " << message;   \
67                         throw std::runtime_error(os.str());                                    \
68                 }                                                                          \
69         } while (0)
70
71 #define THREAD_REQUIRE(test) THREAD_REQUIRE_MESSAGE(test, "")
72
73 class NoOpService : public GenericSocketService {
74         void Event(const AcceptEvent &) override {}
75         void Event(const WriteEvent &) override {}
76         void Event(const ReadEvent &) override {}
77         void Event(const CloseEvent &) override {}
78         void Event(const SecurityEvent &) override {}
79
80         void Start() override {}
81         void Stop() override {}
82 };
83
84 class TestConnection final : public ServiceConnection {
85 public:
86         explicit TestConnection(const std::string& socketPath) :
87                 ServiceConnection(socketPath.c_str()),
88                 m_id(m_counter++) {
89                 auto ret = prepareConnection();
90                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "ret = " << ret);
91         }
92
93         int Send(const CKM::RawBuffer &send_buf) {
94                 m_sent += send_buf.size();
95                 return ServiceConnection::send(SerializeMessage(send_buf));
96         }
97
98         template <typename T>
99         void Receive(const T& logReceived) {
100                 if (m_sent == 0) {
101                         // expect timeout
102                         auto ret = m_socket.waitForSocket(POLLIN, 100);
103                         BOOST_REQUIRE_MESSAGE(ret == 0, "ret = " << ret);
104                         logReceived(0);
105                         return;
106                 }
107
108                 int ret = ServiceConnection::receive(m_recv);
109                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "ret = " << ret);
110                 BOOST_REQUIRE(m_recv.Ready());
111                 while (m_recv.Ready()) {
112                         RawBuffer tmp;
113                         m_recv.Deserialize(tmp);
114                         const auto size = tmp.size();
115                         BOOST_REQUIRE_MESSAGE(size <= m_sent, size << ">" << m_sent);
116                         logReceived(size);
117                         m_sent -= size;
118                 }
119         }
120
121         size_t GetId() const { return m_id; }
122
123 private:
124         size_t m_sent = 0;
125         size_t m_id;
126         MessageBuffer m_recv;
127         static inline size_t m_counter = 0;
128 };
129
130 class SocketManagerLoop final {
131 public:
132         explicit SocketManagerLoop(SocketManager& manager) :
133                 m_manager(manager),
134                 m_thread([&]{
135                         try {
136                                 manager.MainLoop();
137                         } catch (const std::exception& e) {
138                                 m_exception = true;
139                                 m_what = e.what();
140                         } catch (...) {
141                                 m_exception = true;
142                         }
143                 })
144         {
145         }
146
147         ~SocketManagerLoop() {
148                 m_manager.MainLoopStop();
149                 m_thread.join();
150
151                 BOOST_CHECK_MESSAGE(!m_exception, m_what);
152         }
153
154 private:
155         bool m_exception = false;
156         std::string m_what = "Unknown exception";
157         SocketManager& m_manager;
158         std::thread m_thread;
159 };
160
161 std::string Id2SockPath(int id) {
162         return std::string(SERVICE_SOCKET_TEST) + std::to_string(id);
163 }
164
165 void unlinkIfExists(const char* path) {
166         int ret = unlink(path);
167         int err = errno;
168         BOOST_REQUIRE(ret == 0 || (ret == -1 && err == ENOENT));
169 }
170
171 enum class SockState {
172         CLOSED = 0,
173         RD = 1,
174         WR = 2,
175         RW = RD | WR,
176 };
177
178 SockState operator & (SockState lhs, SockState rhs) {
179         using T = std::underlying_type_t <SockState>;
180         return static_cast<SockState>(static_cast<T>(lhs) & static_cast<T>(rhs));
181 }
182
183 } // namespace
184
185 BOOST_AUTO_TEST_SUITE(SOCKET_MANAGER_TEST)
186
187 POSITIVE_TEST_CASE(StressTestGrowingTimeoutQueue)
188 {
189         constexpr unsigned INITIAL_CONNECTIONS = 20;
190         constexpr unsigned REPEATS = 100000;
191         constexpr auto INTERVAL = REPEATS/10;
192
193         class TestService final : public NoOpService {
194         public:
195                 ServiceDescriptionVector GetServiceDescription() override {
196                         return ServiceDescriptionVector {
197                                 {SERVICE_SOCKET_TEST, "", SOCKET_ID_TEST}
198                         };
199                 }
200                 void Event(const AcceptEvent &e) override {
201                         std::unique_lock<std::mutex> lock(m_mutex);
202
203                         THREAD_REQUIRE_MESSAGE(m_connections.empty() || m_connections.back().client != -1,
204                                                "Unexpected server entry waiting for client match " <<
205                                                m_connections.back().server);
206
207                         m_connections.push_back({-1 , e.connectionID.sock});
208
209                         LogDebug("AcceptEvent. Added: ? <=>" << e.connectionID.sock);
210
211                         CompareSizes();
212
213                         lock.unlock();
214                         m_cv.notify_one();
215                 }
216                 void Event(const CloseEvent &e) override {
217                         std::unique_lock<std::mutex> lock(m_mutex);
218                         THREAD_REQUIRE(!m_connections.empty());
219
220                         auto serverMatch = [&](const SocketPair& pair){
221                                 return pair.server == e.connectionID.sock;
222                         };
223                         auto it = std::find_if(m_connections.begin(), m_connections.end(), serverMatch);
224
225                         THREAD_REQUIRE_MESSAGE(it != m_connections.end(),
226                                                "Can't find connection for server socket = " <<
227                                                e.connectionID.sock);
228
229                         LogDebug("CloseEvent. Removing: " << it->client << "<=>" << it->server);
230                         THREAD_REQUIRE(it->client != -1);
231
232                         m_connections.erase(it);
233
234                         CompareSizes();
235
236                         lock.unlock();
237                         m_cv.notify_one();
238                 }
239
240                 void ConnectAndWait(SockRAII& client) {
241                         std::unique_lock<std::mutex> lock(m_mutex);
242
243                         THREAD_REQUIRE_MESSAGE(m_connections.empty() || m_connections.back().client != -1,
244                                                "Unexpected server entry waiting for client match " <<
245                                                m_connections.back().server);
246
247                         int ret = client.connect(GetServiceDescription()[0].serviceHandlerPath.c_str());
248                         BOOST_REQUIRE(ret == CKM_API_SUCCESS);
249
250                         LogDebug("Connected. Waiting for AcceptEvent for: " << client.get() << "<=> ?");
251
252                         BOOST_REQUIRE(m_cv.wait_for(lock, CV_TIMEOUT, [&]{ return AcceptEventArrived(); }));
253
254                         m_connections.back().client = client.get();
255
256                         LogDebug("Accepted. Matched client & server: " << m_connections.back().client <<
257                                  "<=>" << m_connections.back().server);
258                 }
259
260                 void DisconnectAndWait(SockRAII& client) {
261                         int sock = client.get();
262                         client.disconnect();
263
264                         LogDebug("Disconnected. Waiting for CloseEvent for: " << sock << "<=> ?");
265
266                         std::unique_lock<std::mutex> lock(m_mutex);
267                         BOOST_REQUIRE(m_cv.wait_for(lock, CV_TIMEOUT, [&]{ return ClientAbsent(sock); }));
268                 }
269
270                 void WaitForRemainingClosures() {
271                         std::unique_lock<std::mutex> lock(m_mutex);
272                         if (!m_connections.empty())
273                                 BOOST_TEST_MESSAGE("Waiting for remaining " << m_connections.size() <<
274                                                    " to close.");
275
276                         BOOST_REQUIRE(m_cv.wait_for(lock,
277                                                     std::chrono::seconds(OVERRIDE_SOCKET_TIMEOUT + 2),
278                                                     [&]{ return m_connections.empty(); }));
279
280                         CompareSizes();
281                 }
282
283         private:
284                 bool ClientAbsent(int client) const {
285                         auto it = std::find_if(m_connections.begin(),
286                                                m_connections.end(), [&](const SocketPair& pair){
287                                 return pair.client == client;
288                         });
289                         return it == m_connections.end();
290                 }
291
292                 bool AcceptEventArrived() const {
293                         return !m_connections.empty() && m_connections.back().client == -1;
294                 }
295
296                 void CompareSizes() const {
297                         auto manager = static_cast<TestSocketManager*>(m_serviceManager);
298                         THREAD_REQUIRE(m_connections.size() == manager->TimeoutQueueSize());
299                 }
300
301                 std::mutex m_mutex;
302                 struct SocketPair {
303                         int client;
304                         int server;
305                 };
306                 std::vector<SocketPair> m_connections;
307                 std::condition_variable m_cv;
308         };
309
310         unlinkIfExists(SERVICE_SOCKET_TEST);
311
312         TestSocketManager manager;
313         auto service = new TestService();
314         manager.RegisterSocketService(service);
315
316         SocketManagerLoop loop(manager);
317
318         {
319                 SockRAII socket[INITIAL_CONNECTIONS];
320                 for (unsigned i=0;i<INITIAL_CONNECTIONS;i++)
321                         service->ConnectAndWait(socket[i]);
322
323                 BOOST_REQUIRE(manager.TimeoutQueueSize() == INITIAL_CONNECTIONS);
324
325                 SockRAII socket2;
326                 for(unsigned i=0;i<REPEATS;i++) {
327                         service->ConnectAndWait(socket2);
328                         service->DisconnectAndWait(socket2);
329
330                         if ((i + 1) % INTERVAL == 0)
331                                 BOOST_TEST_MESSAGE("Creating connections: " << i + 1 << "/" << REPEATS);
332                 }
333
334                 // wait for remaining connections to close if any
335                 service->WaitForRemainingClosures();
336         }
337 }
338
339 POSITIVE_TEST_CASE(StressTestRandomSocketEvents)
340 {
341         // Too many services or connections may trigger server side timeouts (OVERRIDE_SOCKET_TIMEOUT)
342         constexpr int SERVICES = 4;
343         constexpr int INTERVAL = 1000;
344         constexpr int REPEATS = 10000;
345         constexpr int MAX_CONNECTIONS = 4;
346         // client and server read 2048B and 4096B at once respectively
347         constexpr size_t MAX_BUF_SIZE = 5000;
348
349         enum Event {
350                 CONNECT,
351                 DISCONNECT,
352                 SEND,
353                 RECEIVE,
354
355                 CNT
356         };
357
358         class TestService final : public NoOpService {
359         public:
360                 explicit TestService(int id) :
361                         m_desc({{Id2SockPath(id).c_str(), "", SOCKET_ID_TEST + id}}),
362                         m_id(id) {
363
364                         unlinkIfExists(GetSocketPath().c_str());
365                 }
366
367                 ServiceDescriptionVector GetServiceDescription() override { return m_desc; }
368
369                 void Event(const ReadEvent &e) override {
370                         LogDebug(e.connectionID.sock << ":" << e.connectionID.counter << " Received " <<
371                                  e.rawBuffer.size() << "B");
372                         m_serviceManager->Write(e.connectionID, e.rawBuffer);
373                 }
374
375                 size_t GetConnectionCount() const { return m_connections.size(); }
376
377                 void AddConnection() {
378                         m_connections.emplace_back(new TestConnection(GetSocketPath()));
379                         LogDebug(Prefix(m_connections.back()->GetId()) << "Connected");
380                 }
381
382                 void Disconnect(size_t idx) {
383                         auto it = m_connections.begin() + idx;
384                         auto cid = (*it)->GetId();
385                         if (idx != m_connections.size() - 1)
386                                 *it = std::move(m_connections.back());
387                         m_connections.pop_back();
388                         LogDebug(Prefix(cid) << "Disconnected");
389                 }
390
391                 void Send(size_t idx) {
392                         auto buffer = createRandom(Random(MAX_BUF_SIZE) + 1);
393                         auto& conn = m_connections.at(idx);
394                         auto ret = conn->Send(buffer);
395                         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "ret = " << ret);
396                         LogDebug(Prefix(conn->GetId())<< "Sent " << buffer.size() << "B");
397                 }
398
399                 void Receive(size_t idx) {
400                         auto& conn = m_connections.at(idx);
401                         conn->Receive([&](const size_t received) {
402                                 LogDebug(Prefix(conn->GetId()) << "Received " << received << "B");
403                         });
404                 }
405
406         private:
407                 const std::string& GetSocketPath() const {
408                         return m_desc.at(0).serviceHandlerPath;
409                 }
410
411                 std::string Prefix(size_t idx) const {
412                         return std::string(" ") + std::to_string(m_id) + ":" + std::to_string(idx) + " ";
413                 }
414
415                 ServiceDescriptionVector m_desc;
416                 int m_id;
417                 std::vector<std::unique_ptr<TestConnection>> m_connections;
418         };
419
420         SocketManager manager;
421         TestService* services[SERVICES];
422
423         for (int i = 0;i<SERVICES;i++) {
424                 services[i] = new TestService(i);
425                 manager.RegisterSocketService(services[i]);
426         }
427
428         SocketManagerLoop loop(manager);
429
430         for (unsigned i = 0;i < REPEATS; i++) {
431                 // random service
432                 auto service = services[Random(SERVICES)];
433
434                 // always connect if there are no active connections
435                 auto eIdx = CONNECT;
436                 auto cIdx = 0;
437                 size_t cCnt = service->GetConnectionCount();
438                 if (cCnt > 0) {
439                         cIdx = Random(cCnt);
440                         eIdx = static_cast<Event>(Random(CNT));
441                         if (eIdx == CONNECT && cCnt == MAX_CONNECTIONS)
442                                 eIdx = SEND; // don't connect if there are too many
443                 }
444
445                 switch (eIdx) {
446                 case CONNECT:
447                         service->AddConnection();
448                         break;
449
450                 case DISCONNECT:
451                         service->Disconnect(cIdx);
452                         break;
453
454                 case SEND:
455                         service->Send(cIdx);
456                         break;
457
458                 case RECEIVE:
459                         service->Receive(cIdx);
460                         break;
461
462                 default:
463                         BOOST_FAIL("Unexpected event");
464                 }
465
466                 if ((i + 1) % INTERVAL == 0)
467                         BOOST_TEST_MESSAGE("Executing random socket actions: " << i + 1 << "/" << REPEATS);
468         }
469 }
470
471 NEGATIVE_TEST_CASE(CynaraSocket)
472 {
473         struct TestSocketManagerExt : public TestSocketManager {
474                 void CreateSocket(int sock) {
475                         SocketManager::CreateDefaultReadSocketDescription(sock, false);
476                 }
477
478                 void CloseSocket(int sock) { SocketManager::CloseSocket(sock); }
479
480                 int OutOfRangeSocket() const { return static_cast<int>(m_socketDescriptionVector.size()); }
481
482                 size_t OpenedSockets() const {
483                         return std::count_if(m_socketDescriptionVector.begin(),
484                                              m_socketDescriptionVector.end(),
485                                              [](const SocketDescription& desc) { return desc.isOpen(); });
486                 }
487
488                 void RequireOpened(size_t opened) const {
489                         BOOST_REQUIRE(opened == OpenedSockets());
490
491                         BOOST_REQUIRE(m_timeoutQueue.empty());
492                 }
493
494                 void RequireCynara(int cynaraSocket) const {
495                         BOOST_REQUIRE(m_cynaraSocket == cynaraSocket);
496                 }
497
498                 void RequireSocket(int fd, SockState state) const {
499                         BOOST_REQUIRE(fd < OutOfRangeSocket());
500
501                         BOOST_REQUIRE(((state & SockState::RD) == SockState::RD) == FD_ISSET(fd, &m_readSet));
502                         BOOST_REQUIRE(((state & SockState::WR) == SockState::WR) == FD_ISSET(fd, &m_writeSet));
503                         BOOST_REQUIRE((state == SockState::CLOSED) == !m_socketDescriptionVector[fd].isOpen());
504                 }
505         };
506
507         constexpr int INVALID_FD = -1;
508
509         TestSocketManagerExt manager;
510         const size_t START_SOCKETS = manager.OpenedSockets();
511         const int OTHER_SOCKET = manager.OutOfRangeSocket();
512         const int CYNARA_SOCKET = OTHER_SOCKET + 1;
513         const int CLOSED_SOCKET = OTHER_SOCKET + 2;
514         const int NEW_CYNARA_SOCKET = OTHER_SOCKET + 3;
515
516         manager.RequireOpened(START_SOCKETS);
517         manager.RequireCynara(INVALID_FD);
518
519         // new descriptor
520         manager.CreateSocket(OTHER_SOCKET);
521         manager.RequireOpened(START_SOCKETS + 1);
522         manager.RequireSocket(OTHER_SOCKET, SockState::RD);
523         manager.RequireCynara(INVALID_FD);
524
525         // new cynara socket
526         manager.CynaraSocket(INVALID_FD, CYNARA_SOCKET, false);
527         manager.RequireOpened(START_SOCKETS + 2);
528         manager.RequireSocket(CYNARA_SOCKET, SockState::RD);
529         manager.RequireCynara(CYNARA_SOCKET);
530
531         // invalid descriptors
532         manager.CynaraSocket(INVALID_FD, INVALID_FD, false);
533         manager.RequireOpened(START_SOCKETS + 2);
534         manager.RequireSocket(CYNARA_SOCKET, SockState::RD);
535         manager.RequireCynara(CYNARA_SOCKET);
536
537         // close not opened
538         manager.CynaraSocket(CLOSED_SOCKET, INVALID_FD, false);
539         manager.RequireOpened(START_SOCKETS + 2);
540         manager.RequireSocket(CYNARA_SOCKET, SockState::RD);
541         manager.RequireCynara(CYNARA_SOCKET);
542         manager.RequireSocket(CLOSED_SOCKET, SockState::CLOSED);
543
544         // close not cynara
545         manager.CynaraSocket(OTHER_SOCKET, INVALID_FD, false);
546         manager.RequireOpened(START_SOCKETS + 2);
547         manager.RequireSocket(CYNARA_SOCKET, SockState::RD);
548         manager.RequireCynara(CYNARA_SOCKET);
549         manager.RequireSocket(OTHER_SOCKET, SockState::RD);
550
551         // close out of bounds
552         manager.CynaraSocket(manager.OutOfRangeSocket(), INVALID_FD, false);
553         manager.RequireOpened(START_SOCKETS + 2);
554         manager.RequireSocket(CYNARA_SOCKET, SockState::RD);
555         manager.RequireCynara(CYNARA_SOCKET);
556
557         // open already opened
558         manager.CynaraSocket(INVALID_FD, OTHER_SOCKET, false);
559         manager.RequireOpened(START_SOCKETS + 2);
560         manager.RequireSocket(CYNARA_SOCKET, SockState::RD);
561         manager.RequireCynara(CYNARA_SOCKET);
562         manager.RequireSocket(OTHER_SOCKET, SockState::RD);
563
564         // open already opened for cynara
565         manager.CynaraSocket(INVALID_FD, CYNARA_SOCKET, false);
566         manager.RequireOpened(START_SOCKETS + 2);
567         manager.RequireSocket(CYNARA_SOCKET, SockState::RD);
568         manager.RequireCynara(CYNARA_SOCKET);
569
570         // close old & open new cynara socket in WR mode
571         manager.CynaraSocket(CYNARA_SOCKET, NEW_CYNARA_SOCKET, true);
572         manager.RequireOpened(START_SOCKETS + 2);
573         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::RW);
574         manager.RequireCynara(NEW_CYNARA_SOCKET);
575         manager.RequireSocket(CYNARA_SOCKET, SockState::CLOSED);
576
577         // do it again
578         manager.CynaraSocket(CYNARA_SOCKET, NEW_CYNARA_SOCKET, true);
579         manager.RequireOpened(START_SOCKETS + 2);
580         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::RW);
581         manager.RequireCynara(NEW_CYNARA_SOCKET);
582         manager.RequireSocket(CYNARA_SOCKET, SockState::CLOSED);
583
584         // change to RO
585         manager.CynaraSocket(NEW_CYNARA_SOCKET, NEW_CYNARA_SOCKET, false);
586         manager.RequireOpened(START_SOCKETS + 2);
587         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::RD);
588         manager.RequireCynara(NEW_CYNARA_SOCKET);
589
590         // again (no changes)
591         manager.CynaraSocket(NEW_CYNARA_SOCKET, NEW_CYNARA_SOCKET, false);
592         manager.RequireOpened(START_SOCKETS + 2);
593         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::RD);
594         manager.RequireCynara(NEW_CYNARA_SOCKET);
595
596         // close other socket manually
597         manager.CloseSocket(OTHER_SOCKET);
598         manager.RequireOpened(START_SOCKETS + 1);
599         manager.RequireSocket(OTHER_SOCKET, SockState::CLOSED);
600
601         // reopen other socket
602         manager.CreateSocket(OTHER_SOCKET);
603         manager.RequireOpened(START_SOCKETS + 2);
604         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::RD);
605         manager.RequireCynara(NEW_CYNARA_SOCKET);
606         manager.RequireSocket(OTHER_SOCKET, SockState::RD);
607
608         // close old closed cynara socket
609         manager.CynaraSocket(CYNARA_SOCKET, INVALID_FD, false);
610         manager.RequireOpened(START_SOCKETS + 2);
611         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::RD);
612         manager.RequireCynara(NEW_CYNARA_SOCKET);
613         manager.RequireSocket(CYNARA_SOCKET, SockState::CLOSED);
614
615         // open second cynara socket
616         manager.CynaraSocket(INVALID_FD, CYNARA_SOCKET, false);
617         manager.RequireOpened(START_SOCKETS + 2);
618         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::RD);
619         manager.RequireCynara(NEW_CYNARA_SOCKET);
620         manager.RequireSocket(CYNARA_SOCKET, SockState::CLOSED);
621
622         // close new cynara socket
623         manager.CynaraSocket(NEW_CYNARA_SOCKET, INVALID_FD, false);
624         manager.RequireOpened(START_SOCKETS + 1);
625         manager.RequireSocket(NEW_CYNARA_SOCKET, SockState::CLOSED);
626         manager.RequireCynara(INVALID_FD);
627
628         // close other socket manually
629         manager.CloseSocket(OTHER_SOCKET);
630         manager.RequireOpened(START_SOCKETS);
631         manager.RequireSocket(OTHER_SOCKET, SockState::CLOSED);
632 }
633
634 BOOST_AUTO_TEST_SUITE_END()