mirror of
https://github.com/progval/irctest.git
synced 2025-04-05 14:59:49 +00:00
Compare commits
1 Commits
ban-privms
...
sopel-scra
Author | SHA1 | Date | |
---|---|---|---|
1d8d78e62a |
47
.github/workflows/test-devel.yml
vendored
47
.github/workflows/test-devel.yml
vendored
@ -400,7 +400,6 @@ jobs:
|
||||
- test-unrealircd-5
|
||||
- test-unrealircd-anope
|
||||
- test-unrealircd-atheme
|
||||
- test-unrealircd-dlk
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -1128,52 +1127,6 @@ jobs:
|
||||
with:
|
||||
name: pytest-results_unrealircd-atheme_devel
|
||||
path: pytest.xml
|
||||
test-unrealircd-dlk:
|
||||
needs:
|
||||
- build-unrealircd
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
- name: Download build artefacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: installed-unrealircd
|
||||
path: '~'
|
||||
- name: Unpack artefacts
|
||||
run: cd ~; find -name 'artefacts-*.tar.gz' -exec tar -xzf '{}' \;
|
||||
- name: Checkout Dlk
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: Dlk-Services
|
||||
ref: main
|
||||
repository: DalekIRC/Dalek-Services
|
||||
- name: Build Dlk
|
||||
run: |
|
||||
pip install pifpaf
|
||||
wget -q https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
wget -q https://wordpress.org/latest.zip -O wordpress-latest.zip
|
||||
- name: Install system dependencies
|
||||
run: sudo apt-get install atheme-services faketime
|
||||
- name: Install irctest dependencies
|
||||
run: |-
|
||||
python -m pip install --upgrade pip
|
||||
pip install pytest pytest-xdist -r requirements.txt
|
||||
- name: Test with pytest
|
||||
run: PYTEST_ARGS='--junit-xml pytest.xml' PATH=$HOME/.local/bin:$PATH PATH=~/.local/unrealircd/sbin:~/.local/unrealircd/bin:$PATH
|
||||
IRCTEST_DLK_PATH="${{ github.workspace }}/Dlk-Services" IRCTEST_WP_CLI_PATH="${{
|
||||
github.workspace }}/wp-cli.phar" IRCTEST_WP_ZIP_PATH="${{ github.workspace
|
||||
}}/wordpress-latest.zip" make unrealircd-dlk
|
||||
timeout-minutes: 30
|
||||
- if: always()
|
||||
name: Publish results
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: pytest-results_unrealircd-dlk_devel
|
||||
path: pytest.xml
|
||||
name: irctest with devel versions
|
||||
'on':
|
||||
schedule:
|
||||
|
47
.github/workflows/test-stable.yml
vendored
47
.github/workflows/test-stable.yml
vendored
@ -443,7 +443,6 @@ jobs:
|
||||
- test-unrealircd-5
|
||||
- test-unrealircd-anope
|
||||
- test-unrealircd-atheme
|
||||
- test-unrealircd-dlk
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -1286,52 +1285,6 @@ jobs:
|
||||
with:
|
||||
name: pytest-results_unrealircd-atheme_stable
|
||||
path: pytest.xml
|
||||
test-unrealircd-dlk:
|
||||
needs:
|
||||
- build-unrealircd
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
- name: Download build artefacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: installed-unrealircd
|
||||
path: '~'
|
||||
- name: Unpack artefacts
|
||||
run: cd ~; find -name 'artefacts-*.tar.gz' -exec tar -xzf '{}' \;
|
||||
- name: Checkout Dlk
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: Dlk-Services
|
||||
ref: effd18652fc1c847d1959089d9cca9ff9837a8c0
|
||||
repository: DalekIRC/Dalek-Services
|
||||
- name: Build Dlk
|
||||
run: |
|
||||
pip install pifpaf
|
||||
wget -q https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
wget -q https://wordpress.org/latest.zip -O wordpress-latest.zip
|
||||
- name: Install system dependencies
|
||||
run: sudo apt-get install atheme-services faketime
|
||||
- name: Install irctest dependencies
|
||||
run: |-
|
||||
python -m pip install --upgrade pip
|
||||
pip install pytest pytest-xdist -r requirements.txt
|
||||
- name: Test with pytest
|
||||
run: PYTEST_ARGS='--junit-xml pytest.xml' PATH=$HOME/.local/bin:$PATH PATH=~/.local/unrealircd/sbin:~/.local/unrealircd/bin:$PATH
|
||||
IRCTEST_DLK_PATH="${{ github.workspace }}/Dlk-Services" IRCTEST_WP_CLI_PATH="${{
|
||||
github.workspace }}/wp-cli.phar" IRCTEST_WP_ZIP_PATH="${{ github.workspace
|
||||
}}/wordpress-latest.zip" make unrealircd-dlk
|
||||
timeout-minutes: 30
|
||||
- if: always()
|
||||
name: Publish results
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: pytest-results_unrealircd-dlk_stable
|
||||
path: pytest.xml
|
||||
name: irctest with stable versions
|
||||
'on':
|
||||
pull_request: null
|
||||
|
7
Makefile
7
Makefile
@ -274,10 +274,3 @@ unrealircd-anope:
|
||||
--services-controller=irctest.controllers.anope_services \
|
||||
-m 'services' \
|
||||
-k '$(UNREALIRCD_SELECTORS)'
|
||||
|
||||
unrealircd-dlk:
|
||||
pifpaf run mysql -- $(PYTEST) $(PYTEST_ARGS) \
|
||||
--controller=irctest.controllers.unrealircd \
|
||||
--services-controller=irctest.controllers.dlk_services \
|
||||
-m 'services' \
|
||||
-k '$(UNREALIRCD_SELECTORS)'
|
||||
|
@ -301,11 +301,10 @@ class BaseServicesController(_BaseController):
|
||||
c.sendLine("PONG :" + msg.params[0])
|
||||
c.getMessages()
|
||||
|
||||
timeout = time.time() + 3
|
||||
timeout = time.time() + 5
|
||||
while True:
|
||||
c.sendLine(f"PRIVMSG {self.server_controller.nickserv} :help")
|
||||
|
||||
msgs = self.getNickServResponse(c, timeout=1)
|
||||
c.sendLine(f"PRIVMSG {self.server_controller.nickserv} :HELP")
|
||||
msgs = self.getNickServResponse(c)
|
||||
for msg in msgs:
|
||||
if msg.command == "401":
|
||||
# NickServ not available yet
|
||||
@ -331,12 +330,11 @@ class BaseServicesController(_BaseController):
|
||||
c.disconnect()
|
||||
self.services_up = True
|
||||
|
||||
def getNickServResponse(self, client: Any, timeout: int = 0) -> List[Message]:
|
||||
def getNickServResponse(self, client: Any) -> List[Message]:
|
||||
"""Wrapper aroung getMessages() that waits longer, because NickServ
|
||||
is queried asynchronously."""
|
||||
msgs: List[Message] = []
|
||||
start_time = time.time()
|
||||
while not msgs and (not timeout or start_time + timeout > time.time()):
|
||||
while not msgs:
|
||||
time.sleep(0.05)
|
||||
msgs = client.getMessages()
|
||||
return msgs
|
||||
|
@ -1,245 +0,0 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
import secrets
|
||||
import subprocess
|
||||
from typing import Optional, Type
|
||||
|
||||
import irctest
|
||||
from irctest.basecontrollers import BaseServicesController, DirectoryBasedController
|
||||
import irctest.cases
|
||||
import irctest.runner
|
||||
|
||||
TEMPLATE_DLK_CONFIG = """\
|
||||
info {{
|
||||
SID "00A";
|
||||
network-name "testnetwork";
|
||||
services-name "services.example.org";
|
||||
admin-email "admin@example.org";
|
||||
}}
|
||||
|
||||
link {{
|
||||
hostname "{server_hostname}";
|
||||
port "{server_port}";
|
||||
password "password";
|
||||
}}
|
||||
|
||||
log {{
|
||||
debug "yes";
|
||||
}}
|
||||
|
||||
sql {{
|
||||
port "3306";
|
||||
username "pifpaf";
|
||||
password "pifpaf";
|
||||
database "pifpaf";
|
||||
sockfile "{mysql_socket}";
|
||||
prefix "{dlk_prefix}";
|
||||
}}
|
||||
|
||||
wordpress {{
|
||||
prefix "{wp_prefix}";
|
||||
}}
|
||||
|
||||
"""
|
||||
|
||||
TEMPLATE_DLK_WP_CONFIG = """
|
||||
<?php
|
||||
|
||||
global $wpconfig;
|
||||
$wpconfig = [
|
||||
|
||||
"dbprefix" => "{wp_prefix}",
|
||||
|
||||
|
||||
"default_avatar" => "https://valware.uk/wp-content/plugins/ultimate-member/assets/img/default_avatar.jpg",
|
||||
"forumschan" => "#DLK-Support",
|
||||
|
||||
];
|
||||
"""
|
||||
|
||||
TEMPLATE_WP_CONFIG = """
|
||||
define( 'DB_NAME', 'pifpaf' );
|
||||
define( 'DB_USER', 'pifpaf' );
|
||||
define( 'DB_PASSWORD', 'pifpaf' );
|
||||
define( 'DB_HOST', 'localhost:{mysql_socket}' );
|
||||
define( 'DB_CHARSET', 'utf8' );
|
||||
define( 'DB_COLLATE', '' );
|
||||
|
||||
define( 'AUTH_KEY', 'put your unique phrase here' );
|
||||
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
|
||||
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
|
||||
define( 'NONCE_KEY', 'put your unique phrase here' );
|
||||
define( 'AUTH_SALT', 'put your unique phrase here' );
|
||||
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
|
||||
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
|
||||
define( 'NONCE_SALT', 'put your unique phrase here' );
|
||||
|
||||
$table_prefix = '{wp_prefix}';
|
||||
|
||||
define( 'WP_DEBUG', false );
|
||||
|
||||
if (!defined('ABSPATH')) {{
|
||||
define( 'ABSPATH', '{wp_path}' );
|
||||
}}
|
||||
|
||||
/* That's all, stop editing! Happy publishing. */
|
||||
|
||||
/** Absolute path to the WordPress directory. */
|
||||
|
||||
|
||||
/** Sets up WordPress vars and included files. */
|
||||
require_once ABSPATH . 'wp-settings.php';
|
||||
"""
|
||||
|
||||
|
||||
class DlkController(BaseServicesController, DirectoryBasedController):
|
||||
"""Mixin for server controllers that rely on DLK"""
|
||||
|
||||
software_name = "Dlk-Services"
|
||||
|
||||
def run_sql(self, sql: str) -> None:
|
||||
mysql_socket = os.environ["PIFPAF_MYSQL_SOCKET"]
|
||||
subprocess.run(
|
||||
["mysql", "-S", mysql_socket, "pifpaf"],
|
||||
input=sql.encode(),
|
||||
check=True,
|
||||
)
|
||||
|
||||
def run(self, protocol: str, server_hostname: str, server_port: int) -> None:
|
||||
self.create_config()
|
||||
|
||||
if protocol == "unreal4":
|
||||
protocol = "unreal5"
|
||||
assert protocol in ("unreal5",), protocol
|
||||
|
||||
mysql_socket = os.environ["PIFPAF_MYSQL_SOCKET"]
|
||||
|
||||
assert self.directory
|
||||
|
||||
try:
|
||||
self.wp_cli_path = Path(os.environ["IRCTEST_WP_CLI_PATH"])
|
||||
if not self.wp_cli_path.is_file():
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
raise RuntimeError(
|
||||
"$IRCTEST_WP_CLI_PATH must be set to a WP-CLI executable (eg. "
|
||||
"downloaded from <https://raw.githubusercontent.com/wp-cli/builds/"
|
||||
"gh-pages/phar/wp-cli.phar>)"
|
||||
) from None
|
||||
|
||||
try:
|
||||
self.dlk_path = Path(os.environ["IRCTEST_DLK_PATH"])
|
||||
if not self.dlk_path.is_dir():
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
raise RuntimeError("$IRCTEST_DLK_PATH is not set") from None
|
||||
self.dlk_path = self.dlk_path.resolve()
|
||||
|
||||
# Unpack a fresh Wordpress install in the temporary directory.
|
||||
# In theory we could have a common Wordpress install and only wp-config.php
|
||||
# in the temporary directory; but wp-cli assumes wp-config.php must be
|
||||
# in a Wordpress directory, and fails in various places if it isn't.
|
||||
# Rather than symlinking everything to make it work, let's just copy
|
||||
# the whole code, it's not that big.
|
||||
try:
|
||||
wp_zip_path = Path(os.environ["IRCTEST_WP_ZIP_PATH"])
|
||||
if not wp_zip_path.is_file():
|
||||
raise KeyError()
|
||||
except KeyError:
|
||||
raise RuntimeError(
|
||||
"$IRCTEST_WP_ZIP_PATH must be set to a Wordpress source zipball "
|
||||
"(eg. downloaded from <https://wordpress.org/latest.zip>)"
|
||||
) from None
|
||||
subprocess.run(
|
||||
["unzip", wp_zip_path, "-d", self.directory], stdout=subprocess.DEVNULL
|
||||
)
|
||||
self.wp_path = self.directory / "wordpress"
|
||||
|
||||
rand_hex = secrets.token_hex(6)
|
||||
self.wp_prefix = f"wp{rand_hex}_"
|
||||
self.dlk_prefix = f"dlk{rand_hex}_"
|
||||
template_vars = dict(
|
||||
protocol=protocol,
|
||||
server_hostname=server_hostname,
|
||||
server_port=server_port,
|
||||
mysql_socket=mysql_socket,
|
||||
wp_path=self.wp_path,
|
||||
wp_prefix=self.wp_prefix,
|
||||
dlk_prefix=self.dlk_prefix,
|
||||
)
|
||||
|
||||
# Configure Wordpress
|
||||
wp_config_path = self.directory / "wp-config.php"
|
||||
with open(wp_config_path, "w") as fd:
|
||||
fd.write(TEMPLATE_WP_CONFIG.format(**template_vars))
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
"php",
|
||||
self.wp_cli_path,
|
||||
"core",
|
||||
"install",
|
||||
"--url=http://localhost/",
|
||||
"--title=irctest site",
|
||||
"--admin_user=adminuser",
|
||||
"--admin_email=adminuser@example.org",
|
||||
f"--path={self.wp_path}",
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
||||
# Configure Dlk
|
||||
dlk_log_dir = self.directory / "logs"
|
||||
dlk_conf_dir = self.directory / "conf"
|
||||
dlk_conf_path = dlk_conf_dir / "dalek.conf"
|
||||
os.mkdir(dlk_conf_dir)
|
||||
with open(dlk_conf_path, "w") as fd:
|
||||
fd.write(TEMPLATE_DLK_CONFIG.format(**template_vars))
|
||||
dlk_wp_config_path = dlk_conf_dir / "wordpress.conf"
|
||||
with open(dlk_wp_config_path, "w") as fd:
|
||||
fd.write(TEMPLATE_DLK_WP_CONFIG.format(**template_vars))
|
||||
(dlk_conf_dir / "modules.conf").symlink_to(self.dlk_path / "conf/modules.conf")
|
||||
|
||||
self.proc = subprocess.Popen(
|
||||
[
|
||||
"php",
|
||||
"src/dalek",
|
||||
],
|
||||
cwd=self.dlk_path,
|
||||
env={
|
||||
**os.environ,
|
||||
"DALEK_CONF_DIR": str(dlk_conf_dir),
|
||||
"DALEK_LOG_DIR": str(dlk_log_dir),
|
||||
},
|
||||
)
|
||||
|
||||
def terminate(self) -> None:
|
||||
super().terminate()
|
||||
|
||||
def kill(self) -> None:
|
||||
super().kill()
|
||||
|
||||
def registerUser(
|
||||
self,
|
||||
case: irctest.cases.BaseServerTestCase,
|
||||
username: str,
|
||||
password: Optional[str] = None,
|
||||
) -> None:
|
||||
assert password
|
||||
subprocess.run(
|
||||
[
|
||||
"php",
|
||||
self.wp_cli_path,
|
||||
"user",
|
||||
"create",
|
||||
username,
|
||||
f"{username}@example.org",
|
||||
f"--user_pass={password}",
|
||||
f"--path={self.wp_path}",
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
def get_irctest_controller_class() -> Type[DlkController]:
|
||||
return DlkController
|
@ -27,7 +27,11 @@ auth_password = {password}
|
||||
|
||||
class SopelController(BaseClientController):
|
||||
software_name = "Sopel"
|
||||
supported_sasl_mechanisms = {"PLAIN"}
|
||||
supported_sasl_mechanisms = {
|
||||
"PLAIN",
|
||||
"SCRAM-SHA-256",
|
||||
"EXTERNAL",
|
||||
}
|
||||
supports_sts = False
|
||||
|
||||
def __init__(self, test_config: TestCaseControllerConfig):
|
||||
@ -61,6 +65,8 @@ class SopelController(BaseClientController):
|
||||
# Runs a client with the config given as arguments
|
||||
if tls_config is not None:
|
||||
raise NotImplementedByController("TLS configuration")
|
||||
if auth and len(auth.mechanisms) > 1:
|
||||
raise NotImplementedByController("multiple SASL mechanisms")
|
||||
assert self.proc is None
|
||||
self.create_config()
|
||||
with self.open_file(self.filename) as fd:
|
||||
@ -70,7 +76,12 @@ class SopelController(BaseClientController):
|
||||
port=port,
|
||||
username=auth.username if auth else "",
|
||||
password=auth.password if auth else "",
|
||||
auth_method="auth_method = sasl" if auth else "",
|
||||
auth_method=(
|
||||
f"auth_method = sasl\n"
|
||||
f"auth_target = {auth.mechanisms[0].to_string()}"
|
||||
)
|
||||
if auth
|
||||
else "",
|
||||
)
|
||||
)
|
||||
self.proc = subprocess.Popen(["sopel", "--quiet", "-c", self.filename])
|
||||
|
@ -173,7 +173,6 @@ def build_module_html(
|
||||
|
||||
|
||||
def build_test_table(jobs: List[str], results: List[CaseResult]) -> ET.Element:
|
||||
multiple_modules = len({r.module_name for r in results}) > 1
|
||||
results_by_module_and_class = group_by(
|
||||
results, lambda r: (r.module_name, r.class_name)
|
||||
)
|
||||
@ -190,29 +189,19 @@ def build_test_table(jobs: List[str], results: List[CaseResult]) -> ET.Element:
|
||||
for ((module_name, class_name), class_results) in sorted(
|
||||
results_by_module_and_class.items()
|
||||
):
|
||||
if multiple_modules:
|
||||
# if the page shows classes from various modules, use the fully-qualified
|
||||
# name in order to disambiguate and be clearer (eg. show
|
||||
# "irctest.server_tests.extended_join.MetadataTestCase" instead of just
|
||||
# "MetadataTestCase" which looks like it's about IRCv3's METADATA spec.
|
||||
qualified_class_name = f"{module_name}.{class_name}"
|
||||
else:
|
||||
# otherwise, it's not needed, so let's not display it
|
||||
qualified_class_name = class_name
|
||||
|
||||
module = importlib.import_module(module_name)
|
||||
|
||||
# Header row: class name
|
||||
header_row = ET.SubElement(table, "tr")
|
||||
th = ET.SubElement(header_row, "th", colspan=str(len(jobs) + 1))
|
||||
row_anchor = f"{qualified_class_name}"
|
||||
row_anchor = f"{class_name}"
|
||||
section_header = ET.SubElement(
|
||||
ET.SubElement(th, "h2"),
|
||||
"a",
|
||||
href=f"#{row_anchor}",
|
||||
id=row_anchor,
|
||||
)
|
||||
section_header.text = qualified_class_name
|
||||
section_header.text = class_name
|
||||
append_docstring(th, getattr(module, class_name))
|
||||
|
||||
# Header row: one column for each implementation
|
||||
@ -221,7 +210,7 @@ def build_test_table(jobs: List[str], results: List[CaseResult]) -> ET.Element:
|
||||
# One row for each test:
|
||||
results_by_test = group_by(class_results, key=lambda r: r.test_name)
|
||||
for (test_name, test_results) in sorted(results_by_test.items()):
|
||||
row_anchor = f"{qualified_class_name}.{test_name}"
|
||||
row_anchor = f"{class_name}.{test_name}"
|
||||
if len(row_anchor) >= 50:
|
||||
# Too long; give up on generating readable URL
|
||||
# TODO: only hash test parameter
|
||||
@ -303,7 +292,7 @@ def write_html_pages(
|
||||
for result in results
|
||||
)
|
||||
assert is_client != is_server, (job, is_client, is_server)
|
||||
if job.endswith(("-atheme", "-anope", "-dlk")):
|
||||
if job.endswith(("-atheme", "-anope")):
|
||||
assert is_server
|
||||
job_categories[job] = "server-with-services"
|
||||
elif is_server:
|
||||
|
@ -7,18 +7,14 @@ and ban exception (`Modern <https://modern.ircdocs.horse/#exception-channel-mode
|
||||
"""
|
||||
|
||||
from irctest import cases, runner
|
||||
from irctest.numerics import (
|
||||
ERR_BANNEDFROMCHAN,
|
||||
ERR_CANNOTSENDTOCHAN,
|
||||
RPL_BANLIST,
|
||||
RPL_ENDOFBANLIST,
|
||||
)
|
||||
from irctest.numerics import ERR_BANNEDFROMCHAN, RPL_BANLIST, RPL_ENDOFBANLIST
|
||||
from irctest.patma import ANYSTR, StrRe
|
||||
|
||||
|
||||
class BanModeTestCase(cases.BaseServerTestCase):
|
||||
@cases.mark_specifications("RFC1459", "RFC2812", "Modern")
|
||||
def testBanJoin(self):
|
||||
def testBan(self):
|
||||
"""Basic ban operation"""
|
||||
self.connectClient("chanop", name="chanop")
|
||||
self.joinChannel("chanop", "#chan")
|
||||
self.getMessages("chanop")
|
||||
@ -36,55 +32,6 @@ class BanModeTestCase(cases.BaseServerTestCase):
|
||||
self.sendLine("bar", "JOIN #chan")
|
||||
self.assertMessageMatch(self.getMessage("bar"), command="JOIN")
|
||||
|
||||
@cases.mark_specifications("Modern")
|
||||
def testBanPrivmsg(self):
|
||||
"""
|
||||
TODO: this checks the following quote is false:
|
||||
|
||||
"If `<target>` is a channel name and the client is [banned](#ban-channel-mode)
|
||||
and not covered by a [ban exception](#ban-exception-channel-mode), the
|
||||
message will not be delivered and the command will silently fail."
|
||||
-- https://modern.ircdocs.horse/#privmsg-message
|
||||
|
||||
to check https://github.com/ircdocs/modern-irc/pull/201
|
||||
"""
|
||||
self.connectClient("chanop", name="chanop")
|
||||
self.joinChannel("chanop", "#chan")
|
||||
self.getMessages("chanop")
|
||||
|
||||
self.connectClient("Bar", name="bar")
|
||||
self.getMessages("bar")
|
||||
self.sendLine("bar", "JOIN #chan")
|
||||
self.getMessages("bar")
|
||||
self.getMessages("chanop")
|
||||
|
||||
self.sendLine("chanop", "MODE #chan +b bar!*@*")
|
||||
self.assertMessageMatch(self.getMessage("chanop"), command="MODE")
|
||||
self.getMessages("chanop")
|
||||
self.getMessages("bar")
|
||||
|
||||
self.sendLine("bar", "PRIVMSG #chan :hello world")
|
||||
self.assertMessageMatch(
|
||||
self.getMessage("bar"),
|
||||
command=ERR_CANNOTSENDTOCHAN,
|
||||
params=["Bar", "#chan", ANYSTR],
|
||||
)
|
||||
self.assertEqual(self.getMessages("bar"), [])
|
||||
self.assertEqual(self.getMessages("chanop"), [])
|
||||
|
||||
self.sendLine("chanop", "MODE #chan -b bar!*@*")
|
||||
self.assertMessageMatch(self.getMessage("chanop"), command="MODE")
|
||||
self.getMessages("chanop")
|
||||
self.getMessages("bar")
|
||||
|
||||
self.sendLine("bar", "PRIVMSG #chan :hello again")
|
||||
self.assertEqual(self.getMessages("bar"), [])
|
||||
self.assertMessageMatch(
|
||||
self.getMessage("chanop"),
|
||||
command="PRIVMSG",
|
||||
params=["#chan", "hello again"],
|
||||
)
|
||||
|
||||
@cases.mark_specifications("Modern")
|
||||
def testBanList(self):
|
||||
"""`RPL_BANLIST <https://modern.ircdocs.horse/#rplbanlist-367>`_"""
|
||||
|
@ -178,14 +178,6 @@ class SaslTestCase(cases.BaseServerTestCase):
|
||||
),
|
||||
"Anope does not handle split AUTHENTICATE (reported on IRC)",
|
||||
)
|
||||
@cases.xfailIf(
|
||||
lambda self: (
|
||||
self.controller.services_controller is not None
|
||||
and self.controller.services_controller.software_name == "Dlk-Services"
|
||||
),
|
||||
"Dlk does not handle split AUTHENTICATE "
|
||||
"https://github.com/DalekIRC/Dalek-Services/issues/28",
|
||||
)
|
||||
def testPlainLarge(self):
|
||||
"""Test the client splits large AUTHENTICATE messages whose payload
|
||||
is not a multiple of 400.
|
||||
|
@ -37,8 +37,8 @@ class BaseWhoTestCase:
|
||||
self.sendLine(1, f"USER {self.username} 0 * :{self.realname}")
|
||||
if auth:
|
||||
self.sendLine(1, "CAP END")
|
||||
self.getRegistrationMessage(1)
|
||||
self.skipToWelcome(1)
|
||||
self.getMessages(1)
|
||||
self.sendLine(1, "JOIN #chan")
|
||||
|
||||
self.getMessages(1)
|
||||
|
@ -71,10 +71,7 @@ class _WhoisTestMixin(cases.BaseServerTestCase):
|
||||
last_message,
|
||||
command=RPL_ENDOFWHOIS,
|
||||
params=["nick1", "nick2", ANYSTR],
|
||||
fail_msg=(
|
||||
f"Expected RPL_ENDOFWHOIS ({RPL_ENDOFWHOIS}) as last message, "
|
||||
f"got {{msg}}"
|
||||
),
|
||||
fail_msg=f"Last message was not RPL_ENDOFWHOIS ({RPL_ENDOFWHOIS})",
|
||||
)
|
||||
|
||||
unexpected_messages = []
|
||||
|
@ -98,7 +98,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
|
||||
"Servers MUST reply with either ERR_WASNOSUCHNICK or [...],
|
||||
both followed with RPL_ENDOFWHOWAS"
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
self.connectClient("nick1")
|
||||
|
||||
@ -210,7 +210,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
"The history is searched backward, returning the most recent entry first."
|
||||
-- https://datatracker.ietf.org/doc/html/rfc1459#section-4.5.3
|
||||
-- https://datatracker.ietf.org/doc/html/rfc2812#section-3.6.3
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
self._testWhowasMultiple(second_result=True, whowas_command="WHOWAS nick2")
|
||||
|
||||
@ -224,7 +224,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
"If there are multiple entries, up to <count> replies will be returned"
|
||||
-- https://datatracker.ietf.org/doc/html/rfc1459#section-4.5.3
|
||||
-- https://datatracker.ietf.org/doc/html/rfc2812#section-3.6.3
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
self._testWhowasMultiple(second_result=False, whowas_command="WHOWAS nick2 1")
|
||||
|
||||
@ -238,7 +238,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
"If there are multiple entries, up to <count> replies will be returned"
|
||||
-- https://datatracker.ietf.org/doc/html/rfc1459#section-4.5.3
|
||||
-- https://datatracker.ietf.org/doc/html/rfc2812#section-3.6.3
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
self._testWhowasMultiple(second_result=True, whowas_command="WHOWAS nick2 2")
|
||||
|
||||
@ -253,10 +253,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
is done."
|
||||
-- https://datatracker.ietf.org/doc/html/rfc1459#section-4.5.3
|
||||
-- https://datatracker.ietf.org/doc/html/rfc2812#section-3.6.3
|
||||
|
||||
"If given, <count> SHOULD be a positive number. Otherwise, a full search
|
||||
"is done.
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
self._testWhowasMultiple(second_result=True, whowas_command="WHOWAS nick2 -1")
|
||||
|
||||
@ -274,10 +271,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
is done."
|
||||
-- https://datatracker.ietf.org/doc/html/rfc1459#section-4.5.3
|
||||
-- https://datatracker.ietf.org/doc/html/rfc2812#section-3.6.3
|
||||
|
||||
"If given, <count> SHOULD be a positive number. Otherwise, a full search
|
||||
"is done.
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
self._testWhowasMultiple(second_result=True, whowas_command="WHOWAS nick2 0")
|
||||
|
||||
@ -286,7 +280,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
"""
|
||||
"Wildcards are allowed in the <target> parameter."
|
||||
-- https://datatracker.ietf.org/doc/html/rfc2812#section-3.6.3
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
if self.controller.software_name == "Bahamut":
|
||||
raise runner.OptionalExtensionNotSupported("WHOWAS mask")
|
||||
@ -330,7 +324,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
"""
|
||||
"If the `<nick>` argument is missing, they SHOULD send a single reply, using
|
||||
either ERR_NONICKNAMEGIVEN or ERR_NEEDMOREPARAMS"
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
# But no one seems to follow this. Most implementations use ERR_NEEDMOREPARAMS
|
||||
# instead of ERR_NONICKNAMEGIVEN; and I couldn't find any that returns
|
||||
@ -364,7 +358,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
"""
|
||||
https://datatracker.ietf.org/doc/html/rfc1459#section-4.5.3
|
||||
https://datatracker.ietf.org/doc/html/rfc2812#section-3.6.3
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
|
||||
and:
|
||||
|
||||
@ -377,7 +371,7 @@ class WhowasTestCase(cases.BaseServerTestCase):
|
||||
|
||||
"Servers MUST reply with either ERR_WASNOSUCHNICK or [...],
|
||||
both followed with RPL_ENDOFWHOWAS"
|
||||
-- https://modern.ircdocs.horse/#whowas-message
|
||||
-- https://github.com/ircdocs/modern-irc/pull/170
|
||||
"""
|
||||
self.connectClient("nick1")
|
||||
|
||||
|
@ -146,7 +146,7 @@ def get_test_job(*, config, test_config, test_id, version_flavor, jobs):
|
||||
for software_id in test_config.get("software", []):
|
||||
software_config = config["software"][software_id]
|
||||
|
||||
env += software_config.get("env", "") + " "
|
||||
env += test_config.get("env", {}).get(version_flavor.value, "") + " "
|
||||
if "prefix" in software_config:
|
||||
env += (
|
||||
f"PATH={software_config['prefix']}/sbin"
|
||||
|
@ -304,7 +304,6 @@ software:
|
||||
|
||||
#############################
|
||||
# Services:
|
||||
|
||||
anope:
|
||||
name: Anope
|
||||
repository: anope/anope
|
||||
@ -322,24 +321,6 @@ software:
|
||||
make -C build -j 4
|
||||
make -C build install
|
||||
|
||||
dlk:
|
||||
name: Dlk
|
||||
repository: DalekIRC/Dalek-Services
|
||||
separate_build_job: false
|
||||
path: Dlk-Services
|
||||
refs:
|
||||
stable: &dlk_stable "effd18652fc1c847d1959089d9cca9ff9837a8c0"
|
||||
release: *dlk_stable
|
||||
devel: "main"
|
||||
devel_release: *dlk_stable
|
||||
build_script: |
|
||||
pip install pifpaf
|
||||
wget -q https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
wget -q https://wordpress.org/latest.zip -O wordpress-latest.zip
|
||||
env: >-
|
||||
IRCTEST_DLK_PATH="${{ github.workspace }}/Dlk-Services"
|
||||
IRCTEST_WP_CLI_PATH="${{ github.workspace }}/wp-cli.phar"
|
||||
IRCTEST_WP_ZIP_PATH="${{ github.workspace }}/wordpress-latest.zip"
|
||||
|
||||
|
||||
#############################
|
||||
@ -444,9 +425,6 @@ tests:
|
||||
unrealircd-anope:
|
||||
software: [unrealircd, anope]
|
||||
|
||||
unrealircd-dlk:
|
||||
software: [unrealircd, dlk]
|
||||
|
||||
|
||||
limnoria:
|
||||
software: [limnoria]
|
||||
|
Reference in New Issue
Block a user