Files
netbox-plugin-dns-bridge/netbox_dns_bridge/tests/test_utils.py
T
sven 4ad110ca53 new file: conftest.py
new file:   netbox_dns_bridge/tests/__init__.py
new file:   netbox_dns_bridge/tests/_helpers.py
new file:   netbox_dns_bridge/tests/conftest.py
new file:   netbox_dns_bridge/tests/test_bootstrap.py
new file:   netbox_dns_bridge/tests/test_catalog_zone_manager.py
new file:   netbox_dns_bridge/tests/test_dns_server.py
new file:   netbox_dns_bridge/tests/test_management_commands.py
new file:   netbox_dns_bridge/tests/test_models.py
new file:   netbox_dns_bridge/tests/test_notify_handler.py
new file:   netbox_dns_bridge/tests/test_request_handler_integration.py
new file:   netbox_dns_bridge/tests/test_request_handler_unit.py
new file:   netbox_dns_bridge/tests/test_signals.py
new file:   netbox_dns_bridge/tests/test_smoke.py
new file:   netbox_dns_bridge/tests/test_utils.py
new file:   netbox_dns_bridge/tests/test_views.py
modified:   pyproject.toml
Add some tests. #AI generated
2026-08-12 12:25:46 +02:00

210 lines
8.5 KiB
Python

