--- /dev/null
+/.cache/
+/__pycache__/
rm -f traffic traffic.out.* traffic.json.* traffic.xml.*
rm -f zones zones.out.* zones.json.* zones.xml.* zones.expect.*
rm -f dig.out*
-rm -f */named.memstats
-rm -f */named.conf
-rm -f */named.run*
+rm -f ns*/named.memstats
+rm -f ns*/named.conf
+rm -f ns*/named.run*
rm -f ns*/named.lock
rm -f ns*/named.stats
rm -f xml.*stats json.*stats
rm -f ns2/Kdnssec* ns2/dnssec.*.id
rm -f ns2/Kmanykeys* ns2/manykeys.*.id
rm -f ns2/*.db.signed* ns2/dsset-*. ns2/*.jbk
-rm -f ns2/core
+rm -f ns2/dnssec.db.signed* ns2/dsset-dnssec.
+rm -f ns3/*.db
+rm -rf /.cache /__pycache__
--- /dev/null
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import pytest
+import os
+
+def pytest_configure(config):
+ config.addinivalue_line(
+ "markers", "requests: mark tests that need requests to function"
+ )
+ config.addinivalue_line(
+ "markers", "json: mark tests that need json to function"
+ )
+ config.addinivalue_line(
+ "markers", "xml: mark tests that need xml.etree to function"
+ )
+
+
+def pytest_collection_modifyitems(config, items):
+ # Test for requests module
+ skip_requests = pytest.mark.skip(reason="need requests module to run")
+ try:
+ import requests # noqa: F401
+ except ModuleNotFoundError:
+ for item in items:
+ if "requests" in item.keywords:
+ item.add_marker(skip_requests)
+ # Test for json module
+ skip_json = pytest.mark.skip(reason="need json module to run")
+ try:
+ import json # noqa: F401
+ except ModuleNotFoundError:
+ for item in items:
+ if "json" in item.keywords:
+ item.add_marker(skip_json)
+ # Test for xml module
+ skip_xml = pytest.mark.skip(reason="need xml module to run")
+ try:
+ import xml # noqa: F401
+ except ModuleNotFoundError:
+ for item in items:
+ if "xml" in item.keywords:
+ item.add_marker(skip_xml)
+ # Test if JSON statistics channel was enabled
+ no_jsonstats = pytest.mark.skip(reason="need JSON statistics to be enabled")
+ if os.getenv("HAVEJSONSTATS") is None:
+ for item in items:
+ if "json" in item.keywords:
+ item.add_marker(no_jsonstats)
+ # Test if XML statistics channel was enabled
+ no_xmlstats = pytest.mark.skip(reason="need XML statistics to be enabled")
+ if os.getenv("HAVEXMLSTATS") is None:
+ for item in items:
+ if "xml" in item.keywords:
+ item.add_marker(no_xmlstats)
+
+
+@pytest.fixture
+def statsport(request):
+ port = os.getenv("EXTRAPORT1")
+ if port is None:
+ port = 5301
+ else:
+ port = int(port)
+
+ return port
--- /dev/null
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+from datetime import datetime, timedelta
+
+# ISO datetime format without msec
+fmt = '%Y-%m-%dT%H:%M:%SZ'
+
+# The constants were taken from BIND 9 source code (lib/dns/zone.c)
+max_refresh = timedelta(seconds=2419200) # 4 weeks
+max_expires = timedelta(seconds=14515200) # 24 weeks
+now = datetime.utcnow().replace(microsecond=0)
+dayzero = datetime.utcfromtimestamp(0).replace(microsecond=0)
+
+
+# Generic helper functions
+def check_expires(expires, min, max):
+ assert expires >= min
+ assert expires <= max
+
+
+def check_refresh(refresh, min, max):
+ assert refresh >= min
+ assert refresh <= max
+
+
+def check_loaded(loaded, expected):
+ # Sanity check the zone timers values
+ assert loaded == expected
+ assert loaded < now
+
+
+def check_zone_timers(loaded, expires, refresh, loaded_exp):
+ # Sanity checks the zone timers values
+ if expires is not None:
+ check_expires(expires, now, now + max_expires)
+ if refresh is not None:
+ check_refresh(refresh, now, now + max_refresh)
+ check_loaded(loaded, loaded_exp)
+
+
+def zone_mtime(zonedir, name):
+ import os
+ import os.path
+ from datetime import datetime
+
+ si = os.stat(os.path.join(zonedir, "{}.db".format(name)))
+ mtime = datetime.utcfromtimestamp(si.st_mtime).replace(microsecond=0)
+
+ return mtime
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+short TXT "short text"
+long TXT (
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ "longlonglonglonglonglonglonglonglonglong"
+ )
+
+mail A 10.0.0.2
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify explicit;
+ minimal-responses no;
+ version none; // make statistics independent of the version number
+};
+
+statistics-channels { inet 10.53.0.1 port @EXTRAPORT1@ allow { localhost; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-transfer { any; };
+};
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
recursion no;
- notify yes;
+ notify no;
minimal-responses no;
version none; // make statistics independent of the version number
};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ minimal-responses no;
+ version none; // make statistics independent of the version number
+};
+
+statistics-channels { inet 10.53.0.3 port @EXTRAPORT1@ allow { localhost; }; };
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type secondary;
+ file "example.db";
+ masters { 10.53.0.1; };
+};
# shellcheck source=conf.sh
. "$SYSTEMTESTTOP/conf.sh"
-copy_setports ns2/named.conf.in ns2/named.conf
+for conf in ns*/named.conf.in; do
+ copy_setports "$conf" "$(dirname "$conf")/$(basename "$conf" .in)"
+done
-(
- cd ns2
- $SHELL sign.sh
-)
+(cd ns2 && $SHELL sign.sh)
--- /dev/null
+#!/usr/bin/python3
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import pytest
+from datetime import datetime
+from helper import fmt, zone_mtime, check_zone_timers, dayzero
+
+
+# JSON helper functions
+def fetch_json(statsip, statsport):
+ import requests
+
+ r = requests.get("http://{}:{}/json/v1/zones".format(statsip, statsport))
+ assert r.status_code == 200
+
+ data = r.json()
+
+ return data["views"]["_default"]["zones"]
+
+
+def load_timers_from_json(zone, primary=True):
+ name = zone['name']
+
+ # Check if the primary zone timer exists
+ assert 'loaded' in zone
+ loaded = datetime.strptime(zone['loaded'], fmt)
+
+ if primary:
+ # Check if the secondary zone timers does not exist
+ assert 'expires' not in zone
+ assert 'refresh' not in zone
+ expires = None
+ refresh = None
+ else:
+ assert 'expires' in zone
+ assert 'refresh' in zone
+ expires = datetime.strptime(zone['expires'], fmt)
+ refresh = datetime.strptime(zone['refresh'], fmt)
+
+ return (name, loaded, expires, refresh)
+
+
+@pytest.mark.json
+@pytest.mark.requests
+def test_zone_timers_primary_json(statsport):
+ statsip = "10.53.0.1"
+ zonedir = "ns1"
+
+ zones = fetch_json(statsip, statsport)
+
+ for zone in zones:
+ (name, loaded, expires, refresh) = load_timers_from_json(zone, True)
+ mtime = zone_mtime(zonedir, name)
+ check_zone_timers(loaded, expires, refresh, mtime)
+
+
+@pytest.mark.json
+@pytest.mark.requests
+def test_zone_timers_secondary_json(statsport):
+ statsip = "10.53.0.3"
+
+ zones = fetch_json(statsip, statsport)
+
+ for zone in zones:
+ (name, loaded, expires, refresh) = load_timers_from_json(zone, False)
+ check_zone_timers(loaded, expires, refresh, dayzero)
--- /dev/null
+#!/usr/bin/python3
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+import pytest
+from datetime import datetime
+from helper import fmt, zone_mtime, check_zone_timers, dayzero
+
+
+# XML helper functions
+def fetch_xml(statsip, statsport):
+ import xml.etree.ElementTree as ET
+ import requests
+
+ r = requests.get("http://{}:{}/xml/v3/zones".format(statsip, statsport))
+ assert r.status_code == 200
+
+ root = ET.fromstring(r.text)
+
+ default_view = None
+ for view in root.find('views').iter('view'):
+ if view.attrib['name'] == "_default":
+ default_view = view
+ break
+ assert default_view is not None
+
+ return default_view.find('zones').findall('zone')
+
+
+def load_timers_from_xml(zone, primary=True):
+ name = zone.attrib['name']
+
+ loaded_el = zone.find('loaded')
+ assert loaded_el is not None
+ loaded = datetime.strptime(loaded_el.text, fmt)
+
+ expires_el = zone.find('expires')
+ refresh_el = zone.find('refresh')
+ if primary:
+ assert expires_el is None
+ assert refresh_el is None
+ expires = None
+ refresh = None
+ else:
+ assert expires_el is not None
+ assert refresh_el is not None
+ expires = datetime.strptime(expires_el.text, fmt)
+ refresh = datetime.strptime(refresh_el.text, fmt)
+
+ return (name, loaded, expires, refresh)
+
+
+@pytest.mark.xml
+@pytest.mark.requests
+def test_zone_timers_primary_xml(statsport):
+ statsip = "10.53.0.1"
+ zonedir = "ns1"
+
+ zones = fetch_xml(statsip, statsport)
+
+ for zone in zones:
+ (name, loaded, expires, refresh) = load_timers_from_xml(zone, True)
+ mtime = zone_mtime(zonedir, name)
+ check_zone_timers(loaded, expires, refresh, mtime)
+
+
+@pytest.mark.xml
+@pytest.mark.requests
+def test_zone_timers_secondary_xml(statsport):
+ statsip = "10.53.0.3"
+
+ zones = fetch_xml(statsip, statsport)
+
+ for zone in zones:
+ (name, loaded, expires, refresh) = load_timers_from_xml(zone, False)
+ check_zone_timers(loaded, expires, refresh, dayzero)
./bin/tests/system/statistics/setup.sh SH 2018,2019,2020
./bin/tests/system/statistics/tests.sh SH 2012,2015,2016,2017,2018,2019,2020
./bin/tests/system/statschannel/clean.sh SH 2015,2016,2017,2018,2019,2020
+./bin/tests/system/statschannel/conftest.py PYTHON 2020
./bin/tests/system/statschannel/fetch.pl PERL 2015,2016,2018,2019,2020
+./bin/tests/system/statschannel/helper.py PYTHON 2020
./bin/tests/system/statschannel/mem-xml.pl PERL 2017,2018,2019,2020
./bin/tests/system/statschannel/ns2/sign.sh SH 2019,2020
./bin/tests/system/statschannel/server-json.pl PERL 2015,2016,2017,2018,2019,2020
./bin/tests/system/statschannel/server-xml.pl PERL 2015,2016,2017,2018,2019,2020
./bin/tests/system/statschannel/setup.sh SH 2018,2019,2020
+./bin/tests/system/statschannel/tests-json.py PYTHON-BIN 2020
+./bin/tests/system/statschannel/tests-xml.py PYTHON-BIN 2020
./bin/tests/system/statschannel/tests.sh SH 2015,2016,2017,2018,2019,2020
./bin/tests/system/statschannel/traffic-json.pl PERL 2015,2016,2017,2018,2019,2020
./bin/tests/system/statschannel/traffic-xml.pl PERL 2015,2016,2017,2018,2019,2020