summaryrefslogtreecommitdiffstats
path: root/tests/libzscanner
diff options
context:
space:
mode:
Diffstat (limited to 'tests/libzscanner')
-rw-r--r--tests/libzscanner/TESTS86
-rw-r--r--tests/libzscanner/data/00-0_general.in27
-rw-r--r--tests/libzscanner/data/00-0_general.out70
-rw-r--r--tests/libzscanner/data/00-1_general.in7
-rw-r--r--tests/libzscanner/data/00-1_general.out2
-rw-r--r--tests/libzscanner/data/00-2_general.in1
-rw-r--r--tests/libzscanner/data/00-2_general.out2
-rw-r--r--tests/libzscanner/data/00-3_general.in4
-rw-r--r--tests/libzscanner/data/00-3_general.out6
-rw-r--r--tests/libzscanner/data/00-4_general.in0
-rw-r--r--tests/libzscanner/data/00-4_general.out0
-rw-r--r--tests/libzscanner/data/01_owner.in37
-rw-r--r--tests/libzscanner/data/01_owner.out138
-rw-r--r--tests/libzscanner/data/02_class.in10
-rw-r--r--tests/libzscanner/data/02_class.out16
-rw-r--r--tests/libzscanner/data/03_rrttl.in26
-rw-r--r--tests/libzscanner/data/03_rrttl.out100
-rw-r--r--tests/libzscanner/data/04-0_ORIGIN.in29
-rw-r--r--tests/libzscanner/data/04-0_ORIGIN.out86
-rw-r--r--tests/libzscanner/data/04-1_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-1_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-2_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-2_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-3_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-3_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-4_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-4_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-5_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-5_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-6_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-6_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-7_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-7_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-8_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-8_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/04-9_ORIGIN.in4
-rw-r--r--tests/libzscanner/data/04-9_ORIGIN.out2
-rw-r--r--tests/libzscanner/data/05-0_TTL.in36
-rw-r--r--tests/libzscanner/data/05-0_TTL.out92
-rw-r--r--tests/libzscanner/data/05-1_TTL.in4
-rw-r--r--tests/libzscanner/data/05-1_TTL.out2
-rw-r--r--tests/libzscanner/data/05-2_TTL.in4
-rw-r--r--tests/libzscanner/data/05-2_TTL.out2
-rw-r--r--tests/libzscanner/data/05-3_TTL.in4
-rw-r--r--tests/libzscanner/data/05-3_TTL.out2
-rw-r--r--tests/libzscanner/data/05-4_TTL.in4
-rw-r--r--tests/libzscanner/data/05-4_TTL.out2
-rw-r--r--tests/libzscanner/data/06-0_INCLUDE.in29
-rw-r--r--tests/libzscanner/data/06-0_INCLUDE.out138
-rw-r--r--tests/libzscanner/data/06-1_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-1_INCLUDE.out2
-rw-r--r--tests/libzscanner/data/06-2_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-2_INCLUDE.out2
-rw-r--r--tests/libzscanner/data/06-3_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-3_INCLUDE.out2
-rw-r--r--tests/libzscanner/data/06-4_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-4_INCLUDE.out2
-rw-r--r--tests/libzscanner/data/06-5_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-5_INCLUDE.out0
-rw-r--r--tests/libzscanner/data/06-6_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-6_INCLUDE.out4
-rw-r--r--tests/libzscanner/data/06-7_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-7_INCLUDE.out4
-rw-r--r--tests/libzscanner/data/06-8_INCLUDE.in5
-rw-r--r--tests/libzscanner/data/06-8_INCLUDE.out12
-rw-r--r--tests/libzscanner/data/07-0-rdata.in1
-rw-r--r--tests/libzscanner/data/07-0-rdata.out2
-rw-r--r--tests/libzscanner/data/07-1-rdata.in1
-rw-r--r--tests/libzscanner/data/07-1-rdata.out2
-rw-r--r--tests/libzscanner/data/07-2-rdata.in1
-rw-r--r--tests/libzscanner/data/07-2-rdata.out6
-rw-r--r--tests/libzscanner/data/07-3-rdata.in1
-rw-r--r--tests/libzscanner/data/07-3-rdata.out6
-rw-r--r--tests/libzscanner/data/07-4-rdata.in1
-rw-r--r--tests/libzscanner/data/07-4-rdata.out6
-rw-r--r--tests/libzscanner/data/10_A.in19
-rw-r--r--tests/libzscanner/data/10_A.out50
-rw-r--r--tests/libzscanner/data/11_AAAA.in21
-rw-r--r--tests/libzscanner/data/11_AAAA.out62
-rw-r--r--tests/libzscanner/data/12_TXT.in37
-rw-r--r--tests/libzscanner/data/12_TXT.out138
-rw-r--r--tests/libzscanner/data/13_SPF.in14
-rw-r--r--tests/libzscanner/data/13_SPF.out32
-rw-r--r--tests/libzscanner/data/14_NS.in38
-rw-r--r--tests/libzscanner/data/14_NS.out144
-rw-r--r--tests/libzscanner/data/15_CNAME.in14
-rw-r--r--tests/libzscanner/data/15_CNAME.out32
-rw-r--r--tests/libzscanner/data/16_PTR.in14
-rw-r--r--tests/libzscanner/data/16_PTR.out32
-rw-r--r--tests/libzscanner/data/17_DNAME.in14
-rw-r--r--tests/libzscanner/data/17_DNAME.out32
-rw-r--r--tests/libzscanner/data/18_MX.in23
-rw-r--r--tests/libzscanner/data/18_MX.out62
-rw-r--r--tests/libzscanner/data/19_AFSDB.in14
-rw-r--r--tests/libzscanner/data/19_AFSDB.out32
-rw-r--r--tests/libzscanner/data/20_RT.in14
-rw-r--r--tests/libzscanner/data/20_RT.out32
-rw-r--r--tests/libzscanner/data/21_KX.in14
-rw-r--r--tests/libzscanner/data/21_KX.out32
-rw-r--r--tests/libzscanner/data/22_HINFO.in26
-rw-r--r--tests/libzscanner/data/22_HINFO.out88
-rw-r--r--tests/libzscanner/data/23_MINFO.in18
-rw-r--r--tests/libzscanner/data/23_MINFO.out48
-rw-r--r--tests/libzscanner/data/24_RP.in14
-rw-r--r--tests/libzscanner/data/24_RP.out32
-rw-r--r--tests/libzscanner/data/25_SOA.in31
-rw-r--r--tests/libzscanner/data/25_SOA.out74
-rw-r--r--tests/libzscanner/data/26_SRV.in25
-rw-r--r--tests/libzscanner/data/26_SRV.out66
-rw-r--r--tests/libzscanner/data/27_NAPTR.in20
-rw-r--r--tests/libzscanner/data/27_NAPTR.out56
-rw-r--r--tests/libzscanner/data/28_TYPE.in27
-rw-r--r--tests/libzscanner/data/28_TYPE.out64
-rw-r--r--tests/libzscanner/data/29_CERT.in58
-rw-r--r--tests/libzscanner/data/29_CERT.out244
-rw-r--r--tests/libzscanner/data/30_KEY.in31
-rw-r--r--tests/libzscanner/data/30_KEY.out86
-rw-r--r--tests/libzscanner/data/31_DNSKEY.in32
-rw-r--r--tests/libzscanner/data/31_DNSKEY.out92
-rw-r--r--tests/libzscanner/data/32_APL.in30
-rw-r--r--tests/libzscanner/data/32_APL.out104
-rw-r--r--tests/libzscanner/data/33_DS.in23
-rw-r--r--tests/libzscanner/data/33_DS.out62
-rw-r--r--tests/libzscanner/data/34_SSHFP.in21
-rw-r--r--tests/libzscanner/data/34_SSHFP.out54
-rw-r--r--tests/libzscanner/data/35_IPSECKEY.in29
-rw-r--r--tests/libzscanner/data/35_IPSECKEY.out94
-rw-r--r--tests/libzscanner/data/36_RRSIG.in46
-rw-r--r--tests/libzscanner/data/36_RRSIG.out140
-rw-r--r--tests/libzscanner/data/37_NSEC.in20
-rw-r--r--tests/libzscanner/data/37_NSEC.out64
-rw-r--r--tests/libzscanner/data/38_DHCID.in26
-rw-r--r--tests/libzscanner/data/38_DHCID.out72
-rw-r--r--tests/libzscanner/data/39_NSEC3.in46
-rw-r--r--tests/libzscanner/data/39_NSEC3.out144
-rw-r--r--tests/libzscanner/data/40_NSEC3PARAM.in23
-rw-r--r--tests/libzscanner/data/40_NSEC3PARAM.out58
-rw-r--r--tests/libzscanner/data/41_TLSA.in21
-rw-r--r--tests/libzscanner/data/41_TLSA.out54
-rw-r--r--tests/libzscanner/data/42_LOC.in64
-rw-r--r--tests/libzscanner/data/42_LOC.out248
-rw-r--r--tests/libzscanner/data/43_EUI48.in22
-rw-r--r--tests/libzscanner/data/43_EUI48.out60
-rw-r--r--tests/libzscanner/data/44_EUI64.in22
-rw-r--r--tests/libzscanner/data/44_EUI64.out60
-rw-r--r--tests/libzscanner/data/45_NID.in14
-rw-r--r--tests/libzscanner/data/45_NID.out32
-rw-r--r--tests/libzscanner/data/46_L32.in21
-rw-r--r--tests/libzscanner/data/46_L32.out54
-rw-r--r--tests/libzscanner/data/47_L64.in23
-rw-r--r--tests/libzscanner/data/47_L64.out62
-rw-r--r--tests/libzscanner/data/48_LP.in14
-rw-r--r--tests/libzscanner/data/48_LP.out32
-rw-r--r--tests/libzscanner/data/49_CDS.in23
-rw-r--r--tests/libzscanner/data/49_CDS.out62
-rw-r--r--tests/libzscanner/data/50_CDNSKEY.in32
-rw-r--r--tests/libzscanner/data/50_CDNSKEY.out92
-rw-r--r--tests/libzscanner/data/51_URI.in22
-rw-r--r--tests/libzscanner/data/51_URI.out60
-rw-r--r--tests/libzscanner/data/52_CAA.in23
-rw-r--r--tests/libzscanner/data/52_CAA.out70
-rw-r--r--tests/libzscanner/data/53_SMIMEA.in13
-rw-r--r--tests/libzscanner/data/53_SMIMEA.out26
-rw-r--r--tests/libzscanner/data/54_OPENPGPKEY.in13
-rw-r--r--tests/libzscanner/data/54_OPENPGPKEY.out26
-rw-r--r--tests/libzscanner/data/55_CSYNC.in22
-rw-r--r--tests/libzscanner/data/55_CSYNC.out68
-rw-r--r--tests/libzscanner/data/56_ZONEMD.in21
-rw-r--r--tests/libzscanner/data/56_ZONEMD.out54
-rw-r--r--tests/libzscanner/data/57_SVCB.in102
-rw-r--r--tests/libzscanner/data/57_SVCB.out306
-rw-r--r--tests/libzscanner/data/58_HTTPS.in19
-rw-r--r--tests/libzscanner/data/58_HTTPS.out46
-rw-r--r--tests/libzscanner/data/includes/include19
-rw-r--r--tests/libzscanner/data/includes/include26
-rw-r--r--tests/libzscanner/data/includes/include30
-rw-r--r--tests/libzscanner/data/includes/include41
-rw-r--r--tests/libzscanner/data/includes/include51
-rw-r--r--tests/libzscanner/data/includes/include61
-rw-r--r--tests/libzscanner/processing.c184
-rw-r--r--tests/libzscanner/processing.h31
-rw-r--r--tests/libzscanner/test_zscanner.in41
-rw-r--r--tests/libzscanner/zscanner-tool.c257
183 files changed, 6653 insertions, 0 deletions
diff --git a/tests/libzscanner/TESTS b/tests/libzscanner/TESTS
new file mode 100644
index 0000000..227cdb4
--- /dev/null
+++ b/tests/libzscanner/TESTS
@@ -0,0 +1,86 @@
+00-0_general
+00-1_general
+00-2_general
+00-3_general
+00-4_general
+01_owner
+02_class
+03_rrttl
+04-0_ORIGIN
+04-1_ORIGIN
+04-2_ORIGIN
+04-3_ORIGIN
+04-4_ORIGIN
+04-5_ORIGIN
+04-6_ORIGIN
+04-7_ORIGIN
+04-8_ORIGIN
+04-9_ORIGIN
+05-0_TTL
+05-1_TTL
+05-2_TTL
+05-3_TTL
+05-4_TTL
+06-0_INCLUDE
+06-1_INCLUDE
+06-2_INCLUDE
+06-3_INCLUDE
+06-4_INCLUDE
+06-5_INCLUDE
+06-6_INCLUDE
+06-7_INCLUDE
+06-8_INCLUDE
+07-0-rdata
+07-1-rdata
+07-2-rdata
+07-3-rdata
+07-4-rdata
+10_A
+11_AAAA
+12_TXT
+13_SPF
+14_NS
+15_CNAME
+16_PTR
+17_DNAME
+18_MX
+19_AFSDB
+20_RT
+21_KX
+22_HINFO
+23_MINFO
+24_RP
+25_SOA
+26_SRV
+27_NAPTR
+28_TYPE
+29_CERT
+30_KEY
+31_DNSKEY
+32_APL
+33_DS
+34_SSHFP
+35_IPSECKEY
+36_RRSIG
+37_NSEC
+38_DHCID
+39_NSEC3
+40_NSEC3PARAM
+41_TLSA
+42_LOC
+43_EUI48
+44_EUI64
+45_NID
+46_L32
+47_L64
+48_LP
+49_CDS
+50_CDNSKEY
+51_URI
+52_CAA
+53_SMIMEA
+54_OPENPGPKEY
+55_CSYNC
+56_ZONEMD
+57_SVCB
+58_HTTPS
diff --git a/tests/libzscanner/data/00-0_general.in b/tests/libzscanner/data/00-0_general.in
new file mode 100644
index 0000000..21e9d03
--- /dev/null
+++ b/tests/libzscanner/data/00-0_general.in
@@ -0,0 +1,27 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+t01 IN 10 NS @ ; All items are mentioned
+ IN 10 NS @ ; Same as above without OWNER
+t02 20 IN NS @ ; Switched CLASS and TTL
+ 20 IN NS @ ; Same as above without OWNER
+t03 30 NS @ ; Missing CLASS
+ 30 NS @ ; Same as above without OWNER
+t04 IN NS @ ; Missing TTL
+ IN NS @ ; Same as above without OWNER
+t05 NS @ ; Missing CLASS and TTL
+ NS @ ; Same as above without OWNER
+
+@ ( ) NS ( ; Multiline 1/5
+ ) () ( ; Multiline 2/5
+
+ @ ; Multiline 4/5
+ ) (
+) ; Multiline 6/6
+
+; KO
+@ A (
+ 1.1.1
+ ) ; Error in multiline
+@ NS ((@)) ; Nested parentheses - ERROR = STOP PROCESSING!
diff --git a/tests/libzscanner/data/00-0_general.out b/tests/libzscanner/data/00-0_general.out
new file mode 100644
index 0000000..522b3a6
--- /dev/null
+++ b/tests/libzscanner/data/00-0_general.out
@@ -0,0 +1,70 @@
+OWNER=0374303100
+CLASS=0001
+RRTTL=0000000A
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303100
+CLASS=0001
+RRTTL=0000000A
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303200
+CLASS=0001
+RRTTL=00000014
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303200
+CLASS=0001
+RRTTL=00000014
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303300
+CLASS=0001
+RRTTL=0000001E
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303300
+CLASS=0001
+RRTTL=0000001E
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303500
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303500
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZS_BAD_IPV4
+------
+ERROR=ZS_LEFT_PARENTHESIS
+------
diff --git a/tests/libzscanner/data/00-1_general.in b/tests/libzscanner/data/00-1_general.in
new file mode 100644
index 0000000..2423909
--- /dev/null
+++ b/tests/libzscanner/data/00-1_general.in
@@ -0,0 +1,7 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+@ TXT ( "text" ; Unclosed multiline block
+
+;comment
diff --git a/tests/libzscanner/data/00-1_general.out b/tests/libzscanner/data/00-1_general.out
new file mode 100644
index 0000000..85b0653
--- /dev/null
+++ b/tests/libzscanner/data/00-1_general.out
@@ -0,0 +1,2 @@
+ERROR=ZS_UNCLOSED_MULTILINE
+------
diff --git a/tests/libzscanner/data/00-2_general.in b/tests/libzscanner/data/00-2_general.in
new file mode 100644
index 0000000..460eeb5
--- /dev/null
+++ b/tests/libzscanner/data/00-2_general.in
@@ -0,0 +1 @@
+$ORIGIN .
diff --git a/tests/libzscanner/data/00-2_general.out b/tests/libzscanner/data/00-2_general.out
new file mode 100644
index 0000000..79776a7
--- /dev/null
+++ b/tests/libzscanner/data/00-2_general.out
@@ -0,0 +1,2 @@
+ERROR=ZS_DOS_NEWLINE
+------
diff --git a/tests/libzscanner/data/00-3_general.in b/tests/libzscanner/data/00-3_general.in
new file mode 100644
index 0000000..6ce107c
--- /dev/null
+++ b/tests/libzscanner/data/00-3_general.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+$TTL 1
+
+. NS @ ; No newline \ No newline at end of file
diff --git a/tests/libzscanner/data/00-3_general.out b/tests/libzscanner/data/00-3_general.out
new file mode 100644
index 0000000..bc06672
--- /dev/null
+++ b/tests/libzscanner/data/00-3_general.out
@@ -0,0 +1,6 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
diff --git a/tests/libzscanner/data/00-4_general.in b/tests/libzscanner/data/00-4_general.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libzscanner/data/00-4_general.in
diff --git a/tests/libzscanner/data/00-4_general.out b/tests/libzscanner/data/00-4_general.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libzscanner/data/00-4_general.out
diff --git a/tests/libzscanner/data/01_owner.in b/tests/libzscanner/data/01_owner.in
new file mode 100644
index 0000000..0108be3
--- /dev/null
+++ b/tests/libzscanner/data/01_owner.in
@@ -0,0 +1,37 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+. NS @ ; The simplest owner
+tld. NS @ ; FQD tld owner
+tld NS @ ; Relative form
+ NS @ ; The previous owner
+*. NS @ ; FQD with asterisk
+* NS @ ; Alone asterisk
+*.* NS @ ; More asterisks
+*a.a*a.** NS @ ; Also possible
+@ NS @ ; Use origin
+0123456789 NS @ ; Digits
+0/25.2.0.192.in-addr.arpa. NS @ ; CIDR notation
+_a_.-b-c-./d/. NS @ ; Allowed characters '_' '-' '/' anywhere
+ABCDEFGHIJKLMNOPQRSTUVWXYZ NS @ ; All upper-case letters
+abcdefghijklmnopqrstuvwxyz NS @ ; All lower-case letters
+\000\0320\ \\\"\.\@\*.tld. NS @ ; Label with special chars
+b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. NS @ ; IPv6 reverse
+12345678901234567890123456789012345678901234567890123456789012\051.tld. NS @ ; Label of maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901. NS @ ; Domain name of maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901 NS @ ; Domain name of maximal length (after appending origin)
+
+; KO
+& NS @ ; Bad (unslashed) character
+ NS @ ; Bad previous
+.a NS @ ; Leading dot
+@@ NS @ ; Double @@
+.. NS @ ; Missing label between dots
+\1 NS @ ; Slash notation requires 3 digits
+\12 NS @ ; Slash notation requires 3 digits
+12345678901234567890123456789012345678901234567890123456789012\0514.tld. NS @ ; Label exceeded maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012. NS @ ; Domain name exceeded maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012 NS @ ; Domain name exceeded maximal length (after appending origin)
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.1 NS @ ; Domain name exceeded maximal length (maximal dname length check is after each valid label)
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.123456789012345678901234567890123456789012345678901234567890123 NS @ ; Domain name exceeded maximal length (maximal dname length check is after each valid label)
diff --git a/tests/libzscanner/data/01_owner.out b/tests/libzscanner/data/01_owner.out
new file mode 100644
index 0000000..26a8454
--- /dev/null
+++ b/tests/libzscanner/data/01_owner.out
@@ -0,0 +1,138 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=012A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=012A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=012A012A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=022A6103612A61022A2A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0A3031323334353637383900
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=04302F3235013201300331393207696E2D61646472046172706100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=035F615F052D622D632D032F642F00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=1A4142434445464748494A4B4C4D4E4F505152535455565758595A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=1A6162636465666768696A6B6C6D6E6F707172737475767778797A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=09002030205C222E402A03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZS_BAD_OWNER
+------
+WARNG=ZS_BAD_PREVIOUS_OWNER
+------
+WARNG=ZS_BAD_DNAME_CHAR
+------
+WARNG=ZS_BAD_DNAME_CHAR
+------
+WARNG=ZS_BAD_DNAME_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_LABEL_OVERFLOW
+------
+WARNG=ZS_DNAME_OVERFLOW
+------
+WARNG=ZS_DNAME_OVERFLOW
+------
+WARNG=ZS_DNAME_OVERFLOW
+------
+WARNG=ZS_DNAME_OVERFLOW
+------
diff --git a/tests/libzscanner/data/02_class.in b/tests/libzscanner/data/02_class.in
new file mode 100644
index 0000000..c4347e7
--- /dev/null
+++ b/tests/libzscanner/data/02_class.in
@@ -0,0 +1,10 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ IN NS @ ; The only accepted class IN
+@ in NS @ ; Class in lower-case
+
+; KO
+@ CH NS @ ; Unsupported class
+@ CLASS1 NS @ ; Unsupported notation
diff --git a/tests/libzscanner/data/02_class.out b/tests/libzscanner/data/02_class.out
new file mode 100644
index 0000000..69daae3
--- /dev/null
+++ b/tests/libzscanner/data/02_class.out
@@ -0,0 +1,16 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZS_UNSUPPORTED_TYPE
+------
+WARNG=ZS_UNSUPPORTED_TYPE
+------
diff --git a/tests/libzscanner/data/03_rrttl.in b/tests/libzscanner/data/03_rrttl.in
new file mode 100644
index 0000000..7c57d73
--- /dev/null
+++ b/tests/libzscanner/data/03_rrttl.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ 0 NS @ ; Minimal ttl
+@ 3600 NS @ ; Inner value
+@ 4294967295 NS @ ; Maximal ttl
+@ 1S NS @ ; 1 second (upper-case)
+@ 1s NS @ ; 1 second (lower-case)
+@ 1M NS @ ; 1 minute (upper-case)
+@ 1m NS @ ; 1 minute (lower-case)
+@ 1H NS @ ; 1 hour (upper-case)
+@ 1h NS @ ; 1 hour (lower-case)
+@ 1D NS @ ; 1 day (upper-case)
+@ 1d NS @ ; 1 day (lower-case)
+@ 1W NS @ ; 1 week (upper-case)
+@ 1w NS @ ; 1 week (lower-case)
+@ 1w1d1h1m1s NS @ ; More time units
+@ 1s1m1m NS @ ; Same time units, non decreasing order
+
+; KO
+@ -1 NS @ ; Negative ttl
+@ 4294967296 NS @ ; 32bit overflow
+@ 100000000W NS @ ; 32bit overflow
+@ 4294967295s1w NS @ ; 32bit overflow
+@ 1x NS @ ; Unknown time unit
diff --git a/tests/libzscanner/data/03_rrttl.out b/tests/libzscanner/data/03_rrttl.out
new file mode 100644
index 0000000..f5cc907
--- /dev/null
+++ b/tests/libzscanner/data/03_rrttl.out
@@ -0,0 +1,100 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000000
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=FFFFFFFF
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=000A9A4D
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000079
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_BAD_TIME_UNIT
+------
diff --git a/tests/libzscanner/data/04-0_ORIGIN.in b/tests/libzscanner/data/04-0_ORIGIN.in
new file mode 100644
index 0000000..4d65ec4
--- /dev/null
+++ b/tests/libzscanner/data/04-0_ORIGIN.in
@@ -0,0 +1,29 @@
+$TTL 1
+
+; OK
+$ORIGIN . ; Root domain
+@ NS @ ; Use origin
+a. NS @ ; Absolute dname
+a NS @ ; Relative dname
+$ORIGIN tld. ; 1. level domain
+@ NS @ ; Use origin
+a. NS @ ; Absolute dname
+a NS @ ; Relative dname
+$ORIGIN second.tld. ; 2. level domain
+@ NS @ ; Use origin
+a. NS @ ; Absolute dname
+a NS @ ; Relative dname
+$ORIGIN \0320\ \\\"\.\@\*.tld. ; Label with special chars
+@ NS @ ; Use origin
+$ORIGIN b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. ; IPv6 reverse
+@ NS @ ; Use origin
+$ORIGIN 12345678901234567890123456789012345678901234567890123456789012\051.tld. ; Label of maximal length
+@ NS @ ; Use origin
+$ORIGIN 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901. ; Domain name of maximal length
+@ NS @ ; Use origin
+$origin . ; Lower-case
+@ NS @ ; Use origin
+
+; KO
+$ORIGIN ; Empty input
+. NS . ; Is OK, but shouldn't be processed due to previous error stop!
diff --git a/tests/libzscanner/data/04-0_ORIGIN.out b/tests/libzscanner/data/04-0_ORIGIN.out
new file mode 100644
index 0000000..92dc459
--- /dev/null
+++ b/tests/libzscanner/data/04-0_ORIGIN.out
@@ -0,0 +1,86 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016103746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=067365636F6E6403746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=067365636F6E6403746C6400
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=067365636F6E6403746C6400
+------
+OWNER=0161067365636F6E6403746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=067365636F6E6403746C6400
+------
+OWNER=082030205C222E402A03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+------
+OWNER=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+------
+OWNER=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+ERROR=ZS_BAD_ORIGIN
+------
diff --git a/tests/libzscanner/data/04-1_ORIGIN.in b/tests/libzscanner/data/04-1_ORIGIN.in
new file mode 100644
index 0000000..871c064
--- /dev/null
+++ b/tests/libzscanner/data/04-1_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN tld ; Not FQD
diff --git a/tests/libzscanner/data/04-1_ORIGIN.out b/tests/libzscanner/data/04-1_ORIGIN.out
new file mode 100644
index 0000000..467de10
--- /dev/null
+++ b/tests/libzscanner/data/04-1_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_ORIGIN
+------
diff --git a/tests/libzscanner/data/04-2_ORIGIN.in b/tests/libzscanner/data/04-2_ORIGIN.in
new file mode 100644
index 0000000..8dd2e20
--- /dev/null
+++ b/tests/libzscanner/data/04-2_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN % ; Bad (unslashed) character
diff --git a/tests/libzscanner/data/04-2_ORIGIN.out b/tests/libzscanner/data/04-2_ORIGIN.out
new file mode 100644
index 0000000..467de10
--- /dev/null
+++ b/tests/libzscanner/data/04-2_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_ORIGIN
+------
diff --git a/tests/libzscanner/data/04-3_ORIGIN.in b/tests/libzscanner/data/04-3_ORIGIN.in
new file mode 100644
index 0000000..26d1872
--- /dev/null
+++ b/tests/libzscanner/data/04-3_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN .. ; Missing label between dots
diff --git a/tests/libzscanner/data/04-3_ORIGIN.out b/tests/libzscanner/data/04-3_ORIGIN.out
new file mode 100644
index 0000000..b7d67e5
--- /dev/null
+++ b/tests/libzscanner/data/04-3_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/04-4_ORIGIN.in b/tests/libzscanner/data/04-4_ORIGIN.in
new file mode 100644
index 0000000..0be4721
--- /dev/null
+++ b/tests/libzscanner/data/04-4_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN \1 ; Slash notation requires 3 digits
diff --git a/tests/libzscanner/data/04-4_ORIGIN.out b/tests/libzscanner/data/04-4_ORIGIN.out
new file mode 100644
index 0000000..03a0738
--- /dev/null
+++ b/tests/libzscanner/data/04-4_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/04-5_ORIGIN.in b/tests/libzscanner/data/04-5_ORIGIN.in
new file mode 100644
index 0000000..170d465
--- /dev/null
+++ b/tests/libzscanner/data/04-5_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN \12 ; Slash notation requires 3 digits
diff --git a/tests/libzscanner/data/04-5_ORIGIN.out b/tests/libzscanner/data/04-5_ORIGIN.out
new file mode 100644
index 0000000..03a0738
--- /dev/null
+++ b/tests/libzscanner/data/04-5_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/04-6_ORIGIN.in b/tests/libzscanner/data/04-6_ORIGIN.in
new file mode 100644
index 0000000..db9652d
--- /dev/null
+++ b/tests/libzscanner/data/04-6_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN .tld ; Leading dot
diff --git a/tests/libzscanner/data/04-6_ORIGIN.out b/tests/libzscanner/data/04-6_ORIGIN.out
new file mode 100644
index 0000000..b7d67e5
--- /dev/null
+++ b/tests/libzscanner/data/04-6_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/04-7_ORIGIN.in b/tests/libzscanner/data/04-7_ORIGIN.in
new file mode 100644
index 0000000..556646c
--- /dev/null
+++ b/tests/libzscanner/data/04-7_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN tld. x ; Unexpected item
diff --git a/tests/libzscanner/data/04-7_ORIGIN.out b/tests/libzscanner/data/04-7_ORIGIN.out
new file mode 100644
index 0000000..b7d67e5
--- /dev/null
+++ b/tests/libzscanner/data/04-7_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/04-8_ORIGIN.in b/tests/libzscanner/data/04-8_ORIGIN.in
new file mode 100644
index 0000000..445cbec
--- /dev/null
+++ b/tests/libzscanner/data/04-8_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN 12345678901234567890123456789012345678901234567890123456789012\0514.tld. ; Label exceeded maximal length
diff --git a/tests/libzscanner/data/04-8_ORIGIN.out b/tests/libzscanner/data/04-8_ORIGIN.out
new file mode 100644
index 0000000..788a495
--- /dev/null
+++ b/tests/libzscanner/data/04-8_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_LABEL_OVERFLOW
+------
diff --git a/tests/libzscanner/data/04-9_ORIGIN.in b/tests/libzscanner/data/04-9_ORIGIN.in
new file mode 100644
index 0000000..e0a4b95
--- /dev/null
+++ b/tests/libzscanner/data/04-9_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012. ; Domain name exceeded maximal length
diff --git a/tests/libzscanner/data/04-9_ORIGIN.out b/tests/libzscanner/data/04-9_ORIGIN.out
new file mode 100644
index 0000000..eef0ab5
--- /dev/null
+++ b/tests/libzscanner/data/04-9_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZS_DNAME_OVERFLOW
+------
diff --git a/tests/libzscanner/data/05-0_TTL.in b/tests/libzscanner/data/05-0_TTL.in
new file mode 100644
index 0000000..baa8f38
--- /dev/null
+++ b/tests/libzscanner/data/05-0_TTL.in
@@ -0,0 +1,36 @@
+$ORIGIN .
+
+; OK
+$TTL 0 ; Minimal ttl
+@ NS @ ; Use ttl
+$TTL 3600 ; Inner value
+@ NS @ ; Use ttl
+$TTL 4294967295 ; Maximal ttl
+@ NS @ ; Use ttl
+$TTL 1S ; 1 second (upper-case)
+@ NS @ ; Use ttl
+$TTL 1s ; 1 second (lower-case)
+@ NS @ ; Use ttl
+$TTL 1M ; 1 minute (upper-case)
+@ NS @ ; Use ttl
+$TTL 1m ; 1 minute (lower-case)
+@ NS @ ; Use ttl
+$TTL 1H ; 1 hour (upper-case)
+@ NS @ ; Use ttl
+$TTL 1h ; 1 hour (lower-case)
+@ NS @ ; Use ttl
+$TTL 1D ; 1 day (upper-case)
+@ NS @ ; Use ttl
+$TTL 1d ; 1 day (lower-case)
+@ NS @ ; Use ttl
+$TTL 1W ; 1 week (upper-case)
+@ NS @ ; Use ttl
+$TTL 1w ; 1 week (lower-case)
+@ NS @ ; Use ttl
+$TTL 1w1d1h1m1s ; More time units
+@ NS @ ; Use ttl
+$TTL 1s1m1m ; Same time units, non decreasing order
+@ NS @ ; Use ttl
+
+; KO
+$TTL -1 ; Negative ttl
diff --git a/tests/libzscanner/data/05-0_TTL.out b/tests/libzscanner/data/05-0_TTL.out
new file mode 100644
index 0000000..93c7651
--- /dev/null
+++ b/tests/libzscanner/data/05-0_TTL.out
@@ -0,0 +1,92 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000000
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=FFFFFFFF
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=000A9A4D
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000079
+RTYPE=0002
+RDATA=00
+------
+ERROR=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/05-1_TTL.in b/tests/libzscanner/data/05-1_TTL.in
new file mode 100644
index 0000000..519fe79
--- /dev/null
+++ b/tests/libzscanner/data/05-1_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 4294967296 ; 32bit overflow
diff --git a/tests/libzscanner/data/05-1_TTL.out b/tests/libzscanner/data/05-1_TTL.out
new file mode 100644
index 0000000..1849267
--- /dev/null
+++ b/tests/libzscanner/data/05-1_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZS_NUMBER32_OVERFLOW
+------
diff --git a/tests/libzscanner/data/05-2_TTL.in b/tests/libzscanner/data/05-2_TTL.in
new file mode 100644
index 0000000..ed112da
--- /dev/null
+++ b/tests/libzscanner/data/05-2_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 100000000W ; 32bit overflow
diff --git a/tests/libzscanner/data/05-2_TTL.out b/tests/libzscanner/data/05-2_TTL.out
new file mode 100644
index 0000000..1849267
--- /dev/null
+++ b/tests/libzscanner/data/05-2_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZS_NUMBER32_OVERFLOW
+------
diff --git a/tests/libzscanner/data/05-3_TTL.in b/tests/libzscanner/data/05-3_TTL.in
new file mode 100644
index 0000000..d96c9ba
--- /dev/null
+++ b/tests/libzscanner/data/05-3_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 4294967295s1w ; 32bit overflow
diff --git a/tests/libzscanner/data/05-3_TTL.out b/tests/libzscanner/data/05-3_TTL.out
new file mode 100644
index 0000000..1849267
--- /dev/null
+++ b/tests/libzscanner/data/05-3_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZS_NUMBER32_OVERFLOW
+------
diff --git a/tests/libzscanner/data/05-4_TTL.in b/tests/libzscanner/data/05-4_TTL.in
new file mode 100644
index 0000000..efaf4d0
--- /dev/null
+++ b/tests/libzscanner/data/05-4_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 1x ; Unknown time unit
diff --git a/tests/libzscanner/data/05-4_TTL.out b/tests/libzscanner/data/05-4_TTL.out
new file mode 100644
index 0000000..d4bef98
--- /dev/null
+++ b/tests/libzscanner/data/05-4_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_TIME_UNIT
+------
diff --git a/tests/libzscanner/data/06-0_INCLUDE.in b/tests/libzscanner/data/06-0_INCLUDE.in
new file mode 100644
index 0000000..962e6c9
--- /dev/null
+++ b/tests/libzscanner/data/06-0_INCLUDE.in
@@ -0,0 +1,29 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+0. NS @
+
+$INCLUDE ./includes/include1 ; Relative path without origin
+1. NS @
+
+$INCLUDE "./includes/include2" . ; Quoted filename and the simplest origin
+2. NS @
+
+$INCLUDE ./includes/include\050 tld. ; Simple origin
+3. NS @
+
+$INCLUDE \./includes/include2 _a_.-b-c-./d/. ; Slashed character in file name, allowed characters in origin
+4. NS @
+
+$INCLUDE ./includes/include2 \0320\ \\\"\.\@\*.tld. ; Origin with special chars
+5. NS @
+
+$INCLUDE @TMPDIR@/includes/include2 ; Absolute path without origin
+6. NS @
+
+$INCLUDE @TMPDIR@/includes/include2 tld. ; Absolute path with origin
+7. NS @
+
+; KO (DISABLED - different results)
+;$INCLUDE ; Empty parameters
diff --git a/tests/libzscanner/data/06-0_INCLUDE.out b/tests/libzscanner/data/06-0_INCLUDE.out
new file mode 100644
index 0000000..2536f72
--- /dev/null
+++ b/tests/libzscanner/data/06-0_INCLUDE.out
@@ -0,0 +1,138 @@
+OWNER=013000
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016105746C64316100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=016105746C64316200
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=05746C64316200
+------
+OWNER=013100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016200
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013200
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016203746C6400
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013300
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0162035F615F052D622D632D032F642F00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=035F615F052D622D632D032F642F00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0162082030205C222E402A03746C6400
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013500
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016200
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013600
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016203746C6400
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013700
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
diff --git a/tests/libzscanner/data/06-1_INCLUDE.in b/tests/libzscanner/data/06-1_INCLUDE.in
new file mode 100644
index 0000000..194fb52
--- /dev/null
+++ b/tests/libzscanner/data/06-1_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include1 a ; Origin is not FQDN
diff --git a/tests/libzscanner/data/06-1_INCLUDE.out b/tests/libzscanner/data/06-1_INCLUDE.out
new file mode 100644
index 0000000..6634921
--- /dev/null
+++ b/tests/libzscanner/data/06-1_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_INCLUDE_ORIGIN
+------
diff --git a/tests/libzscanner/data/06-2_INCLUDE.in b/tests/libzscanner/data/06-2_INCLUDE.in
new file mode 100644
index 0000000..21bcf05
--- /dev/null
+++ b/tests/libzscanner/data/06-2_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include1 % ; Bad origin
diff --git a/tests/libzscanner/data/06-2_INCLUDE.out b/tests/libzscanner/data/06-2_INCLUDE.out
new file mode 100644
index 0000000..6634921
--- /dev/null
+++ b/tests/libzscanner/data/06-2_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZS_BAD_INCLUDE_ORIGIN
+------
diff --git a/tests/libzscanner/data/06-3_INCLUDE.in b/tests/libzscanner/data/06-3_INCLUDE.in
new file mode 100644
index 0000000..f7079b4
--- /dev/null
+++ b/tests/libzscanner/data/06-3_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE @TMPDIR@/ ; Given file is a directory
diff --git a/tests/libzscanner/data/06-3_INCLUDE.out b/tests/libzscanner/data/06-3_INCLUDE.out
new file mode 100644
index 0000000..6823154
--- /dev/null
+++ b/tests/libzscanner/data/06-3_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZS_FILE_INVALID
+------
diff --git a/tests/libzscanner/data/06-4_INCLUDE.in b/tests/libzscanner/data/06-4_INCLUDE.in
new file mode 100644
index 0000000..3cdc79d
--- /dev/null
+++ b/tests/libzscanner/data/06-4_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE @TMPDIR@/file-doesnt-exist ; File doesn't exist
diff --git a/tests/libzscanner/data/06-4_INCLUDE.out b/tests/libzscanner/data/06-4_INCLUDE.out
new file mode 100644
index 0000000..e09e5d1
--- /dev/null
+++ b/tests/libzscanner/data/06-4_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZS_FILE_OPEN
+------
diff --git a/tests/libzscanner/data/06-5_INCLUDE.in b/tests/libzscanner/data/06-5_INCLUDE.in
new file mode 100644
index 0000000..1d65812
--- /dev/null
+++ b/tests/libzscanner/data/06-5_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include3 ; Blank include file
diff --git a/tests/libzscanner/data/06-5_INCLUDE.out b/tests/libzscanner/data/06-5_INCLUDE.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libzscanner/data/06-5_INCLUDE.out
diff --git a/tests/libzscanner/data/06-6_INCLUDE.in b/tests/libzscanner/data/06-6_INCLUDE.in
new file mode 100644
index 0000000..cbfda64
--- /dev/null
+++ b/tests/libzscanner/data/06-6_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include4 ; Include file contains warning
diff --git a/tests/libzscanner/data/06-6_INCLUDE.out b/tests/libzscanner/data/06-6_INCLUDE.out
new file mode 100644
index 0000000..a9c0259
--- /dev/null
+++ b/tests/libzscanner/data/06-6_INCLUDE.out
@@ -0,0 +1,4 @@
+WARNG=ZS_BAD_RDATA
+------
+ERROR=ZS_UNPROCESSED_INCLUDE
+------
diff --git a/tests/libzscanner/data/06-7_INCLUDE.in b/tests/libzscanner/data/06-7_INCLUDE.in
new file mode 100644
index 0000000..24deef7
--- /dev/null
+++ b/tests/libzscanner/data/06-7_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include5 ; Include file contains error
diff --git a/tests/libzscanner/data/06-7_INCLUDE.out b/tests/libzscanner/data/06-7_INCLUDE.out
new file mode 100644
index 0000000..cbbb0c1
--- /dev/null
+++ b/tests/libzscanner/data/06-7_INCLUDE.out
@@ -0,0 +1,4 @@
+ERROR=ZS_BAD_NUMBER
+------
+ERROR=ZS_UNPROCESSED_INCLUDE
+------
diff --git a/tests/libzscanner/data/06-8_INCLUDE.in b/tests/libzscanner/data/06-8_INCLUDE.in
new file mode 100644
index 0000000..c856668
--- /dev/null
+++ b/tests/libzscanner/data/06-8_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include6 ; Include file contains include
diff --git a/tests/libzscanner/data/06-8_INCLUDE.out b/tests/libzscanner/data/06-8_INCLUDE.out
new file mode 100644
index 0000000..4581388
--- /dev/null
+++ b/tests/libzscanner/data/06-8_INCLUDE.out
@@ -0,0 +1,12 @@
+OWNER=016200
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
diff --git a/tests/libzscanner/data/07-0-rdata.in b/tests/libzscanner/data/07-0-rdata.in
new file mode 100644
index 0000000..a79403f
--- /dev/null
+++ b/tests/libzscanner/data/07-0-rdata.in
@@ -0,0 +1 @@
+@ A \ \ No newline at end of file
diff --git a/tests/libzscanner/data/07-0-rdata.out b/tests/libzscanner/data/07-0-rdata.out
new file mode 100644
index 0000000..ed303f6
--- /dev/null
+++ b/tests/libzscanner/data/07-0-rdata.out
@@ -0,0 +1,2 @@
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
diff --git a/tests/libzscanner/data/07-1-rdata.in b/tests/libzscanner/data/07-1-rdata.in
new file mode 100644
index 0000000..7a5a11a
--- /dev/null
+++ b/tests/libzscanner/data/07-1-rdata.in
@@ -0,0 +1 @@
+@ TXT \ \ No newline at end of file
diff --git a/tests/libzscanner/data/07-1-rdata.out b/tests/libzscanner/data/07-1-rdata.out
new file mode 100644
index 0000000..1702677
--- /dev/null
+++ b/tests/libzscanner/data/07-1-rdata.out
@@ -0,0 +1,2 @@
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/07-2-rdata.in b/tests/libzscanner/data/07-2-rdata.in
new file mode 100644
index 0000000..7a4c8fe
--- /dev/null
+++ b/tests/libzscanner/data/07-2-rdata.in
@@ -0,0 +1 @@
+@ TXT \092 \ No newline at end of file
diff --git a/tests/libzscanner/data/07-2-rdata.out b/tests/libzscanner/data/07-2-rdata.out
new file mode 100644
index 0000000..3f52437
--- /dev/null
+++ b/tests/libzscanner/data/07-2-rdata.out
@@ -0,0 +1,6 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000000
+RTYPE=0010
+RDATA=015C
+------
diff --git a/tests/libzscanner/data/07-3-rdata.in b/tests/libzscanner/data/07-3-rdata.in
new file mode 100644
index 0000000..338b212
--- /dev/null
+++ b/tests/libzscanner/data/07-3-rdata.in
@@ -0,0 +1 @@
+@ TXT \\ \ No newline at end of file
diff --git a/tests/libzscanner/data/07-3-rdata.out b/tests/libzscanner/data/07-3-rdata.out
new file mode 100644
index 0000000..3f52437
--- /dev/null
+++ b/tests/libzscanner/data/07-3-rdata.out
@@ -0,0 +1,6 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000000
+RTYPE=0010
+RDATA=015C
+------
diff --git a/tests/libzscanner/data/07-4-rdata.in b/tests/libzscanner/data/07-4-rdata.in
new file mode 100644
index 0000000..74a45dd
--- /dev/null
+++ b/tests/libzscanner/data/07-4-rdata.in
@@ -0,0 +1 @@
+@ TXT \# 2 015C \ No newline at end of file
diff --git a/tests/libzscanner/data/07-4-rdata.out b/tests/libzscanner/data/07-4-rdata.out
new file mode 100644
index 0000000..3f52437
--- /dev/null
+++ b/tests/libzscanner/data/07-4-rdata.out
@@ -0,0 +1,6 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000000
+RTYPE=0010
+RDATA=015C
+------
diff --git a/tests/libzscanner/data/10_A.in b/tests/libzscanner/data/10_A.in
new file mode 100644
index 0000000..6c7c90a
--- /dev/null
+++ b/tests/libzscanner/data/10_A.in
@@ -0,0 +1,19 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ A 0.0.0.0 ; Minimal ipv4 address
+@ A 255.255.255.255 ; Maximal ipv4 address
+@ A \# 4 00000000 ; Hexadecimal rdata
+@ TYPE1 \# 4 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE1 0.0.0.0 ; TYPE
+@ a 0.0.0.0 ; Type in lower-case
+
+; KO
+@ A
+@ A ; Empty rdata
+@ A \# 0 ; Hex empty rdata
+@ A 0.0.0.256 ; 8bit overflow
+@ A 0.0.0 ; Short address
+@ A 0.0.0.A ; Bad character
+@ A 0.0.0.0 1.1.1.1 ; Unexpected item
diff --git a/tests/libzscanner/data/10_A.out b/tests/libzscanner/data/10_A.out
new file mode 100644
index 0000000..dda68ab
--- /dev/null
+++ b/tests/libzscanner/data/10_A.out
@@ -0,0 +1,50 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_IPV4
+------
+WARNG=ZS_BAD_IPV4
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/11_AAAA.in b/tests/libzscanner/data/11_AAAA.in
new file mode 100644
index 0000000..48c4b37
--- /dev/null
+++ b/tests/libzscanner/data/11_AAAA.in
@@ -0,0 +1,21 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ AAAA 0:0:0:0:0:0:0:0 ; Minimal ipv6 address
+@ AAAA FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF ; Maximal ipv6 address
+@ AAAA \# 16 00000000 00000000 00000000 00000000 ; Hexadecimal rdata
+@ TYPE28 \# 16 00000000 00000000 00000000 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE28 0:0:0:0:0:0:0:0 ; TYPE
+@ AAAA 0::1.2.3.4 ; ipv6 address based on ipv4 address
+@ AAAA :: ; Double colon
+@ aaAA :: ; Type in lower-case
+
+; KO
+@ AAAA
+@ AAAA ; Empty rdata
+@ AAAA \# 0 ; Hex empty rdata
+@ AAAA 0::FFFFF ; 16bit overflow
+@ AAAA 0:0:0:0:0:0:0 ; Short address
+@ AAAA 0:0:0:0:0:0:0:X ; Bad character
+@ AAAA :: :: ; Unexpected item
diff --git a/tests/libzscanner/data/11_AAAA.out b/tests/libzscanner/data/11_AAAA.out
new file mode 100644
index 0000000..0cb174a
--- /dev/null
+++ b/tests/libzscanner/data/11_AAAA.out
@@ -0,0 +1,62 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000001020304
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_IPV6
+------
+WARNG=ZS_BAD_IPV6
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/12_TXT.in b/tests/libzscanner/data/12_TXT.in
new file mode 100644
index 0000000..cdd0eaa
--- /dev/null
+++ b/tests/libzscanner/data/12_TXT.in
@@ -0,0 +1,37 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ TXT "" ; Blank string
+@ TXT a ; One char string
+@ TXT \ ; One space char
+@ TXT "\ " ; One space char in quotes
+@ TXT \021 ; One unprintable char
+@ TXT "\\ \"" ; Special chars
+@ TXT "" "test1" "\255" test2 ; Array of text strings
+@ TXT "" "" "" ; Array of blank strings
+@ TXT first \# "\#" ; Array with special string
+@ TXT \0320\ \\\"\;\.\@\*.tld. ; Special domain as a string
+@ TXT " !\"#$%&'()*+,-./0123456789:;<=>?@" ; First part of all printables
+@ TXT "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" ; Second part of all printables
+@ TXT "abcdefghijklmnopqrstuvwxyz{|}~" ; Third part of all printables
+@ TXT \# 1 00 ; Hexadecimal rdata
+@ TYPE16 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE16 "" ; TYPE
+@ TXT ( ; Special multi-line string
+"first
+second"
+third ; Second string
+)
+@ TXT "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\053" ; Text string of maximal length (255 chars)
+@ TXT "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\0536" ; Minimum overflowed text string which should be divided into two strings.
+@ TXT "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\053\054" ; Minimum overflowed text string which should be divided into two strings (decimal version).
+@ txt "" ; Type in lower-case
+
+; KO
+@ TXT
+@ TXT ; Empty rdata
+@ TXT \# 0 ; Hex empty rdata
+@ TXT \01 ; Missing digit in decimal notation
+@ TXT \256 ; 8bit overflow in decimal notation
+@ TXT """ ; '"' char without forward slash
diff --git a/tests/libzscanner/data/12_TXT.out b/tests/libzscanner/data/12_TXT.out
new file mode 100644
index 0000000..283b1e0
--- /dev/null
+++ b/tests/libzscanner/data/12_TXT.out
@@ -0,0 +1,138 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0115
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=035C2022
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0005746573743101FF057465737432
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=05666972737401230123
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0E2030205C223B2E402A2E746C642E
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=21202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F40
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=204142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=1E6162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0C66697273740A7365636F6E64057468697264
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=FF6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E3132333435
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=FF6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E31323334350136
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=FF6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E31323334350136
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_TEXT
+------
diff --git a/tests/libzscanner/data/13_SPF.in b/tests/libzscanner/data/13_SPF.in
new file mode 100644
index 0000000..0ad6c84
--- /dev/null
+++ b/tests/libzscanner/data/13_SPF.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The SPF is the same as the TXT, so there are the differences and basics only.
+
+; OK
+@ SPF "" "test1" "\255" test2 ; Array of text strings
+@ SPF \# 1 00 ; Hexadecimal rdata
+@ TYPE99 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE99 "" ; TYPE
+@ spf "" ; Type in lower-case
+
+; KO
+@ SPF
diff --git a/tests/libzscanner/data/13_SPF.out b/tests/libzscanner/data/13_SPF.out
new file mode 100644
index 0000000..be7fb35
--- /dev/null
+++ b/tests/libzscanner/data/13_SPF.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=0005746573743101FF057465737432
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/14_NS.in b/tests/libzscanner/data/14_NS.in
new file mode 100644
index 0000000..b56a579
--- /dev/null
+++ b/tests/libzscanner/data/14_NS.in
@@ -0,0 +1,38 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NS . ; The simplest owner
+@ NS tld. ; FQD tld owner
+@ NS tld ; Relative form
+@ NS *. ; FQD with asterisk
+@ NS * ; Alone asterisk
+@ NS *.* ; More asterisks
+@ NS *a.a*a.** ; Also possible
+@ NS @ ; Use origin
+@ NS 0123456789 ; Digits
+@ NS _a_.-b-c-./d/. ; Allowed characters '_' '-' '/' anywhere
+@ NS ABCDEFGHIJKLMNOPQRSTUVWXYZ ; All upper-case letters
+@ NS abcdefghijklmnopqrstuvwxyz ; All lower-case letters
+@ NS \0320\ \\\"\.\@\*.tld. ; Label with special chars
+@ NS b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. ; IPv6 reverse
+@ NS 123456789012345678901234567890123456789012345678901234567890123.tld. ; Label of maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901. ; Domain name of maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901 ; Domain name of maximal length (after appending origin)
+@ TYPE2 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE2 @ ; TYPE
+@ ns @ ; Type in lower-case
+
+; KO
+@ NS
+@ NS ; Empty rdata
+@ NS \# 0 ; Hex empty rdata
+@ NS & ; Bad (unslashed) character
+@ NS @@ ; Double @@
+@ NS .. ; Missing label between dots
+@ NS \1 ; Slash notation requires 3 digits
+@ NS \12 ; Slash notation requires 3 digits
+@ NS 1234567890123456789012345678901234567890123456789012345678901234.tld. ; Label exceeded maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012. ; Domain name exceeded maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012 ; Domain name exceeded maximal length (after appending origin)
+@ NS . x ; Unexpected item
diff --git a/tests/libzscanner/data/14_NS.out b/tests/libzscanner/data/14_NS.out
new file mode 100644
index 0000000..08d739a
--- /dev/null
+++ b/tests/libzscanner/data/14_NS.out
@@ -0,0 +1,144 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=012A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=012A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=012A012A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=022A6103612A61022A2A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=0A3031323334353637383900
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=035F615F052D622D632D032F642F00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=1A4142434445464748494A4B4C4D4E4F505152535455565758595A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=1A6162636465666768696A6B6C6D6E6F707172737475767778797A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_DNAME_CHAR
+------
+WARNG=ZS_BAD_DNAME_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_LABEL_OVERFLOW
+------
+WARNG=ZS_DNAME_OVERFLOW
+------
+WARNG=ZS_DNAME_OVERFLOW
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/15_CNAME.in b/tests/libzscanner/data/15_CNAME.in
new file mode 100644
index 0000000..806b8f9
--- /dev/null
+++ b/tests/libzscanner/data/15_CNAME.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The CNAME is the same as the NS, so there are the differences and basics only.
+
+; OK
+@ CNAME test.example.com ; Relative dname
+@ CNAME \# 1 00 ; Hexadecimal rdata
+@ TYPE5 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE5 @ ; TYPE
+@ cname @ ; Type in lower-case
+
+; KO
+@ CNAME
diff --git a/tests/libzscanner/data/15_CNAME.out b/tests/libzscanner/data/15_CNAME.out
new file mode 100644
index 0000000..3c3a55d
--- /dev/null
+++ b/tests/libzscanner/data/15_CNAME.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=0474657374076578616D706C6503636F6D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/16_PTR.in b/tests/libzscanner/data/16_PTR.in
new file mode 100644
index 0000000..3694e7d
--- /dev/null
+++ b/tests/libzscanner/data/16_PTR.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The PTR is the same as the NS, so there are the differences and basics only.
+
+; OK
+@ PTR test.example.com ; Relative dname
+@ PTR \# 1 00 ; Hexadecimal rdata
+@ TYPE12 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE12 @ ; TYPE
+@ ptr @ ; Type in lower-case
+
+; KO
+@ PTR
diff --git a/tests/libzscanner/data/16_PTR.out b/tests/libzscanner/data/16_PTR.out
new file mode 100644
index 0000000..55d94b9
--- /dev/null
+++ b/tests/libzscanner/data/16_PTR.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=0474657374076578616D706C6503636F6D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/17_DNAME.in b/tests/libzscanner/data/17_DNAME.in
new file mode 100644
index 0000000..5e9ba71
--- /dev/null
+++ b/tests/libzscanner/data/17_DNAME.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The DNAME is the same as the NS, so there are the differences and basics only.
+
+; OK
+@ DNAME test.example.com ; Relative dname
+@ DNAME \# 1 00 ; Hexadecimal rdata
+@ TYPE39 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE39 @ ; TYPE
+@ dname @ ; Type in lower-case
+
+; KO
+@ DNAME
diff --git a/tests/libzscanner/data/17_DNAME.out b/tests/libzscanner/data/17_DNAME.out
new file mode 100644
index 0000000..35f11d8
--- /dev/null
+++ b/tests/libzscanner/data/17_DNAME.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=0474657374076578616D706C6503636F6D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/18_MX.in b/tests/libzscanner/data/18_MX.in
new file mode 100644
index 0000000..61e6afb
--- /dev/null
+++ b/tests/libzscanner/data/18_MX.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; For more tests on dname see NS test (same processing)
+
+; OK
+@ MX 0 @ ; Minimal priority
+@ MX 65535 @ ; Maximal priority
+@ MX 1 mail ; Relative dname
+@ MX 1 mail.tld. ; Absolute dname
+@ MX \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE15 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE15 1 @ ; TYPE
+@ mx 1 @ ; Type in lower-case
+
+; KO
+@ MX
+@ MX ; Empty rdata
+@ MX \# 0 ; Hex empty rdata
+@ MX -1 @ ; Negative number
+@ MX 65536 @ ; 16bit overflow
+@ MX 1 $ ; Bad dname
+@ MX 0 @ x ; Unexpected item
diff --git a/tests/libzscanner/data/18_MX.out b/tests/libzscanner/data/18_MX.out
new file mode 100644
index 0000000..0a50038
--- /dev/null
+++ b/tests/libzscanner/data/18_MX.out
@@ -0,0 +1,62 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=FFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001046D61696C03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=000100
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/19_AFSDB.in b/tests/libzscanner/data/19_AFSDB.in
new file mode 100644
index 0000000..be569e4
--- /dev/null
+++ b/tests/libzscanner/data/19_AFSDB.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The AFSDB is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ AFSDB 1 mail ; Relative dname
+@ AFSDB \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE18 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE18 1 @ ; TYPE
+@ afsdb 1 @ ; Type in lower-case
+
+; KO
+@ AFSDB
diff --git a/tests/libzscanner/data/19_AFSDB.out b/tests/libzscanner/data/19_AFSDB.out
new file mode 100644
index 0000000..b5c77eb
--- /dev/null
+++ b/tests/libzscanner/data/19_AFSDB.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=0001046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=000100
+------
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/20_RT.in b/tests/libzscanner/data/20_RT.in
new file mode 100644
index 0000000..3bc774d
--- /dev/null
+++ b/tests/libzscanner/data/20_RT.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The RT is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ RT 1 mail ; Relative dname
+@ RT \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE21 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE21 1 @ ; TYPE
+@ rt 1 @ ; Type in lower-case
+
+; KO
+@ RT
diff --git a/tests/libzscanner/data/20_RT.out b/tests/libzscanner/data/20_RT.out
new file mode 100644
index 0000000..8be89a3
--- /dev/null
+++ b/tests/libzscanner/data/20_RT.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=0001046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=000100
+------
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/21_KX.in b/tests/libzscanner/data/21_KX.in
new file mode 100644
index 0000000..529480d
--- /dev/null
+++ b/tests/libzscanner/data/21_KX.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The KX is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ KX 1 mail ; Relative dname
+@ KX \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE36 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE36 1 @ ; TYPE
+@ kx 1 @ ; Type in lower-case
+
+; KO
+@ KX
diff --git a/tests/libzscanner/data/21_KX.out b/tests/libzscanner/data/21_KX.out
new file mode 100644
index 0000000..1bc91e6
--- /dev/null
+++ b/tests/libzscanner/data/21_KX.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=0001046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=000100
+------
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/22_HINFO.in b/tests/libzscanner/data/22_HINFO.in
new file mode 100644
index 0000000..4cd5ab8
--- /dev/null
+++ b/tests/libzscanner/data/22_HINFO.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ HINFO "" "" ; Blank string
+@ HINFO a b ; One char string
+@ HINFO \ \ ; One space char
+@ HINFO "\ " "\ " ; One space char in quotes
+@ HINFO \021 \022 ; One unprintable char
+@ HINFO "\\ \"" "\\ \"" ; Special chars
+@ HINFO first \# ; Array with special string
+@ HINFO \# 2 00 00 ; Hexadecimal rdata
+@ TYPE13 \# 2 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE13 "" "" ; TYPE
+@ HINFO "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\053" "" ; Text string of maximal length (255 chars)
+@ hinfo "" "" ; Type in lower-case
+
+; KO
+@ HINFO
+@ HINFO ; Empty rdata
+@ HINFO \# 0 ; Hex empty rdata
+@ HINFO \01 "" ; Missing digit in decimal notation
+@ HINFO \256 "" ; 8bit overflow in decimal notation
+@ HINFO """ "" ; '"' char without forward slash
+@ HINFO "" "" "" ; Unexpected item
+@ HINFO "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\0536" "" ; Maximal length overflow
diff --git a/tests/libzscanner/data/22_HINFO.out b/tests/libzscanner/data/22_HINFO.out
new file mode 100644
index 0000000..fa66729
--- /dev/null
+++ b/tests/libzscanner/data/22_HINFO.out
@@ -0,0 +1,88 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01610162
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01200120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01200120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01150116
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=035C2022035C2022
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0566697273740123
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=FF6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E313233343500
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_TEXT
+------
+WARNG=ZS_BAD_REST
+------
+WARNG=ZS_ITEM_OVERFLOW
+------
diff --git a/tests/libzscanner/data/23_MINFO.in b/tests/libzscanner/data/23_MINFO.in
new file mode 100644
index 0000000..7b34c60
--- /dev/null
+++ b/tests/libzscanner/data/23_MINFO.in
@@ -0,0 +1,18 @@
+$ORIGIN .
+$TTL 1
+
+; For more tests on dname see NS test (same processing)
+
+; OK
+@ MINFO . . ; The simplest dnames
+@ MINFO @ @ ; Use origin
+@ MINFO mail mail.tld. ; Relative and absolute dnames
+@ MINFO \# 2 00 00 ; Hexadecimal rdata
+@ TYPE14 \# 2 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE14 @ @ ; TYPE
+@ minfo @ @ ; Type in lower-case
+
+; KO
+@ MINFO
+@ MINFO ; Empty rdata
+@ MINFO \# 0 ; Hex empty rdata
diff --git a/tests/libzscanner/data/23_MINFO.out b/tests/libzscanner/data/23_MINFO.out
new file mode 100644
index 0000000..8154c0c
--- /dev/null
+++ b/tests/libzscanner/data/23_MINFO.out
@@ -0,0 +1,48 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=046D61696C00046D61696C03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=0000
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/24_RP.in b/tests/libzscanner/data/24_RP.in
new file mode 100644
index 0000000..a70d792
--- /dev/null
+++ b/tests/libzscanner/data/24_RP.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The RP is the same as the MINFO, so there are the differences and basics only.
+
+; OK
+@ RP mail mail.tld. ; Relative and absolute dnames
+@ RP \# 2 00 00 ; Hexadecimal rdata
+@ TYPE17 \# 2 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE17 @ @ ; TYPE
+@ rp @ @ ; Type in lower-case
+
+; KO
+@ RP
diff --git a/tests/libzscanner/data/24_RP.out b/tests/libzscanner/data/24_RP.out
new file mode 100644
index 0000000..d13b1ba
--- /dev/null
+++ b/tests/libzscanner/data/24_RP.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=046D61696C00046D61696C03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=0000
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/25_SOA.in b/tests/libzscanner/data/25_SOA.in
new file mode 100644
index 0000000..bf093d4
--- /dev/null
+++ b/tests/libzscanner/data/25_SOA.in
@@ -0,0 +1,31 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ SOA @ @ 0 0 0 0 0 ; The simplest variant
+@ SOA tld. tld 0 0 0 0 0 ; Absolute and relative dnames.
+@ SOA @ @ 4294967295 0 0 0 0 ; Maximal serial
+@ SOA @ @ 0 4294967295 4294967295 4294967295 4294967295 ; Maximal times
+@ SOA @ @ 0 1d 1h 1m 1s ; Time units
+@ TYPE6 \# 22 00 00 0000000000000000000000000000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE6 @ @ 0 0 0 0 0 ; TYPE
+@ SOA ns.tld. first\.second.tld. ( ; Multiline record
+ 2007120710
+ 1w2d3h4m5s
+ 2h
+ 3m
+ 4s
+)
+@ soa @ @ 0 0 0 0 0 ; Type in lower-case
+
+; KO
+@ SOA
+@ SOA ; Empty rdata
+@ SOA \# 0 ; Hex empty rdata
+@ SOA @ @ 1h 0 0 0 0 ; Bad number
+@ SOA @ @ 4294967296 0 0 0 0 ; Serial overflow
+@ SOA @ @ 0 4294967296 0 0 0 ; Refresh overflow
+@ SOA @ @ 0 0 4294967296 0 0 ; Retry overflow
+@ SOA @ @ 0 0 0 4294967296 0 ; Expire overflow
+@ SOA @ @ 0 0 0 0 4294967296 ; Minimum overflow
+@ SOA @ @ 0 0 0 0 0 x ; Unexpected item
diff --git a/tests/libzscanner/data/25_SOA.out b/tests/libzscanner/data/25_SOA.out
new file mode 100644
index 0000000..f658442
--- /dev/null
+++ b/tests/libzscanner/data/25_SOA.out
@@ -0,0 +1,74 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00000000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=03746C640003746C64000000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=0000FFFFFFFF00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=0000000000000001518000000E100000003C00000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00000000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00000000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=026E7303746C64000C66697273742E7365636F6E6403746C640077A23B46000C08A500001C20000000B400000004
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00000000000000000000000000000000000000000000
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/26_SRV.in b/tests/libzscanner/data/26_SRV.in
new file mode 100644
index 0000000..001e1e6
--- /dev/null
+++ b/tests/libzscanner/data/26_SRV.in
@@ -0,0 +1,25 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ SRV 0 0 0 @ ; The simplest variant
+_ldap._tcp.test.tld. SRV 0 0 0 @ ; Underscores in owner
+@ SRV 65535 65535 65535 @ ; Maximal numbers
+@ SRV 0 0 0 \0320\ \\\"\.\@\*.tld. ; Dname with specials
+@ TYPE33 \# 7 000000000000 00 ; TYPE + Hexadecimal rdata
+@ TYPE33 0 0 0 @ ; TYPE
+@ srv 0 0 0 @ ; Type in lower-case
+
+; KO
+@ SRV
+@ SRV ; Empty rdata
+@ SRV \# 0 ; Hex empty rdata
+@ SRV 1h 0 0 @ ; Bad priority
+@ SRV 0 1h 0 @ ; Bad weight
+@ SRV 0 0 1h @ ; Bad port
+@ SRV 0 0 0 % ; Bad target
+@ SRV 65536 0 0 @ ; Priority overflow
+@ SRV 0 65536 0 @ ; Weight overflow
+@ SRV 0 0 65536 @ ; Port overflow
+@ SRV 0 0 0 @ x ; Unexpected item
+@ SRV 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/26_SRV.out b/tests/libzscanner/data/26_SRV.out
new file mode 100644
index 0000000..eadb804
--- /dev/null
+++ b/tests/libzscanner/data/26_SRV.out
@@ -0,0 +1,66 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=00000000000000
+------
+OWNER=055F6C646170045F746370047465737403746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=00000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=FFFFFFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=000000000000082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=00000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=00000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=00000000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_REST
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/27_NAPTR.in b/tests/libzscanner/data/27_NAPTR.in
new file mode 100644
index 0000000..44fd346
--- /dev/null
+++ b/tests/libzscanner/data/27_NAPTR.in
@@ -0,0 +1,20 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NAPTR 0 0 "" "" "" @ ; The simplest variant
+@ NAPTR 65535 65535 "" "" "" @ ; Maximal numbers
+@ NAPTR 65535 65535 "" "" "!^urn:cid:.+@([^\.]+\.)(.*)$!\\2!i" @ ; Regexp example
+@ NAPTR 0 0 "" "" "" \0320\ \\\"\.\@\*.tld. ; Dname with specials
+@ TYPE35 \# 8 00000000000000 00 ; TYPE + Hexadecimal rdata
+@ TYPE35 0 0 "" "" "" @ ; TYPE
+@ naptr 0 0 "" "" "" @ ; Type in lower-case
+
+; KO
+@ NAPTR
+@ NAPTR ; Empty rdata
+@ NAPTR \# 0 ; Hex empty rdata
+@ NAPTR 65536 0 "" "" "" @ ; Order overflow
+@ NAPTR 0 65536 "" "" "" @ ; Preference overflow
+@ NAPTR 0 0 "" "" "" @ x ; Unexpected item
+@ NAPTR 0 0 "" "" "" ; Missing item
diff --git a/tests/libzscanner/data/27_NAPTR.out b/tests/libzscanner/data/27_NAPTR.out
new file mode 100644
index 0000000..cc34e26
--- /dev/null
+++ b/tests/libzscanner/data/27_NAPTR.out
@@ -0,0 +1,56 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=FFFFFFFF00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=FFFFFFFF00001F215E75726E3A6369643A2E2B40285B5E2E5D2B2E29282E2A2924215C32216900
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=00000000000000082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=0000000000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_REST
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/28_TYPE.in b/tests/libzscanner/data/28_TYPE.in
new file mode 100644
index 0000000..f8189e8
--- /dev/null
+++ b/tests/libzscanner/data/28_TYPE.in
@@ -0,0 +1,27 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ TYPE0 \# 0 ; Minimal type number
+@ TYPE65535 \# 0 ; Maximal type number
+@ TYPE55555 \# 0 ; Without hex rdata
+@ TYPE55555 \# 1 00 ; Without hex rdata
+@ TYPE1 \# 4 00000000 ; Known type
+@ TYPE1 0.0.0.0 ; Known type in text format
+@ TYPE55555 ( ; Multiline begin
+ \#
+ 5
+ 0102 03
+ 04 05
+ ) ; Multiline end
+@ type55555 \# 0 ; Type in lower-case
+
+; KO
+@ TYPE55555
+@ TYPE55555 ; Without text rdata
+@ TYPE65536 ; Type number overflow
+@ TYPE65535x ; Bad type
+@ TYPE55555 \# ; Missing hex length
+@ TYPE55555 \# 1 0000 ; Too long rdata
+@ TYPE55555 \# 2 00 ; Bad rdata length
+@ TYPE55555 \# 1 00 x ; Unexpected data
diff --git a/tests/libzscanner/data/28_TYPE.out b/tests/libzscanner/data/28_TYPE.out
new file mode 100644
index 0000000..0aa409a
--- /dev/null
+++ b/tests/libzscanner/data/28_TYPE.out
@@ -0,0 +1,64 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0000
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=FFFF
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=0102030405
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=
+------
+WARNG=ZS_CANNOT_TEXT_DATA
+------
+WARNG=ZS_CANNOT_TEXT_DATA
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_RDATA_LENGTH
+------
+WARNG=ZS_BAD_RDATA_LENGTH
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/29_CERT.in b/tests/libzscanner/data/29_CERT.in
new file mode 100644
index 0000000..ee70ce2
--- /dev/null
+++ b/tests/libzscanner/data/29_CERT.in
@@ -0,0 +1,58 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ CERT 0 0 0 AA== ; The simplest variant
+@ CERT 65535 65535 255 AA== ; Maximal numbers
+@ CERT PKIX 0 0 AA== ; Certificate type mnemo
+@ CERT SPKI 0 0 AA== ; Certificate type mnemo
+@ CERT PGP 0 0 AA== ; Certificate type mnemo
+@ CERT IPKIX 0 0 AA== ; Certificate type mnemo
+@ CERT ISPKI 0 0 AA== ; Certificate type mnemo
+@ CERT IPGP 0 0 AA== ; Certificate type mnemo
+@ CERT ACPKIX 0 0 AA== ; Certificate type mnemo
+@ CERT IACPKIX 0 0 AA== ; Certificate type mnemo
+@ CERT URI 0 0 AA== ; Certificate type mnemo
+@ CERT OID 0 0 AA== ; Certificate type mnemo
+@ CERT 0 0 RSAMD5 AA== ; Algorithm mnemo
+@ CERT 0 0 DH AA== ; Algorithm mnemo
+@ CERT 0 0 DSA AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA1 AA== ; Algorithm mnemo
+@ CERT 0 0 DSA-NSEC3-SHA1 AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA1-NSEC3-SHA1 AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA256 AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA512 AA== ; Algorithm mnemo
+@ CERT 0 0 ECC-GOST AA== ; Algorithm mnemo
+@ CERT 0 0 ECDSAP256SHA256 AA== ; Algorithm mnemo
+@ CERT 0 0 ECDSAP384SHA384 AA== ; Algorithm mnemo
+@ CERT 0 0 ED25519 AA== ; Algorithm mnemo
+@ CERT 0 0 ED448 AA== ; Algorithm mnemo
+@ CERT 0 0 INDIRECT AA== ; Algorithm mnemo
+@ CERT 0 0 PRIVATEDNS AA== ; Algorithm mnemo
+@ CERT 0 0 PRIVATEOID AA== ; Algorithm mnemo
+@ CERT 0 0 0 Zm8= ; One char padding
+@ CERT 0 0 0 Zm9v ; Without padding
+@ CERT 0 0 0 Zm9vYg== ; Two base64 blocks
+@ CERT 0 0 0 Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE37 \# 6 000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE37 0 0 0 AA== ; TYPE
+@ cert 0 0 0 AA== ; Type in lower-case
+
+; KO
+@ CERT
+@ CERT ; Empty rdata
+@ CERT \# 0 ; Hex empty rdata
+@ CERT 65536 0 0 AA== ; Type overflow
+@ CERT X 0 0 AA== ; Bad type mnemonic
+@ CERT 0 65536 0 AA== ; Key tag overflow
+@ CERT 0 0 256 AA== ; Algorithm overflow
+@ CERT 0 0 0 A ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 AB ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 ABC ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 AA == ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 A=== ; Bad padding
+@ CERT 0 0 0 = ; Bad padding
+@ CERT 0 0 0 == ; Bad padding
+@ CERT 0 0 0 === ; Bad padding
+@ CERT 0 0 0 ==== ; Bad padding
+@ CERT 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/29_CERT.out b/tests/libzscanner/data/29_CERT.out
new file mode 100644
index 0000000..da2c897
--- /dev/null
+++ b/tests/libzscanner/data/29_CERT.out
@@ -0,0 +1,244 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=FFFFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000100000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000200000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000300000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000400000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000500000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000600000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000700000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000800000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00FD00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00FE00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000200
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000300
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000500
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000600
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000700
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000800
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000E00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000F00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000001000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00000000FC00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00000000FD00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00000000FE00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_CERT_TYPE
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/30_KEY.in b/tests/libzscanner/data/30_KEY.in
new file mode 100644
index 0000000..263fa03
--- /dev/null
+++ b/tests/libzscanner/data/30_KEY.in
@@ -0,0 +1,31 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ KEY 0 0 0 AA== ; The simplest variant
+@ KEY 65535 255 255 AA== ; Maximal numbers
+@ KEY 0 0 0 Zm8= ; One char padding
+@ KEY 0 0 0 Zm9v ; Without padding
+@ KEY 0 0 0 Zm9vYg== ; Two base64 blocks
+@ KEY 0 0 0 Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE25 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE25 0 0 0 AA== ; TYPE
+@ key 0 0 0 AA== ; Type in lower-case
+
+; KO
+@ KEY
+@ KEY ; Empty rdata
+@ KEY \# 0 ; Hex empty rdata
+@ KEY 65536 0 0 AA== ; Type overflow
+@ KEY 0 256 0 AA== ; Key tag overflow
+@ KEY 0 0 256 AA== ; Algorithm overflow
+@ KEY 0 0 0 A ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 AB ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 ABC ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 AA == ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 A=== ; Bad padding
+@ KEY 0 0 0 = ; Bad padding
+@ KEY 0 0 0 == ; Bad padding
+@ KEY 0 0 0 === ; Bad padding
+@ KEY 0 0 0 ==== ; Bad padding
+@ KEY 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/30_KEY.out b/tests/libzscanner/data/30_KEY.out
new file mode 100644
index 0000000..1ec998b
--- /dev/null
+++ b/tests/libzscanner/data/30_KEY.out
@@ -0,0 +1,86 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/31_DNSKEY.in b/tests/libzscanner/data/31_DNSKEY.in
new file mode 100644
index 0000000..871de97
--- /dev/null
+++ b/tests/libzscanner/data/31_DNSKEY.in
@@ -0,0 +1,32 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ DNSKEY 0 0 0 AA== ; The simplest variant
+@ DNSKEY 65535 255 255 AA== ; Maximal numbers
+@ DNSKEY 0 0 RSAMD5 AA== ; Algorithm mnemonic
+@ DNSKEY 0 0 0 Zm8= ; One char padding
+@ DNSKEY 0 0 0 Zm9v ; Without padding
+@ DNSKEY 0 0 0 Zm9vYg== ; Two base64 blocks
+@ DNSKEY 0 0 0 Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE48 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE48 0 0 0 AA== ; TYPE
+@ dnskey 0 0 0 AA== ; Type in lower-case
+
+; KO
+@ DNSKEY
+@ DNSKEY ; Empty rdata
+@ DNSKEY \# 0 ; Hex empty rdata
+@ DNSKEY 65536 0 0 AA== ; Type overflow
+@ DNSKEY 0 256 0 AA== ; Key tag overflow
+@ DNSKEY 0 0 256 AA== ; Algorithm overflow
+@ DNSKEY 0 0 0 A ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 AB ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 ABC ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 AA == ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 A=== ; Bad padding
+@ DNSKEY 0 0 0 = ; Bad padding
+@ DNSKEY 0 0 0 == ; Bad padding
+@ DNSKEY 0 0 0 === ; Bad padding
+@ DNSKEY 0 0 0 ==== ; Bad padding
+@ DNSKEY 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/31_DNSKEY.out b/tests/libzscanner/data/31_DNSKEY.out
new file mode 100644
index 0000000..fa034c5
--- /dev/null
+++ b/tests/libzscanner/data/31_DNSKEY.out
@@ -0,0 +1,92 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/32_APL.in b/tests/libzscanner/data/32_APL.in
new file mode 100644
index 0000000..ea9a747
--- /dev/null
+++ b/tests/libzscanner/data/32_APL.in
@@ -0,0 +1,30 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ APL ; The simplest variant - blank list
+@ APL 1:0.0.0.0/0 ; Minimal ipv4 prefix length
+@ APL 1:255.255.255.255/32 ; Maximal ipv4 prefix length
+@ APL 1:255.255.255.255/30 ; Prefix length isn't multiple of 8
+@ APL 2:::/0 ; Minimal ipv6 address
+@ APL 2:0::0/0 ; Minimal ipv6 prefix length
+@ APL 2:0::0/128 ; Maximal ipv6 prefix length
+@ APL 2:FFFF:FFFF:FFFF::/2 ; Trailing zeroes test
+@ APL !1:0.0.0.0/0 ; Negation flag
+@ APL 1:0.0.0.0/0 1:255.255.255.255/32 ; More APLs
+@ TYPE42 \# 4 00010000 ; TYPE + Hexadecimal rdata
+@ TYPE42 1:0.0.0.0/0 ; TYPE
+@ APL \# 0 ; Zero length rdata
+@ apl 1:0.0.0.0/0 ; Type in lower-case
+
+; KO
+@ APL 0:0.0.0.0/32 ; Bad address family
+@ APL x:0.0.0.0/32 ; Bad address family
+@ APL !x:0.0.0.0/32 ; Bad address family
+@ APL 2:0.0.0.0/32 ; Address family mismatch
+@ APL 1:0::0/32 ; Address family mismatch
+@ APL 1:0.0.0.0/33 ; Prefix length is too long
+@ APL 2:0::0/129 ; Prefix length is too long
+@ APL 2::/0 ; Bad ipv6 address
+@ APL 2:0::0/x ; Bad prefix length
+@ APL 1:0.0.0.0/ ; Missing prefix length
diff --git a/tests/libzscanner/data/32_APL.out b/tests/libzscanner/data/32_APL.out
new file mode 100644
index 0000000..50ec101
--- /dev/null
+++ b/tests/libzscanner/data/32_APL.out
@@ -0,0 +1,104 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00012004FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00011E04FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00020000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00020000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00028000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00020206FFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010080
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=0001000000012004FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+WARNG=ZS_BAD_APL
+------
+WARNG=ZS_BAD_APL
+------
+WARNG=ZS_BAD_APL
+------
+WARNG=ZS_BAD_IPV6
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_APL
+------
+WARNG=ZS_BAD_APL
+------
+WARNG=ZS_BAD_IPV6
+------
+WARNG=ZS_BAD_APL
+------
+WARNG=ZS_BAD_APL
+------
diff --git a/tests/libzscanner/data/33_DS.in b/tests/libzscanner/data/33_DS.in
new file mode 100644
index 0000000..a5d805c
--- /dev/null
+++ b/tests/libzscanner/data/33_DS.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ DS 0 0 0 00 ; The simplest variant
+@ DS 65535 255 255 00 ; Maximal numbers
+@ DS 0 RSAMD5 0 00 ; Algorithm mnemonic
+@ DS 0 0 0 01 02 0304 ; Hex block with blank spaces between them
+@ TYPE43 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE43 0 0 0 00 ; TYPE
+@ ds 0 0 0 00 ; Type in lower-case
+
+; KO
+@ DS
+@ DS ; Empty rdata
+@ DS \# 0 ; Hex empty rdata
+@ DS 65536 0 0 00 ; Key tag overflow
+@ DS 0 256 0 00 ; Algorithm overflow
+@ DS 0 0 256 00 ; Digest type overflow
+@ DS 0 0 0 0 ; Continuous block length must be multiple of 2
+@ DS 0 0 0 00 0 ; Continuous block length must be multiple of 2
+@ DS 0 0 0 XX ; Bad hex character
+@ DS 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/33_DS.out b/tests/libzscanner/data/33_DS.out
new file mode 100644
index 0000000..2257119
--- /dev/null
+++ b/tests/libzscanner/data/33_DS.out
@@ -0,0 +1,62 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000001020304
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/34_SSHFP.in b/tests/libzscanner/data/34_SSHFP.in
new file mode 100644
index 0000000..89c4de3
--- /dev/null
+++ b/tests/libzscanner/data/34_SSHFP.in
@@ -0,0 +1,21 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ SSHFP 0 0 00 ; The simplest variant
+@ SSHFP 255 255 00 ; Maximal numbers
+@ SSHFP 0 0 01 02 0304 ; Hex block with blank spaces between them
+@ TYPE44 \# 3 000000 ; TYPE + Hexadecimal rdata
+@ TYPE44 0 0 00 ; TYPE
+@ sshfp 0 0 00 ; Type in lower-case
+
+; KO
+@ SSHFP
+@ SSHFP ; Empty rdata
+@ SSHFP \# 0 ; Hex empty rdata
+@ SSHFP 256 0 00 ; Algorithm overflow
+@ SSHFP 0 256 00 ; Fp type overflow
+@ SSHFP 0 0 0 ; Continuous block length must be multiple of 2
+@ SSHFP 0 0 00 0 ; Continuous block length must be multiple of 2
+@ SSHFP 0 0 XX ; Bad hex character
+@ SSHFP 0 0 ; Missing item
diff --git a/tests/libzscanner/data/34_SSHFP.out b/tests/libzscanner/data/34_SSHFP.out
new file mode 100644
index 0000000..da8ce6d
--- /dev/null
+++ b/tests/libzscanner/data/34_SSHFP.out
@@ -0,0 +1,54 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=FFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000001020304
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/35_IPSECKEY.in b/tests/libzscanner/data/35_IPSECKEY.in
new file mode 100644
index 0000000..dc56bd7
--- /dev/null
+++ b/tests/libzscanner/data/35_IPSECKEY.in
@@ -0,0 +1,29 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ IPSECKEY 0 0 0 . ; The simplest variant - no gw, no key
+@ IPSECKEY 255 3 255 . AA== ; Maximal numbers
+@ IPSECKEY 0 1 0 0.0.0.0 ; IPv4 address
+@ IPSECKEY 0 2 0 :: ; IPv6 address
+@ IPSECKEY 0 3 0 \0320\ \\\"\.\@\*.tld. ; Special chars in domain name
+@ IPSECKEY 0 0 1 . Zm8= ; One char padding
+@ IPSECKEY 0 0 1 . Zm9v ; Without padding
+@ IPSECKEY 0 0 1 . Zm9vYg== ; Two base64 blocks
+@ IPSECKEY 0 0 1 . Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE45 \# 3 000000 ; TYPE + Hexadecimal rdata
+@ TYPE45 0 0 1 . AA== ; TYPE
+@ ipseckey 0 0 1 . AA== ; Type in lower-case
+
+; KO
+@ IPSECKEY
+@ IPSECKEY ; Empty rdata
+@ IPSECKEY \# 0 ; Hex empty rdata
+@ IPSECKEY 256 0 0 . ; Precedence overflow
+@ IPSECKEY 0 4 0 . ; Unknown gateway
+@ IPSECKEY 0 0 256 . AA== ; Algorithm overflow
+@ IPSECKEY 0 0 0 . AA== ; If alg is 0 then key shouldn't be given
+@ IPSECKEY 0 0 0 a% ; Bad domain name char
+@ IPSECKEY 0 0 1 . A ; Continuous block length must be multiple of 4
+@ IPSECKEY 0 0 1 . = ; Bad padding
+@ IPSECKEY 0 0 ; Missing item
diff --git a/tests/libzscanner/data/35_IPSECKEY.out b/tests/libzscanner/data/35_IPSECKEY.out
new file mode 100644
index 0000000..718ce22
--- /dev/null
+++ b/tests/libzscanner/data/35_IPSECKEY.out
@@ -0,0 +1,94 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=FF03FF0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00010000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00020000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000300082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00000100
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_GATEWAY
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_GATEWAY_KEY
+------
+WARNG=ZS_BAD_GATEWAY
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_GATEWAY_KEY
+------
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/36_RRSIG.in b/tests/libzscanner/data/36_RRSIG.in
new file mode 100644
index 0000000..cb873fc
--- /dev/null
+++ b/tests/libzscanner/data/36_RRSIG.in
@@ -0,0 +1,46 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ RRSIG TYPE0 0 0 0 0 0 0 . AA== ; The simplest variant
+@ RRSIG A 2 3 4 5 6 7 \008. CQ== ; Human visual test - block numbering
+@ RRSIG TYPE65535 255 255 4294967295 4294967295 4294967295 65535 . AA== ; Maximal numbers
+@ RRSIG TYPE0 RSAMD5 0 0 0 0 0 . AA== ; Algorithm mnemonic
+@ RRSIG A 0 0 0 19700101000000 0 0 . AA== ; Minimal date format
+@ RRSIG A 0 0 0 0 21051231235959 0 . AA== ; Maximal date format (zscanner original limit)
+@ RRSIG A 0 0 0 0 22251231235959 0 . AA== ; Maximal date format (zscanner limit)
+@ RRSIG TYPE0 0 0 0 0 0 0 \0320\ \\\"\.\@\*.tld. AA== ; Special chars in domain name
+@ RRSIG A 0 0 0 0 0 0 . Zm8= ; One char padding
+@ RRSIG A 0 0 0 0 0 0 . Zm9v ; Without padding
+@ RRSIG A 0 0 0 0 0 0 . Zm9vYg== ; Two base64 blocks
+@ RRSIG A 0 0 0 0 0 0 . Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE46 \# 20 000100000000000000000000000000000000 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE46 A 0 0 0 0 0 0 . AA== ; TYPE
+@ rrsig A 0 0 0 0 0 0 . AA== ; Type in lower-case
+
+; KO
+@ RRSIG
+@ RRSIG ; Empty rdata
+@ RRSIG \# 0 ; Hex empty rdata
+@ RRSIG X 0 0 0 0 0 0 . AA== ; Unknown type
+@ RRSIG TYPE65536 0 0 0 0 0 0 . AA== ; Type overflow
+@ RRSIG A 256 0 0 0 0 0 . AA== ; Algorithm overflow
+@ RRSIG A 0 256 0 0 0 0 . AA== ; Labels overflow
+@ RRSIG A 0 0 4294967296 0 0 0 . AA== ; TTL overflow
+@ RRSIG A 0 0 0 9294967296 0 0 . AA== ; Sig. exp. overflow
+@ RRSIG A 0 0 0 0 4294967296 0 . AA== ; Sig. inc. overflow
+@ RRSIG A 0 0 0 0 0 65536 . AA== ; Key tag overflow
+@ RRSIG A 0 0 0 0 22260101000000 0 . AA== ; Date overflow
+@ RRSIG A 0 0 0 0 2226010100000x 0 . AA== ; Bad timestamp char
+@ RRSIG A 0 0 0 0 222601010000000 0 . AA== ; Bad timestamp length
+@ RRSIG A 0 0 0 0 0 0 a% AA== ; Bad domain char
+@ RRSIG A 0 0 0 0 0 0 . A ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . AB ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . ABC ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . AA == ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . A=== ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . = ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . == ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . === ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . ==== ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . ; Missing item
diff --git a/tests/libzscanner/data/36_RRSIG.out b/tests/libzscanner/data/36_RRSIG.out
new file mode 100644
index 0000000..dff1471
--- /dev/null
+++ b/tests/libzscanner/data/36_RRSIG.out
@@ -0,0 +1,140 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=0000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=00010203000000040000000500000006000701080009
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=0000010000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=0001000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000FFCEDD7F00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000E1853CFF00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000000000000000000000000000000000000082030205C222E402A03746C640000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=00010000000000000000000000000000000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=00010000000000000000000000000000000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=00010000000000000000000000000000000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=00010000000000000000000000000000000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=0001000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=0001000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=0001000000000000000000000000000000000000
+------
+WARNG=ZS_UNSUPPORTED_TYPE
+------
+WARNG=ZS_UNSUPPORTED_TYPE
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_UNSUPPORTED_TYPE
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_DATE
+------
+WARNG=ZS_BAD_TIMESTAMP_CHAR
+------
+WARNG=ZS_BAD_TIMESTAMP_LENGTH
+------
+WARNG=ZS_BAD_DNAME_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/37_NSEC.in b/tests/libzscanner/data/37_NSEC.in
new file mode 100644
index 0000000..1efa4ea
--- /dev/null
+++ b/tests/libzscanner/data/37_NSEC.in
@@ -0,0 +1,20 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NSEC . ; The simplest variant - without bitmap
+@ NSEC \0320\ \\\"\.\@\*.tld. ; Special chars in domain name
+@ NSEC . TYPE0 ; Minimal type number
+@ NSEC . TYPE65535 ; Maximal type number
+@ NSEC . TYPE0 A NS ; First bitmap window
+@ NSEC . TYPE0 TYPE256 TYPE512 TYPE32768 ; First, second, third and 128. bitmap window
+@ TYPE47 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE47 . ; TYPE
+@ nsec . ; Type in lower-case
+
+; KO
+@ NSEC
+@ NSEC ; Empty rdata
+@ NSEC \# 0 ; Hex empty rdata
+@ NSEC . TYPE65536 ; Type number overflow
+@ NSEC . X ; Unknown type
diff --git a/tests/libzscanner/data/37_NSEC.out b/tests/libzscanner/data/37_NSEC.out
new file mode 100644
index 0000000..7a62def
--- /dev/null
+++ b/tests/libzscanner/data/37_NSEC.out
@@ -0,0 +1,64 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00000180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00FF200000000000000000000000000000000000000000000000000000000000000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=000001E0
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00000180010180020180800180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_BITMAP
+------
diff --git a/tests/libzscanner/data/38_DHCID.in b/tests/libzscanner/data/38_DHCID.in
new file mode 100644
index 0000000..4c0642a
--- /dev/null
+++ b/tests/libzscanner/data/38_DHCID.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ DHCID AA== ; The simplest variant
+@ DHCID Zm8= ; One char padding
+@ DHCID Zm9v ; Without padding
+@ DHCID Zm9vYg== ; Two base64 blocks
+@ DHCID Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE49 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE49 AA== ; TYPE
+@ dhcid AA== ; Type in lower-case
+
+; KO
+@ DHCID
+@ DHCID ; Empty rdata
+@ DHCID \# 0 ; Hex empty rdata
+@ DHCID A ; Continuous block length must be multiple of 4
+@ DHCID AB ; Continuous block length must be multiple of 4
+@ DHCID ABC ; Continuous block length must be multiple of 4
+@ DHCID AA == ; Continuous block length must be multiple of 4
+@ DHCID A=== ; Bad padding
+@ DHCID = ; Bad padding
+@ DHCID == ; Bad padding
+@ DHCID === ; Bad padding
+@ DHCID ==== ; Bad padding
diff --git a/tests/libzscanner/data/38_DHCID.out b/tests/libzscanner/data/38_DHCID.out
new file mode 100644
index 0000000..8dc8ec9
--- /dev/null
+++ b/tests/libzscanner/data/38_DHCID.out
@@ -0,0 +1,72 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/39_NSEC3.in b/tests/libzscanner/data/39_NSEC3.in
new file mode 100644
index 0000000..cadbfa9
--- /dev/null
+++ b/tests/libzscanner/data/39_NSEC3.in
@@ -0,0 +1,46 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NSEC3 0 0 0 - 00====== ; The simplest variant - without bitmap
+@ NSEC3 255 255 65535 - 00====== ; Maximal numbers
+@ NSEC3 0 0 0 00FF 00====== ; Hex string
+@ NSEC3 0 0 0 - 00====== ; Eight char padding
+@ NSEC3 0 0 0 - CPNG==== ; Four char padding
+@ NSEC3 0 0 0 - CPNMU=== ; Three char padding
+@ NSEC3 0 0 0 - CPNMUOG= ; One char padding
+@ NSEC3 0 0 0 - CPNMUOJ1 ; Without padding
+@ NSEC3 0 0 0 - CPNMUOJ1E8====== ; Two base32hex blocks
+@ NSEC3 0 0 0 - 00====== TYPE0 ; Minimal type number
+@ NSEC3 0 0 0 - 00====== TYPE65535 ; Maximal type number
+@ NSEC3 0 0 0 - 00====== TYPE0 A NS ; First bitmap window
+@ NSEC3 0 0 0 - 00====== TYPE0 TYPE256 TYPE512 TYPE32768 ; First, second, third and 128. bitmap window
+@ TYPE50 \# 7 00000000000100 ; TYPE + Hexadecimal rdata
+@ TYPE50 0 0 0 - 00====== ; TYPE
+@ nsec3 0 0 0 - 00====== ; Type in lower-case
+
+; KO
+@ NSEC3
+@ NSEC3 ; Empty rdata
+@ NSEC3 \# 0 ; Hex empty rdata
+@ NSEC3 256 0 0 - 00====== ; Algorithm overflow
+@ NSEC3 0 256 0 - 00====== ; Flags overflow
+@ NSEC3 0 0 65536 - 00====== ; Iterations overflow
+@ NSEC3 0 0 0 0 00====== ; Hex block must be multiple of 2
+@ NSEC3 0 0 0 0X 00====== ; Bad hex char
+@ NSEC3 0 0 0 00 FF 00====== ; Hex string with blank space inside
+@ NSEC3 0 0 0 - 1 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 12 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 123 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 1234 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 12345 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 123456 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 1234567 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 123456 78 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - ======== ; Bad padding
+@ NSEC3 0 0 0 - 1======= ; Bad padding
+@ NSEC3 0 0 0 - 123===== ; Bad padding
+@ NSEC3 0 0 0 - 123456== ; Bad padding
+@ NSEC3 0 0 0 - CPNMUOJ1 E8====== ; Two base32hex blocks with blank space between them
+@ NSEC3 0 0 0 - 00====== TYPE65536 ; Type number overflow
+@ NSEC3 0 0 0 - 00====== X ; Unknown type
diff --git a/tests/libzscanner/data/39_NSEC3.out b/tests/libzscanner/data/39_NSEC3.out
new file mode 100644
index 0000000..1aaec4f
--- /dev/null
+++ b/tests/libzscanner/data/39_NSEC3.out
@@ -0,0 +1,144 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=FFFFFFFF000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000200FF0100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000002666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000003666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000004666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000005666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000006666F6F626172
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100000180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100FF200000000000000000000000000000000000000000000000000000000000000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000001000001E0
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100000180010180020180800180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BASE32HEX_CHAR
+------
+WARNG=ZS_BAD_BITMAP
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_BITMAP
+------
diff --git a/tests/libzscanner/data/40_NSEC3PARAM.in b/tests/libzscanner/data/40_NSEC3PARAM.in
new file mode 100644
index 0000000..694e3f7
--- /dev/null
+++ b/tests/libzscanner/data/40_NSEC3PARAM.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NSEC3PARAM 0 0 0 - ; The simplest variant
+@ NSEC3PARAM 255 255 65535 - ; Maximal numbers
+@ NSEC3PARAM 0 0 0 0102FF ; Hex string
+@ TYPE51 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE51 0 0 0 - ; TYPE
+@ nsec3param 0 0 0 - ; Type in lower-case
+
+; KO
+@ NSEC3PARAM
+@ NSEC3PARAM ; Empty rdata
+@ NSEC3PARAM \# 0 ; Hex empty rdata
+@ NSEC3PARAM 256 0 0 00 ; Algorithm overflow
+@ NSEC3PARAM 0 256 0 00 ; Flags overflow
+@ NSEC3PARAM 0 0 65536 00 ; Iterations overflow
+@ NSEC3PARAM 0 0 0 0 ; Hex block length must be multiple of 2
+@ NSEC3PARAM 0 0 0 0x ; Bad hex char
+@ NSEC3PARAM 0 0 0 00 00 ; Hex block must not contain blank spaces
+@ NSEC3PARAM 0 0 0 00 x ; Unexpected item
+@ NSEC3PARAM 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/40_NSEC3PARAM.out b/tests/libzscanner/data/40_NSEC3PARAM.out
new file mode 100644
index 0000000..83b9bb1
--- /dev/null
+++ b/tests/libzscanner/data/40_NSEC3PARAM.out
@@ -0,0 +1,58 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=00000000030102FF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_REST
+------
+WARNG=ZS_BAD_REST
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/41_TLSA.in b/tests/libzscanner/data/41_TLSA.in
new file mode 100644
index 0000000..927498e
--- /dev/null
+++ b/tests/libzscanner/data/41_TLSA.in
@@ -0,0 +1,21 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ TLSA 0 0 0 00 ; The simplest variant
+@ TLSA 255 255 255 00 ; Maximal numbers
+@ TLSA 0 0 0 0102 00 FF ; Hex string with blank spaces inside
+@ TYPE52 \# 4 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE52 0 0 0 00 ; TYPE
+@ tlsa 0 0 0 00 ; Type in lower-case
+
+; KO
+@ TLSA
+@ TLSA ; Empty rdata
+@ TLSA \# 0 ; Hex empty rdata
+@ TLSA 256 0 0 00 ; Algorithm overflow
+@ TLSA 0 256 0 00 ; Flags overflow
+@ TLSA 0 0 256 00 ; Iterations overflow
+@ TLSA 0 0 0 0 ; Hex block length must be multiple of 2
+@ TLSA 0 0 0 0x ; Bad hex char
+@ TLSA 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/41_TLSA.out b/tests/libzscanner/data/41_TLSA.out
new file mode 100644
index 0000000..6f5b6a1
--- /dev/null
+++ b/tests/libzscanner/data/41_TLSA.out
@@ -0,0 +1,54 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=FFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=000000010200FF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/42_LOC.in b/tests/libzscanner/data/42_LOC.in
new file mode 100644
index 0000000..9eaae1d
--- /dev/null
+++ b/tests/libzscanner/data/42_LOC.in
@@ -0,0 +1,64 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ LOC 1 N 1 E 0 ; The simplest case
+@ LOC 0 1 N 1 E 0 ; Combination of parameters
+@ LOC 0 0 1 N 1 E 0 ; Combination of parameters
+@ LOC 1 N 0 1 E 0 ; Combination of parameters
+@ LOC 1 N 0 0 1 E 0 ; Combination of parameters
+@ LOC 1 N 0 0 1 E 0m ; Combination of parameters
+@ LOC 1 N 1 E 0 1 ; Combination of parameters
+@ LOC 1 N 1 E 0 1m ; Combination of parameters
+@ LOC 1 N 1 E 0 0 1 ; Combination of parameters
+@ LOC 1 N 1 E 0 0 1m ; Combination of parameters
+@ LOC 1 N 1 E 0 0 0 1 ; Combination of parameters
+@ LOC 1 N 1 E 0 0 0 1m ; Combination of parameters
+@ LOC 0 0 0 N 0 0 0 E -100000.00 0 0 0 ; Minimal values
+@ LOC 90 59 59.999 S 180 59 59.999 W 42849672.95m 90000000.00m 90000000.00m 90000000.00m ; Maximal values
+@ LOC 0 S 0 0 0.001 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 0.01 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 0.1 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 1.0 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 10 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 W 0 0.01 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 0.10 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 1.0 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 10 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 100 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 1000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 10000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 100000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 1000000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 10000000 ; Number to [mantisa,exponent] test
+@ LOC \# 16 00 00 00 00 00000000 00000000 00000000 ; Hexadecimal rdata
+@ TYPE29 \# 16 00 00 00 00 00000000 00000000 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE29 0 N 0 E 0 ; TYPE
+@ loc 0 N 0 E 0 ; Type in lower-case
+
+; KO
+@ LOC
+@ LOC ; Empty rdata
+@ LOC \# 0 ; Hex empty rdata
+@ LOC 91 0 0 N 0 0 0 E 0 0 0 0 ; Degree overflow
+@ LOC 0 60 0 N 0 0 0 E 0 0 0 0 ; Minute overflow
+@ LOC 0 0 60 0 N 0 0 0 E 0 0 0 0 ; Second overflow
+@ LOC 0 0 0 N 181 0 0 E 0 0 0 0 ; Degree overflow
+@ LOC 0 0 0 N 0 60 0 E 0 0 0 0 ; Minute overflow
+@ LOC 0 0 0 N 0 0 60 E 0 0 0 0 ; Second overflow
+@ LOC 0 0 0 N 0 0 0 E 42849672.96 0 0 0 ; Altitude overflow
+@ LOC 0 0 0 N 0 0 0 E 42849673 0 0 0 ; Altitude overflow
+@ LOC 0 0 0 N 0 0 0 E -100000.01 0 0 0 ; Altitude underflow
+@ LOC 0 0 0 N 0 0 0 E -100001 0 0 0 ; Altitude underflow
+@ LOC 0 0 0 N 0 0 0 E 0 90000000.01 0 0 ; Size overflow
+@ LOC 0 0 0 N 0 0 0 E 0 90000001 0 0 ; Size overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 90000000.01 0 ; HP overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 90000001 0 ; HP overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 0 90000000.01 ; VP overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 0 90000001 ; VP overflow
+@ LOC 1 1 E 0 ; Missing N or S
+@ LOC 1 x 1 E 0 ; Bad letter
+@ LOC 1 N 1 0 ; Missing E or W
+@ LOC 1 N 1 x 0 ; Bad letter
+@ LOC 1 N 1 E ; Missing altitude
+@ LOC 0 0 0 N 0 0 0 E 0 0 0 0 x ; Unexpected item
diff --git a/tests/libzscanner/data/42_LOC.out b/tests/libzscanner/data/42_LOC.out
new file mode 100644
index 0000000..730cc3b
--- /dev/null
+++ b/tests/libzscanner/data/42_LOC.out
@@ -0,0 +1,248 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138000EA608036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800003E88036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808000EA6000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE80800003E800989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE80800003E800989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000012138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000012138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000000128036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000000128036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00000000800000008000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=009999996C79388159295F81FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFFFF00989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFFF600989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFF9C00989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFC1800989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFD8F000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00101613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00111613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00131613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00141613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00151613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00161613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00171613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00181613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00191613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000008000000000989680
+------
+WARNG=ZS_BAD_LOC_DATA
+------
+WARNG=ZS_BAD_LOC_DATA
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_LOC_DATA
+------
+WARNG=ZS_BAD_LOC_DATA
+------
+WARNG=ZS_BAD_LOC_DATA
+------
+WARNG=ZS_BAD_LOC_DATA
+------
+WARNG=ZS_BAD_LOC_DATA
+------
+WARNG=ZS_BAD_LOC_DATA
+------
diff --git a/tests/libzscanner/data/43_EUI48.in b/tests/libzscanner/data/43_EUI48.in
new file mode 100644
index 0000000..a2abbec
--- /dev/null
+++ b/tests/libzscanner/data/43_EUI48.in
@@ -0,0 +1,22 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ EUI48 00-00-00-00-00-00 ; The simplest case
+@ EUI48 FF-FF-FF-FF-FF-FF ; The maximal case
+@ EUI48 aa-bb-cc-dd-ee-ff ; Lower-case
+@ EUI48 \# 6 000000000000 ; Hexadecimal rdata
+@ TYPE108 \# 6 000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE108 00-00-00-00-00-00 ; TYPE
+@ eui48 00-00-00-00-00-00 ; Type in lower-case
+
+; KO
+@ EUI48
+@ EUI48 ; Empty rdata
+@ EUI48 \# 0 ; Hex empty rdata
+@ EUI48 00-00-00-00-00 ; Too few hex pairs
+@ EUI48 00-00-00-00-00-00-00 ; Too many hex pairs
+@ EUI48 00-00-00-00-00-0 ; Missing char in a hex pair
+@ EUI48 00:00-00-00-00-00 ; Bad separator
+@ EUI48 00-00-00-x0-00-00 ; Bad character
+@ EUI48 00-00-00-00-00-00 x ; Unexpected item
diff --git a/tests/libzscanner/data/43_EUI48.out b/tests/libzscanner/data/43_EUI48.out
new file mode 100644
index 0000000..a54a314
--- /dev/null
+++ b/tests/libzscanner/data/43_EUI48.out
@@ -0,0 +1,60 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=FFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=AABBCCDDEEFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_EUI_LENGTH
+------
+WARNG=ZS_BAD_EUI_LENGTH
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_CHAR_DASH
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/44_EUI64.in b/tests/libzscanner/data/44_EUI64.in
new file mode 100644
index 0000000..10f6346
--- /dev/null
+++ b/tests/libzscanner/data/44_EUI64.in
@@ -0,0 +1,22 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ EUI64 00-00-00-00-00-00-00-00 ; The simplest case
+@ EUI64 FF-FF-FF-FF-FF-FF-FF-FF ; The maximal case
+@ EUI64 aa-bb-cc-dd-ee-ff-01-02 ; Lower-case
+@ EUI64 \# 8 0000000000000000 ; Hexadecimal rdata
+@ TYPE109 \# 8 0000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE109 00-00-00-00-00-00-00-00 ; TYPE
+@ eui64 00-00-00-00-00-00-00-00 ; Type in lower-case
+
+; KO
+@ EUI64
+@ EUI64 ; Empty rdata
+@ EUI64 \# 0 ; Hex empty rdata
+@ EUI64 00-00-00-00-00-00-00 ; Too few hex pairs
+@ EUI64 00-00-00-00-00-00-00-00-00 ; Too many hex pairs
+@ EUI64 00-00-00-00-00-00-00-0 ; Missing char in a hex pair
+@ EUI64 00:00-00-00-00-00-00-00 ; Bad separator
+@ EUI64 00-00-00-x0-00-00-00-00 ; Bad character
+@ EUI64 00-00-00-00-00-00-00-00 x ; Unexpected item
diff --git a/tests/libzscanner/data/44_EUI64.out b/tests/libzscanner/data/44_EUI64.out
new file mode 100644
index 0000000..4cce5f5
--- /dev/null
+++ b/tests/libzscanner/data/44_EUI64.out
@@ -0,0 +1,60 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=FFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=AABBCCDDEEFF0102
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_EUI_LENGTH
+------
+WARNG=ZS_BAD_EUI_LENGTH
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_CHAR_DASH
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/45_NID.in b/tests/libzscanner/data/45_NID.in
new file mode 100644
index 0000000..a85f9c3
--- /dev/null
+++ b/tests/libzscanner/data/45_NID.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The NID is the same as the L64, so there are the differences and basics only.
+
+; OK
+@ NID 0 0000:0000:0000:0000 ; The simplest case
+@ NID \# 10 00000000000000000000 ; Hexadecimal rdata
+@ TYPE104 \# 10 00000000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE104 0 0000:0000:0000:0000 ; TYPE
+@ nid 0 0000:0000:0000:0000 ; Type in lower-case
+
+; KO
+@ NID
diff --git a/tests/libzscanner/data/45_NID.out b/tests/libzscanner/data/45_NID.out
new file mode 100644
index 0000000..a2bfb4c
--- /dev/null
+++ b/tests/libzscanner/data/45_NID.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/46_L32.in b/tests/libzscanner/data/46_L32.in
new file mode 100644
index 0000000..866e953
--- /dev/null
+++ b/tests/libzscanner/data/46_L32.in
@@ -0,0 +1,21 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ L32 0 0.0.0.0 ; The simplest case
+@ L32 65535 255.255.255.255 ; The maximal case
+@ L32 \# 6 000000000000 ; Hexadecimal rdata
+@ TYPE105 \# 6 000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE105 0 0.0.0.0 ; TYPE
+@ l32 0 0.0.0.0 ; Type in lower-case
+
+; KO
+@ L32
+@ L32 ; Empty rdata
+@ L32 \# 0 ; Hex empty rdata
+@ L32 65536 0.0.0.0 ; Too big preference
+@ L32 0 0.0.0.256 ; 8-bit overflow
+@ L32 0 0.0.0 ; Short address
+@ L32 0 0.0.0.0.0 ; Long address
+@ L32 0 0.0.0.x ; Bad character
+@ L32 0 0.0.0.0 x ; Unexpected item
diff --git a/tests/libzscanner/data/46_L32.out b/tests/libzscanner/data/46_L32.out
new file mode 100644
index 0000000..e9c77b5
--- /dev/null
+++ b/tests/libzscanner/data/46_L32.out
@@ -0,0 +1,54 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=FFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_IPV4
+------
+WARNG=ZS_BAD_IPV4
+------
+WARNG=ZS_BAD_IPV4
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/47_L64.in b/tests/libzscanner/data/47_L64.in
new file mode 100644
index 0000000..b4aabf3
--- /dev/null
+++ b/tests/libzscanner/data/47_L64.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ L64 0 0000:0000:0000:0000 ; The simplest case
+@ L64 65535 FFFF:FFFF:FFFF:FFFF ; The maximal case
+@ L64 0 abcd:ef00:0000:0000 ; Lower-case
+@ L64 \# 10 00000000000000000000 ; Hexadecimal rdata
+@ TYPE106 \# 10 00000000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE106 0 0000:0000:0000:0000 ; TYPE
+@ l64 0 0000:0000:0000:0000 ; Type in lower-case
+
+; KO
+@ L64
+@ L64 ; Empty rdata
+@ L64 \# 0 ; Hex empty rdata
+@ L64 65536 ; Too big preference
+@ L64 0 0000:0000:0000 ; Missing label
+@ L64 0 0000:0000:0000:0000:0000 ; Too many labels
+@ L64 0 0000:0000:0000:000 ; Missing hex character
+@ L64 0 0000:0000:0000-0000 ; Bad separator
+@ L64 0 0000:0000:0000:x000 ; Bad hex character
+@ L64 0 0000:0000:0000:0000 x ; Unexpected item
diff --git a/tests/libzscanner/data/47_L64.out b/tests/libzscanner/data/47_L64.out
new file mode 100644
index 0000000..106ee58
--- /dev/null
+++ b/tests/libzscanner/data/47_L64.out
@@ -0,0 +1,62 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=FFFFFFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=0000ABCDEF0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_L64_LENGTH
+------
+WARNG=ZS_BAD_L64_LENGTH
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_CHAR_COLON
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/48_LP.in b/tests/libzscanner/data/48_LP.in
new file mode 100644
index 0000000..bc537d0
--- /dev/null
+++ b/tests/libzscanner/data/48_LP.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The LP is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ LP 1 mail ; Relative dname
+@ LP \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE107 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE107 1 @ ; TYPE
+@ lp 1 @ ; Type in lower-case
+
+; KO
+@ LP
diff --git a/tests/libzscanner/data/48_LP.out b/tests/libzscanner/data/48_LP.out
new file mode 100644
index 0000000..4961c7e
--- /dev/null
+++ b/tests/libzscanner/data/48_LP.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=0001046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=000100
+------
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/49_CDS.in b/tests/libzscanner/data/49_CDS.in
new file mode 100644
index 0000000..7b6c347
--- /dev/null
+++ b/tests/libzscanner/data/49_CDS.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ CDS 0 0 0 00 ; The simplest variant
+@ CDS 65535 255 255 00 ; Maximal numbers
+@ CDS 0 RSAMD5 0 00 ; Algorithm mnemonic
+@ CDS 0 0 0 01 02 0304 ; Hex block with blank spaces between them
+@ TYPE59 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE59 0 0 0 00 ; TYPE
+@ cds 0 0 0 00 ; Type in lower-case
+
+; KO
+@ CDS
+@ CDS ; Empty rdata
+@ CDS \# 0 ; Hex empty rdata
+@ CDS 65536 0 0 00 ; Key tag overflow
+@ CDS 0 256 0 00 ; Algorithm overflow
+@ CDS 0 0 256 00 ; Digest type overflow
+@ CDS 0 0 0 0 ; Continuous block length must be multiple of 2
+@ CDS 0 0 0 00 0 ; Continuous block length must be multiple of 2
+@ CDS 0 0 0 XX ; Bad hex character
+@ CDS 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/49_CDS.out b/tests/libzscanner/data/49_CDS.out
new file mode 100644
index 0000000..de40722
--- /dev/null
+++ b/tests/libzscanner/data/49_CDS.out
@@ -0,0 +1,62 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003B
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003B
+RDATA=0000010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003B
+RDATA=0000000001020304
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003B
+RDATA=0000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/50_CDNSKEY.in b/tests/libzscanner/data/50_CDNSKEY.in
new file mode 100644
index 0000000..dc91462
--- /dev/null
+++ b/tests/libzscanner/data/50_CDNSKEY.in
@@ -0,0 +1,32 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ CDNSKEY 0 0 0 AA== ; The simplest variant
+@ CDNSKEY 65535 255 255 AA== ; Maximal numbers
+@ CDNSKEY 0 0 RSAMD5 AA== ; Algorithm mnemonic
+@ CDNSKEY 0 0 0 Zm8= ; One char padding
+@ CDNSKEY 0 0 0 Zm9v ; Without padding
+@ CDNSKEY 0 0 0 Zm9vYg== ; Two base64 blocks
+@ CDNSKEY 0 0 0 Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE60 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE60 0 0 0 AA== ; TYPE
+@ cdnskey 0 0 0 AA== ; Type in lower-case
+
+; KO
+@ CDNSKEY
+@ CDNSKEY ; Empty rdata
+@ CDNSKEY \# 0 ; Hex empty rdata
+@ CDNSKEY 65536 0 0 AA== ; Type overflow
+@ CDNSKEY 0 256 0 AA== ; Key tag overflow
+@ CDNSKEY 0 0 256 AA== ; Algorithm overflow
+@ CDNSKEY 0 0 0 A ; Continuous block length must be multiple of 4
+@ CDNSKEY 0 0 0 AB ; Continuous block length must be multiple of 4
+@ CDNSKEY 0 0 0 ABC ; Continuous block length must be multiple of 4
+@ CDNSKEY 0 0 0 AA == ; Continuous block length must be multiple of 4
+@ CDNSKEY 0 0 0 A=== ; Bad padding
+@ CDNSKEY 0 0 0 = ; Bad padding
+@ CDNSKEY 0 0 0 == ; Bad padding
+@ CDNSKEY 0 0 0 === ; Bad padding
+@ CDNSKEY 0 0 0 ==== ; Bad padding
+@ CDNSKEY 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/50_CDNSKEY.out b/tests/libzscanner/data/50_CDNSKEY.out
new file mode 100644
index 0000000..3100313
--- /dev/null
+++ b/tests/libzscanner/data/50_CDNSKEY.out
@@ -0,0 +1,92 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=0000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=00000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=00000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=00000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=00000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003C
+RDATA=0000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_BASE64_CHAR
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/51_URI.in b/tests/libzscanner/data/51_URI.in
new file mode 100644
index 0000000..8d18f42
--- /dev/null
+++ b/tests/libzscanner/data/51_URI.in
@@ -0,0 +1,22 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ URI 0 0 a ; The simplest variant
+@ URI 65535 65535 ftp://a ; Maximal priority and weight
+@ URI 0 0 "ftp://a" ; Quoted target
+@ URI 0 0 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 ; Target longer than 255
+@ TYPE256 \# 5 0000000061 ; TYPE + Hexadecimal rdata
+@ TYPE256 0 0 a ; TYPE
+@ uri 0 0 a ; Type in lower-case
+
+; OK extensions
+@ URI 0 0 "" ; Empty target
+
+; KO
+@ URI
+@ URI ; Empty rdata
+@ URI \# 0 ; Hex empty rdata
+@ URI 65536 0 a ; Priority overflow
+@ URI 0 65536 a ; Weight overflow
+@ URI 0 0 a a ; Unexpected item
diff --git a/tests/libzscanner/data/51_URI.out b/tests/libzscanner/data/51_URI.out
new file mode 100644
index 0000000..9dcf933
--- /dev/null
+++ b/tests/libzscanner/data/51_URI.out
@@ -0,0 +1,60 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=0000000061
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=FFFFFFFF6674703A2F2F61
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=000000006674703A2F2F61
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=00000000303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=0000000061
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=0000000061
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=0000000061
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0100
+RDATA=00000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/52_CAA.in b/tests/libzscanner/data/52_CAA.in
new file mode 100644
index 0000000..7043ce5
--- /dev/null
+++ b/tests/libzscanner/data/52_CAA.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ CAA 0 a a ; The simplest variant
+@ CAA 255 a a ; Maximal flags
+@ CAA 0 a "a ; b" ; Quoted value
+@ CAA 0 a 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 ; Value longer than 255
+@ TYPE257 \# 4 00016161 ; TYPE + Hexadecimal rdata
+@ TYPE257 0 a a ; TYPE
+@ caa 0 a a ; Type in lower-case
+
+; OK fallbacks and extensions
+@ CAA 0 "" a ; Empty tag
+@ CAA 0 "a" a ; Quoted tag
+@ CAA 0 abcdefghijklmnopqrstuvwxyz0123456789 a ; All allowed characters, longer than 15
+
+; KO
+@ CAA
+@ CAA ; Empty rdata
+@ CAA \# 0 ; Hex empty rdata
+@ CAA 256 a a ; Flags overflow
+@ CAA 0 a a a ; Unexpected item
diff --git a/tests/libzscanner/data/52_CAA.out b/tests/libzscanner/data/52_CAA.out
new file mode 100644
index 0000000..e5eefdf
--- /dev/null
+++ b/tests/libzscanner/data/52_CAA.out
@@ -0,0 +1,70 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=00016161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=FF016161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=00016161203B2062
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=000161303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=00016161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=00016161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=00016161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=000061
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=00016161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0101
+RDATA=00246162636465666768696A6B6C6D6E6F707172737475767778797A3031323334353637383961
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_REST
+------
diff --git a/tests/libzscanner/data/53_SMIMEA.in b/tests/libzscanner/data/53_SMIMEA.in
new file mode 100644
index 0000000..aec390f
--- /dev/null
+++ b/tests/libzscanner/data/53_SMIMEA.in
@@ -0,0 +1,13 @@
+$ORIGIN .
+$TTL 1
+
+; SMIMEA is the same as TLSA, so there are differences and basics only.
+
+; OK
+@ SMIMEA 0 0 0 00 ; The simplest variant
+@ TYPE53 \# 4 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE53 0 0 0 00 ; TYPE
+@ smimea 0 0 0 00 ; Type in lower-case
+
+; KO
+@ SMIMEA
diff --git a/tests/libzscanner/data/53_SMIMEA.out b/tests/libzscanner/data/53_SMIMEA.out
new file mode 100644
index 0000000..c270a7d
--- /dev/null
+++ b/tests/libzscanner/data/53_SMIMEA.out
@@ -0,0 +1,26 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0035
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0035
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0035
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0035
+RDATA=00000000
+------
+WARNG=ZS_BAD_NUMBER
+------
diff --git a/tests/libzscanner/data/54_OPENPGPKEY.in b/tests/libzscanner/data/54_OPENPGPKEY.in
new file mode 100644
index 0000000..a788a28
--- /dev/null
+++ b/tests/libzscanner/data/54_OPENPGPKEY.in
@@ -0,0 +1,13 @@
+$ORIGIN .
+$TTL 1
+
+; OPENPGPKEY is the same as DHCID, so there are differences and basics only.
+
+; OK
+@ OPENPGPKEY AA== ; The simplest variant
+@ TYPE61 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE61 AA== ; TYPE
+@ openpgpkey AA== ; Type in lower-case
+
+; KO
+@ OPENPGPKEY
diff --git a/tests/libzscanner/data/54_OPENPGPKEY.out b/tests/libzscanner/data/54_OPENPGPKEY.out
new file mode 100644
index 0000000..8741e4e
--- /dev/null
+++ b/tests/libzscanner/data/54_OPENPGPKEY.out
@@ -0,0 +1,26 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003D
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003D
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003D
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003D
+RDATA=00
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/55_CSYNC.in b/tests/libzscanner/data/55_CSYNC.in
new file mode 100644
index 0000000..97dcfa2
--- /dev/null
+++ b/tests/libzscanner/data/55_CSYNC.in
@@ -0,0 +1,22 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ CSYNC 0 0 ; The simplest variant - without bitmap
+@ CSYNC 4294967295 65535 ; Maximal numbers
+@ CSYNC 0 0 TYPE0 ; Minimal type number
+@ CSYNC 0 0 TYPE65535 ; Maximal type number
+@ CSYNC 0 0 TYPE0 A NS ; First bitmap window
+@ CSYNC 0 0 TYPE0 TYPE256 TYPE512 TYPE32768 ; First, second, third and 128. bitmap window
+@ TYPE62 \# 6 000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE62 0 0 ; TYPE
+@ csync 0 0 ; Type in lower-case
+
+; KO
+@ CSYNC
+@ CSYNC ; Empty rdata
+@ CSYNC \# 0 ; Hex empty rdata
+@ CSYNC 4294967296 0 ; Serial overflow
+@ CSYNC 0 65536 ; Flags overflow
+@ CSYNC 0 0 TYPE65536 ; Type number overflow
+@ CSYNC 0 0 X ; Unknown type
diff --git a/tests/libzscanner/data/55_CSYNC.out b/tests/libzscanner/data/55_CSYNC.out
new file mode 100644
index 0000000..d762c2b
--- /dev/null
+++ b/tests/libzscanner/data/55_CSYNC.out
@@ -0,0 +1,68 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=FFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=000000000000000180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=000000000000FF200000000000000000000000000000000000000000000000000000000000000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=0000000000000001E0
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=000000000000000180010180020180800180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003E
+RDATA=000000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_BITMAP
+------
diff --git a/tests/libzscanner/data/56_ZONEMD.in b/tests/libzscanner/data/56_ZONEMD.in
new file mode 100644
index 0000000..2342350
--- /dev/null
+++ b/tests/libzscanner/data/56_ZONEMD.in
@@ -0,0 +1,21 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ ZONEMD 0 0 0 00 ; The simplest variant
+@ ZONEMD 4294967295 255 255 00 ; Maximal numbers
+@ ZONEMD 0 0 0 0102 00 FF ; Hex string with blank spaces inside
+@ TYPE63 \# 7 00000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE63 0 0 0 00 ; TYPE
+@ zonemd 0 0 0 00 ; Type in lower-case
+
+; KO
+@ ZONEMD
+@ ZONEMD ; Empty rdata
+@ ZONEMD \# 0 ; Hex empty rdata
+@ ZONEMD 4294967296 0 0 00 ; Serial overflow
+@ ZONEMD 0 256 0 00 ; Type overflow
+@ ZONEMD 0 0 256 00 ; Reserved overflow
+@ ZONEMD 0 0 0 0 ; Hex block length must be multiple of 2
+@ ZONEMD 0 0 0 0x ; Bad hex char
+@ ZONEMD 0 0 0 ; Missing item
diff --git a/tests/libzscanner/data/56_ZONEMD.out b/tests/libzscanner/data/56_ZONEMD.out
new file mode 100644
index 0000000..0f56c24
--- /dev/null
+++ b/tests/libzscanner/data/56_ZONEMD.out
@@ -0,0 +1,54 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003F
+RDATA=00000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003F
+RDATA=FFFFFFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003F
+RDATA=000000000000010200FF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003F
+RDATA=00000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003F
+RDATA=00000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=003F
+RDATA=00000000000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER32_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_NUMBER8_OVERFLOW
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
diff --git a/tests/libzscanner/data/57_SVCB.in b/tests/libzscanner/data/57_SVCB.in
new file mode 100644
index 0000000..c4ce534
--- /dev/null
+++ b/tests/libzscanner/data/57_SVCB.in
@@ -0,0 +1,102 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ SVCB 0 .
+@ SVCB 0 @ ; Comment
+@ SVCB 65535 . mandatory=alpn alpn=h2
+@ SVCB 1 . mandatory="alpn" alpn=h2
+@ SVCB 1 . alpn=h2
+@ SVCB 1 . alpn="abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\053" ; Text string of maximal length (255 chars)
+@ SVCB 1 . alpn="part1,part2,part3\\,part4\\\\"
+@ SVCB 1 . alpn=part1\,\p\a\r\t2\044part3\092,part4\092\\
+@ SVCB 1 . no-default-alpn
+@ SVCB 1 . port=0
+@ SVCB 1 . port="65535"
+@ SVCB 1 . ipv4hint=0.0.0.0
+@ SVCB 1 . ipv4hint="255.255.255.255"
+@ SVCB 1 . ech=AA==
+@ SVCB 1 . ech="Zm9vYg=="
+@ SVCB 1 . ipv6hint=::1
+@ SVCB 1 . ipv6hint="::1"
+@ SVCB 1 . key7
+@ SVCB 1 . key65535
+@ SVCB 1 . key65535=a
+@ SVCB 1 . key65535="a"
+@ SVCB 1 . key65535="a" key1000=b port=4 key7 mandatory=key7,port
+@ TYPE64 \# 3 000000
+@ TYPE64 0 .
+@ svcb 0 .
+
+; RFC OK examples
+example.com. HTTPS 0 foo.example.com.
+example.com. SVCB 1 .
+example.com. SVCB 16 foo.example.com. port=53
+example.com. SVCB 1 foo.example.com. key667=hello
+example.com. SVCB 1 foo.example.com. key667="hello\210qoo"
+example.com. SVCB 1 foo.example.com. (
+ ipv6hint="2001:db8::1,2001:db8::53:1"
+ )
+example.com. SVCB 1 example.com. ipv6hint="::ffff:198.51.100.100"
+example.com. SVCB 16 foo.example.org. (
+ alpn=h2,h3-19 mandatory=ipv4hint,alpn
+ ipv4hint=192.0.2.1
+ )
+example.com. SVCB 16 foo.example.org. alpn="f\\\\oo\\,bar,h2"
+example.com. SVCB 16 foo.example.org. alpn=f\\\092oo\092,bar,h2
+
+; KO
+@ SVCB
+@ SVCB ; Empty rdata
+@ SVCB \# 0 ; Hex empty rdata
+@ SVCB 65536 . ; Priority overflow
+@ SVCB 0 ; Missing item
+@ SVCB 1 . bogus ; Unknown parameter
+@ SVCB 1 . PORT=0 ; Capital letter in parameter name
+@ SVCB 1 . mandatory
+@ SVCB 1 . mandatory=
+@ SVCB 1 . mandatory=a,
+@ SVCB 1 . mandatory=a,,b
+@ SVCB 1 . mandatory=mandatory
+@ SVCB 1 . mandatory=bogus
+@ SVCB 1 . alpn
+@ SVCB 1 . alpn=
+@ SVCB 1 . alpn=a,
+@ SVCB 1 . alpn=a,,b
+@ SVCB 1 . alpn="abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\0536" ; Text string overflow (256 chars)
+@ SVCB 1 . no-default-alpn=
+@ SVCB 1 . no-default-alpn=h1
+@ SVCB 1 . no-default-alpn="h1"
+@ SVCB 1 . port
+@ SVCB 1 . port=
+@ SVCB 1 . port=65536
+@ SVCB 1 . port=1,2
+@ SVCB 1 . ipv4hint
+@ SVCB 1 . ipv4hint=
+@ SVCB 1 . ipv4hint=1.2.3
+@ SVCB 1 . ipv4hint=1.2.3.4,
+@ SVCB 1 . ipv4hint=1.2.3.4,,2.3.4.5
+@ SVCB 1 . ech
+@ SVCB 1 . ech=
+@ SVCB 1 . ech=AA==,AA==
+@ SVCB 1 . ech=W
+@ SVCB 1 . ipv6hint
+@ SVCB 1 . ipv6hint=
+@ SVCB 1 . ipv6hint=::1,,::2
+@ SVCB 1 . ipv6hint=::W
+
+; RFC KO examples
+example.com. SVCB 1 foo.example.com. (
+ key123=abc key123=def
+ )
+example.com. SVCB 1 foo.example.com. mandatory
+example.com. SVCB 1 foo.example.com. alpn
+example.com. SVCB 1 foo.example.com. port
+example.com. SVCB 1 foo.example.com. ipv4hint
+example.com. SVCB 1 foo.example.com. ipv6hint
+example.com. SVCB 1 foo.example.com. no-default-alpn=abc
+example.com. SVCB 1 foo.example.com. mandatory=key123
+example.com. SVCB 1 foo.example.com. mandatory=mandatory
+example.com. SVCB 1 foo.example.com. (
+ mandatory=key123,key123 key123=abc
+ )
diff --git a/tests/libzscanner/data/57_SVCB.out b/tests/libzscanner/data/57_SVCB.out
new file mode 100644
index 0000000..a799eb7
--- /dev/null
+++ b/tests/libzscanner/data/57_SVCB.out
@@ -0,0 +1,306 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=FFFF0000000002000100010003026832
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000000002000100010003026832
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000010003026832
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000010100FF6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E3132333435
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000100000100190570617274310570617274320C70617274332C70617274345C
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000100000100190570617274310570617274320C70617274332C70617274345C
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000020000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000100000300020000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000030002FFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=0001000004000400000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000040004FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=0001000005000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000050004666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=0001000006001000000000000000000000000000000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=0001000006001000000000000000000000000000000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000070000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000100FFFF0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000100FFFF000161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000100FFFF000161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=00010000000004000300070003000200040007000003E8000162FFFF000161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000000
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0041
+RDATA=000003666F6F076578616D706C6503636F6D00
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000100
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=001003666F6F076578616D706C6503636F6D00000300020035
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000103666F6F076578616D706C6503636F6D00029B000568656C6C6F
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000103666F6F076578616D706C6503636F6D00029B000968656C6C6FD2716F6F
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=000103666F6F076578616D706C6503636F6D000006002020010DB800000000000000000000000120010DB8000000000000000000530001
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=0001076578616D706C6503636F6D000006001000000000000000000000FFFFC6336464
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=001003666F6F076578616D706C65036F7267000000000400010004000100090268320568332D313900040004C0000201
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=001003666F6F076578616D706C65036F7267000001000C08665C6F6F2C626172026832
+------
+OWNER=076578616D706C6503636F6D00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0040
+RDATA=001003666F6F076578616D706C65036F7267000001000C08665C6F6F2C626172026832
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_RDATA
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_MANDATORY
+------
+WARNG=ZS_BAD_SVCB_MANDATORY
+------
+WARNG=ZS_BAD_SVCB_MANDATORY
+------
+WARNG=ZS_BAD_SVCB_MANDATORY
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_EMPTY_LIST_ITEM
+------
+WARNG=ZS_EMPTY_LIST_ITEM
+------
+WARNG=ZS_ITEM_OVERFLOW
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_IPV4
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_BAD_ADDRESS_CHAR
+------
+WARNG=ZS_DUPLICATE_SVCB_KEY
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_BAD_SVCB_PARAM
+------
+WARNG=ZS_MISSING_SVCB_MANDATORY
+------
+WARNG=ZS_BAD_SVCB_MANDATORY
+------
+WARNG=ZS_DUPLICATE_SVCB_MANDATORY
+------
diff --git a/tests/libzscanner/data/58_HTTPS.in b/tests/libzscanner/data/58_HTTPS.in
new file mode 100644
index 0000000..674f865
--- /dev/null
+++ b/tests/libzscanner/data/58_HTTPS.in
@@ -0,0 +1,19 @@
+$ORIGIN .
+$TTL 1
+
+; HTTPS is the same as SVCB, so there are the differences and basics only.
+
+; OK
+@ HTTPS 0 .
+@ HTTPS 65535 @ ; Comment
+@ HTTPS 1 . key65535="a" key1000=b port=4 key7 mandatory=key7,port
+@ TYPE65 \# 3 000000
+@ TYPE65 0 .
+@ https 0 .
+
+; KO
+@ HTTPS
+@ HTTPS ; Empty rdata
+@ HTTPS \# 0 ; Hex empty rdata
+@ HTTPS 65536 . ; Priority overflow
+@ HTTPS 0 ; Missing item
diff --git a/tests/libzscanner/data/58_HTTPS.out b/tests/libzscanner/data/58_HTTPS.out
new file mode 100644
index 0000000..8ec9a35
--- /dev/null
+++ b/tests/libzscanner/data/58_HTTPS.out
@@ -0,0 +1,46 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0041
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0041
+RDATA=FFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0041
+RDATA=00010000000004000300070003000200040007000003E8000162FFFF000161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0041
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0041
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0041
+RDATA=000000
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_NUMBER
+------
+WARNG=ZS_BAD_HEX_CHAR
+------
+WARNG=ZS_NUMBER16_OVERFLOW
+------
+WARNG=ZS_BAD_RDATA
+------
diff --git a/tests/libzscanner/data/includes/include1 b/tests/libzscanner/data/includes/include1
new file mode 100644
index 0000000..9de1859
--- /dev/null
+++ b/tests/libzscanner/data/includes/include1
@@ -0,0 +1,9 @@
+$TTL 1
+
+a NS @
+
+$ORIGIN tld1a.
+a NS @
+
+$ORIGIN tld1b.
+a NS @
diff --git a/tests/libzscanner/data/includes/include2 b/tests/libzscanner/data/includes/include2
new file mode 100644
index 0000000..1e14e96
--- /dev/null
+++ b/tests/libzscanner/data/includes/include2
@@ -0,0 +1,6 @@
+$TTL 1H
+
+b NS @
+
+$ORIGIN tld1a.
+b NS @
diff --git a/tests/libzscanner/data/includes/include3 b/tests/libzscanner/data/includes/include3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libzscanner/data/includes/include3
diff --git a/tests/libzscanner/data/includes/include4 b/tests/libzscanner/data/includes/include4
new file mode 100644
index 0000000..7e8d5e2
--- /dev/null
+++ b/tests/libzscanner/data/includes/include4
@@ -0,0 +1 @@
+a NS ; Missing data
diff --git a/tests/libzscanner/data/includes/include5 b/tests/libzscanner/data/includes/include5
new file mode 100644
index 0000000..ac98e01
--- /dev/null
+++ b/tests/libzscanner/data/includes/include5
@@ -0,0 +1 @@
+$TTL x ; Bad number
diff --git a/tests/libzscanner/data/includes/include6 b/tests/libzscanner/data/includes/include6
new file mode 100644
index 0000000..b5e8cb8
--- /dev/null
+++ b/tests/libzscanner/data/includes/include6
@@ -0,0 +1 @@
+$INCLUDE include2 ; Include in include
diff --git a/tests/libzscanner/processing.c b/tests/libzscanner/processing.c
new file mode 100644
index 0000000..22066dd
--- /dev/null
+++ b/tests/libzscanner/processing.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "libzscanner/scanner.h"
+#include "libzscanner/functions.c"
+#include "libzscanner/processing.h"
+#include "libknot/descriptor.c"
+
+const char *separator = "------\n";
+
+static void print_wire_dname(const uint8_t *dname, uint32_t dname_length)
+{
+ uint32_t label_length = 0, i = 0;
+
+ for (i = 0; i < dname_length; i++) {
+ if (label_length == 0) {
+ label_length = dname[i];
+ printf("(%u)", label_length);
+ continue;
+ }
+ printf("%c", (char)dname[i]);
+ label_length--;
+ }
+}
+
+void debug_process_error(zs_scanner_t *s)
+{
+ if (s->error.fatal) {
+ printf("LINE(%03"PRIu64") ERROR(%s) FILE(%s) NEAR(%s)\n",
+ s->line_counter,
+ zs_strerror(s->error.code),
+ s->file.name,
+ s->buffer);
+ } else {
+ printf("LINE(%03"PRIu64") WARNING(%s) FILE(%s) NEAR(%s)\n",
+ s->line_counter,
+ zs_strerror(s->error.code),
+ s->file.name,
+ s->buffer);
+ }
+ fflush(stdout);
+}
+
+void debug_process_record(zs_scanner_t *s)
+{
+ uint32_t i;
+
+ char rclass[32];
+ char rtype[32];
+
+ if (knot_rrclass_to_string(s->r_class, rclass, sizeof(rclass)) > 0 &&
+ knot_rrtype_to_string(s->r_type, rtype, sizeof(rtype)) > 0) {
+ printf("LINE(%03"PRIu64") %s %6u %*s ",
+ s->line_counter, rclass, s->r_ttl, 5, rtype);
+ } else {
+ printf("LINE(%03"PRIu64") %u %6u %*u ",
+ s->line_counter, s->r_class, s->r_ttl, 5, s->r_type);
+ }
+
+ print_wire_dname(s->r_owner, s->r_owner_length);
+
+ printf(" \\# %u ", s->r_data_length);
+
+ int block = *((int *)(s->process.data));
+ for (i = 0; i < s->r_data_length; i++) {
+ if (block > 0 && i > 0 && (i % block) == 0) {
+ printf(" ");
+ }
+ printf("%02X", (s->r_data)[i]);
+ }
+ printf("\n");
+ fflush(stdout);
+}
+
+void debug_process_comment(zs_scanner_t *s)
+{
+ printf("LINE(%03"PRIu64") COMMENT(%.*s)\n", s->line_counter,
+ (int)s->buffer_length, s->buffer);
+ fflush(stdout);
+}
+
+void test_process_error(zs_scanner_t *s)
+{
+ if (s->error.fatal) {
+ printf("ERROR=%s\n%s", zs_errorname(s->error.code), separator);
+ } else {
+ printf("WARNG=%s\n%s", zs_errorname(s->error.code), separator);
+ }
+ fflush(stdout);
+}
+
+void test_process_record(zs_scanner_t *s)
+{
+ uint32_t i;
+
+ printf("OWNER=");
+ for (i = 0; i < s->r_owner_length; i++) {
+ printf("%02X", s->r_owner[i]);
+ }
+ printf("\n");
+ printf("CLASS=%04X\n", s->r_class);
+ printf("RRTTL=%08X\n", s->r_ttl);
+ printf("RTYPE=%04X\n", s->r_type);
+ printf("RDATA=");
+ for (i = 0; i < s->r_data_length; i++) {
+ printf("%02X", (s->r_data)[i]);
+ }
+ printf("\n%s", separator);
+ fflush(stdout);
+}
+
+int test_date_to_timestamp(void)
+{
+ time_t ref_timestamp, max_timestamp;
+ uint32_t test_timestamp;
+ uint8_t buffer[16];
+ uint64_t val1, val2; // For time_t type unification.
+ struct tm tm;
+
+ // Set UTC for strftime.
+ putenv("TZ=UTC");
+ tzset();
+
+ // Get maximal allowed timestamp.
+ strptime("22251231235959", "%Y%m%d%H%M%S", &tm);
+ max_timestamp = mktime(&tm);
+
+ // Testing loop over whole input interval.
+ for (ref_timestamp = 0;
+ ref_timestamp < max_timestamp;
+ ref_timestamp += 1) {
+ struct tm result;
+ // Get reference (correct) timestamp.
+ strftime((char*)buffer, sizeof(buffer), "%Y%m%d%H%M%S",
+ gmtime_r(&ref_timestamp, &result));
+
+ // Get testing timestamp.
+ test_timestamp = 0U; // prevents Wuninitialized
+ date_to_timestamp(buffer, &test_timestamp);
+
+ // Some continuous logging.
+ if (ref_timestamp % 10000000 == 0) {
+ val1 = ref_timestamp;
+ printf("%s = %"PRIu32"\n", buffer, (uint32_t)val1);
+ }
+
+ // Comparing results.
+ if ((uint32_t)ref_timestamp != test_timestamp) {
+ val1 = ref_timestamp;
+
+ if (ref_timestamp > test_timestamp) {
+ val2 = ref_timestamp - test_timestamp;
+ printf("%s = %"PRIu64", in - out = %"PRIu64"\n",
+ buffer, val1, val2);
+ } else {
+ val2 = test_timestamp - ref_timestamp;
+ printf("%s = %"PRIu64", out - in = %"PRIu64"\n",
+ buffer, val1, val2);
+ }
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/tests/libzscanner/processing.h b/tests/libzscanner/processing.h
new file mode 100644
index 0000000..47cf03b
--- /dev/null
+++ b/tests/libzscanner/processing.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "libzscanner/scanner.h"
+
+void debug_process_error(zs_scanner_t *scanner);
+
+void debug_process_record(zs_scanner_t *scanner);
+
+void debug_process_comment(zs_scanner_t *scanner);
+
+void test_process_error(zs_scanner_t *scanner);
+
+void test_process_record(zs_scanner_t *scanner);
+
+int test_date_to_timestamp(void);
diff --git a/tests/libzscanner/test_zscanner.in b/tests/libzscanner/test_zscanner.in
new file mode 100644
index 0000000..10d2b5c
--- /dev/null
+++ b/tests/libzscanner/test_zscanner.in
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+SOURCE=@top_srcdir@/tests/libzscanner
+BUILD=@top_builddir@/tests/libzscanner
+
+. @top_srcdir@/tests/tap/libtap.sh
+
+cd "$BUILD"
+
+TMPDIR=$(test_tmpdir)
+TESTS_DIR="$SOURCE"/data
+ZSCANNER_TOOL="$BUILD"/zscanner-tool
+
+plan 86
+
+mkdir -p "$TMPDIR"/includes/
+for a in 1 2 3 4 5 6; do
+ cat "$TESTS_DIR"/includes/include"$a" > "$TMPDIR"/includes/include"$a";
+done
+
+for case in $(cat "$SOURCE"/TESTS); do
+ casein=$(test_file_path data/"$case".in)
+ caseout=$(test_file_path data/"$case".out)
+ filein="$TMPDIR"/"$case".in
+ fileout="$TMPDIR"/"$case".out
+
+ sed -e "s|@TMPDIR@|$TMPDIR|;" < "$casein" > "$filein"
+
+ "$ZSCANNER_TOOL" -m 2 . "$filein" > "$fileout"
+
+ if cmp -s "$fileout" "$caseout"; then
+ ok "$case: output matches" true
+ rm "$filein"
+ rm "$fileout"
+ else
+ ok "$case: output differs" false
+ diff -urNap "$caseout" "$fileout" | while read line; do diag "$line"; done
+ fi
+done
+
+rm -rf "$TMPDIR"/includes/
diff --git a/tests/libzscanner/zscanner-tool.c b/tests/libzscanner/zscanner-tool.c
new file mode 100644
index 0000000..d5f514d
--- /dev/null
+++ b/tests/libzscanner/zscanner-tool.c
@@ -0,0 +1,257 @@
+/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <getopt.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "libzscanner/processing.h"
+#include "libzscanner/scanner.h"
+
+#define DEFAULT_MODE 1
+#define DEFAULT_CLASS 1
+#define DEFAULT_TTL 0
+
+static void *timestamp_worker(void *data)
+{
+ int *ret = (int *)data;
+ *ret = test_date_to_timestamp();
+ return NULL;
+}
+
+static void help(void)
+{
+ printf("\nZone scanner testing tool.\n"
+ "Usage: zscanner-tool [parameters] origin zonefile\n"
+ "\n"
+ "Parameters:\n"
+ " -m [0,1,2] Processing mode.\n"
+ " 0 Empty output.\n"
+ " 1 Debug output (DEFAULT).\n"
+ " 2 Test output.\n"
+ " -b <num> Divide hex string to blocks of length <num>.\n"
+ " -s State parsing mode.\n"
+ " -t Launch unit tests.\n"
+ " -h Print this help.\n");
+}
+
+static int time_test(void)
+{
+ pthread_t t1, t2, t3;
+ int ret1, ret2, ret3;
+
+ pthread_create(&t1, NULL, timestamp_worker, &ret1);
+ pthread_create(&t2, NULL, timestamp_worker, &ret2);
+ pthread_create(&t3, NULL, timestamp_worker, &ret3);
+
+ pthread_join(t1, NULL);
+ pthread_join(t2, NULL);
+ pthread_join(t3, NULL);
+
+ if (ret1 != 0 || ret2 != 0 || ret3 != 0) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int include(zs_scanner_t *s);
+
+static int state_parsing(zs_scanner_t *s)
+{
+ while (zs_parse_record(s) == 0) {
+ switch (s->state) {
+ case ZS_STATE_DATA:
+ if (s->process.record != NULL) {
+ s->process.record(s);
+ }
+ break;
+ case ZS_STATE_ERROR:
+ if (s->process.error != NULL) {
+ s->process.error(s);
+ }
+ if (s->error.fatal) {
+ return -1;
+ }
+ break;
+ case ZS_STATE_INCLUDE:
+ if (include(s) != 0) {
+ return -1;
+ }
+ break;
+ default:
+ return (s->error.counter == 0) ? 0 : -1;
+ }
+ }
+
+ return -1;
+}
+
+static int include(zs_scanner_t *s)
+{
+ zs_scanner_t *ss;
+ int ret = 0;
+
+ if ((ss = malloc(sizeof(zs_scanner_t))) == NULL ||
+ zs_init(ss, (char *)s->buffer, s->default_class, s->default_ttl) != 0 ||
+ zs_set_input_file(ss, (char *)(s->include_filename)) != 0 ||
+ zs_set_processing(ss, s->process.record, s->process.error, s->process.data) != 0 ||
+ state_parsing(ss) != 0) {
+ if (ss == NULL) {
+ s->error.code = ZS_ENOMEM;
+ } else if (ss->error.counter > 0) {
+ s->error.counter += ss->error.counter;
+ s->error.code = ZS_UNPROCESSED_INCLUDE;
+ } else {
+ s->error.code = ss->error.code;
+ }
+
+ if (s->process.error != NULL) {
+ s->buffer[0] = '\0'; // Clear unrelated content.
+ s->buffer_length = 0;
+ s->error.counter++;
+ s->error.fatal = true;
+ s->process.error(s);
+ }
+
+ ret = -1;
+ }
+
+ zs_deinit(ss);
+ free(ss);
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int mode = DEFAULT_MODE, block = 0, state = 0, test = 0;
+
+ // Command line long options.
+ struct option opts[] = {
+ { "mode", required_argument, NULL, 'm' },
+ { "block", required_argument, NULL, 'b' },
+ { "state", no_argument, NULL, 's' },
+ { "test", no_argument, NULL, 't' },
+ { "help", no_argument, NULL, 'h' },
+ { NULL }
+ };
+
+ // Parsed command line arguments.
+ int opt = 0, li = 0;
+ while ((opt = getopt_long(argc, argv, "m:b:sth", opts, &li)) != -1) {
+ switch (opt) {
+ case 'm':
+ mode = atoi(optarg);
+ break;
+ case 'b':
+ block = atoi(optarg);
+ break;
+ case 's':
+ state = 1;
+ break;
+ case 't':
+ test = 1;
+ break;
+ case 'h':
+ help();
+ return EXIT_SUCCESS;
+ default:
+ help();
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (test == 1) {
+ return time_test();
+ }
+
+ // Check if there are 2 remaining non-options.
+ if (argc - optind != 2) {
+ help();
+ return EXIT_FAILURE;
+ }
+
+ const char *origin = argv[optind];
+ const char *zone_file = argv[optind + 1];
+
+ // Create a zone scanner.
+ zs_scanner_t *s = malloc(sizeof(zs_scanner_t));
+ if (s == NULL) {
+ printf("Scanner create error!\n");
+ return EXIT_FAILURE;
+ }
+ if (zs_init(s, origin, DEFAULT_CLASS, DEFAULT_TTL) != 0) {
+ printf("Scanner init error!\n");
+ free(s);
+ return EXIT_FAILURE;
+ }
+ if (zs_set_input_file(s, zone_file) != 0) {
+ printf("Scanner file error!\n");
+ zs_deinit(s);
+ free(s);
+ return EXIT_FAILURE;
+ }
+
+ // Set the processing mode.
+ int ret;
+ switch (mode) {
+ case 0:
+ ret = 0;
+ break;
+ case 1:
+ ret = zs_set_processing(s, debug_process_record, debug_process_error, &block);
+ ret += zs_set_processing_comment(s, debug_process_comment);
+ break;
+ case 2:
+ ret = zs_set_processing(s, test_process_record, test_process_error, NULL);
+ break;
+ default:
+ printf("Bad mode number!\n");
+ help();
+ return EXIT_FAILURE;
+ }
+ if (ret != 0) {
+ printf("Processing setup error!\n");
+ return EXIT_FAILURE;
+ }
+
+ // Parse the file.
+ ret = state ? state_parsing(s) : zs_parse_all(s);
+ if (ret == 0) {
+ if (mode == DEFAULT_MODE) {
+ printf("Zone file has been processed successfully\n");
+ }
+
+ zs_deinit(s);
+ free(s);
+ return EXIT_SUCCESS;
+ } else {
+ if (s->error.counter > 0 && mode == DEFAULT_MODE) {
+ printf("Zone processing has stopped with "
+ "%"PRIu64" warnings/errors!\n",
+ s->error.counter);
+ } else if (mode == DEFAULT_MODE) {
+ printf("%s\n", zs_strerror(s->error.code));
+ }
+
+ zs_deinit(s);
+ free(s);
+ return EXIT_FAILURE;
+ }
+}