"""Tests for netbox_dns_bridge.utils: get_logger, build_dns_zone, export_bind_zone_file."""
import os
import tempfile
import dns.name
import dns.rdatatype
import dns.rdataclass
import pytest
from netbox_dns_bridge.utils import get_logger, build_dns_zone, export_bind_zone_file
class TestGetLogger:
def test_returns_dns_bridge_logger(self):
logger = get_logger("some.module")
assert logger.name == "dns-bridge"
def test_ignores_name_argument(self):
a = get_logger("module.a")
b = get_logger("module.b")
assert a is b
assert a.name == "dns-bridge"
def test_logger_is_singleton(self):
import logging
logger = get_logger("x")
assert logger is logging.getLogger("dns-bridge")
@pytest.mark.django_db
class TestBuildDnsZone:
def test_basic_a_record(self, make_zone, make_record):
zone = make_zone(name="a.test")
make_record(zone, name="www", type_="A", value="192.0.2.1")
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("a.test", dns.name.root)
rds = dns_zone.get_rdataset(origin, dns.rdatatype.SOA)
assert rds is not None
a_rds = dns_zone.get_rdataset(
dns.name.from_text("www", origin), dns.rdatatype.A
)
assert a_rds is not None
assert str(a_rds[0]) == "192.0.2.1"
def test_apex_record_empty_name(self, make_zone, make_record):
zone = make_zone(name="apex.test")
make_record(zone, name="@", type_="A", value="192.0.2.10")
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("apex.test", dns.name.root)
a_rds = dns_zone.get_rdataset(origin, dns.rdatatype.A)
assert a_rds is not None
assert str(a_rds[0]) == "192.0.2.10"
def test_ttl_fallback_to_zone_default(self, make_zone, make_record):
zone = make_zone(name="ttl.test", default_ttl=7200)
make_record(zone, name="host", type_="A", value="192.0.2.2", ttl=None)
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("ttl.test", dns.name.root)
a_rds = dns_zone.get_rdataset(
dns.name.from_text("host", origin), dns.rdatatype.A
)
assert a_rds.ttl == 7200
def test_record_ttl_overrides_zone_default(self, make_zone, make_record):
zone = make_zone(name="ttl2.test", default_ttl=7200)
make_record(zone, name="host", type_="A", value="192.0.2.3", ttl=300)
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("ttl2.test", dns.name.root)
a_rds = dns_zone.get_rdataset(
dns.name.from_text("host", origin), dns.rdatatype.A
)
assert a_rds.ttl == 300
def test_txt_record_quoting(self, make_zone, make_record):
zone = make_zone(name="txt.test")
make_record(zone, name="spf", type_="TXT", value="v=spf1 -all")
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("txt.test", dns.name.root)
txt_rds = dns_zone.get_rdataset(
dns.name.from_text("spf", origin), dns.rdatatype.TXT
)
assert txt_rds is not None
assert str(txt_rds[0]) == '"v=spf1 -all"'
def test_txt_record_already_quoted(self, make_zone, make_record):
zone = make_zone(name="txtq.test")
make_record(zone, name="dkim", type_="TXT", value='"k=rsa; p=MIGf"')
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("txtq.test", dns.name.root)
txt_rds = dns_zone.get_rdataset(
dns.name.from_text("dkim", origin), dns.rdatatype.TXT
)
assert txt_rds is not None
assert "k=rsa" in str(txt_rds[0])
def test_txt_record_long_value_chunked(self, make_zone, make_record):
zone = make_zone(name="longtxt.test")
long_val = "a" * 300
make_record(zone, name="big", type_="TXT", value=long_val)
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("longtxt.test", dns.name.root)
txt_rds = dns_zone.get_rdataset(
dns.name.from_text("big", origin), dns.rdatatype.TXT
)
assert txt_rds is not None
wire = str(txt_rds[0])
assert "a" * 300 in wire.replace('"', "").replace(" ", "")
def test_absolute_name_record(self, make_zone, make_record):
zone = make_zone(name="abs.test")
make_record(zone, name="out.abs.test.", type_="A", value="192.0.2.99")
dns_zone = build_dns_zone(zone)
abs_name = dns.name.from_text("out.abs.test", dns.name.root)
a_rds = dns_zone.get_rdataset(abs_name, dns.rdatatype.A)
assert a_rds is not None
assert str(a_rds[0]) == "192.0.2.99"
def test_multiple_records_same_name_type(self, make_zone, make_record):
zone = make_zone(name="multi.test")
make_record(zone, name="lb", type_="A", value="192.0.2.1")
make_record(zone, name="lb", type_="A", value="192.0.2.2")
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("multi.test", dns.name.root)
a_rds = dns_zone.get_rdataset(
dns.name.from_text("lb", origin), dns.rdatatype.A
)
assert a_rds is not None
assert len(a_rds) == 2
values = {str(r) for r in a_rds}
assert values == {"192.0.2.1", "192.0.2.2"}
def test_inactive_records_excluded(self, make_zone, make_record):
from netbox_dns.choices import RecordStatusChoices
zone = make_zone(name="inactive.test")
make_record(zone, name="active", type_="A", value="192.0.2.1",
status=RecordStatusChoices.STATUS_ACTIVE)
make_record(zone, name="inactive", type_="A", value="192.0.2.2",
status=RecordStatusChoices.STATUS_INACTIVE)
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("inactive.test", dns.name.root)
assert dns_zone.get_rdataset(
dns.name.from_text("active", origin), dns.rdatatype.A
) is not None
assert dns_zone.get_rdataset(
dns.name.from_text("inactive", origin), dns.rdatatype.A
) is None
def test_zone_rdclass_is_in(self, make_zone, make_record):
zone = make_zone(name="rdclass.test")
make_record(zone, name="x", type_="A", value="192.0.2.1")
dns_zone = build_dns_zone(zone)
assert dns_zone.rdclass == dns.rdataclass.IN
def test_aaaa_record(self, make_zone, make_record):
zone = make_zone(name="aaaa.test")
make_record(zone, name="v6", type_="AAAA", value="2001:db8::1")
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("aaaa.test", dns.name.root)
aaaa_rds = dns_zone.get_rdataset(
dns.name.from_text("v6", origin), dns.rdatatype.AAAA
)
assert aaaa_rds is not None
assert str(aaaa_rds[0]) == "2001:db8::1"
def test_cname_record(self, make_zone, make_record):
zone = make_zone(name="cname.test")
make_record(zone, name="alias", type_="CNAME", value="target.test.")
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("cname.test", dns.name.root)
cnames = dns_zone.get_rdataset(
dns.name.from_text("alias", origin), dns.rdatatype.CNAME
)
assert cnames is not None
assert str(cnames[0]) == "target.test."
def test_mx_record(self, make_zone, make_record):
zone = make_zone(name="mx.test")
make_record(zone, name="@", type_="MX", value="10 mail.test.")
dns_zone = build_dns_zone(zone)
origin = dns.name.from_text("mx.test", dns.name.root)
mx_rds = dns_zone.get_rdataset(origin, dns.rdatatype.MX)
assert mx_rds is not None
assert mx_rds[0].preference == 10
assert str(mx_rds[0].exchange) == "mail.test."
@pytest.mark.django_db
class TestExportBindZoneFile:
def test_writes_valid_zone_file(self, make_zone, make_record):
zone = make_zone(name="export.test")
make_record(zone, name="www", type_="A", value="192.0.2.1")
with tempfile.NamedTemporaryFile(mode="w", suffix=".zone", delete=False) as f:
path = f.name
try:
export_bind_zone_file(zone, path)
with open(path) as f:
content = f.read()
assert "SOA" in content
assert "192.0.2.1" in content
assert "www" in content
finally:
os.unlink(path)
def test_io_error_on_bad_path(self, make_zone):
zone = make_zone(name="badpath.test")
with pytest.raises(IOError):
export_bind_zone_file(zone, "/nonexistent/dir/zone.file")