2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
21 #include <condition_variable>
24 #include <boost/test/test_tools.hpp>
25 #include <boost_macros_wrapper.h>
27 #include <client-common.h>
28 #include <socket-manager.h>
31 using namespace std::chrono_literals;
35 constexpr char SERVICE_SOCKET_TEST[] = "/tmp/.central-key-manager-test.sock";
36 constexpr CKM::InterfaceID SOCKET_ID_TEST = 42;
38 class TestService : public GenericSocketService {
40 ServiceDescriptionVector GetServiceDescription() override {
41 return ServiceDescriptionVector {
42 {SERVICE_SOCKET_TEST, "", SOCKET_ID_TEST}
45 void Event(const AcceptEvent &) override { Connected(true); }
46 void Event(const WriteEvent &) override {}
47 void Event(const ReadEvent &) override {}
48 void Event(const CloseEvent &) override { Connected(false); }
49 void Event(const SecurityEvent &) override {}
51 void Start() override {}
52 void Stop() override {}
54 void WaitUntilConnected(bool isConnected) {
55 std::unique_lock<std::mutex> lock(m_mutex);
56 BOOST_REQUIRE(m_cv.wait_for(lock, 10s, [&]{ return m_connected == isConnected; }));
59 void Connected(bool isConnected) {
60 std::unique_lock<std::mutex> lock(m_mutex);
61 m_connected = isConnected;
67 bool m_connected = false;
69 std::condition_variable m_cv;
72 struct TestSocketManager : public SocketManager {
73 size_t TimeoutQueueSize() const { return m_timeoutQueue.size(); }
78 BOOST_AUTO_TEST_SUITE(SOCKET_MANAGER_TEST)
80 POSITIVE_TEST_CASE(StressTestGrowingTimeoutQueue)
82 constexpr unsigned REPEATS = 100000;
83 constexpr auto INTERVAL = REPEATS/10;
85 int ret = unlink(SERVICE_SOCKET_TEST);
87 BOOST_REQUIRE(ret == 0 || (ret == -1 && err == ENOENT));
89 TestSocketManager manager;
90 auto service = new TestService();
91 manager.RegisterSocketService(service);
93 bool exception = false;
94 std::string what("Unknown exception");
99 } catch (const std::exception& e) {
109 ret = socket.connect(SERVICE_SOCKET_TEST);
110 BOOST_REQUIRE(ret == CKM_API_SUCCESS);
111 service->WaitUntilConnected(true);
112 BOOST_REQUIRE(manager.TimeoutQueueSize() == 1);
113 service->Connected(false);
115 // check if the closed socket timeouts are removed from the queue.
117 for(unsigned i=0;i<REPEATS;i++) {
118 ret = socket2.connect(SERVICE_SOCKET_TEST);
119 BOOST_REQUIRE(ret == CKM_API_SUCCESS);
120 service->WaitUntilConnected(true);
122 socket2.disconnect();
123 service->WaitUntilConnected(false);
125 if ((i + 1) % INTERVAL == 0)
126 BOOST_TEST_MESSAGE("Creating connections: " << i + 1 << "/" << REPEATS);
128 BOOST_TEST_MESSAGE("Waiting " << OVERRIDE_SOCKET_TIMEOUT + 2 << "s for socket timeouts.");
130 // all sockets should be closed after timeout and the queue should be empty
131 std::this_thread::sleep_for(std::chrono::seconds(OVERRIDE_SOCKET_TIMEOUT + 2));
132 BOOST_REQUIRE(manager.TimeoutQueueSize() == 0);
135 manager.MainLoopStop();
138 BOOST_REQUIRE_MESSAGE(!exception, what);
141 BOOST_AUTO_TEST_SUITE_END()