mirror of
https://github.com/znc/znc.git
synced 2026-08-07 09:22:55 +02:00
Merge branch 'master' into sasl
Conflicts: include/znc/Client.h src/Client.cpp src/Modules.cpp test/integration/tests/modules.cpp
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
# Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -14,17 +14,23 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(ZNCIntegrationTest LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD true)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG true)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(Qt5Network 5.4 REQUIRED HINTS ${Qt5_HINTS})
|
||||
if(DEFINED ENV{ZNC_QT_VER})
|
||||
set(ZNC_QT_VER $ENV{ZNC_QT_VER})
|
||||
else()
|
||||
set(ZNC_QT_VER 6)
|
||||
endif()
|
||||
|
||||
find_package(Qt${ZNC_QT_VER}Network 5.4 REQUIRED HINTS ${Qt_HINTS})
|
||||
|
||||
# Force the simple internal regex engine to get consistent behavior on all
|
||||
# platforms. See
|
||||
@@ -42,9 +48,10 @@ add_executable(inttest
|
||||
"${GTEST_ROOT}/src/gtest-all.cc"
|
||||
"${GMOCK_ROOT}/src/gmock-all.cc")
|
||||
|
||||
target_link_libraries(inttest Qt5::Network Threads::Threads)
|
||||
target_link_libraries(inttest Qt${ZNC_QT_VER}::Network Threads::Threads)
|
||||
target_include_directories(inttest PUBLIC
|
||||
"${PROJECT_SOURCE_DIR}/framework"
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
"${GTEST_ROOT}" "${GTEST_ROOT}/include"
|
||||
"${GMOCK_ROOT}" "${GMOCK_ROOT}/include")
|
||||
target_compile_definitions(inttest PRIVATE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include "znctest.h"
|
||||
|
||||
#ifndef ZNC_BIN_DIR
|
||||
@@ -48,6 +49,14 @@ void WriteConfig(QString path) {
|
||||
p.ReadUntil("Launch ZNC now?"); p.Write("no");
|
||||
p.ShouldFinishItself();
|
||||
// clang-format on
|
||||
|
||||
// Default 30s is too slow for the test
|
||||
QFile conf(path + "/configs/znc.conf");
|
||||
ASSERT_TRUE(conf.open(QIODevice::Append | QIODevice::Text));
|
||||
QTextStream out(&conf);
|
||||
out << R"(
|
||||
ServerThrottle = 5
|
||||
)";
|
||||
}
|
||||
|
||||
void ZNCTest::SetUp() {
|
||||
@@ -111,6 +120,12 @@ std::unique_ptr<QNetworkReply> ZNCTest::HandleHttp(QNetworkReply* reply) {
|
||||
std::cout << "Got HTTP reply" << std::endl;
|
||||
loop.quit();
|
||||
});
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QObject::connect(reply, &QNetworkReply::errorOccurred,
|
||||
[&](QNetworkReply::NetworkError e) {
|
||||
ADD_FAILURE() << reply->errorString().toStdString();
|
||||
});
|
||||
#else
|
||||
QObject::connect(
|
||||
reply,
|
||||
static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(
|
||||
@@ -118,6 +133,7 @@ std::unique_ptr<QNetworkReply> ZNCTest::HandleHttp(QNetworkReply* reply) {
|
||||
[&](QNetworkReply::NetworkError e) {
|
||||
ADD_FAILURE() << reply->errorString().toStdString();
|
||||
});
|
||||
#endif
|
||||
QTimer::singleShot(30000 /* msec */, &loop, [&]() {
|
||||
ADD_FAILURE() << "connection timeout";
|
||||
loop.quit();
|
||||
@@ -152,7 +168,7 @@ void ZNCTest::InstallModule(QString name, QString content) {
|
||||
QStringList lines = content.split("\n");
|
||||
int maxoffset = -1;
|
||||
for (const QString& line : lines) {
|
||||
int nonspace = line.indexOf(QRegExp("\\S"));
|
||||
int nonspace = line.indexOf(QRegularExpression("\\S"));
|
||||
if (nonspace == -1) continue;
|
||||
if (nonspace < maxoffset || maxoffset == -1) maxoffset = nonspace;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,11 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "znctest.h"
|
||||
#include "znctestconfig.h"
|
||||
|
||||
using testing::HasSubstr;
|
||||
using testing::ContainsRegex;
|
||||
|
||||
namespace znc_inttest {
|
||||
namespace {
|
||||
@@ -165,6 +168,7 @@ TEST_F(ZNCTest, InvalidConfigInChan) {
|
||||
auto znc = Run();
|
||||
znc->ShouldFinishItself(1);
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, Encoding) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
@@ -269,6 +273,55 @@ TEST_F(ZNCTest, AwayNotify) {
|
||||
client.Write("znc shutdown");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ExtendedJoin) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
auto client = LoginClient();
|
||||
ircd.Write(":server 001 user :welcome");
|
||||
client.ReadUntil(" 001 ");
|
||||
ircd.Write(":nick!user@host JOIN #channel account :Real Name");
|
||||
// Not sure why it is like this when server sends such format unexpectedly.
|
||||
client.ReadUntil("JOIN #channel account :Real Name");
|
||||
ircd.Write("CAP nick ACK extended-join");
|
||||
ircd.Write(":nick!user@host JOIN #channel2 account :Real Name");
|
||||
QByteArray line;
|
||||
client.ReadUntilAndGet("JOIN", line);
|
||||
EXPECT_EQ(line.toStdString(), "JOIN #channel2");
|
||||
client.Write("CAP REQ extended-join");
|
||||
client.ReadUntil("CAP user ACK :extended-join");
|
||||
ircd.Write(":nick!user@host JOIN #channel3 account :Real Name");
|
||||
client.ReadUntil("JOIN #channel3 account :Real Name");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, CAP302LSWaitFull) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
ircd.ReadUntil("CAP LS 302");
|
||||
ircd.Write("CAP user LS * :away-notify");
|
||||
ASSERT_THAT(ircd.ReadRemainder().toStdString(), Not(HasSubstr("away-notify")));
|
||||
ircd.Write("CAP user LS :blahblah");
|
||||
ircd.ReadUntil("CAP REQ :away-notify");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, CAP302NewDel) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
auto client = LoginClient();
|
||||
ircd.Write("CAP nick LS :blahblah");
|
||||
ircd.ReadUntil("CAP END");
|
||||
ircd.Write(":server 001 nick :Hello");
|
||||
client.Write("CAP REQ :away-notify");
|
||||
client.ReadUntil("NAK :away-notify");
|
||||
client.Write("CAP REQ :cap-notify");
|
||||
client.ReadUntil("ACK :cap-notify");
|
||||
ircd.Write("CAP nick NEW :away-notify");
|
||||
ircd.ReadUntil("CAP REQ :away-notify");
|
||||
ircd.Write("CAP nick ACK :away-notify");
|
||||
client.ReadUntil("CAP nick NEW :away-notify");
|
||||
ircd.Write("CAP nick DEL :away-notify");
|
||||
client.ReadUntil("CAP nick DEL :away-notify");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, JoinKey) {
|
||||
QFile conf(m_dir.path() + "/configs/znc.conf");
|
||||
ASSERT_TRUE(conf.open(QIODevice::Append | QIODevice::Text));
|
||||
@@ -296,15 +349,15 @@ TEST_F(ZNCTest, StatusEchoMessage) {
|
||||
client.Write("CAP REQ :echo-message");
|
||||
client.Write("PRIVMSG *status :blah");
|
||||
client.ReadUntil(":nick!user@irc.znc.in PRIVMSG *status :blah");
|
||||
client.ReadUntil(":*status!znc@znc.in PRIVMSG nick :Unknown command");
|
||||
client.ReadUntil(":*status!status@znc.in PRIVMSG nick :Unknown command");
|
||||
client.Write("znc delnetwork test");
|
||||
client.ReadUntil("Network deleted");
|
||||
auto client2 = LoginClient();
|
||||
client2.Write("PRIVMSG *status :blah2");
|
||||
client2.ReadUntil(":*status!znc@znc.in PRIVMSG nick :Unknown command");
|
||||
client2.ReadUntil(":*status!status@znc.in PRIVMSG nick :Unknown command");
|
||||
auto client3 = LoginClient();
|
||||
client3.Write("PRIVMSG *status :blah3");
|
||||
client3.ReadUntil(":*status!znc@znc.in PRIVMSG nick :Unknown command");
|
||||
client3.ReadUntil(":*status!status@znc.in PRIVMSG nick :Unknown command");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, MoveChannels) {
|
||||
@@ -430,5 +483,346 @@ TEST_F(ZNCTest, DenyOptions) {
|
||||
client2.ReadUntil("Access denied!");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, CAP302MultiLS) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
auto client = LoginClient();
|
||||
InstallModule("testmod.cpp", R"(
|
||||
#include <znc/Client.h>
|
||||
#include <znc/Modules.h>
|
||||
class TestModule : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(TestModule) {}
|
||||
void OnClientCapLs(CClient* pClient, SCString& ssCaps) override {
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
ssCaps.insert("testcap-" + CString(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
GLOBALMODULEDEFS(TestModule, "Test")
|
||||
)");
|
||||
client.Write("znc loadmod testmod");
|
||||
client.ReadUntil("Loaded module testmod");
|
||||
|
||||
auto client2 = ConnectClient();
|
||||
client2.Write("CAP LS");
|
||||
client2.ReadUntil("LS :");
|
||||
auto rem = client2.ReadRemainder();
|
||||
ASSERT_GT(rem.indexOf("testcap-10"), 10);
|
||||
ASSERT_EQ(rem.indexOf("testcap-80"), -1);
|
||||
ASSERT_EQ(rem.indexOf("LS"), -1);
|
||||
|
||||
client2 = ConnectClient();
|
||||
client2.Write("CAP LS 302");
|
||||
client2.ReadUntil("LS * :");
|
||||
rem = client2.ReadRemainder();
|
||||
int w = 0;
|
||||
ASSERT_GT(w = rem.indexOf("testcap-10"), 1);
|
||||
ASSERT_GT(w = rem.indexOf("testcap-22", w), 1);
|
||||
ASSERT_GT(w = rem.indexOf("LS * :", w), 1);
|
||||
ASSERT_GT(rem.indexOf("testcap-80", w), 1);
|
||||
ASSERT_GT(rem.indexOf("LS :", w), 1);
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, CAP302LSValue) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
auto client = LoginClient();
|
||||
InstallModule("testmod.cpp", R"(
|
||||
#include <znc/Client.h>
|
||||
#include <znc/Modules.h>
|
||||
class TestModule : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(TestModule) {}
|
||||
void OnClientCapLs(CClient* pClient, SCString& ssCaps) override {
|
||||
if (pClient->HasCap302()) {
|
||||
ssCaps.insert("testcap=blah");
|
||||
} else {
|
||||
ssCaps.insert("testcap");
|
||||
}
|
||||
}
|
||||
};
|
||||
GLOBALMODULEDEFS(TestModule, "Test")
|
||||
)");
|
||||
client.Write("znc loadmod testmod");
|
||||
client.ReadUntil("Loaded module testmod");
|
||||
|
||||
auto client2 = ConnectClient();
|
||||
client2.Write("CAP LS");
|
||||
client2.ReadUntil("testcap ");
|
||||
|
||||
client2 = ConnectClient();
|
||||
client2.Write("CAP LS 302");
|
||||
client2.ReadUntil("testcap=");
|
||||
}
|
||||
|
||||
class AllLanguages : public ZNCTest, public testing::WithParamInterface<int> {};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(LanguagesTests, AllLanguages, testing::Values(1, 2, 3));
|
||||
|
||||
TEST_P(AllLanguages, ServerDependentCapInModule) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
auto client = LoginClient();
|
||||
switch (GetParam()) {
|
||||
case 1:
|
||||
InstallModule("testmod.cpp", R"(
|
||||
#include <znc/Modules.h>
|
||||
class TestModule : public CModule {
|
||||
class TestCap : public CCapability {
|
||||
void OnServerChangedSupport(CIRCNetwork* pNetwork, bool bState) override {
|
||||
GetModule()->PutModule("Server changed support: " + CString(bState));
|
||||
}
|
||||
void OnClientChangedSupport(CClient* pClient, bool bState) override {
|
||||
GetModule()->PutModule("Client changed support: " + CString(bState));
|
||||
}
|
||||
};
|
||||
public:
|
||||
MODCONSTRUCTOR(TestModule) {
|
||||
AddServerDependentCapability("testcap", std::make_unique<TestCap>());
|
||||
}
|
||||
};
|
||||
MODULEDEFS(TestModule, "Test")
|
||||
)");
|
||||
break;
|
||||
case 2:
|
||||
#ifndef WANT_PYTHON
|
||||
GTEST_SKIP() << "Modpython is disabled";
|
||||
#endif
|
||||
znc->CanLeak();
|
||||
InstallModule("testmod.py", R"(
|
||||
import znc
|
||||
class testmod(znc.Module):
|
||||
def OnLoad(self, args, ret):
|
||||
def server_change(net, state):
|
||||
self.PutModule('Server changed support: ' + ('true' if state else 'false'))
|
||||
def client_change(client, state):
|
||||
self.PutModule('Client changed support: ' + ('true' if state else 'false'))
|
||||
self.AddServerDependentCapability('testcap', server_change, client_change)
|
||||
return True
|
||||
)");
|
||||
client.Write("znc loadmod modpython");
|
||||
break;
|
||||
case 3:
|
||||
#ifndef WANT_PERL
|
||||
GTEST_SKIP() << "Modperl is disabled";
|
||||
#endif
|
||||
znc->CanLeak();
|
||||
InstallModule("testmod.pm", R"(
|
||||
package testmod;
|
||||
use base 'ZNC::Module';
|
||||
sub OnLoad {
|
||||
my $self = shift;
|
||||
$self->AddServerDependentCapability('testcap', sub {
|
||||
my ($net, $state) = @_;
|
||||
$self->PutModule('Server changed support: ' . ($state ? 'true' : 'false'));
|
||||
}, sub {
|
||||
my ($client, $state) = @_;
|
||||
$self->PutModule('Client changed support: ' . ($state ? 'true' : 'false'));
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
1;
|
||||
)");
|
||||
client.Write("znc loadmod modperl");
|
||||
break;
|
||||
}
|
||||
client.Write("znc loadmod testmod");
|
||||
client.ReadUntil("Loaded module testmod");
|
||||
client.Write("znc addnetwork net2");
|
||||
client.Close();
|
||||
|
||||
client = ConnectClient();
|
||||
client.Write("CAP LS 302");
|
||||
client.Write("PASS :hunter2");
|
||||
client.Write("NICK nick");
|
||||
client.Write("USER user/test x x :x");
|
||||
client.Write("CAP END");
|
||||
client.ReadUntil("Welcome");
|
||||
|
||||
ircd.Write("001 nick Welcome");
|
||||
ircd.Write("CAP nick NEW testcap=value");
|
||||
ircd.ReadUntil("CAP REQ :testcap");
|
||||
ircd.Write("CAP nick ACK :testcap");
|
||||
client.ReadUntil(":Server changed support: true");
|
||||
client.ReadUntil("CAP nick NEW :testcap=value");
|
||||
client.Write("CAP REQ testcap");
|
||||
client.ReadUntil(":Client changed support: true");
|
||||
client.ReadUntil("CAP nick ACK :testcap");
|
||||
|
||||
client.Write("CAP LS");
|
||||
client.ReadUntil(" testcap=value ");
|
||||
|
||||
ircd.Write("CAP nick DEL testcap");
|
||||
client.ReadUntil(":Server changed support: false");
|
||||
client.ReadUntil("CAP nick DEL :testcap");
|
||||
client.ReadUntil(":Client changed support: false");
|
||||
|
||||
ircd.Close();
|
||||
// TODO combine multiple DELs to single line
|
||||
client.ReadUntil("CAP nick DEL :testcap");
|
||||
client.ReadUntil(":Client changed support: false");
|
||||
|
||||
ircd = ConnectIRCd();
|
||||
ircd.ReadUntil("CAP LS 302");
|
||||
ircd.Write("CAP nick LS :testcap=new");
|
||||
ircd.ReadUntil("CAP REQ :testcap");
|
||||
ircd.Write("CAP nick ACK :testcap");
|
||||
client.ReadUntil(":Server changed support: true");
|
||||
ircd.ReadUntil("CAP END");
|
||||
// NEW waits until 001
|
||||
ASSERT_THAT(ircd.ReadRemainder().toStdString(), Not(HasSubstr("testcap")));
|
||||
ircd.Write("001 nick Welcome");
|
||||
// TODO combine multiple NEWs to single line
|
||||
client.ReadUntil("CAP nick NEW :testcap=new");
|
||||
client.ReadUntil("Welcome");
|
||||
|
||||
// NEW with new value without DEL
|
||||
ircd.Write("CAP nick NEW testcap=another");
|
||||
client.ReadUntil("CAP nick NEW :testcap=another");
|
||||
|
||||
client.Write("znc jumpnetwork net2");
|
||||
client.ReadUntil("CAP nick DEL :testcap");
|
||||
client.ReadUntil(":Client changed support: false");
|
||||
|
||||
client.Write("znc jumpnetwork test");
|
||||
client.ReadUntil("CAP nick NEW :testcap=another");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, HashUpgrade) {
|
||||
QFile conf(m_dir.path() + "/configs/znc.conf");
|
||||
ASSERT_TRUE(conf.open(QIODevice::Append | QIODevice::Text));
|
||||
QTextStream out(&conf);
|
||||
out << R"(
|
||||
<User foo>
|
||||
<Pass pass>
|
||||
Method = MD5
|
||||
Salt = abc
|
||||
Hash = defdf93cef7fa7a8ee88e65d0e277b99
|
||||
</Pass>
|
||||
</User>
|
||||
)";
|
||||
out.flush();
|
||||
conf.close();
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
|
||||
auto client = ConnectClient();
|
||||
client.Write("PASS :hunter2");
|
||||
client.Write("NICK nick");
|
||||
client.Write("USER foo x x :x");
|
||||
client.ReadUntil("Welcome");
|
||||
client.Close();
|
||||
|
||||
client = LoginClient();
|
||||
client.Write("znc saveconfig");
|
||||
client.ReadUntil("Wrote config");
|
||||
|
||||
ASSERT_TRUE(conf.open(QIODevice::ReadOnly | QIODevice::Text));
|
||||
QTextStream in(&conf);
|
||||
QString config = in.readAll();
|
||||
// It was upgraded to either Argon2 or SHA256
|
||||
EXPECT_THAT(config.toStdString(), Not(ContainsRegex("Method.*MD5")));
|
||||
|
||||
// Check that still can login after the upgrade
|
||||
client = ConnectClient();
|
||||
client.Write("PASS :hunter2");
|
||||
client.Write("NICK nick");
|
||||
client.Write("USER foo x x :x");
|
||||
client.ReadUntil("Welcome");
|
||||
client.Close();
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, CapReqWithoutLs) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
|
||||
auto client = ConnectClient();
|
||||
client.Write("CAP REQ nonono");
|
||||
client.Write("PASS :hunter2");
|
||||
client.Write("NICK nick");
|
||||
client.Write("USER foo x x :x");
|
||||
ASSERT_THAT(client.ReadRemainder().toStdString(), Not(HasSubstr("Welcome")));
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ChgHostEmulation) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
ircd.Write("CAP user LS :chghost");
|
||||
ircd.ReadUntil("CAP REQ :chghost");
|
||||
ircd.Write("CAP user ACK :chghost");
|
||||
|
||||
auto client1 = LoginClient();
|
||||
auto client2 = LoginClient();
|
||||
client2.Write("CAP REQ :chghost");
|
||||
client2.ReadUntil("ACK");
|
||||
|
||||
ircd.Write(":user!oldident@oldhost JOIN #chan");
|
||||
|
||||
ircd.Write(":user!oldident@oldhost CHGHOST newident newhost");
|
||||
client1.ReadUntil(":user!oldident@oldhost QUIT :Changing hostname");
|
||||
client1.ReadUntil(":user!newident@newhost JOIN #chan");
|
||||
ASSERT_THAT(client1.ReadRemainder().toStdString(), Not(HasSubstr("MODE")));
|
||||
client2.ReadUntil(":user!oldident@oldhost CHGHOST newident newhost");
|
||||
client2.Close();
|
||||
|
||||
ircd.Write(":server MODE #chan +v user");
|
||||
client1.ReadUntil("MODE");
|
||||
ircd.Write(":user!newident@newhost CHGHOST ident-2 host-2");
|
||||
client1.ReadUntil(":irc.znc.in MODE #chan +v user");
|
||||
|
||||
ircd.Write(":server MODE #chan +o user");
|
||||
client1.ReadUntil("MODE");
|
||||
ircd.Write(":user!ident-2@host-2 CHGHOST ident-3 host-3");
|
||||
client1.ReadUntil(":irc.znc.in MODE #chan +ov user user");
|
||||
|
||||
// Only attached channel should receive emulation
|
||||
ircd.Write(":user!ident-3@host-3 JOIN #chan2");
|
||||
client1.ReadUntil("JOIN #chan2");
|
||||
client1.Write("DETACH #chan2");
|
||||
client1.ReadUntil("Detached 1 channel");
|
||||
ircd.Write(":user!ident-3@host-3 CHGHOST ident host");
|
||||
ASSERT_THAT(client1.ReadRemainder().toStdString(),
|
||||
Not(HasSubstr("#chan2")));
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ChgHostOnce) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
ircd.Write("CAP user LS :chghost");
|
||||
ircd.ReadUntil("CAP REQ :chghost");
|
||||
ircd.Write("CAP user ACK :chghost");
|
||||
|
||||
auto client = LoginClient();
|
||||
client.Write("CAP REQ :chghost");
|
||||
client.ReadUntil("ACK");
|
||||
|
||||
ircd.Write(":user!oldident@oldhost JOIN #chan");
|
||||
ircd.Write(":user!oldident@oldhost JOIN #chan2");
|
||||
ircd.Write(":user!oldident@oldhost CHGHOST newident newhost");
|
||||
client.ReadUntil("CHGHOST");
|
||||
ASSERT_THAT(client.ReadRemainder().toStdString(),
|
||||
Not(HasSubstr("CHGHOST")));
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ChgHostOnlyNicksAlreadyOnChannels) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
ircd.Write("CAP user LS :chghost");
|
||||
ircd.ReadUntil("CAP REQ :chghost");
|
||||
ircd.Write("CAP user ACK :chghost");
|
||||
|
||||
auto client = LoginClient();
|
||||
ircd.Write(":user!ident@host JOIN #chan1");
|
||||
ircd.Write(":user!ident@host JOIN #chan2");
|
||||
ircd.Write(":another!ident@host JOIN #chan1");
|
||||
client.ReadUntil("another");
|
||||
|
||||
ircd.Write(":another!ident@host CHGHOST i2 h2");
|
||||
ASSERT_THAT(client.ReadRemainder().toStdString(),
|
||||
AllOf(HasSubstr("JOIN #chan1"),
|
||||
Not(HasSubstr("#chan2"))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace znc_inttest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -234,7 +234,7 @@ TEST_F(ZNCTest, KeepNickModule) {
|
||||
ircd.ReadUntil("NICK user");
|
||||
ircd.Write(":server 435 user_ user #error :Nope :-P");
|
||||
client.ReadUntil(
|
||||
":*keepnick!znc@znc.in PRIVMSG user_ "
|
||||
":*keepnick!keepnick@znc.in PRIVMSG user_ "
|
||||
":Unable to obtain nick user: Nope :-P, #error");
|
||||
}
|
||||
|
||||
@@ -350,5 +350,21 @@ TEST_F(ZNCTest, SaslPlainModule) {
|
||||
client2.ReadUntil(":irc.znc.in 903 foo :SASL authentication successful");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, SaslRequire) {
|
||||
auto znc = Run();
|
||||
auto ircd = ConnectIRCd();
|
||||
auto client = LoginClient();
|
||||
client.Write("znc loadmod sasl");
|
||||
client.Write("PRIVMSG *sasl :set * *");
|
||||
client.Write("PRIVMSG *sasl :requireauth yes");
|
||||
client.ReadUntil("Password has been set");
|
||||
client.Write("znc jump");
|
||||
ircd = ConnectIRCd();
|
||||
ircd.ReadUntil("CAP LS");
|
||||
ircd.Write(":server 001 nick :Hello");
|
||||
ircd.ReadUntil("QUIT :SASL not available");
|
||||
auto ircd2 = ConnectIRCd();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace znc_inttest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2023 ZNC, see the NOTICE file for details.
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,15 +15,15 @@
|
||||
*/
|
||||
|
||||
#include "znctest.h"
|
||||
#include "znctestconfig.h"
|
||||
|
||||
namespace znc_inttest {
|
||||
namespace {
|
||||
|
||||
TEST_F(ZNCTest, Modperl) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PERL
|
||||
GTEST_SKIP() << "Modperl is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
auto ircd = ConnectIRCd();
|
||||
@@ -31,16 +31,15 @@ TEST_F(ZNCTest, Modperl) {
|
||||
client.Write("znc loadmod modperl");
|
||||
client.Write("znc loadmod perleval");
|
||||
client.Write("PRIVMSG *perleval :2+2");
|
||||
client.ReadUntil(":*perleval!znc@znc.in PRIVMSG nick :Result: 4");
|
||||
client.ReadUntil(":*perleval!perleval@znc.in PRIVMSG nick :Result: 4");
|
||||
client.Write("PRIVMSG *perleval :$self->GetUser->GetUsername");
|
||||
client.ReadUntil("Result: user");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, Modpython) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PYTHON
|
||||
GTEST_SKIP() << "Modpython is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
auto ircd = ConnectIRCd();
|
||||
@@ -48,7 +47,7 @@ TEST_F(ZNCTest, Modpython) {
|
||||
client.Write("znc loadmod modpython");
|
||||
client.Write("znc loadmod pyeval");
|
||||
client.Write("PRIVMSG *pyeval :2+2");
|
||||
client.ReadUntil(":*pyeval!znc@znc.in PRIVMSG nick :4");
|
||||
client.ReadUntil(":*pyeval!pyeval@znc.in PRIVMSG nick :4");
|
||||
client.Write("PRIVMSG *pyeval :module.GetUser().GetUsername()");
|
||||
client.ReadUntil("nick :'user'");
|
||||
ircd.Write(":server 001 nick :Hello");
|
||||
@@ -60,15 +59,14 @@ TEST_F(ZNCTest, Modpython) {
|
||||
client.Write("PRIVMSG *controlpanel :Set ClientEncoding $me Western");
|
||||
client.Write("JOIN #a\342");
|
||||
client.ReadUntil(
|
||||
":*controlpanel!znc@znc.in PRIVMSG nick :ClientEncoding = UTF-8");
|
||||
":*controlpanel!controlpanel@znc.in PRIVMSG nick :ClientEncoding = UTF-8");
|
||||
ircd.ReadUntil("JOIN #a\xEF\xBF\xBD");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModpythonSocket) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PYTHON
|
||||
GTEST_SKIP() << "Modpython is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -107,10 +105,9 @@ TEST_F(ZNCTest, ModpythonSocket) {
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModperlSocket) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PERL
|
||||
GTEST_SKIP() << "Modperl is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -160,10 +157,9 @@ TEST_F(ZNCTest, ModperlSocket) {
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModpythonVCString) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PYTHON
|
||||
GTEST_SKIP() << "Modpython is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -185,10 +181,9 @@ TEST_F(ZNCTest, ModpythonVCString) {
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModperlVCString) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PERL
|
||||
GTEST_SKIP() << "Modperl is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -214,10 +209,9 @@ TEST_F(ZNCTest, ModperlVCString) {
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModperlNV) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PERL
|
||||
GTEST_SKIP() << "Modperl is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -244,10 +238,9 @@ TEST_F(ZNCTest, ModperlNV) {
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModpythonPackage) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PYTHON
|
||||
GTEST_SKIP() << "Modpython is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -277,13 +270,20 @@ TEST_F(ZNCTest, ModpythonPackage) {
|
||||
client.Write("znc updatemod packagetest");
|
||||
client.Write("PRIVMSG *packagetest :foo");
|
||||
client.ReadUntil("value = b");
|
||||
// Test if python modules are viewable via *status.
|
||||
// https://github.com/znc/znc/issues/1884
|
||||
client.Write("znc listavailmods");
|
||||
client.ReadUntil(":*status!status@znc.in PRIVMSG nick :\x02 packagetest");
|
||||
client.ReadUntil(":*status!status@znc.in PRIVMSG nick :\x02 pyeval\x0F: Evaluates python code");
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModpythonModperl) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
#ifndef WANT_PYTHON
|
||||
GTEST_SKIP() << "Modpython is disabled";
|
||||
#endif
|
||||
#ifndef WANT_PERL
|
||||
GTEST_SKIP() << "Modperl is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -297,11 +297,9 @@ TEST_F(ZNCTest, ModpythonModperl) {
|
||||
}
|
||||
|
||||
TEST_F(ZNCTest, ModpythonCommand) {
|
||||
if (QProcessEnvironment::systemEnvironment().value(
|
||||
"DISABLED_ZNC_PERL_PYTHON_TEST") == "1") {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef WANT_PYTHON
|
||||
GTEST_SKIP() << "Modpython is disabled";
|
||||
#endif
|
||||
auto znc = Run();
|
||||
znc->CanLeak();
|
||||
|
||||
@@ -328,7 +326,7 @@ TEST_F(ZNCTest, ModpythonCommand) {
|
||||
client.Write("znc loadmod modpython");
|
||||
client.Write("znc loadmod cmdtest");
|
||||
client.Write("PRIVMSG *cmdtest :ping or");
|
||||
client.ReadUntil(":*cmdtest!znc@znc.in PRIVMSG nick :ping or pong");
|
||||
client.ReadUntil(":*cmdtest!cmdtest@znc.in PRIVMSG nick :ping or pong");
|
||||
|
||||
InstallTranslation("cmdtest", "ru_RU", R"(
|
||||
msgid ""
|
||||
@@ -352,9 +350,9 @@ TEST_F(ZNCTest, ModpythonCommand) {
|
||||
|
||||
client.Write("PRIVMSG *controlpanel :set language $me ru-RU");
|
||||
client.Write("PRIVMSG *cmdtest :help");
|
||||
client.ReadUntil(":*cmdtest!znc@znc.in PRIVMSG nick :\x02ping аргумент\x0F: бла");
|
||||
client.ReadUntil(":*cmdtest!cmdtest@znc.in PRIVMSG nick :\x02ping аргумент\x0F: бла");
|
||||
client.Write("PRIVMSG *cmdtest :ping");
|
||||
client.ReadUntil(":*cmdtest!znc@znc.in PRIVMSG nick :ping понг");
|
||||
client.ReadUntil(":*cmdtest!cmdtest@znc.in PRIVMSG nick :ping понг");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ZNCTESTCONFIG_H
|
||||
#define ZNCTESTCONFIG_H
|
||||
|
||||
#cmakedefine WANT_PYTHON 1
|
||||
#cmakedefine WANT_PERL 1
|
||||
|
||||
#endif /* ZNCTESTCONFIG_H */
|
||||
Reference in New Issue
Block a user