From 951c39479f69ee2f549bce2b692ded419b3fe23c Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Tue, 22 Apr 2025 01:10:22 +0100 Subject: [PATCH] Update several tests to accept empty string or "localhost" For unix sockets the behavior of getpeername() is different on different OS This required to add support of regex to the integration test framework --- test/integration/framework/base.h | 39 ++++++++++++++++++++++++---- test/integration/tests/modules.cpp | 37 ++++++++++++++------------ test/integration/tests/scripting.cpp | 12 ++++----- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/test/integration/framework/base.h b/test/integration/framework/base.h index 71098fd7..1663f121 100644 --- a/test/integration/framework/base.h +++ b/test/integration/framework/base.h @@ -20,12 +20,11 @@ #include #include -#include #include +#include +#include #include -#include - namespace znc_inttest { template @@ -35,6 +34,7 @@ class IO { : m_device(device), m_verbose(verbose) {} virtual ~IO() {} void ReadUntil(QByteArray pattern); + void ReadUntilRe(QString pattern); /* * Reads from Device until pattern is matched and returns this pattern * up to and excluding the first newline. Pattern itself can contain a newline. @@ -116,7 +116,36 @@ void IO::ReadUntil(QByteArray pattern) { } const int timeout_ms = QDateTime::currentDateTime().msecsTo(deadline); - ASSERT_GT(timeout_ms, 0) << "Wanted:" << pattern.toStdString(); + ASSERT_GT(timeout_ms, 0) << "Wanted: " << pattern.toStdString(); + ASSERT_TRUE(m_device->waitForReadyRead(timeout_ms)) + << "Wanted: " << pattern.toStdString(); + QByteArray chunk = m_device->readAll(); + if (m_verbose) { + std::cout << chunk.toStdString() << std::flush; + } + m_readed += chunk; + } +} + +template +void IO::ReadUntilRe(QString pattern) { + QRegularExpression expr(pattern); + auto deadline = QDateTime::currentDateTime().addSecs(60); + while (true) { + QRegularExpressionMatch match = + expr.match(QString::fromUtf8(m_readed), 0, + QRegularExpression::PartialPreferCompleteMatch); + if (match.hasMatch()) { + m_readed.remove(0, match.capturedEnd()); + return; + } + if (!match.hasPartialMatch()) { + m_readed.clear(); + } + const int timeout_ms = + QDateTime::currentDateTime().msecsTo(deadline); + ASSERT_GT(timeout_ms, 0) + << "Wanted: " << pattern.toStdString(); ASSERT_TRUE(m_device->waitForReadyRead(timeout_ms)) << "Wanted: " << pattern.toStdString(); QByteArray chunk = m_device->readAll(); @@ -158,7 +187,7 @@ void IO::ReadUntilAndGet(QByteArray pattern, QByteArray& match) { } const int timeout_ms = QDateTime::currentDateTime().msecsTo(deadline); - ASSERT_GT(timeout_ms, 0) << "Wanted:" << pattern.toStdString(); + ASSERT_GT(timeout_ms, 0) << "Wanted: " << pattern.toStdString(); ASSERT_TRUE(m_device->waitForReadyRead(timeout_ms)) << "Wanted: " << pattern.toStdString(); QByteArray chunk = m_device->readAll(); diff --git a/test/integration/tests/modules.cpp b/test/integration/tests/modules.cpp index 5815c088..652fccb4 100644 --- a/test/integration/tests/modules.cpp +++ b/test/integration/tests/modules.cpp @@ -39,23 +39,23 @@ TEST_F(ZNCTest, NotifyConnectModule) { client2.Write("PASS :hunter2"); client2.Write("NICK nick"); client2.Write("USER user/test x x :x"); - client.ReadUntil("NOTICE nick :*** user attached from localhost"); + client.ReadUntil("NOTICE nick :*** user attached from "); auto client3 = ConnectClient(); client3.Write("PASS :hunter2"); client3.Write("NICK nick"); client3.Write("USER user@identifier/test x x :x"); client.ReadUntil( - "NOTICE nick :*** user@identifier attached from localhost"); + "NOTICE nick :*** user@identifier attached from "); client2.ReadUntil( - "NOTICE nick :*** user@identifier attached from localhost"); + "NOTICE nick :*** user@identifier attached from "); client2.Write("QUIT"); - client.ReadUntil("NOTICE nick :*** user detached from localhost"); + client.ReadUntil("NOTICE nick :*** user detached from "); client3.Close(); client.ReadUntil( - "NOTICE nick :*** user@identifier detached from localhost"); + "NOTICE nick :*** user@identifier detached from "); } TEST_F(ZNCTest, ClientNotifyModule) { @@ -65,41 +65,46 @@ TEST_F(ZNCTest, ClientNotifyModule) { client.Write("znc loadmod clientnotify"); client.ReadUntil("Loaded module"); - auto check_not_sent = [](Socket& client, std::string wrongAnswer){ - auto result = QString{client.ReadRemainder()}.toStdString(); - EXPECT_THAT(result, Not(HasSubstr((wrongAnswer)))) << "Got an answer from the ClientNotifyModule even though we didnt want one with the given configuration"; + auto check_not_sent = [](Socket& client, QString wrongAnswer) { + QString result = QString::fromUtf8(client.ReadRemainder()); + QRegularExpression expr(wrongAnswer); + QRegularExpressionMatch match = expr.match(result); + EXPECT_FALSE(match.hasMatch()) + << "Got an answer from the ClientNotifyModule even though we didnt " + "want one with the given configuration: " + << wrongAnswer.toStdString() << result.toStdString(); }; auto client2 = LoginClient(); - client.ReadUntil(":Another client (localhost) authenticated as your user. Use the 'ListClients' command to see all 2 clients."); + client.ReadUntilRe(R"(:Another client \((localhost)?\) authenticated as your user. Use the 'ListClients' command to see all 2 clients.)"); auto client3 = LoginClient(); - client.ReadUntil(":Another client (localhost) authenticated as your user. Use the 'ListClients' command to see all 3 clients."); + client.ReadUntilRe(R"(:Another client \((localhost)?\) authenticated as your user. Use the 'ListClients' command to see all 3 clients.)"); // disable notifications for every message client.Write("PRIVMSG *clientnotify :NewOnly on"); // check that we do not ge a notification after connecting from a know ip auto client4 = LoginClient(); - check_not_sent(client, ":Another client (localhost) authenticated as your user. Use the 'ListClients' command to see all 4 clients."); + check_not_sent(client, ":Another client (.*) authenticated as your user. Use the 'ListClients' command to see all 4 clients."); // choose to notify only on new client ids client.Write("PRIVMSG *clientnotify :NotifyOnNewID on"); auto client5 = LoginClient("identifier123"); - client.ReadUntil(":Another client (localhost / identifier123) authenticated as your user. Use the 'ListClients' command to see all 5 clients."); + client.ReadUntilRe(R"(:Another client \((localhost)? / identifier123\) authenticated as your user. Use the 'ListClients' command to see all 5 clients.)"); auto client6 = LoginClient("identifier123"); - check_not_sent(client, ":Another client (localhost / identifier123) authenticated as your user. Use the 'ListClients' command to see all 6 clients."); + check_not_sent(client, ":Another client (.* / identifier123) authenticated as your user. Use the 'ListClients' command to see all 6 clients."); auto client7 = LoginClient("not_identifier123"); - client.ReadUntil(":Another client (localhost / not_identifier123) authenticated as your user. Use the 'ListClients' command to see all 7 clients."); + client.ReadUntilRe(R"(:Another client \((localhost)? / not_identifier123\) authenticated as your user. Use the 'ListClients' command to see all 7 clients.)"); // choose to notify from both clientids and new IPs client.Write("PRIVMSG *clientnotify :NotifyOnNewIP on"); auto client8 = LoginClient(); - check_not_sent(client, ":Another client (localhost / identifier123) authenticated as your user. Use the 'ListClients' command to see all 8 clients."); + check_not_sent(client, ":Another client (.* / identifier123) authenticated as your user. Use the 'ListClients' command to see all 8 clients."); auto client9 = LoginClient("definitely_not_identifier123"); - client.ReadUntil(":Another client (localhost / definitely_not_identifier123) authenticated as your user. Use the 'ListClients' command to see all 9 clients."); + client.ReadUntilRe(R"(:Another client \((localhost)? / definitely_not_identifier123\) authenticated as your user. Use the 'ListClients' command to see all 9 clients.)"); } TEST_F(ZNCTest, ShellModule) { diff --git a/test/integration/tests/scripting.cpp b/test/integration/tests/scripting.cpp index fbba2f3d..afeeaeb7 100644 --- a/test/integration/tests/scripting.cpp +++ b/test/integration/tests/scripting.cpp @@ -490,9 +490,9 @@ TEST_F(ZNCTest, ModpythonSaslAuth) { client2.Write("AUTHENTICATE FOO"); client2.ReadUntil("AUTHENTICATE " + QByteArrayLiteral("Welcome").toBase64()); client2.Write("AUTHENTICATE +"); - client2.ReadUntil( - ":irc.znc.in 900 nick nick!user@localhost user :You are now logged in " - "as user"); + client2.ReadUntilRe( + ":irc.znc.in 900 nick nick!user@(localhost)? user :You are now logged " + "in as user"); } TEST_F(ZNCTest, ModperlSaslAuth) { @@ -547,9 +547,9 @@ TEST_F(ZNCTest, ModperlSaslAuth) { client2.Write("AUTHENTICATE FOO"); client2.ReadUntil("AUTHENTICATE " + QByteArrayLiteral("Welcome").toBase64()); client2.Write("AUTHENTICATE +"); - client2.ReadUntil( - ":irc.znc.in 900 nick nick!user@localhost user :You are now logged in " - "as user"); + client2.ReadUntilRe( + ":irc.znc.in 900 nick nick!user@(localhost)? user :You are now logged " + "in as user"); } } // namespace