Add cmd_paste to flaskpaste plugin (create paste, return URL). Add test suites for encode, hash, defang, cidr, and dns plugins (83 new test cases, 1093 total). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
170 lines
5.5 KiB
Python
170 lines
5.5 KiB
Python
"""Tests for the DNS lookup plugin."""
|
|
|
|
import asyncio
|
|
import importlib.util
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
from derp.irc import Message
|
|
|
|
# plugins/ is not a Python package -- load the module from file path
|
|
_spec = importlib.util.spec_from_file_location(
|
|
"plugins.dns", Path(__file__).resolve().parent.parent / "plugins" / "dns.py",
|
|
)
|
|
_mod = importlib.util.module_from_spec(_spec)
|
|
sys.modules[_spec.name] = _mod
|
|
_spec.loader.exec_module(_mod)
|
|
|
|
from plugins.dns import cmd_dns # noqa: E402
|
|
|
|
# -- Helpers -----------------------------------------------------------------
|
|
|
|
class _FakeBot:
|
|
def __init__(self):
|
|
self.replied: list[str] = []
|
|
|
|
async def reply(self, message, text: str) -> None:
|
|
self.replied.append(text)
|
|
|
|
|
|
def _msg(text: str) -> Message:
|
|
return Message(
|
|
raw="", prefix="alice!~alice@host", nick="alice",
|
|
command="PRIVMSG", params=["#test", text], tags={},
|
|
)
|
|
|
|
|
|
def _mock_query(rcode, results):
|
|
"""Create an AsyncMock returning (rcode, results)."""
|
|
mock = AsyncMock(return_value=(rcode, results))
|
|
return mock
|
|
|
|
|
|
# -- Auto-detect type --------------------------------------------------------
|
|
|
|
class TestAutoDetect:
|
|
def test_domain_defaults_to_a(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, ["93.184.216.34"])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com")))
|
|
assert "A:" in bot.replied[0]
|
|
assert "93.184.216.34" in bot.replied[0]
|
|
|
|
def test_ip_defaults_to_ptr(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, ["dns.google"])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns 8.8.8.8")))
|
|
assert "PTR:" in bot.replied[0]
|
|
assert "dns.google" in bot.replied[0]
|
|
|
|
|
|
# -- Explicit type -----------------------------------------------------------
|
|
|
|
class TestExplicitType:
|
|
def test_mx(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, ["10 mail.example.com"])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com MX")))
|
|
assert "MX:" in bot.replied[0]
|
|
assert "mail.example.com" in bot.replied[0]
|
|
|
|
def test_aaaa(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, ["2606:2800:220:1:248:1893:25c8:1946"])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com AAAA")))
|
|
assert "AAAA:" in bot.replied[0]
|
|
|
|
def test_txt(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, ["v=spf1 -all"])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com TXT")))
|
|
assert "TXT:" in bot.replied[0]
|
|
assert "v=spf1" in bot.replied[0]
|
|
|
|
def test_case_insensitive(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, ["93.184.216.34"])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com a")))
|
|
assert "A:" in bot.replied[0]
|
|
|
|
|
|
# -- Unknown type ------------------------------------------------------------
|
|
|
|
class TestUnknownType:
|
|
def test_unknown_type(self):
|
|
bot = _FakeBot()
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com BOGUS")))
|
|
assert "Unknown type" in bot.replied[0]
|
|
|
|
|
|
# -- Invalid PTR IP ----------------------------------------------------------
|
|
|
|
class TestInvalidPtr:
|
|
def test_invalid_ip_for_ptr(self):
|
|
bot = _FakeBot()
|
|
asyncio.run(cmd_dns(bot, _msg("!dns notanip PTR")))
|
|
assert "Invalid IP for PTR" in bot.replied[0]
|
|
|
|
|
|
# -- Query results -----------------------------------------------------------
|
|
|
|
class TestQueryResults:
|
|
def test_success(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, ["93.184.216.34", "93.184.216.35"])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com")))
|
|
assert "93.184.216.34" in bot.replied[0]
|
|
assert "93.184.216.35" in bot.replied[0]
|
|
|
|
def test_timeout(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(-1, [])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com")))
|
|
assert "timeout" in bot.replied[0]
|
|
|
|
def test_network_error(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(-2, [])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com")))
|
|
assert "network error" in bot.replied[0]
|
|
|
|
def test_nxdomain(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(3, [])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns nonexistent.test")))
|
|
assert "NXDOMAIN" in bot.replied[0]
|
|
|
|
def test_no_records(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(0, [])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com AAAA")))
|
|
assert "no records" in bot.replied[0]
|
|
|
|
def test_servfail(self):
|
|
bot = _FakeBot()
|
|
mock = _mock_query(2, [])
|
|
with patch.object(_mod, "_query", mock):
|
|
asyncio.run(cmd_dns(bot, _msg("!dns example.com")))
|
|
assert "SERVFAIL" in bot.replied[0]
|
|
|
|
|
|
# -- Missing args ------------------------------------------------------------
|
|
|
|
class TestMissingArgs:
|
|
def test_no_args(self):
|
|
bot = _FakeBot()
|
|
asyncio.run(cmd_dns(bot, _msg("!dns")))
|
|
assert "Usage" in bot.replied[0]
|