Skip to content

Commit

Permalink
test (all): to add tests for records, zones load, server and resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrey-Ved committed Dec 24, 2023
1 parent a987541 commit 997b1f1
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 6 deletions.
10 changes: 5 additions & 5 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@


def add_path(
additional_path: str | Path,
file_name: str | Path
file_name: str | Path,
additional_path: str | Path | None = None,
) -> str:
root_path = dirname(
dirname(
Expand All @@ -30,13 +30,13 @@ def settings_init(
configs_dir: str | Path,
):
dynaconf = Dynaconf(
settings_files=[add_path(configs_dir, config_file), ],
settings_files=[add_path(config_file, configs_dir), ],
load_dotenv=True,
envvar_prefix=False,
dotenv_path=add_path(configs_dir, dotenv_file)
dotenv_path=add_path(dotenv_file, configs_dir)
)

dynaconf.dns.zones_file = add_path(configs_dir, dynaconf.dns.zones_file)
dynaconf.dns.zones_file = add_path(dynaconf.dns.zones_file, configs_dir)
dynaconf.dns.cache_expiration_time_s = dynaconf.dns.cache_expiration_time_m * 60

dynaconf.redis.secret = dynaconf.redis_secret
Expand Down
7 changes: 7 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[pytest]
pythonpath = . app test
python_files = *_test.py *_tests.py test_*.py

markers =
smoke: mark as smoke
regress: mark as regress
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ pytest==7.4.3
dnslib==0.9.23
dynaconf==3.2.4
redis==5.0.1
cryptography==41.0.7
cryptography==41.0.7
dnspython==2.4.2
Empty file added tests/__init__.py
Empty file.
66 changes: 66 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import pytest

from dns.resolver import Resolver as RawResolver
from typing import Any, Dict, List

from app.config import add_path
from app.dns.server import DNSServer


def convert_answer(answer) -> Dict[str, Any]:
rd_type = answer.rdtype.name
d = {'type': rd_type}
if rd_type == 'MX':
d.update(
preference=answer.preference,
value=answer.exchange.to_text(),
)
elif rd_type == 'SOA':
d.update(
rname=str(answer.rname.choose_relativity()),
mname=str(answer.mname.choose_relativity()),
serial=answer.serial,
refresh=answer.refresh,
retry=answer.retry,
expire=answer.expire,
minimum=answer.minimum,
)
else:
d['value'] = answer.to_text()
return d


@pytest.fixture(scope="session")
def zones_file():
return add_path('test_zones.json', 'tests')


@pytest.fixture(scope='session')
def dns_server(zones_file):
port = 5053
upstream = '8.8.8.8'
cache = {}

server = DNSServer.from_file(
port=port,
upstream=upstream,
cache=cache,
zones_file=zones_file,
)
server.start()
assert server.is_running
yield server
server.stop()


@pytest.fixture(scope='session')
def dns_resolver(dns_server: DNSServer):
resolver = RawResolver()
resolver.nameservers = ['127.0.0.1']
resolver.port = dns_server.port

def resolve(name: str, type_: str) -> List[Dict[str, Any]]:
answers = resolver.resolve(name, type_)
return [convert_answer(answer) for answer in answers]

yield resolve
14 changes: 14 additions & 0 deletions tests/test_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"dns": {
"upstream": "8.8.8.8",
"port": 53,
"zones_file": "test_zones.json",
"cache_expiration_time_m": 30
},
"redis": {
"host": "localhost",
"port": 6379,
"db": 0,
"prefix": "test-dns-serv>>> "
}
}
38 changes: 38 additions & 0 deletions tests/test_load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from app.dns.load_records import load_records, Records, Zone
from app.dns.record import Record


def test_load_records(zones_file):
records = load_records(zones_file)

assert records == Records(
zones=[
Zone(host='example.com', type='A', answer='1.2.3.4'),
Zone(host='example.com', type='A', answer='1.2.3.4'),
Zone(host='example.com', type='CNAME', answer='whatever.com'),
Zone(host='example.com', type='MX', answer=['whatever.com.', 5]),
Zone(host='example.com', type='MX', answer=['mx2.whatever.com.', 10]),
Zone(host='example.com', type='MX', answer=['mx3.whatever.com.', 20]),
Zone(host='example.com', type='NS', answer='ns1.whatever.com.'),
Zone(host='example.com', type='NS', answer='ns2.whatever.com.'),
Zone(host='example.com', type='TXT', answer='hello this is some text'),
Zone(host='example.com', type='SOA', answer=['ns1.example.com', 'dns.example.com']),
Zone(
host='testing.com',
type='TXT',
answer=(
'one long value: IICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgFWZUed1qcBziAsqZ/LzT2ASxJYuJ5sko1CzWFhFu'
'xiluNnwKjSknSjanyYnm0vro4dhAtyiQ7OPVROOaNy9Iyklvu91KuhbYi6l80Rrdnuq1yjM//xjaB6DGx8+m1ENML8PEdSFbK'
'Qbh9akm2bkNw5DC5a8Slp7j+eEVHkgV3k3oRhkPcrKyoPVvniDNH+Ln7DnSGC+Aw5Sp+fhu5aZmoODhhX5/1mANBgkqhkiG9w'
'0BAQEFAAOCAg8AMIICCgKCAgEA26JaFWZUed1qcBziAsqZ/LzTF2ASxJYuJ5sk'
),
),
Zone(host='_caldavs._tcp.example.com', type='SRV', answer=[0, 1, 80, 'caldav']),
Zone(host='e56.com', type='A', answer='2.3.4.5'),
],
)


def test_create_server(zones_file):
records = load_records(zones_file)
[Record(zone) for zone in records.zones]
110 changes: 110 additions & 0 deletions tests/test_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import pytest

from dirty_equals import IsIP, IsPositive
from dns.resolver import NXDOMAIN
from typing import Any, Callable, Dict, List

from app.dns.load_records import Zone
from app.dns.server import DNSServer


Resolver = Callable[[str, str], List[Dict[str, Any]]]


def test_a_record(dns_resolver: Resolver):
assert dns_resolver('example.com', 'A') == [
{
'type': 'A',
'value': '1.2.3.4',
},
]


def test_cname_record(dns_resolver: Resolver):
assert dns_resolver('example.com', 'CNAME') == [
{
'type': 'CNAME',
'value': 'whatever.com.',
},
]


def test_mx_record(dns_resolver: Resolver):
assert dns_resolver('example.com', 'MX') == [
{
'type': 'MX',
'preference': 5,
'value': 'whatever.com.',
},
{
'type': 'MX',
'preference': 10,
'value': 'mx2.whatever.com.',
},
{
'type': 'MX',
'preference': 20,
'value': 'mx3.whatever.com.',
},
]


def test_proxy(dns_resolver: Resolver):
assert dns_resolver('example.org', 'A') == [
{
'type': 'A',
'value': IsIP(version=4),
},
]


def test_soa(dns_resolver: Resolver):
assert dns_resolver('example.com', 'SOA') == [
{
'type': 'SOA',
'rname': 'dns.example.com.',
'mname': 'ns1.example.com.', # noqa
'serial': IsPositive(),
'refresh': 3600,
'retry': 10800,
'expire': 86400,
'minimum': 3600,
}
]


def test_dynamic_zone_update(dns_server: DNSServer, dns_resolver: Resolver):
assert dns_resolver('example.com', 'A') == [
{
'type': 'A',
'value': '1.2.3.4',
},
]
with pytest.raises(NXDOMAIN):
dns_resolver('another-example.org', 'A')

dns_server.add_record(Zone(host='another-example.com', type='A', answer='2.3.4.5'))

assert dns_resolver('example.com', 'A') == [
{
'type': 'A',
'value': '1.2.3.4',
},
]
assert dns_resolver('another-example.com', 'A') == [
{
'type': 'A',
'value': '2.3.4.5',
},
]

dns_server.set_records([Zone(host='example.com', type='A', answer='4.5.6.7')])

assert dns_resolver('example.com', 'A') == [
{
'type': 'A',
'value': '4.5.6.7',
},
]
with pytest.raises(NXDOMAIN):
dns_resolver('another-example.org', 'A')
86 changes: 86 additions & 0 deletions tests/test_zones.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"zones": [
{
"host": "example.com",
"type": "A",
"answer": "1.2.3.4"
},
{
"host": "example.com",
"type": "A",
"answer": "1.2.3.4"
},
{
"host": "example.com",
"type": "CNAME",
"answer": "whatever.com"
},
{
"host": "example.com",
"type": "MX",
"answer": [
"whatever.com.",
5
]
},
{
"host": "example.com",
"type": "MX",
"answer": [
"mx2.whatever.com.",
10
]
},
{
"host": "example.com",
"type": "MX",
"answer": [
"mx3.whatever.com.",
20
]
},
{
"host": "example.com",
"type": "NS",
"answer": "ns1.whatever.com."
},
{
"host": "example.com",
"type": "NS",
"answer": "ns2.whatever.com."
},
{
"host": "example.com",
"type": "TXT",
"answer": "hello this is some text"
},
{
"host": "example.com",
"type": "SOA",
"answer": [
"ns1.example.com",
"dns.example.com"
]
},
{
"host": "testing.com",
"type": "TXT",
"answer": "one long value: IICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAg\nFWZUed1qcBziAsqZ/LzT2ASxJYuJ5sko1CzWFhFuxiluNnwKjSknSjanyYnm0vro4dhAtyiQ7O\nPVROOaNy9Iyklvu91KuhbYi6l80Rrdnuq1yjM//xjaB6DGx8+m1ENML8PEdSFbKQbh9akm2bkN\nw5DC5a8Slp7j+eEVHkgV3k3oRhkPcrKyoPVvniDNH+Ln7DnSGC+Aw5Sp+fhu5aZmoODhhX5/1m\nANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA26JaFWZUed1qcBziAsqZ/LzTF2ASxJYuJ5sk\n"
},
{
"host": "_caldavs._tcp.example.com",
"type": "SRV",
"answer": [
0,
1,
80,
"caldav"
]
},
{
"host": "e56.com",
"type": "A",
"answer": "2.3.4.5"
}
]
}

0 comments on commit 997b1f1

Please sign in to comment.