mirror of
https://github.com/progval/irctest.git
synced 2025-04-05 14:59:49 +00:00
Run Atheme with Charybdis, to enable tests depending on SASL
This commit is contained in:
4
.github/workflows/charybdis.yml
vendored
4
.github/workflows/charybdis.yml
vendored
@ -28,6 +28,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
sudo apt-get install atheme-services
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install pytest -r requirements.txt
|
pip install pytest -r requirements.txt
|
||||||
|
|
||||||
@ -49,5 +50,6 @@ jobs:
|
|||||||
- name: Test with pytest
|
- name: Test with pytest
|
||||||
run: |
|
run: |
|
||||||
# testQuitErrors is very flaky
|
# testQuitErrors is very flaky
|
||||||
PATH=~/.local/bin:$PATH pytest --controller=irctest.controllers.charybdis -k 'not Ergo and not deprecated and not strict and not testDoubleKickMessages and not testQuitErrors'
|
# AccountTagTestCase.testInvite fails because https://github.com/solanum-ircd/solanum/issues/166
|
||||||
|
PATH=~/.local/bin:$PATH pytest --controller=irctest.controllers.charybdis -k 'not Ergo and not deprecated and not strict and not testDoubleKickMessages and not testQuitErrors and not (AccountTagTestCase and testInvite)'
|
||||||
|
|
||||||
|
4
.github/workflows/inspircd.yml
vendored
4
.github/workflows/inspircd.yml
vendored
@ -28,12 +28,10 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
sudo apt-get install atheme-services
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install pytest -r requirements.txt
|
pip install pytest -r requirements.txt
|
||||||
|
|
||||||
- name: Install atheme
|
|
||||||
run: sudo apt-get install atheme-services
|
|
||||||
|
|
||||||
- name: Checkout InspIRCd
|
- name: Checkout InspIRCd
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
|
3
.github/workflows/solanum.yml
vendored
3
.github/workflows/solanum.yml
vendored
@ -28,6 +28,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
sudo apt-get install atheme-services
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install pytest -r requirements.txt
|
pip install pytest -r requirements.txt
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
repository: solanum-ircd/solanum
|
repository: solanum-ircd/solanum
|
||||||
ref: 2e8a889fc94313acf53c430cec1bd044850769a0
|
ref: e370888264da666a1bd9faac86cd5f2aa06084f4
|
||||||
path: solanum
|
path: solanum
|
||||||
|
|
||||||
- name: Build Solanum
|
- name: Build Solanum
|
||||||
|
@ -177,6 +177,7 @@ class BaseClientController(_BaseController):
|
|||||||
class BaseServerController(_BaseController):
|
class BaseServerController(_BaseController):
|
||||||
"""Base controller for IRC server."""
|
"""Base controller for IRC server."""
|
||||||
|
|
||||||
|
software_name: str # Class property
|
||||||
_port_wait_interval = 0.1
|
_port_wait_interval = 0.1
|
||||||
port_open = False
|
port_open = False
|
||||||
port: int
|
port: int
|
||||||
@ -250,19 +251,31 @@ class BaseServicesController(_BaseController):
|
|||||||
c.sendLine("NICK chkNS")
|
c.sendLine("NICK chkNS")
|
||||||
c.sendLine("USER chk chk chk chk")
|
c.sendLine("USER chk chk chk chk")
|
||||||
c.getMessages(synchronize=False)
|
c.getMessages(synchronize=False)
|
||||||
|
c.getMessages()
|
||||||
|
|
||||||
msgs: List[Message] = []
|
timeout = time.time() + 5
|
||||||
while not msgs:
|
while True:
|
||||||
c.sendLine("PRIVMSG NickServ :HELP")
|
c.sendLine("PRIVMSG NickServ :HELP")
|
||||||
msgs = self.getNickServResponse(c)
|
msgs = self.getNickServResponse(c)
|
||||||
if msgs[0].command == "401":
|
for msg in msgs:
|
||||||
# NickServ not available yet
|
if msg.command == "401":
|
||||||
pass
|
# NickServ not available yet
|
||||||
elif msgs[0].command == "NOTICE":
|
pass
|
||||||
# NickServ is available
|
elif msg.command == "NOTICE":
|
||||||
assert "nickserv" in (msgs[0].prefix or "").lower(), msgs
|
# NickServ is available
|
||||||
else:
|
assert "nickserv" in (msg.prefix or "").lower(), msg
|
||||||
assert False, f"unexpected reply from NickServ: {msgs[0]}"
|
print("breaking")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
assert False, f"unexpected reply from NickServ: {msg}"
|
||||||
|
else:
|
||||||
|
if time.time() > timeout:
|
||||||
|
raise Exception("Timeout while waiting for NickServ")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If we're here, it means we broke from the for loop, so NickServ
|
||||||
|
# is available and we can break again
|
||||||
|
break
|
||||||
|
|
||||||
c.sendLine("QUIT")
|
c.sendLine("QUIT")
|
||||||
c.getMessages()
|
c.getMessages()
|
||||||
@ -296,6 +309,8 @@ class BaseServicesController(_BaseController):
|
|||||||
case.getMessages(client)
|
case.getMessages(client)
|
||||||
case.sendLine(client, f"PRIVMSG NickServ :REGISTER {password} foo@example.org")
|
case.sendLine(client, f"PRIVMSG NickServ :REGISTER {password} foo@example.org")
|
||||||
msgs = self.getNickServResponse(case.clients[client])
|
msgs = self.getNickServResponse(case.clients[client])
|
||||||
assert "900" in {msg.command for msg in msgs}, msgs
|
if self.server_controller.software_name == "inspircd":
|
||||||
|
assert "900" in {msg.command for msg in msgs}, msgs
|
||||||
|
assert "NOTICE" in {msg.command for msg in msgs}, msgs
|
||||||
case.sendLine(client, "QUIT")
|
case.sendLine(client, "QUIT")
|
||||||
case.assertDisconnected(client)
|
case.assertDisconnected(client)
|
||||||
|
@ -8,7 +8,7 @@ import irctest.cases
|
|||||||
import irctest.runner
|
import irctest.runner
|
||||||
|
|
||||||
TEMPLATE_CONFIG = """
|
TEMPLATE_CONFIG = """
|
||||||
loadmodule "modules/protocol/inspircd";
|
loadmodule "modules/protocol/{protocol}";
|
||||||
loadmodule "modules/backend/opensex";
|
loadmodule "modules/backend/opensex";
|
||||||
loadmodule "modules/crypto/pbkdf2";
|
loadmodule "modules/crypto/pbkdf2";
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ general {{
|
|||||||
commit_interval = 5;
|
commit_interval = 5;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
uplink "irc.example.com" {{
|
uplink "My.Little.Server" {{
|
||||||
host = "{server_hostname}";
|
host = "{server_hostname}";
|
||||||
port = {server_port};
|
port = {server_port};
|
||||||
send_password = "password";
|
send_password = "password";
|
||||||
@ -55,12 +55,15 @@ saslserv {{
|
|||||||
class AthemeServices(BaseServicesController, DirectoryBasedController):
|
class AthemeServices(BaseServicesController, DirectoryBasedController):
|
||||||
"""Mixin for server controllers that rely on Atheme"""
|
"""Mixin for server controllers that rely on Atheme"""
|
||||||
|
|
||||||
def run(self, server_hostname: str, server_port: int) -> None:
|
def run(self, protocol: str, server_hostname: str, server_port: int) -> None:
|
||||||
self.create_config()
|
self.create_config()
|
||||||
|
|
||||||
|
assert protocol in ("inspircd", "charybdis")
|
||||||
|
|
||||||
with self.open_file("services.conf") as fd:
|
with self.open_file("services.conf") as fd:
|
||||||
fd.write(
|
fd.write(
|
||||||
TEMPLATE_CONFIG.format(
|
TEMPLATE_CONFIG.format(
|
||||||
|
protocol=protocol,
|
||||||
server_hostname=server_hostname,
|
server_hostname=server_hostname,
|
||||||
server_port=server_port,
|
server_port=server_port,
|
||||||
)
|
)
|
||||||
@ -81,7 +84,7 @@ class AthemeServices(BaseServicesController, DirectoryBasedController):
|
|||||||
self.directory,
|
self.directory,
|
||||||
],
|
],
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL,
|
# stderr=subprocess.DEVNULL,
|
||||||
)
|
)
|
||||||
|
|
||||||
def registerUser(
|
def registerUser(
|
||||||
|
@ -7,6 +7,8 @@ from irctest.basecontrollers import (
|
|||||||
DirectoryBasedController,
|
DirectoryBasedController,
|
||||||
NotImplementedByController,
|
NotImplementedByController,
|
||||||
)
|
)
|
||||||
|
from irctest.controllers.atheme_services import AthemeServices
|
||||||
|
from irctest.irc_utils.junkdrawer import find_hostname_and_port
|
||||||
|
|
||||||
TEMPLATE_CONFIG = """
|
TEMPLATE_CONFIG = """
|
||||||
serverinfo {{
|
serverinfo {{
|
||||||
@ -15,23 +17,48 @@ serverinfo {{
|
|||||||
description = "test server";
|
description = "test server";
|
||||||
{ssl_config}
|
{ssl_config}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
general {{
|
||||||
|
throttle_count = 100; # We need to connect lots of clients quickly
|
||||||
|
sasl_service = "SaslServ";
|
||||||
|
}};
|
||||||
|
|
||||||
|
class "server" {{
|
||||||
|
ping_time = 5 minutes;
|
||||||
|
connectfreq = 5 minutes;
|
||||||
|
}};
|
||||||
|
|
||||||
listen {{
|
listen {{
|
||||||
defer_accept = yes;
|
defer_accept = yes;
|
||||||
|
|
||||||
host = "{hostname}";
|
host = "{hostname}";
|
||||||
port = {port};
|
port = {port};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
auth {{
|
auth {{
|
||||||
user = "*";
|
user = "*";
|
||||||
flags = exceed_limit;
|
flags = exceed_limit;
|
||||||
{password_field}
|
{password_field}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
channel {{
|
channel {{
|
||||||
disable_local_channels = no;
|
disable_local_channels = no;
|
||||||
no_create_on_split = no;
|
no_create_on_split = no;
|
||||||
no_join_on_split = no;
|
no_join_on_split = no;
|
||||||
displayed_usercount = 0;
|
displayed_usercount = 0;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
connect "services.example.org" {{
|
||||||
|
host = "localhost"; # Used to validate incoming connection
|
||||||
|
port = 0; # We don't want the servers to connect to services
|
||||||
|
send_password = "password";
|
||||||
|
accept_password = "password";
|
||||||
|
class = "server";
|
||||||
|
flags = topicburst;
|
||||||
|
}};
|
||||||
|
service {{
|
||||||
|
name = "services.example.org";
|
||||||
|
}};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
TEMPLATE_SSL_CONFIG = """
|
TEMPLATE_SSL_CONFIG = """
|
||||||
@ -44,7 +71,7 @@ TEMPLATE_SSL_CONFIG = """
|
|||||||
class CharybdisController(BaseServerController, DirectoryBasedController):
|
class CharybdisController(BaseServerController, DirectoryBasedController):
|
||||||
software_name = "Charybdis"
|
software_name = "Charybdis"
|
||||||
binary_name = "charybdis"
|
binary_name = "charybdis"
|
||||||
supported_sasl_mechanisms: Set[str] = set()
|
supported_sasl_mechanisms = {"PLAIN"}
|
||||||
supports_sts = False
|
supports_sts = False
|
||||||
|
|
||||||
def create_config(self) -> None:
|
def create_config(self) -> None:
|
||||||
@ -67,11 +94,11 @@ class CharybdisController(BaseServerController, DirectoryBasedController):
|
|||||||
raise NotImplementedByController(
|
raise NotImplementedByController(
|
||||||
"Defining valid and invalid METADATA keys."
|
"Defining valid and invalid METADATA keys."
|
||||||
)
|
)
|
||||||
if run_services:
|
|
||||||
raise NotImplementedByController("Registration services")
|
|
||||||
assert self.proc is None
|
assert self.proc is None
|
||||||
self.create_config()
|
|
||||||
self.port = port
|
self.port = port
|
||||||
|
self.hostname = hostname
|
||||||
|
self.create_config()
|
||||||
|
(services_hostname, services_port) = find_hostname_and_port()
|
||||||
password_field = 'password = "{}";'.format(password) if password else ""
|
password_field = 'password = "{}";'.format(password) if password else ""
|
||||||
if ssl:
|
if ssl:
|
||||||
self.gen_ssl()
|
self.gen_ssl()
|
||||||
@ -85,6 +112,8 @@ class CharybdisController(BaseServerController, DirectoryBasedController):
|
|||||||
TEMPLATE_CONFIG.format(
|
TEMPLATE_CONFIG.format(
|
||||||
hostname=hostname,
|
hostname=hostname,
|
||||||
port=port,
|
port=port,
|
||||||
|
services_hostname=services_hostname,
|
||||||
|
services_port=services_port,
|
||||||
password_field=password_field,
|
password_field=password_field,
|
||||||
ssl_config=ssl_config,
|
ssl_config=ssl_config,
|
||||||
)
|
)
|
||||||
@ -102,6 +131,13 @@ class CharybdisController(BaseServerController, DirectoryBasedController):
|
|||||||
# stderr=subprocess.DEVNULL,
|
# stderr=subprocess.DEVNULL,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if run_services:
|
||||||
|
self.wait_for_port()
|
||||||
|
self.services_controller = AthemeServices(self.test_config, self)
|
||||||
|
self.services_controller.run(
|
||||||
|
protocol="charybdis", server_hostname=hostname, server_port=port
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_irctest_controller_class() -> Type[CharybdisController]:
|
def get_irctest_controller_class() -> Type[CharybdisController]:
|
||||||
return CharybdisController
|
return CharybdisController
|
||||||
|
@ -54,7 +54,7 @@ TEMPLATE_CONFIG = """
|
|||||||
|
|
||||||
# Misc:
|
# Misc:
|
||||||
<log method="file" type="*" level="debug" target="/tmp/ircd-{port}.log">
|
<log method="file" type="*" level="debug" target="/tmp/ircd-{port}.log">
|
||||||
<server name="irc.example.com" description="testnet" id="000" network="testnet">
|
<server name="My.Little.Server" description="testnet" id="000" network="testnet">
|
||||||
"""
|
"""
|
||||||
|
|
||||||
TEMPLATE_SSL_CONFIG = """
|
TEMPLATE_SSL_CONFIG = """
|
||||||
@ -128,9 +128,12 @@ class InspircdController(BaseServerController, DirectoryBasedController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if run_services:
|
if run_services:
|
||||||
|
self.wait_for_port()
|
||||||
self.services_controller = AthemeServices(self.test_config, self)
|
self.services_controller = AthemeServices(self.test_config, self)
|
||||||
self.services_controller.run(
|
self.services_controller.run(
|
||||||
server_hostname=services_hostname, server_port=services_port
|
protocol="inspircd",
|
||||||
|
server_hostname=services_hostname,
|
||||||
|
server_port=services_port,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user