This commit is contained in:
2024-09-17 11:15:50 +03:00
parent 97aad47a21
commit 97f1c25ff8

View File

@@ -52,10 +52,13 @@ TEST(ClientServer, OneClient) {
class ClientSendThread { class ClientSendThread {
using ClientType = TestClient<false, false, 100_KiB>; using ClientType = TestClient<false, false, 10_KiB>;
public: public:
ClientSendThread() { client = createAndConnectClient<ClientType>(); } ClientSendThread() {
client = createAndConnectClient<ClientType>();
sendThread.setName("clSend");
}
~ClientSendThread() { ~ClientSendThread() {
sendThread.stopAndWait(); sendThread.stopAndWait();
@@ -63,11 +66,10 @@ public:
} }
void startSend() { void startSend() {
auto c = client; sendThread.start([this] { client->ping(); }, 100._Hz);
sendThread.start([c] { c->ping(); }, 100._Hz);
} }
void sendOnce() {client->ping();} void sendOnce() { client->ping(); }
ClientType * client = nullptr; ClientType * client = nullptr;
PIThread sendThread; PIThread sendThread;
@@ -75,28 +77,24 @@ public:
int getServerPongs(PIClientServer::Server * s) { int getServerPongs(PIClientServer::Server * s) {
int pongs = 0; int pongs = 0;
s->forEachClient([&pongs](PIClientServer::ServerClient * sc){ s->forEachClient([&pongs](PIClientServer::ServerClient * sc) {
const auto c = static_cast<TestServerClient<> *>(sc); const auto c = static_cast<TestServerClient<> *>(sc);
pongs += c->pongCnt(); pongs += c->pongCnt();
}); });
return pongs; return pongs;
} }
int getClientsPongs(const PIVector<ClientSendThread *> & clients) { int getClientsPongs(const PIVector<ClientSendThread *> & clients) {
int pongs = 0; int pongs = 0;
clients.forEach([&pongs](ClientSendThread * c){ clients.forEach([&pongs](ClientSendThread * c) { pongs += c->client->pongCnt(); });
pongs += c->client->pongCnt(); return pongs;
});
return pongs;
} }
int getClientsPings(const PIVector<ClientSendThread *> & clients) { int getClientsPings(const PIVector<ClientSendThread *> & clients) {
int pings = 0; int pings = 0;
clients.forEach([&pings](ClientSendThread * c){ clients.forEach([&pings](ClientSendThread * c) { pings += c->client->pingCnt(); });
pings += c->client->pingCnt(); return pings;
});
return pings;
} }
@@ -113,98 +111,106 @@ TEST(ClientServer, ManyClients) {
waitLoop([s]() { return s->clientsCount() == clients_count; }, loop_timeout); waitLoop([s]() { return s->clientsCount() == clients_count; }, loop_timeout);
EXPECT_EQ(clients_count, s->clientsCount()); EXPECT_EQ(clients_count, s->clientsCount());
EXPECT_EQ(0, getServerPongs(s)); EXPECT_EQ(0, getServerPongs(s));
EXPECT_EQ(getClientsPings(clients), 0); EXPECT_EQ(getClientsPings(clients), 0);
for (const auto c : clients) { for (const auto c: clients) {
c->sendOnce(); c->sendOnce();
} }
EXPECT_EQ(getClientsPings(clients), clients_count); EXPECT_EQ(getClientsPings(clients), clients_count);
EXPECT_TRUE(clients.every([](ClientSendThread * c){return c->client->pingCnt() == 1;})); EXPECT_TRUE(clients.every([](ClientSendThread * c) { return c->client->pingCnt() == 1; }));
EXPECT_TRUE(clients.every([](ClientSendThread * c){return c->client->pongCnt() == 0;})); EXPECT_TRUE(clients.every([](ClientSendThread * c) { return c->client->pongCnt() == 0; }));
waitLoop([s]() { return getServerPongs(s) >= clients_count; }, loop_timeout); waitLoop([s]() { return getServerPongs(s) >= clients_count; }, loop_timeout);
EXPECT_EQ(clients_count, getServerPongs(s)); EXPECT_EQ(clients_count, getServerPongs(s));
s->forEachClient([](PIClientServer::ServerClient * sc) { static_cast<TestServerClient<> *>(sc)->ping(); }); s->forEachClient([](PIClientServer::ServerClient * sc) { static_cast<TestServerClient<> *>(sc)->ping(); });
const auto clientCheckPong = [&clients](){return clients.every([](ClientSendThread * c){return c->client->pongCnt() == 1;});}; const auto clientCheckPong = [&clients]() { return clients.every([](ClientSendThread * c) { return c->client->pongCnt() == 1; }); };
waitLoop([&clientCheckPong]() { return clientCheckPong(); }, loop_timeout); waitLoop([&clientCheckPong]() { return clientCheckPong(); }, loop_timeout);
EXPECT_TRUE(clientCheckPong()); EXPECT_TRUE(clientCheckPong());
for (const auto c : clients) { for (const auto c: clients) {
c->startSend(); c->startSend();
} }
(100_ms).sleep(); (100_ms).sleep();
EXPECT_TRUE(getClientsPings(clients) > clients_count*2); EXPECT_TRUE(getClientsPings(clients) > clients_count * 2);
EXPECT_TRUE(getServerPongs(s) > clients_count*2); EXPECT_TRUE(getServerPongs(s) > clients_count * 2);
piDeleteAllAndClear(clients); piDeleteAllAndClear(clients);
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout); waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout);
EXPECT_EQ(0, s->clientsCount()); EXPECT_EQ(0, s->clientsCount());
delete s; delete s;
} }
TEST(ClientServer, DynamicClients) { TEST(ClientServer, DynamicClients) {
auto const loop_timeout = 1000_ms; auto const loop_timeout = 1000_ms;
constexpr int clients_count = 20; constexpr int clients_count = 20;
PIVector<ClientSendThread *> clients; PIVector<ClientSendThread *> clients;
PIMutex clients_mutex; PIMutex clients_mutex;
auto s = createServer<true, true, 100_KiB>(); auto s = createServer<true, true, 10_KiB>();
const auto spawnClient = [&clients, &clients_mutex]() { const auto spawnClient = [&clients, &clients_mutex]() {
auto c = new ClientSendThread(); auto c = new ClientSendThread();
c->startSend(); c->startSend();
clients_mutex.lock(); clients_mutex.lock();
clients << c; clients << c;
clients_mutex.unlock(); clients_mutex.unlock();
piCout << "new client" << clients.size(); piCout << "new client" << clients.size();
}; };
piForTimes(clients_count) { piForTimes(clients_count) {
spawnClient(); spawnClient();
} }
PIThread spawnThread; PIThread spawnThread;
PIThread deleteThread; PIThread deleteThread;
spawnThread.setName("spawn");
spawnThread.start([&spawnClient](){ deleteThread.setName("delete");
const int new_cnt = randomi() % 10;
piForTimes(new_cnt) { spawnThread.start(
spawnClient(); [&spawnClient]() {
} const int new_cnt = randomi() % 10;
}, 12_Hz); piForTimes(new_cnt) {
spawnClient();
deleteThread.start([&clients, &clients_mutex](){ }
const int rm_cnt = randomi() % 10; },
piForTimes(rm_cnt) { 12_Hz);
ClientSendThread * c = nullptr;
clients_mutex.lock(); deleteThread.start(
if (clients.size() > 10) { [&clients, &clients_mutex]() {
c = clients.take_back(); const int rm_cnt = randomi() % 10;
} piForTimes(rm_cnt) {
clients_mutex.unlock(); ClientSendThread * c = nullptr;
if (c) { clients_mutex.lock();
delete c; if (clients.size() > 10) {
piCout << "remove client" << clients.size(); c = clients.take_front();
} }
} clients_mutex.unlock();
}, 13_Hz); if (c) {
delete c;
(1_s).sleep(); piCout << "remove client" << clients.size();
}
EXPECT_GE(s->clientsCount(), 10); }
},
piCout << "now clients" << clients.size(); 13_Hz);
//delete s; (10_s).sleep();
deleteThread.stopAndWait(); EXPECT_GE(s->clientsCount(), 10);
spawnThread.stopAndWait();
piCout << "now clients" << clients.size();
piCout << "total clients" << clients.size();
piDeleteAllAndClear(clients); deleteThread.stopAndWait();
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout); spawnThread.stopAndWait();
EXPECT_EQ(0, s->clientsCount());
piCout << "total clients" << clients.size();
piDeleteAllAndClear(clients);
waitLoop([s]() { return s->clientsCount() == 0; }, loop_timeout);
EXPECT_EQ(0, s->clientsCount());
delete s;
} }