if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
+find_records() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ awk '$1 == "'"$owner_name"'" && $4 == "'"$rr_type"'" { print }' < "$file"
+}
+
+count_records() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ find_records "$owner_name" "$rr_type" "$file" | wc -l
+}
+
+exactly_one_record_exists_for() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 1
+}
+
+no_records_exist_for() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 0
+}
+
+ensure_no_ds_in_bitmap() {
+ owner_name="$1"
+ rr_type="$2"
+ file="$3"
+ case "$rr_type" in
+ NSEC) start_index=6 ;;
+ NSEC3) start_index=10 ;;
+ *) exit 1 ;;
+ esac
+ find_records "$owner_name" "$rr_type" "$file" | awk '{ for (i='"$start_index"'; i<=NF; i++) if ($i == "DS") exit 1 }'
+}
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using CNAME chaining, NSEC ($n)"
+ret=0
+# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
+# single NSEC record proving nonexistence of a DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
+# Check NSEC records in the AUTHORITY section.
+no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+# Ensure the NSEC record for the zone cut does not have the DS bit set in the
+# type bit map.
+ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #1 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, these two NSEC records are different.
+$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
+# Check NSEC records in the AUTHORITY section.
+no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+# Ensure the NSEC record for the zone cut does not have the DS bit set in the
+# type bit map.
+ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #2 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, the same NSEC record proves nonexistence of both the
+# QNAME and the DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
+# Check NSEC records in the AUTHORITY section.
+no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+# Ensure the NSEC record for the zone cut does not have the DS bit set in the
+# type bit map.
+ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Relevant NSEC3 hashes:
+#
+# - existing names:
+#
+# $ nsec3hash - 1 0 wildcard-nsec3.example.
+# 38IVP9CN0LBISO6H3V5REQCKMTHLI5AN (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 cname.wildcard-nsec3.example.
+# 3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 delegation.wildcard-nsec3.example.
+# AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 *.wildcard-nsec3.example.
+# Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2 (salt=-, hash=1, iterations=0)
+#
+# - nonexistent names:
+#
+# $ nsec3hash - 1 0 a-nonexistent-name.wildcard-nsec3.example.
+# PST9IH6M0DG3M139CO3G12NUP4ER88SH (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3.example.
+# SG2DEHEAOGCKP7FTNQAUVC3I3TIPJH0J (salt=-, hash=1, iterations=0)
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using CNAME chaining, NSEC3 ($n)"
+ret=0
+# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
+# single NSEC3 record proving nonexistence of a DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #1 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, these two NSEC3 records are different.
+$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #2 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, the same NSEC3 record proves nonexistence of both the
+# QNAME and the DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+# Relevant NSEC3 hashes:
+#
+# - existing names with corresponding NSEC3 records:
+#
+# $ nsec3hash - 1 0 *.wildcard-nsec3-optout.example.
+# 2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 cname.wildcard-nsec3-optout.example.
+# OKRFKC9SS1O60E8U2980UD62MUSMKGUG (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 wildcard-nsec3-optout.example.
+# SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI (salt=-, hash=1, iterations=0)
+#
+# - existing name with no corresponding NSEC3 record due to opt-out:
+#
+# $ nsec3hash - 1 0 delegation.wildcard-nsec3-optout.example.
+# UFP8PVECFTD57HU5PUD2HE0ES37QEOAP (salt=-, hash=1, iterations=0)
+#
+# - nonexistent names:
+#
+# $ nsec3hash - 1 0 b-nonexistent-name.wildcard-nsec3-optout.example.
+# 3J38JE2OU0O7B4CE2ADMBBKJ5HT994S5 (salt=-, hash=1, iterations=0)
+# $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3-optout.example.
+# V7OTS4791T9SU0HKVL93EVNAJ9JH2CH3 (salt=-, hash=1, iterations=0)
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using CNAME chaining, NSEC3 with opt-out ($n)"
+ret=0
+# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
+# single NSEC3 record proving nonexistence of a DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #1 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, these two NSEC3 records are different.
+$DIG $DIGOPTS @10.53.0.2 b-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+exactly_one_record_exists_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "checking delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #2 ($n)"
+ret=0
+# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
+# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
+# cut. In this test case, the same NSEC3 record proves nonexistence of both the
+# QNAME and the DS RRset at the zone cut.
+$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1
+# Ensure that the AUTHORITY section contains an NS RRset.
+exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
+# Check NSEC3 records in the AUTHORITY section.
+no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
+# the type bit map.
+ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
n=`expr $n + 1`
echo_i "checking CNAME to DNAME from authoritative ($n)"
ret=0