mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Add reproducer for #5759
Adds a test case that runs IXFR while leaving an rdataset unchanged.
This commit is contained in:
parent
2e1971873a
commit
0041c5756e
8 changed files with 624 additions and 0 deletions
200
bin/tests/system/ixfr-nonminimal/ans2/ans.py
Normal file
200
bin/tests/system/ixfr-nonminimal/ans2/ans.py
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
"""
|
||||
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
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 https://mozilla.org/MPL/2.0/.
|
||||
|
||||
See the COPYRIGHT file distributed with this work for additional
|
||||
information regarding copyright ownership.
|
||||
"""
|
||||
|
||||
import abc
|
||||
|
||||
import dns.rcode
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from typing import AsyncGenerator, Collection, Iterable
|
||||
|
||||
from isctest.asyncserver import (
|
||||
ControllableAsyncDnsServer,
|
||||
DnsResponseSend,
|
||||
QueryContext,
|
||||
ResponseHandler,
|
||||
SwitchControlCommand,
|
||||
)
|
||||
|
||||
|
||||
def rrset(owner: str, rdtype: dns.rdatatype.RdataType, rdata: str) -> dns.rrset.RRset:
|
||||
return dns.rrset.from_text(
|
||||
owner,
|
||||
300,
|
||||
dns.rdataclass.IN,
|
||||
rdtype,
|
||||
rdata,
|
||||
)
|
||||
|
||||
|
||||
def soa(serial: int, *, owner: str = "nil.") -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
owner,
|
||||
dns.rdatatype.SOA,
|
||||
f"ns.nil. root.nil. {serial} 300 300 604800 300",
|
||||
)
|
||||
|
||||
|
||||
def ns() -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
"nil.",
|
||||
dns.rdatatype.NS,
|
||||
"ns.nil.",
|
||||
)
|
||||
|
||||
|
||||
def a(address: str, *, owner: str) -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
owner,
|
||||
dns.rdatatype.A,
|
||||
address,
|
||||
)
|
||||
|
||||
|
||||
def txt(data: str, *, owner: str = "nil.") -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
owner,
|
||||
dns.rdatatype.TXT,
|
||||
f'"{data}"',
|
||||
)
|
||||
|
||||
|
||||
class SoaHandler(ResponseHandler):
|
||||
def __init__(self, serial: int):
|
||||
self._serial = serial
|
||||
|
||||
def match(self, qctx: QueryContext) -> bool:
|
||||
return qctx.qtype == dns.rdatatype.SOA
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
qctx.response.answer.append(soa(self._serial))
|
||||
yield DnsResponseSend(qctx.response)
|
||||
|
||||
|
||||
class AxfrHandler(ResponseHandler):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def answers(self) -> Iterable[Collection[dns.rrset.RRset]]:
|
||||
"""
|
||||
Answer sections of response packets sent in response to
|
||||
AXFR queries.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def match(self, qctx: QueryContext) -> bool:
|
||||
return qctx.qtype == dns.rdatatype.AXFR
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
for answer in self.answers:
|
||||
response = qctx.prepare_new_response()
|
||||
for rrset_ in answer:
|
||||
response.answer.append(rrset_)
|
||||
yield DnsResponseSend(response)
|
||||
|
||||
|
||||
class IxfrHandler(ResponseHandler):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def answer(self) -> Collection[dns.rrset.RRset]:
|
||||
"""
|
||||
Answer section of a response packet sent in response to
|
||||
IXFR queries.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def match(self, qctx: QueryContext) -> bool:
|
||||
return qctx.qtype == dns.rdatatype.IXFR
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
for rrset_ in self.answer:
|
||||
qctx.response.answer.append(rrset_)
|
||||
yield DnsResponseSend(qctx.response)
|
||||
|
||||
|
||||
class InitialAxfrHandler(AxfrHandler):
|
||||
answers = (
|
||||
(soa(1),),
|
||||
(
|
||||
ns(),
|
||||
txt("initial AXFR"),
|
||||
a("10.0.0.61", owner="a.nil."),
|
||||
a("10.0.0.62", owner="b.nil."),
|
||||
),
|
||||
(soa(1),),
|
||||
)
|
||||
|
||||
|
||||
class InitialIxfrHandler(IxfrHandler):
|
||||
answer = (
|
||||
soa(1),
|
||||
ns(),
|
||||
txt("initial AXFR"),
|
||||
a("10.0.0.61", owner="a.nil."),
|
||||
a("10.0.0.62", owner="b.nil."),
|
||||
soa(1),
|
||||
)
|
||||
|
||||
|
||||
class UnchangedIxfrHandler(IxfrHandler):
|
||||
"""
|
||||
IXFR from serial 1 -> 2.
|
||||
|
||||
The diff deletes nothing for the A rrset at a.nil., but re-adds
|
||||
"a.nil. A 10.0.0.61" which already exists. This causes the merge
|
||||
to find no new records, triggering DNS_R_UNCHANGED.
|
||||
|
||||
We also add a new TXT record so the IXFR has at least one real
|
||||
change (the SOA serial bump + TXT addition).
|
||||
"""
|
||||
|
||||
answer = (
|
||||
soa(2),
|
||||
soa(1),
|
||||
soa(2),
|
||||
txt("unchanged ixfr test"),
|
||||
a("10.0.0.61", owner="a.nil."), # already exists -> DNS_R_UNCHANGED
|
||||
soa(2),
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = ControllableAsyncDnsServer(
|
||||
default_aa=True, default_rcode=dns.rcode.NOERROR
|
||||
)
|
||||
switch_command = SwitchControlCommand(
|
||||
{
|
||||
"initial_axfr": (
|
||||
SoaHandler(1),
|
||||
InitialIxfrHandler(),
|
||||
InitialAxfrHandler(),
|
||||
),
|
||||
"unchanged_ixfr": (
|
||||
SoaHandler(2),
|
||||
UnchangedIxfrHandler(),
|
||||
),
|
||||
}
|
||||
)
|
||||
server.install_control_command(switch_command)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
199
bin/tests/system/ixfr-nonminimal/ans4/ans.py
Normal file
199
bin/tests/system/ixfr-nonminimal/ans4/ans.py
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
"""
|
||||
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
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 https://mozilla.org/MPL/2.0/.
|
||||
|
||||
See the COPYRIGHT file distributed with this work for additional
|
||||
information regarding copyright ownership.
|
||||
"""
|
||||
|
||||
import abc
|
||||
|
||||
import dns.rcode
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from typing import AsyncGenerator, Collection, Iterable
|
||||
|
||||
from isctest.asyncserver import (
|
||||
ControllableAsyncDnsServer,
|
||||
DnsResponseSend,
|
||||
QueryContext,
|
||||
ResponseHandler,
|
||||
SwitchControlCommand,
|
||||
)
|
||||
|
||||
|
||||
def rrset(owner: str, rdtype: dns.rdatatype.RdataType, rdata: str) -> dns.rrset.RRset:
|
||||
return dns.rrset.from_text(
|
||||
owner,
|
||||
300,
|
||||
dns.rdataclass.IN,
|
||||
rdtype,
|
||||
rdata,
|
||||
)
|
||||
|
||||
|
||||
def soa(serial: int, *, owner: str = "nil.") -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
owner,
|
||||
dns.rdatatype.SOA,
|
||||
f"ns.nil. root.nil. {serial} 300 300 604800 300",
|
||||
)
|
||||
|
||||
|
||||
def ns() -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
"nil.",
|
||||
dns.rdatatype.NS,
|
||||
"ns.nil.",
|
||||
)
|
||||
|
||||
|
||||
def a(address: str, *, owner: str) -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
owner,
|
||||
dns.rdatatype.A,
|
||||
address,
|
||||
)
|
||||
|
||||
|
||||
def txt(data: str, *, owner: str = "nil.") -> dns.rrset.RRset:
|
||||
return rrset(
|
||||
owner,
|
||||
dns.rdatatype.TXT,
|
||||
f'"{data}"',
|
||||
)
|
||||
|
||||
|
||||
class SoaHandler(ResponseHandler):
|
||||
def __init__(self, serial: int):
|
||||
self._serial = serial
|
||||
|
||||
def match(self, qctx: QueryContext) -> bool:
|
||||
return qctx.qtype == dns.rdatatype.SOA
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
qctx.response.answer.append(soa(self._serial))
|
||||
yield DnsResponseSend(qctx.response)
|
||||
|
||||
|
||||
class AxfrHandler(ResponseHandler):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def answers(self) -> Iterable[Collection[dns.rrset.RRset]]:
|
||||
"""
|
||||
Answer sections of response packets sent in response to
|
||||
AXFR queries.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def match(self, qctx: QueryContext) -> bool:
|
||||
return qctx.qtype == dns.rdatatype.AXFR
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
for answer in self.answers:
|
||||
response = qctx.prepare_new_response()
|
||||
for rrset_ in answer:
|
||||
response.answer.append(rrset_)
|
||||
yield DnsResponseSend(response)
|
||||
|
||||
|
||||
class IxfrHandler(ResponseHandler):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def answer(self) -> Collection[dns.rrset.RRset]:
|
||||
"""
|
||||
Answer section of a response packet sent in response to
|
||||
IXFR queries.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def match(self, qctx: QueryContext) -> bool:
|
||||
return qctx.qtype == dns.rdatatype.IXFR
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[DnsResponseSend, None]:
|
||||
for rrset_ in self.answer:
|
||||
qctx.response.answer.append(rrset_)
|
||||
yield DnsResponseSend(qctx.response)
|
||||
|
||||
|
||||
class InitialAxfrHandler(AxfrHandler):
|
||||
answers = (
|
||||
(soa(1),),
|
||||
(
|
||||
ns(),
|
||||
txt("initial AXFR"),
|
||||
a("10.0.0.62", owner="b.nil."),
|
||||
),
|
||||
(soa(1),),
|
||||
)
|
||||
|
||||
|
||||
class InitialIxfrHandler(IxfrHandler):
|
||||
answer = (
|
||||
soa(1),
|
||||
ns(),
|
||||
txt("initial AXFR"),
|
||||
a("10.0.0.62", owner="b.nil."),
|
||||
soa(1),
|
||||
)
|
||||
|
||||
|
||||
class NxrrsetIxfrHandler(IxfrHandler):
|
||||
"""
|
||||
IXFR from serial 1 -> 2.
|
||||
|
||||
Deletes the only A record at b.nil. (10.0.0.62). Since this is
|
||||
the last record in that rdataset, subtractrdataset() returns
|
||||
DNS_R_NXRRSET.
|
||||
|
||||
Also adds a TXT record so the zone has a real change beyond the
|
||||
SOA serial bump.
|
||||
"""
|
||||
|
||||
answer = (
|
||||
soa(2),
|
||||
soa(1),
|
||||
a("10.0.0.62", owner="b.nil."),
|
||||
txt("initial AXFR"),
|
||||
soa(2),
|
||||
txt("nxrrset ixfr test"),
|
||||
soa(2),
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = ControllableAsyncDnsServer(
|
||||
default_aa=True, default_rcode=dns.rcode.NOERROR
|
||||
)
|
||||
switch_command = SwitchControlCommand(
|
||||
{
|
||||
"initial_axfr": (
|
||||
SoaHandler(1),
|
||||
InitialIxfrHandler(),
|
||||
InitialAxfrHandler(),
|
||||
),
|
||||
"nxrrset_ixfr": (
|
||||
SoaHandler(2),
|
||||
NxrrsetIxfrHandler(),
|
||||
),
|
||||
}
|
||||
)
|
||||
server.install_control_command(switch_command)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
41
bin/tests/system/ixfr-nonminimal/ns1/named.conf.j2
Normal file
41
bin/tests/system/ixfr-nonminimal/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* 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 https://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; };
|
||||
allow-transfer { any; };
|
||||
recursion no;
|
||||
notify yes;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "nil" {
|
||||
type secondary;
|
||||
file "nil.db";
|
||||
primaries { 10.53.0.2; };
|
||||
};
|
||||
41
bin/tests/system/ixfr-nonminimal/ns3/named.conf.j2
Normal file
41
bin/tests/system/ixfr-nonminimal/ns3/named.conf.j2
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* 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 https://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; };
|
||||
allow-transfer { any; };
|
||||
recursion no;
|
||||
notify yes;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
zone "nil" {
|
||||
type secondary;
|
||||
file "nil.db";
|
||||
primaries { 10.53.0.4; };
|
||||
};
|
||||
16
bin/tests/system/ixfr-nonminimal/prereq.sh
Normal file
16
bin/tests/system/ixfr-nonminimal/prereq.sh
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
. ../conf.sh
|
||||
|
||||
exit 0
|
||||
14
bin/tests/system/ixfr-nonminimal/setup.sh
Normal file
14
bin/tests/system/ixfr-nonminimal/setup.sh
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
. ../conf.sh
|
||||
86
bin/tests/system/ixfr-nonminimal/tests.sh
Normal file
86
bin/tests/system/ixfr-nonminimal/tests.sh
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
set -e
|
||||
|
||||
. ../conf.sh
|
||||
|
||||
wait_for_serial() (
|
||||
$DIG $DIGOPTS "@$1" "$2" SOA >"$4"
|
||||
serial=$(awk '$4 == "SOA" { print $7 }' "$4")
|
||||
[ "$3" -eq "${serial:--1}" ]
|
||||
)
|
||||
|
||||
status=0
|
||||
n=0
|
||||
|
||||
DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
|
||||
RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../_common/rndc.conf -s"
|
||||
|
||||
switch_responses() {
|
||||
$DIG $DIGOPTS "@$1" "${2}.switch._control." TXT +time=5 +tries=1 +tcp >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Set up initial_axfr handlers and trigger transfers
|
||||
switch_responses 10.53.0.2 "initial_axfr"
|
||||
switch_responses 10.53.0.4 "initial_axfr"
|
||||
$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
|
||||
$RNDCCMD 10.53.0.3 refresh nil | sed 's/^/ns3 /' | cat_i
|
||||
|
||||
# Wait for initial AXFRs to complete
|
||||
retry_quiet 10 wait_for_serial 10.53.0.1 nil. 1 dig.out.ns1.axfr || {
|
||||
echo_i "ns1 initial AXFR failed"
|
||||
exit 1
|
||||
}
|
||||
retry_quiet 10 wait_for_serial 10.53.0.3 nil. 1 dig.out.ns3.axfr || {
|
||||
echo_i "ns3 initial AXFR failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Test 1: IXFR that re-adds an existing record -> DNS_R_UNCHANGED
|
||||
n=$((n + 1))
|
||||
echo_i "testing IXFR with unchanged rdataset ($n)"
|
||||
ret=0
|
||||
|
||||
switch_responses 10.53.0.2 "unchanged_ixfr"
|
||||
sleep 1
|
||||
|
||||
$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
|
||||
sleep 2
|
||||
|
||||
$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'unchanged ixfr test' >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.1 a.nil. A | grep '10.0.0.61' >/dev/null || ret=1
|
||||
grep "dns_diff_apply: update with no effect" ns1/named.run >/dev/null || ret=1
|
||||
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
# Test 2: IXFR that deletes last record in rdataset -> DNS_R_NXRRSET
|
||||
n=$((n + 1))
|
||||
echo_i "testing IXFR with nxrrset ($n)"
|
||||
ret=0
|
||||
|
||||
switch_responses 10.53.0.4 "nxrrset_ixfr"
|
||||
sleep 1
|
||||
|
||||
$RNDCCMD 10.53.0.3 refresh nil | sed 's/^/ns3 /' | cat_i
|
||||
sleep 2
|
||||
|
||||
$DIG $DIGOPTS @10.53.0.3 nil. TXT | grep 'nxrrset ixfr test' >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 b.nil. A | grep '10.0.0.62' >/dev/null && ret=1
|
||||
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
27
bin/tests/system/ixfr-nonminimal/tests_sh_ixfr_nonminimal.py
Normal file
27
bin/tests/system/ixfr-nonminimal/tests_sh_ixfr_nonminimal.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"dig.out*",
|
||||
"ans*/ans.run",
|
||||
"ns1/nil.db",
|
||||
"ns1/*.jnl",
|
||||
"ns3/nil.db",
|
||||
"ns3/*.jnl",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_my_ixfr_nonminimal(run_tests_sh):
|
||||
run_tests_sh()
|
||||
Loading…
Reference in a new issue