summaryrefslogtreecommitdiffstats
path: root/src/lib/dns/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:15:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:15:43 +0000
commitf5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch)
tree49e44c6f87febed37efb953ab5485aa49f6481a7 /src/lib/dns/tests
parentInitial commit. (diff)
downloadisc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz
isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/dns/tests')
-rw-r--r--src/lib/dns/tests/Makefile.am94
-rw-r--r--src/lib/dns/tests/Makefile.in2357
-rw-r--r--src/lib/dns/tests/dns_exceptions_unittest.cc65
-rw-r--r--src/lib/dns/tests/edns_unittest.cc258
-rw-r--r--src/lib/dns/tests/labelsequence_unittest.cc1243
-rw-r--r--src/lib/dns/tests/master_lexer_inputsource_unittest.cc368
-rw-r--r--src/lib/dns/tests/master_lexer_state_unittest.cc607
-rw-r--r--src/lib/dns/tests/master_lexer_token_unittest.cc162
-rw-r--r--src/lib/dns/tests/master_lexer_unittest.cc521
-rw-r--r--src/lib/dns/tests/master_loader_callbacks_test.cc79
-rw-r--r--src/lib/dns/tests/master_loader_unittest.cc1445
-rw-r--r--src/lib/dns/tests/masterload_unittest.cc397
-rw-r--r--src/lib/dns/tests/message_unittest.cc1162
-rw-r--r--src/lib/dns/tests/messagerenderer_unittest.cc292
-rw-r--r--src/lib/dns/tests/name_unittest.cc797
-rw-r--r--src/lib/dns/tests/nsec3hash_unittest.cc269
-rw-r--r--src/lib/dns/tests/opcode_unittest.cc100
-rw-r--r--src/lib/dns/tests/qid_gen_unittest.cc39
-rw-r--r--src/lib/dns/tests/question_unittest.cc196
-rw-r--r--src/lib/dns/tests/rcode_unittest.cc126
-rw-r--r--src/lib/dns/tests/rdata_afsdb_unittest.cc235
-rw-r--r--src/lib/dns/tests/rdata_caa_unittest.cc322
-rw-r--r--src/lib/dns/tests/rdata_char_string_data_unittest.cc181
-rw-r--r--src/lib/dns/tests/rdata_char_string_unittest.cc246
-rw-r--r--src/lib/dns/tests/rdata_cname_unittest.cc135
-rw-r--r--src/lib/dns/tests/rdata_dhcid_unittest.cc165
-rw-r--r--src/lib/dns/tests/rdata_dname_unittest.cc137
-rw-r--r--src/lib/dns/tests/rdata_dnskey_unittest.cc200
-rw-r--r--src/lib/dns/tests/rdata_ds_like_unittest.cc229
-rw-r--r--src/lib/dns/tests/rdata_hinfo_unittest.cc154
-rw-r--r--src/lib/dns/tests/rdata_in_a_unittest.cc159
-rw-r--r--src/lib/dns/tests/rdata_in_aaaa_unittest.cc151
-rw-r--r--src/lib/dns/tests/rdata_minfo_unittest.cc230
-rw-r--r--src/lib/dns/tests/rdata_mx_unittest.cc147
-rw-r--r--src/lib/dns/tests/rdata_naptr_unittest.cc239
-rw-r--r--src/lib/dns/tests/rdata_ns_unittest.cc145
-rw-r--r--src/lib/dns/tests/rdata_nsec3_unittest.cc226
-rw-r--r--src/lib/dns/tests/rdata_nsec3param_like_unittest.cc272
-rw-r--r--src/lib/dns/tests/rdata_nsec3param_unittest.cc209
-rw-r--r--src/lib/dns/tests/rdata_nsec_unittest.cc138
-rw-r--r--src/lib/dns/tests/rdata_nsecbitmap_unittest.cc269
-rw-r--r--src/lib/dns/tests/rdata_opt_unittest.cc198
-rw-r--r--src/lib/dns/tests/rdata_pimpl_holder_unittest.cc56
-rw-r--r--src/lib/dns/tests/rdata_ptr_unittest.cc145
-rw-r--r--src/lib/dns/tests/rdata_rp_unittest.cc200
-rw-r--r--src/lib/dns/tests/rdata_rrsig_unittest.cc369
-rw-r--r--src/lib/dns/tests/rdata_soa_unittest.cc249
-rw-r--r--src/lib/dns/tests/rdata_srv_unittest.cc205
-rw-r--r--src/lib/dns/tests/rdata_sshfp_unittest.cc311
-rw-r--r--src/lib/dns/tests/rdata_tkey_unittest.cc450
-rw-r--r--src/lib/dns/tests/rdata_tlsa_unittest.cc276
-rw-r--r--src/lib/dns/tests/rdata_tsig_unittest.cc423
-rw-r--r--src/lib/dns/tests/rdata_txt_like_unittest.cc397
-rw-r--r--src/lib/dns/tests/rdata_unittest.cc467
-rw-r--r--src/lib/dns/tests/rdata_unittest.h92
-rw-r--r--src/lib/dns/tests/rdatafields_unittest.cc366
-rw-r--r--src/lib/dns/tests/rrclass_unittest.cc174
-rw-r--r--src/lib/dns/tests/rrcollator_unittest.cc208
-rw-r--r--src/lib/dns/tests/rrparamregistry_unittest.cc185
-rw-r--r--src/lib/dns/tests/rrset_collection_unittest.cc240
-rw-r--r--src/lib/dns/tests/rrset_unittest.cc442
-rw-r--r--src/lib/dns/tests/rrttl_unittest.cc279
-rw-r--r--src/lib/dns/tests/rrtype_unittest.cc195
-rw-r--r--src/lib/dns/tests/run_unittests.cc24
-rw-r--r--src/lib/dns/tests/serial_unittest.cc173
-rw-r--r--src/lib/dns/tests/testdata/Makefile.am219
-rw-r--r--src/lib/dns/tests/testdata/Makefile.in740
-rw-r--r--src/lib/dns/tests/testdata/broken.zone3
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire1.spec5
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire1.wire9
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire2.spec5
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire2.wire9
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire3.spec7
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire3.wire9
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire4.spec7
-rw-r--r--src/lib/dns/tests/testdata/edns_toWire4.wire9
-rw-r--r--src/lib/dns/tests/testdata/example.org17
-rw-r--r--src/lib/dns/tests/testdata/masterload.txt5
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire122
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire10.spec13
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire10.wire19
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire11.spec15
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire11.wire19
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire12.spec21
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire12.wire24
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire13.spec20
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire13.wire35
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire14.spec21
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire14.wire24
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire15.spec22
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire15.wire30
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire16.spec21
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire16.wire24
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire17.spec22
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire17.wire24
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire18.spec23
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire18.wire24
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire19.spec20
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire19.wire28
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire222
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire20.spec20
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire20.wire28
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire21.spec20
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire21.wire28
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire22.spec14
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire22.wire20
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire322
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire423
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire533
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire623
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire727
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire822
-rw-r--r--src/lib/dns/tests/testdata/message_fromWire922
-rw-r--r--src/lib/dns/tests/testdata/message_toText1.spec24
-rw-r--r--src/lib/dns/tests/testdata/message_toText1.txt14
-rw-r--r--src/lib/dns/tests/testdata/message_toText1.wire28
-rw-r--r--src/lib/dns/tests/testdata/message_toText2.spec14
-rw-r--r--src/lib/dns/tests/testdata/message_toText2.txt8
-rw-r--r--src/lib/dns/tests/testdata/message_toText2.wire19
-rw-r--r--src/lib/dns/tests/testdata/message_toText3.spec31
-rw-r--r--src/lib/dns/tests/testdata/message_toText3.txt17
-rw-r--r--src/lib/dns/tests/testdata/message_toText3.wire39
-rw-r--r--src/lib/dns/tests/testdata/message_toWire122
-rw-r--r--src/lib/dns/tests/testdata/message_toWire2.spec21
-rw-r--r--src/lib/dns/tests/testdata/message_toWire2.wire24
-rw-r--r--src/lib/dns/tests/testdata/message_toWire3.spec22
-rw-r--r--src/lib/dns/tests/testdata/message_toWire3.wire30
-rw-r--r--src/lib/dns/tests/testdata/message_toWire4.spec27
-rw-r--r--src/lib/dns/tests/testdata/message_toWire4.wire24
-rw-r--r--src/lib/dns/tests/testdata/message_toWire5.spec36
-rw-r--r--src/lib/dns/tests/testdata/message_toWire5.wire34
-rw-r--r--src/lib/dns/tests/testdata/message_toWire648
-rw-r--r--src/lib/dns/tests/testdata/message_toWire735
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire114
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire1012
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire1112
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire1213
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire135
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire147
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire215
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire3_111
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire3_213
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire445
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire614
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire76
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire827
-rw-r--r--src/lib/dns/tests/testdata/name_fromWire912
-rw-r--r--src/lib/dns/tests/testdata/name_toWire112
-rw-r--r--src/lib/dns/tests/testdata/name_toWire214
-rw-r--r--src/lib/dns/tests/testdata/name_toWire314
-rw-r--r--src/lib/dns/tests/testdata/name_toWire416
-rw-r--r--src/lib/dns/tests/testdata/name_toWire5.spec19
-rw-r--r--src/lib/dns/tests/testdata/name_toWire5.wire12
-rw-r--r--src/lib/dns/tests/testdata/name_toWire6.spec19
-rw-r--r--src/lib/dns/tests/testdata/name_toWire6.wire12
-rw-r--r--src/lib/dns/tests/testdata/name_toWire710
-rw-r--r--src/lib/dns/tests/testdata/name_toWire87
-rw-r--r--src/lib/dns/tests/testdata/name_toWire913
-rw-r--r--src/lib/dns/tests/testdata/omitcheck.txt1
-rw-r--r--src/lib/dns/tests/testdata/origincheck.txt5
-rw-r--r--src/lib/dns/tests/testdata/question_fromWire33
-rw-r--r--src/lib/dns/tests/testdata/question_toWire114
-rw-r--r--src/lib/dns/tests/testdata/question_toWire214
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.spec3
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.wire11
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.spec4
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.spec4
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.spec4
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_toWire1.spec4
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_toWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_toWire2.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_afsdb_toWire2.wire11
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire2.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire3.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire4.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire56
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire64
-rw-r--r--src/lib/dns/tests/testdata/rdata_cname_fromWire44
-rw-r--r--src/lib/dns/tests/testdata/rdata_dhcid_fromWire12
-rw-r--r--src/lib/dns/tests/testdata/rdata_dhcid_toWire7
-rw-r--r--src/lib/dns/tests/testdata/rdata_dname_fromWire44
-rw-r--r--src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_dnskey_fromWire.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_dnskey_fromWire.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_ds_fromWire6
-rw-r--r--src/lib/dns/tests/testdata/rdata_in_a_fromWire19
-rw-r--r--src/lib/dns/tests/testdata/rdata_in_aaaa_fromWire18
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire1.spec3
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire2.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire2.wire11
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire3.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire3.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire4.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire4.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire5.spec5
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire5.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire6.spec5
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_fromWire6.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWire1.spec5
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWire2.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWire2.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_mx_fromWire15
-rw-r--r--src/lib/dns/tests/testdata/rdata_mx_toWire112
-rw-r--r--src/lib/dns/tests/testdata/rdata_mx_toWire212
-rw-r--r--src/lib/dns/tests/testdata/rdata_ns_fromWire44
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire17
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.wire12
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire36
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.spec13
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.wire16
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3param_fromWire15
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire16
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire10.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire10.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire16.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire16.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire210
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire310
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire4.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire4.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire5.spec13
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire5.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire6.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire6.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire7.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire7.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire8.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire8.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire9.spec10
-rw-r--r--src/lib/dns/tests/testdata/rdata_nsec_fromWire9.wire12
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire115
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire24
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire38
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire49
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire1.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire2.spec12
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire2.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire3.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire3.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire4.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire4.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire5.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire5.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire6.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_fromWire6.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_toWire1.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_toWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_toWire2.spec14
-rw-r--r--src/lib/dns/tests/testdata/rdata_rp_toWire2.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_rrsig_fromWire113
-rw-r--r--src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.wire12
-rw-r--r--src/lib/dns/tests/testdata/rdata_soa_fromWire20
-rw-r--r--src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_srv_fromWire36
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire4
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire106
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire114
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire124
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire24
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_sshfp_fromWire96
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire1.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire1.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire2.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire2.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire3.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire3.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire4.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire4.wire17
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire5.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire5.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire6.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire6.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire7.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire7.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire8.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire8.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire9.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_fromWire9.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire1.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire1.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire2.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire2.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire3.spec13
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire3.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire4.spec10
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire4.wire17
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire5.spec10
-rw-r--r--src/lib/dns/tests/testdata/rdata_tkey_toWire5.wire17
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire4
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire106
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire114
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire124
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire24
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire97
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire1.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire1.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire2.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire2.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire3.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire3.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire4.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire4.wire17
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire5.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire5.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire6.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire6.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire7.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire7.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire8.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire8.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire9.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_fromWire9.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire1.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire1.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire2.spec13
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire2.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire3.spec15
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire3.wire14
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire4.spec13
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire4.wire17
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire5.spec13
-rw-r--r--src/lib/dns/tests/testdata/rdata_tsig_toWire5.wire17
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire19
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire2.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire2.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire3.spec8
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire3.wire10
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire4.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire4.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire5.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_txt_fromWire5.wire8
-rw-r--r--src/lib/dns/tests/testdata/rdata_unknown_fromWire13
-rw-r--r--src/lib/dns/tests/testdata/rdatafields1.spec10
-rw-r--r--src/lib/dns/tests/testdata/rdatafields1.wire9
-rw-r--r--src/lib/dns/tests/testdata/rdatafields2.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdatafields2.wire9
-rw-r--r--src/lib/dns/tests/testdata/rdatafields3.spec11
-rw-r--r--src/lib/dns/tests/testdata/rdatafields3.wire12
-rw-r--r--src/lib/dns/tests/testdata/rdatafields4.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdatafields4.wire12
-rw-r--r--src/lib/dns/tests/testdata/rdatafields5.spec12
-rw-r--r--src/lib/dns/tests/testdata/rdatafields5.wire18
-rw-r--r--src/lib/dns/tests/testdata/rdatafields6.spec13
-rw-r--r--src/lib/dns/tests/testdata/rdatafields6.wire18
-rw-r--r--src/lib/dns/tests/testdata/rrcode16_fromWire14
-rw-r--r--src/lib/dns/tests/testdata/rrcode16_fromWire24
-rw-r--r--src/lib/dns/tests/testdata/rrcode32_fromWire14
-rw-r--r--src/lib/dns/tests/testdata/rrcode32_fromWire24
-rw-r--r--src/lib/dns/tests/testdata/rrset_toWire123
-rw-r--r--src/lib/dns/tests/testdata/rrset_toWire238
-rw-r--r--src/lib/dns/tests/testdata/rrset_toWire312
-rw-r--r--src/lib/dns/tests/testdata/rrset_toWire412
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify1.spec19
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify1.wire24
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify10.spec22
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify10.wire24
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify11.spec24
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify11.wire24
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify2.spec32
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify2.wire31
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify3.spec26
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify3.wire25
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify4.spec27
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify4.wire29
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify5.spec26
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify5.wire29
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify6.spec21
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify6.wire24
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify7.spec21
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify7.wire24
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify8.spec23
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify8.wire24
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify9.spec21
-rw-r--r--src/lib/dns/tests/testdata/tsig_verify9.wire24
-rw-r--r--src/lib/dns/tests/testdata/tsigrecord_toWire1.spec16
-rw-r--r--src/lib/dns/tests/testdata/tsigrecord_toWire1.wire14
-rw-r--r--src/lib/dns/tests/testdata/tsigrecord_toWire2.spec19
-rw-r--r--src/lib/dns/tests/testdata/tsigrecord_toWire2.wire20
-rw-r--r--src/lib/dns/tests/tsig_unittest.cc1185
-rw-r--r--src/lib/dns/tests/tsigerror_unittest.cc126
-rw-r--r--src/lib/dns/tests/tsigkey_unittest.cc350
-rw-r--r--src/lib/dns/tests/tsigrecord_unittest.cc158
-rw-r--r--src/lib/dns/tests/unittest_util.cc176
-rw-r--r--src/lib/dns/tests/unittest_util.h88
-rw-r--r--src/lib/dns/tests/zone_checker_unittest.cc349
467 files changed, 29469 insertions, 0 deletions
diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am
new file mode 100644
index 0000000..c89c3db
--- /dev/null
+++ b/src/lib/dns/tests/Makefile.am
@@ -0,0 +1,94 @@
+SUBDIRS = testdata .
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+AM_CPPFLAGS += -DTEST_DATA_SRCDIR=\"$(abs_top_srcdir)/src/lib/dns/tests/testdata\"
+AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dns/tests/testdata\"
+AM_CXXFLAGS = $(KEA_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+
+TESTS =
+if HAVE_GTEST
+TESTS += run_unittests
+run_unittests_SOURCES = unittest_util.h unittest_util.cc
+run_unittests_SOURCES += dns_exceptions_unittest.cc
+run_unittests_SOURCES += edns_unittest.cc
+run_unittests_SOURCES += master_lexer_inputsource_unittest.cc
+run_unittests_SOURCES += labelsequence_unittest.cc
+run_unittests_SOURCES += messagerenderer_unittest.cc
+run_unittests_SOURCES += master_lexer_token_unittest.cc
+run_unittests_SOURCES += master_lexer_unittest.cc
+run_unittests_SOURCES += master_loader_unittest.cc
+run_unittests_SOURCES += master_lexer_state_unittest.cc
+run_unittests_SOURCES += name_unittest.cc
+run_unittests_SOURCES += nsec3hash_unittest.cc
+run_unittests_SOURCES += rrclass_unittest.cc rrtype_unittest.cc
+run_unittests_SOURCES += rrttl_unittest.cc
+run_unittests_SOURCES += rrcollator_unittest.cc
+run_unittests_SOURCES += opcode_unittest.cc
+run_unittests_SOURCES += rcode_unittest.cc
+run_unittests_SOURCES += rdata_unittest.h rdata_unittest.cc
+run_unittests_SOURCES += rdatafields_unittest.cc
+run_unittests_SOURCES += rdata_pimpl_holder_unittest.cc
+run_unittests_SOURCES += rdata_char_string_unittest.cc
+run_unittests_SOURCES += rdata_char_string_data_unittest.cc
+run_unittests_SOURCES += rdata_in_a_unittest.cc rdata_in_aaaa_unittest.cc
+run_unittests_SOURCES += rdata_ns_unittest.cc rdata_soa_unittest.cc
+run_unittests_SOURCES += rdata_txt_like_unittest.cc
+run_unittests_SOURCES += rdata_mx_unittest.cc
+run_unittests_SOURCES += rdata_sshfp_unittest.cc
+run_unittests_SOURCES += rdata_ptr_unittest.cc rdata_cname_unittest.cc
+run_unittests_SOURCES += rdata_dname_unittest.cc
+run_unittests_SOURCES += rdata_afsdb_unittest.cc
+run_unittests_SOURCES += rdata_opt_unittest.cc
+run_unittests_SOURCES += rdata_dhcid_unittest.cc
+run_unittests_SOURCES += rdata_dnskey_unittest.cc
+run_unittests_SOURCES += rdata_ds_like_unittest.cc
+run_unittests_SOURCES += rdata_nsec_unittest.cc
+run_unittests_SOURCES += rdata_nsec3_unittest.cc
+run_unittests_SOURCES += rdata_nsecbitmap_unittest.cc
+run_unittests_SOURCES += rdata_nsec3param_unittest.cc
+run_unittests_SOURCES += rdata_nsec3param_like_unittest.cc
+run_unittests_SOURCES += rdata_rrsig_unittest.cc
+run_unittests_SOURCES += rdata_rp_unittest.cc
+run_unittests_SOURCES += rdata_srv_unittest.cc
+run_unittests_SOURCES += rdata_tlsa_unittest.cc
+run_unittests_SOURCES += rdata_minfo_unittest.cc
+run_unittests_SOURCES += rdata_tsig_unittest.cc
+run_unittests_SOURCES += rdata_naptr_unittest.cc
+run_unittests_SOURCES += rdata_hinfo_unittest.cc
+run_unittests_SOURCES += rdata_caa_unittest.cc
+run_unittests_SOURCES += rdata_tkey_unittest.cc
+run_unittests_SOURCES += rrset_unittest.cc
+run_unittests_SOURCES += qid_gen_unittest.cc
+run_unittests_SOURCES += question_unittest.cc
+run_unittests_SOURCES += rrparamregistry_unittest.cc
+run_unittests_SOURCES += masterload_unittest.cc
+run_unittests_SOURCES += message_unittest.cc
+run_unittests_SOURCES += serial_unittest.cc
+run_unittests_SOURCES += tsig_unittest.cc
+run_unittests_SOURCES += tsigerror_unittest.cc
+run_unittests_SOURCES += tsigkey_unittest.cc
+run_unittests_SOURCES += tsigrecord_unittest.cc
+run_unittests_SOURCES += master_loader_callbacks_test.cc
+run_unittests_SOURCES += rrset_collection_unittest.cc
+run_unittests_SOURCES += zone_checker_unittest.cc
+run_unittests_SOURCES += run_unittests.cc
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
+run_unittests_LDADD = $(top_builddir)/src/lib/dns/libkea-dns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+run_unittests_LDADD += $(CRYPTO_LIBS) $(GTEST_LDADD)
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/dns/tests/Makefile.in b/src/lib/dns/tests/Makefile.in
new file mode 100644
index 0000000..59bb00f
--- /dev/null
+++ b/src/lib/dns/tests/Makefile.in
@@ -0,0 +1,2357 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS = $(am__EXEEXT_1)
+@HAVE_GTEST_TRUE@am__append_1 = run_unittests
+noinst_PROGRAMS = $(am__EXEEXT_2)
+subdir = src/lib/dns/tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \
+ $(top_srcdir)/m4macros/ax_cpp11.m4 \
+ $(top_srcdir)/m4macros/ax_cpp20.m4 \
+ $(top_srcdir)/m4macros/ax_crypto.m4 \
+ $(top_srcdir)/m4macros/ax_find_library.m4 \
+ $(top_srcdir)/m4macros/ax_gssapi.m4 \
+ $(top_srcdir)/m4macros/ax_gtest.m4 \
+ $(top_srcdir)/m4macros/ax_isc_rpath.m4 \
+ $(top_srcdir)/m4macros/ax_netconf.m4 \
+ $(top_srcdir)/m4macros/libtool.m4 \
+ $(top_srcdir)/m4macros/ltoptions.m4 \
+ $(top_srcdir)/m4macros/ltsugar.m4 \
+ $(top_srcdir)/m4macros/ltversion.m4 \
+ $(top_srcdir)/m4macros/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@HAVE_GTEST_TRUE@am__EXEEXT_1 = run_unittests$(EXEEXT)
+am__EXEEXT_2 = $(am__EXEEXT_1)
+PROGRAMS = $(noinst_PROGRAMS)
+am__run_unittests_SOURCES_DIST = unittest_util.h unittest_util.cc \
+ dns_exceptions_unittest.cc edns_unittest.cc \
+ master_lexer_inputsource_unittest.cc labelsequence_unittest.cc \
+ messagerenderer_unittest.cc master_lexer_token_unittest.cc \
+ master_lexer_unittest.cc master_loader_unittest.cc \
+ master_lexer_state_unittest.cc name_unittest.cc \
+ nsec3hash_unittest.cc rrclass_unittest.cc rrtype_unittest.cc \
+ rrttl_unittest.cc rrcollator_unittest.cc opcode_unittest.cc \
+ rcode_unittest.cc rdata_unittest.h rdata_unittest.cc \
+ rdatafields_unittest.cc rdata_pimpl_holder_unittest.cc \
+ rdata_char_string_unittest.cc \
+ rdata_char_string_data_unittest.cc rdata_in_a_unittest.cc \
+ rdata_in_aaaa_unittest.cc rdata_ns_unittest.cc \
+ rdata_soa_unittest.cc rdata_txt_like_unittest.cc \
+ rdata_mx_unittest.cc rdata_sshfp_unittest.cc \
+ rdata_ptr_unittest.cc rdata_cname_unittest.cc \
+ rdata_dname_unittest.cc rdata_afsdb_unittest.cc \
+ rdata_opt_unittest.cc rdata_dhcid_unittest.cc \
+ rdata_dnskey_unittest.cc rdata_ds_like_unittest.cc \
+ rdata_nsec_unittest.cc rdata_nsec3_unittest.cc \
+ rdata_nsecbitmap_unittest.cc rdata_nsec3param_unittest.cc \
+ rdata_nsec3param_like_unittest.cc rdata_rrsig_unittest.cc \
+ rdata_rp_unittest.cc rdata_srv_unittest.cc \
+ rdata_tlsa_unittest.cc rdata_minfo_unittest.cc \
+ rdata_tsig_unittest.cc rdata_naptr_unittest.cc \
+ rdata_hinfo_unittest.cc rdata_caa_unittest.cc \
+ rdata_tkey_unittest.cc rrset_unittest.cc qid_gen_unittest.cc \
+ question_unittest.cc rrparamregistry_unittest.cc \
+ masterload_unittest.cc message_unittest.cc serial_unittest.cc \
+ tsig_unittest.cc tsigerror_unittest.cc tsigkey_unittest.cc \
+ tsigrecord_unittest.cc master_loader_callbacks_test.cc \
+ rrset_collection_unittest.cc zone_checker_unittest.cc \
+ run_unittests.cc
+@HAVE_GTEST_TRUE@am_run_unittests_OBJECTS = \
+@HAVE_GTEST_TRUE@ run_unittests-unittest_util.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-dns_exceptions_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-edns_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-master_lexer_inputsource_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-labelsequence_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-messagerenderer_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-master_lexer_token_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-master_lexer_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-master_loader_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-master_lexer_state_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-name_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-nsec3hash_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rrclass_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rrtype_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rrttl_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rrcollator_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-opcode_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rcode_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdatafields_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_pimpl_holder_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_char_string_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_char_string_data_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_in_a_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_in_aaaa_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_ns_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_soa_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_txt_like_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_mx_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_sshfp_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_ptr_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_cname_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_dname_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_afsdb_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_opt_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_dhcid_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_dnskey_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_ds_like_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_nsec_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_nsec3_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_nsecbitmap_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_nsec3param_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_nsec3param_like_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_rrsig_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_rp_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_srv_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_tlsa_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_minfo_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_tsig_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_naptr_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_hinfo_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_caa_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rdata_tkey_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rrset_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-qid_gen_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-question_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rrparamregistry_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-masterload_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-message_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-serial_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-tsig_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-tsigerror_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-tsigkey_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-tsigrecord_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-master_loader_callbacks_test.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-rrset_collection_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-zone_checker_unittest.$(OBJEXT) \
+@HAVE_GTEST_TRUE@ run_unittests-run_unittests.$(OBJEXT)
+run_unittests_OBJECTS = $(am_run_unittests_OBJECTS)
+am__DEPENDENCIES_1 =
+@HAVE_GTEST_TRUE@run_unittests_DEPENDENCIES = \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dns/libkea-dns++.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/unittests/libutil_unittests.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \
+@HAVE_GTEST_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+run_unittests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(AM_CXXFLAGS) $(CXXFLAGS) $(run_unittests_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = \
+ ./$(DEPDIR)/run_unittests-dns_exceptions_unittest.Po \
+ ./$(DEPDIR)/run_unittests-edns_unittest.Po \
+ ./$(DEPDIR)/run_unittests-labelsequence_unittest.Po \
+ ./$(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Po \
+ ./$(DEPDIR)/run_unittests-master_lexer_state_unittest.Po \
+ ./$(DEPDIR)/run_unittests-master_lexer_token_unittest.Po \
+ ./$(DEPDIR)/run_unittests-master_lexer_unittest.Po \
+ ./$(DEPDIR)/run_unittests-master_loader_callbacks_test.Po \
+ ./$(DEPDIR)/run_unittests-master_loader_unittest.Po \
+ ./$(DEPDIR)/run_unittests-masterload_unittest.Po \
+ ./$(DEPDIR)/run_unittests-message_unittest.Po \
+ ./$(DEPDIR)/run_unittests-messagerenderer_unittest.Po \
+ ./$(DEPDIR)/run_unittests-name_unittest.Po \
+ ./$(DEPDIR)/run_unittests-nsec3hash_unittest.Po \
+ ./$(DEPDIR)/run_unittests-opcode_unittest.Po \
+ ./$(DEPDIR)/run_unittests-qid_gen_unittest.Po \
+ ./$(DEPDIR)/run_unittests-question_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rcode_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_afsdb_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_caa_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_char_string_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_cname_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_dhcid_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_dname_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_dnskey_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_ds_like_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_hinfo_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_in_a_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_minfo_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_mx_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_naptr_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_ns_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_nsec3_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_nsec_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_opt_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_ptr_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_rp_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_rrsig_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_soa_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_srv_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_sshfp_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_tkey_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_tlsa_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_tsig_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_txt_like_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdata_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rdatafields_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rrclass_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rrcollator_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rrparamregistry_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rrset_collection_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rrset_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rrttl_unittest.Po \
+ ./$(DEPDIR)/run_unittests-rrtype_unittest.Po \
+ ./$(DEPDIR)/run_unittests-run_unittests.Po \
+ ./$(DEPDIR)/run_unittests-serial_unittest.Po \
+ ./$(DEPDIR)/run_unittests-tsig_unittest.Po \
+ ./$(DEPDIR)/run_unittests-tsigerror_unittest.Po \
+ ./$(DEPDIR)/run_unittests-tsigkey_unittest.Po \
+ ./$(DEPDIR)/run_unittests-tsigrecord_unittest.Po \
+ ./$(DEPDIR)/run_unittests-unittest_util.Po \
+ ./$(DEPDIR)/run_unittests-zone_checker_unittest.Po
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(run_unittests_SOURCES)
+DIST_SOURCES = $(am__run_unittests_SOURCES_DIST)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ASCIIDOC = @ASCIIDOC@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_INCLUDES = @BOOST_INCLUDES@
+BOOST_LIBS = @BOOST_LIBS@
+BOTAN_TOOL = @BOTAN_TOOL@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTRIB_DIR = @CONTRIB_DIR@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTO_CFLAGS = @CRYPTO_CFLAGS@
+CRYPTO_INCLUDES = @CRYPTO_INCLUDES@
+CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@
+CRYPTO_LIBS = @CRYPTO_LIBS@
+CRYPTO_PACKAGE = @CRYPTO_PACKAGE@
+CRYPTO_RPATH = @CRYPTO_RPATH@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@
+DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@
+DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@
+DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@
+DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@
+DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@
+DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@
+DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@
+DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@
+DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@
+DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@
+DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@
+DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@
+DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@
+DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_INCLUDES = @GTEST_INCLUDES@
+GTEST_LDADD = @GTEST_LDADD@
+GTEST_LDFLAGS = @GTEST_LDFLAGS@
+GTEST_SOURCE = @GTEST_SOURCE@
+HAVE_NETCONF = @HAVE_NETCONF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KEA_CXXFLAGS = @KEA_CXXFLAGS@
+KEA_SRCID = @KEA_SRCID@
+KRB5_CONFIG = @KRB5_CONFIG@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@
+LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@
+LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@
+LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@
+LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@
+LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@
+LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@
+LIBYANG_LIBS = @LIBYANG_LIBS@
+LIBYANG_PREFIX = @LIBYANG_PREFIX@
+LIBYANG_VERSION = @LIBYANG_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@
+LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
+PERL = @PERL@
+PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PKGPYTHONDIR = @PKGPYTHONDIR@
+PKG_CONFIG = @PKG_CONFIG@
+PLANTUML = @PLANTUML@
+PREMIUM_DIR = @PREMIUM_DIR@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SEP = @SEP@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINXBUILD = @SPHINXBUILD@
+SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@
+SR_PLUGINS_PATH = @SR_PLUGINS_PATH@
+SR_REPO_PATH = @SR_REPO_PATH@
+STRIP = @STRIP@
+SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@
+SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@
+SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@
+SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@
+SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@
+SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@
+SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@
+SYSREPO_LIBS = @SYSREPO_LIBS@
+SYSREPO_PREFIX = @SYSREPO_PREFIX@
+SYSREPO_VERSION = @SYSREPO_VERSION@
+USE_LCOV = @USE_LCOV@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@
+YACC = @YACC@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = testdata .
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib \
+ $(BOOST_INCLUDES) \
+ -DTEST_DATA_SRCDIR=\"$(abs_top_srcdir)/src/lib/dns/tests/testdata\" \
+ -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dns/tests/testdata\"
+AM_CXXFLAGS = $(KEA_CXXFLAGS)
+@USE_STATIC_LINK_TRUE@AM_LDFLAGS = -static
+CLEANFILES = *.gcno *.gcda
+TESTS_ENVIRONMENT = $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+@HAVE_GTEST_TRUE@run_unittests_SOURCES = unittest_util.h \
+@HAVE_GTEST_TRUE@ unittest_util.cc dns_exceptions_unittest.cc \
+@HAVE_GTEST_TRUE@ edns_unittest.cc \
+@HAVE_GTEST_TRUE@ master_lexer_inputsource_unittest.cc \
+@HAVE_GTEST_TRUE@ labelsequence_unittest.cc \
+@HAVE_GTEST_TRUE@ messagerenderer_unittest.cc \
+@HAVE_GTEST_TRUE@ master_lexer_token_unittest.cc \
+@HAVE_GTEST_TRUE@ master_lexer_unittest.cc \
+@HAVE_GTEST_TRUE@ master_loader_unittest.cc \
+@HAVE_GTEST_TRUE@ master_lexer_state_unittest.cc \
+@HAVE_GTEST_TRUE@ name_unittest.cc nsec3hash_unittest.cc \
+@HAVE_GTEST_TRUE@ rrclass_unittest.cc rrtype_unittest.cc \
+@HAVE_GTEST_TRUE@ rrttl_unittest.cc rrcollator_unittest.cc \
+@HAVE_GTEST_TRUE@ opcode_unittest.cc rcode_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_unittest.h rdata_unittest.cc \
+@HAVE_GTEST_TRUE@ rdatafields_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_pimpl_holder_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_char_string_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_char_string_data_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_in_a_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_in_aaaa_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_ns_unittest.cc rdata_soa_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_txt_like_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_mx_unittest.cc rdata_sshfp_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_ptr_unittest.cc rdata_cname_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_dname_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_afsdb_unittest.cc rdata_opt_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_dhcid_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_dnskey_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_ds_like_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_nsec_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_nsec3_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_nsecbitmap_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_nsec3param_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_nsec3param_like_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_rrsig_unittest.cc rdata_rp_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_srv_unittest.cc rdata_tlsa_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_minfo_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_tsig_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_naptr_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_hinfo_unittest.cc rdata_caa_unittest.cc \
+@HAVE_GTEST_TRUE@ rdata_tkey_unittest.cc rrset_unittest.cc \
+@HAVE_GTEST_TRUE@ qid_gen_unittest.cc question_unittest.cc \
+@HAVE_GTEST_TRUE@ rrparamregistry_unittest.cc \
+@HAVE_GTEST_TRUE@ masterload_unittest.cc message_unittest.cc \
+@HAVE_GTEST_TRUE@ serial_unittest.cc tsig_unittest.cc \
+@HAVE_GTEST_TRUE@ tsigerror_unittest.cc tsigkey_unittest.cc \
+@HAVE_GTEST_TRUE@ tsigrecord_unittest.cc \
+@HAVE_GTEST_TRUE@ master_loader_callbacks_test.cc \
+@HAVE_GTEST_TRUE@ rrset_collection_unittest.cc \
+@HAVE_GTEST_TRUE@ zone_checker_unittest.cc run_unittests.cc
+@HAVE_GTEST_TRUE@run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+@HAVE_GTEST_TRUE@run_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
+@HAVE_GTEST_TRUE@run_unittests_LDADD = \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/dns/libkea-dns++.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/unittests/libutil_unittests.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/util/libkea-util.la \
+@HAVE_GTEST_TRUE@ $(top_builddir)/src/lib/exceptions/libkea-exceptions.la \
+@HAVE_GTEST_TRUE@ $(CRYPTO_LIBS) $(GTEST_LDADD)
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/dns/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/lib/dns/tests/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+run_unittests$(EXEEXT): $(run_unittests_OBJECTS) $(run_unittests_DEPENDENCIES) $(EXTRA_run_unittests_DEPENDENCIES)
+ @rm -f run_unittests$(EXEEXT)
+ $(AM_V_CXXLD)$(run_unittests_LINK) $(run_unittests_OBJECTS) $(run_unittests_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-dns_exceptions_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-edns_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-labelsequence_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-master_lexer_state_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-master_lexer_token_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-master_lexer_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-master_loader_callbacks_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-master_loader_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-masterload_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-message_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-messagerenderer_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-name_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-nsec3hash_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-opcode_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-qid_gen_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-question_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rcode_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_afsdb_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_caa_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_char_string_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_cname_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_dhcid_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_dname_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_dnskey_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_ds_like_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_hinfo_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_in_a_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_minfo_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_mx_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_naptr_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_ns_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_nsec3_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_nsec_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_opt_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_ptr_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_rp_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_rrsig_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_soa_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_srv_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_sshfp_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_tkey_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_tlsa_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_tsig_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_txt_like_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdata_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rdatafields_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rrclass_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rrcollator_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rrparamregistry_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rrset_collection_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rrset_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rrttl_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-rrtype_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-run_unittests.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-serial_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-tsig_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-tsigerror_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-tsigkey_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-tsigrecord_unittest.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-unittest_util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_unittests-zone_checker_unittest.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+run_unittests-unittest_util.o: unittest_util.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-unittest_util.o -MD -MP -MF $(DEPDIR)/run_unittests-unittest_util.Tpo -c -o run_unittests-unittest_util.o `test -f 'unittest_util.cc' || echo '$(srcdir)/'`unittest_util.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-unittest_util.Tpo $(DEPDIR)/run_unittests-unittest_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='unittest_util.cc' object='run_unittests-unittest_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-unittest_util.o `test -f 'unittest_util.cc' || echo '$(srcdir)/'`unittest_util.cc
+
+run_unittests-unittest_util.obj: unittest_util.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-unittest_util.obj -MD -MP -MF $(DEPDIR)/run_unittests-unittest_util.Tpo -c -o run_unittests-unittest_util.obj `if test -f 'unittest_util.cc'; then $(CYGPATH_W) 'unittest_util.cc'; else $(CYGPATH_W) '$(srcdir)/unittest_util.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-unittest_util.Tpo $(DEPDIR)/run_unittests-unittest_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='unittest_util.cc' object='run_unittests-unittest_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-unittest_util.obj `if test -f 'unittest_util.cc'; then $(CYGPATH_W) 'unittest_util.cc'; else $(CYGPATH_W) '$(srcdir)/unittest_util.cc'; fi`
+
+run_unittests-dns_exceptions_unittest.o: dns_exceptions_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-dns_exceptions_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-dns_exceptions_unittest.Tpo -c -o run_unittests-dns_exceptions_unittest.o `test -f 'dns_exceptions_unittest.cc' || echo '$(srcdir)/'`dns_exceptions_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-dns_exceptions_unittest.Tpo $(DEPDIR)/run_unittests-dns_exceptions_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dns_exceptions_unittest.cc' object='run_unittests-dns_exceptions_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-dns_exceptions_unittest.o `test -f 'dns_exceptions_unittest.cc' || echo '$(srcdir)/'`dns_exceptions_unittest.cc
+
+run_unittests-dns_exceptions_unittest.obj: dns_exceptions_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-dns_exceptions_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-dns_exceptions_unittest.Tpo -c -o run_unittests-dns_exceptions_unittest.obj `if test -f 'dns_exceptions_unittest.cc'; then $(CYGPATH_W) 'dns_exceptions_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/dns_exceptions_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-dns_exceptions_unittest.Tpo $(DEPDIR)/run_unittests-dns_exceptions_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dns_exceptions_unittest.cc' object='run_unittests-dns_exceptions_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-dns_exceptions_unittest.obj `if test -f 'dns_exceptions_unittest.cc'; then $(CYGPATH_W) 'dns_exceptions_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/dns_exceptions_unittest.cc'; fi`
+
+run_unittests-edns_unittest.o: edns_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-edns_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-edns_unittest.Tpo -c -o run_unittests-edns_unittest.o `test -f 'edns_unittest.cc' || echo '$(srcdir)/'`edns_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-edns_unittest.Tpo $(DEPDIR)/run_unittests-edns_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='edns_unittest.cc' object='run_unittests-edns_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-edns_unittest.o `test -f 'edns_unittest.cc' || echo '$(srcdir)/'`edns_unittest.cc
+
+run_unittests-edns_unittest.obj: edns_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-edns_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-edns_unittest.Tpo -c -o run_unittests-edns_unittest.obj `if test -f 'edns_unittest.cc'; then $(CYGPATH_W) 'edns_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/edns_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-edns_unittest.Tpo $(DEPDIR)/run_unittests-edns_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='edns_unittest.cc' object='run_unittests-edns_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-edns_unittest.obj `if test -f 'edns_unittest.cc'; then $(CYGPATH_W) 'edns_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/edns_unittest.cc'; fi`
+
+run_unittests-master_lexer_inputsource_unittest.o: master_lexer_inputsource_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_inputsource_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Tpo -c -o run_unittests-master_lexer_inputsource_unittest.o `test -f 'master_lexer_inputsource_unittest.cc' || echo '$(srcdir)/'`master_lexer_inputsource_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_inputsource_unittest.cc' object='run_unittests-master_lexer_inputsource_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_inputsource_unittest.o `test -f 'master_lexer_inputsource_unittest.cc' || echo '$(srcdir)/'`master_lexer_inputsource_unittest.cc
+
+run_unittests-master_lexer_inputsource_unittest.obj: master_lexer_inputsource_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_inputsource_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Tpo -c -o run_unittests-master_lexer_inputsource_unittest.obj `if test -f 'master_lexer_inputsource_unittest.cc'; then $(CYGPATH_W) 'master_lexer_inputsource_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_inputsource_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_inputsource_unittest.cc' object='run_unittests-master_lexer_inputsource_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_inputsource_unittest.obj `if test -f 'master_lexer_inputsource_unittest.cc'; then $(CYGPATH_W) 'master_lexer_inputsource_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_inputsource_unittest.cc'; fi`
+
+run_unittests-labelsequence_unittest.o: labelsequence_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-labelsequence_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-labelsequence_unittest.Tpo -c -o run_unittests-labelsequence_unittest.o `test -f 'labelsequence_unittest.cc' || echo '$(srcdir)/'`labelsequence_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-labelsequence_unittest.Tpo $(DEPDIR)/run_unittests-labelsequence_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='labelsequence_unittest.cc' object='run_unittests-labelsequence_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-labelsequence_unittest.o `test -f 'labelsequence_unittest.cc' || echo '$(srcdir)/'`labelsequence_unittest.cc
+
+run_unittests-labelsequence_unittest.obj: labelsequence_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-labelsequence_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-labelsequence_unittest.Tpo -c -o run_unittests-labelsequence_unittest.obj `if test -f 'labelsequence_unittest.cc'; then $(CYGPATH_W) 'labelsequence_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/labelsequence_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-labelsequence_unittest.Tpo $(DEPDIR)/run_unittests-labelsequence_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='labelsequence_unittest.cc' object='run_unittests-labelsequence_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-labelsequence_unittest.obj `if test -f 'labelsequence_unittest.cc'; then $(CYGPATH_W) 'labelsequence_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/labelsequence_unittest.cc'; fi`
+
+run_unittests-messagerenderer_unittest.o: messagerenderer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-messagerenderer_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-messagerenderer_unittest.Tpo -c -o run_unittests-messagerenderer_unittest.o `test -f 'messagerenderer_unittest.cc' || echo '$(srcdir)/'`messagerenderer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-messagerenderer_unittest.Tpo $(DEPDIR)/run_unittests-messagerenderer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='messagerenderer_unittest.cc' object='run_unittests-messagerenderer_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-messagerenderer_unittest.o `test -f 'messagerenderer_unittest.cc' || echo '$(srcdir)/'`messagerenderer_unittest.cc
+
+run_unittests-messagerenderer_unittest.obj: messagerenderer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-messagerenderer_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-messagerenderer_unittest.Tpo -c -o run_unittests-messagerenderer_unittest.obj `if test -f 'messagerenderer_unittest.cc'; then $(CYGPATH_W) 'messagerenderer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/messagerenderer_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-messagerenderer_unittest.Tpo $(DEPDIR)/run_unittests-messagerenderer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='messagerenderer_unittest.cc' object='run_unittests-messagerenderer_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-messagerenderer_unittest.obj `if test -f 'messagerenderer_unittest.cc'; then $(CYGPATH_W) 'messagerenderer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/messagerenderer_unittest.cc'; fi`
+
+run_unittests-master_lexer_token_unittest.o: master_lexer_token_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_token_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_token_unittest.Tpo -c -o run_unittests-master_lexer_token_unittest.o `test -f 'master_lexer_token_unittest.cc' || echo '$(srcdir)/'`master_lexer_token_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_token_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_token_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_token_unittest.cc' object='run_unittests-master_lexer_token_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_token_unittest.o `test -f 'master_lexer_token_unittest.cc' || echo '$(srcdir)/'`master_lexer_token_unittest.cc
+
+run_unittests-master_lexer_token_unittest.obj: master_lexer_token_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_token_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_token_unittest.Tpo -c -o run_unittests-master_lexer_token_unittest.obj `if test -f 'master_lexer_token_unittest.cc'; then $(CYGPATH_W) 'master_lexer_token_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_token_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_token_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_token_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_token_unittest.cc' object='run_unittests-master_lexer_token_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_token_unittest.obj `if test -f 'master_lexer_token_unittest.cc'; then $(CYGPATH_W) 'master_lexer_token_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_token_unittest.cc'; fi`
+
+run_unittests-master_lexer_unittest.o: master_lexer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_unittest.Tpo -c -o run_unittests-master_lexer_unittest.o `test -f 'master_lexer_unittest.cc' || echo '$(srcdir)/'`master_lexer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_unittest.cc' object='run_unittests-master_lexer_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_unittest.o `test -f 'master_lexer_unittest.cc' || echo '$(srcdir)/'`master_lexer_unittest.cc
+
+run_unittests-master_lexer_unittest.obj: master_lexer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_unittest.Tpo -c -o run_unittests-master_lexer_unittest.obj `if test -f 'master_lexer_unittest.cc'; then $(CYGPATH_W) 'master_lexer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_unittest.cc' object='run_unittests-master_lexer_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_unittest.obj `if test -f 'master_lexer_unittest.cc'; then $(CYGPATH_W) 'master_lexer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_unittest.cc'; fi`
+
+run_unittests-master_loader_unittest.o: master_loader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_loader_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-master_loader_unittest.Tpo -c -o run_unittests-master_loader_unittest.o `test -f 'master_loader_unittest.cc' || echo '$(srcdir)/'`master_loader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_loader_unittest.Tpo $(DEPDIR)/run_unittests-master_loader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_loader_unittest.cc' object='run_unittests-master_loader_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_loader_unittest.o `test -f 'master_loader_unittest.cc' || echo '$(srcdir)/'`master_loader_unittest.cc
+
+run_unittests-master_loader_unittest.obj: master_loader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_loader_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-master_loader_unittest.Tpo -c -o run_unittests-master_loader_unittest.obj `if test -f 'master_loader_unittest.cc'; then $(CYGPATH_W) 'master_loader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_loader_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_loader_unittest.Tpo $(DEPDIR)/run_unittests-master_loader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_loader_unittest.cc' object='run_unittests-master_loader_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_loader_unittest.obj `if test -f 'master_loader_unittest.cc'; then $(CYGPATH_W) 'master_loader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_loader_unittest.cc'; fi`
+
+run_unittests-master_lexer_state_unittest.o: master_lexer_state_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_state_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_state_unittest.Tpo -c -o run_unittests-master_lexer_state_unittest.o `test -f 'master_lexer_state_unittest.cc' || echo '$(srcdir)/'`master_lexer_state_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_state_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_state_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_state_unittest.cc' object='run_unittests-master_lexer_state_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_state_unittest.o `test -f 'master_lexer_state_unittest.cc' || echo '$(srcdir)/'`master_lexer_state_unittest.cc
+
+run_unittests-master_lexer_state_unittest.obj: master_lexer_state_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_lexer_state_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-master_lexer_state_unittest.Tpo -c -o run_unittests-master_lexer_state_unittest.obj `if test -f 'master_lexer_state_unittest.cc'; then $(CYGPATH_W) 'master_lexer_state_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_state_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_lexer_state_unittest.Tpo $(DEPDIR)/run_unittests-master_lexer_state_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_lexer_state_unittest.cc' object='run_unittests-master_lexer_state_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_lexer_state_unittest.obj `if test -f 'master_lexer_state_unittest.cc'; then $(CYGPATH_W) 'master_lexer_state_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/master_lexer_state_unittest.cc'; fi`
+
+run_unittests-name_unittest.o: name_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-name_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-name_unittest.Tpo -c -o run_unittests-name_unittest.o `test -f 'name_unittest.cc' || echo '$(srcdir)/'`name_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-name_unittest.Tpo $(DEPDIR)/run_unittests-name_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='name_unittest.cc' object='run_unittests-name_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-name_unittest.o `test -f 'name_unittest.cc' || echo '$(srcdir)/'`name_unittest.cc
+
+run_unittests-name_unittest.obj: name_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-name_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-name_unittest.Tpo -c -o run_unittests-name_unittest.obj `if test -f 'name_unittest.cc'; then $(CYGPATH_W) 'name_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/name_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-name_unittest.Tpo $(DEPDIR)/run_unittests-name_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='name_unittest.cc' object='run_unittests-name_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-name_unittest.obj `if test -f 'name_unittest.cc'; then $(CYGPATH_W) 'name_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/name_unittest.cc'; fi`
+
+run_unittests-nsec3hash_unittest.o: nsec3hash_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-nsec3hash_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-nsec3hash_unittest.Tpo -c -o run_unittests-nsec3hash_unittest.o `test -f 'nsec3hash_unittest.cc' || echo '$(srcdir)/'`nsec3hash_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-nsec3hash_unittest.Tpo $(DEPDIR)/run_unittests-nsec3hash_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsec3hash_unittest.cc' object='run_unittests-nsec3hash_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-nsec3hash_unittest.o `test -f 'nsec3hash_unittest.cc' || echo '$(srcdir)/'`nsec3hash_unittest.cc
+
+run_unittests-nsec3hash_unittest.obj: nsec3hash_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-nsec3hash_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-nsec3hash_unittest.Tpo -c -o run_unittests-nsec3hash_unittest.obj `if test -f 'nsec3hash_unittest.cc'; then $(CYGPATH_W) 'nsec3hash_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/nsec3hash_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-nsec3hash_unittest.Tpo $(DEPDIR)/run_unittests-nsec3hash_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='nsec3hash_unittest.cc' object='run_unittests-nsec3hash_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-nsec3hash_unittest.obj `if test -f 'nsec3hash_unittest.cc'; then $(CYGPATH_W) 'nsec3hash_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/nsec3hash_unittest.cc'; fi`
+
+run_unittests-rrclass_unittest.o: rrclass_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrclass_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rrclass_unittest.Tpo -c -o run_unittests-rrclass_unittest.o `test -f 'rrclass_unittest.cc' || echo '$(srcdir)/'`rrclass_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrclass_unittest.Tpo $(DEPDIR)/run_unittests-rrclass_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrclass_unittest.cc' object='run_unittests-rrclass_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrclass_unittest.o `test -f 'rrclass_unittest.cc' || echo '$(srcdir)/'`rrclass_unittest.cc
+
+run_unittests-rrclass_unittest.obj: rrclass_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrclass_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rrclass_unittest.Tpo -c -o run_unittests-rrclass_unittest.obj `if test -f 'rrclass_unittest.cc'; then $(CYGPATH_W) 'rrclass_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrclass_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrclass_unittest.Tpo $(DEPDIR)/run_unittests-rrclass_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrclass_unittest.cc' object='run_unittests-rrclass_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrclass_unittest.obj `if test -f 'rrclass_unittest.cc'; then $(CYGPATH_W) 'rrclass_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrclass_unittest.cc'; fi`
+
+run_unittests-rrtype_unittest.o: rrtype_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrtype_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rrtype_unittest.Tpo -c -o run_unittests-rrtype_unittest.o `test -f 'rrtype_unittest.cc' || echo '$(srcdir)/'`rrtype_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrtype_unittest.Tpo $(DEPDIR)/run_unittests-rrtype_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrtype_unittest.cc' object='run_unittests-rrtype_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrtype_unittest.o `test -f 'rrtype_unittest.cc' || echo '$(srcdir)/'`rrtype_unittest.cc
+
+run_unittests-rrtype_unittest.obj: rrtype_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrtype_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rrtype_unittest.Tpo -c -o run_unittests-rrtype_unittest.obj `if test -f 'rrtype_unittest.cc'; then $(CYGPATH_W) 'rrtype_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrtype_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrtype_unittest.Tpo $(DEPDIR)/run_unittests-rrtype_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrtype_unittest.cc' object='run_unittests-rrtype_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrtype_unittest.obj `if test -f 'rrtype_unittest.cc'; then $(CYGPATH_W) 'rrtype_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrtype_unittest.cc'; fi`
+
+run_unittests-rrttl_unittest.o: rrttl_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrttl_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rrttl_unittest.Tpo -c -o run_unittests-rrttl_unittest.o `test -f 'rrttl_unittest.cc' || echo '$(srcdir)/'`rrttl_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrttl_unittest.Tpo $(DEPDIR)/run_unittests-rrttl_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrttl_unittest.cc' object='run_unittests-rrttl_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrttl_unittest.o `test -f 'rrttl_unittest.cc' || echo '$(srcdir)/'`rrttl_unittest.cc
+
+run_unittests-rrttl_unittest.obj: rrttl_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrttl_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rrttl_unittest.Tpo -c -o run_unittests-rrttl_unittest.obj `if test -f 'rrttl_unittest.cc'; then $(CYGPATH_W) 'rrttl_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrttl_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrttl_unittest.Tpo $(DEPDIR)/run_unittests-rrttl_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrttl_unittest.cc' object='run_unittests-rrttl_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrttl_unittest.obj `if test -f 'rrttl_unittest.cc'; then $(CYGPATH_W) 'rrttl_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrttl_unittest.cc'; fi`
+
+run_unittests-rrcollator_unittest.o: rrcollator_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrcollator_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rrcollator_unittest.Tpo -c -o run_unittests-rrcollator_unittest.o `test -f 'rrcollator_unittest.cc' || echo '$(srcdir)/'`rrcollator_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrcollator_unittest.Tpo $(DEPDIR)/run_unittests-rrcollator_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrcollator_unittest.cc' object='run_unittests-rrcollator_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrcollator_unittest.o `test -f 'rrcollator_unittest.cc' || echo '$(srcdir)/'`rrcollator_unittest.cc
+
+run_unittests-rrcollator_unittest.obj: rrcollator_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrcollator_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rrcollator_unittest.Tpo -c -o run_unittests-rrcollator_unittest.obj `if test -f 'rrcollator_unittest.cc'; then $(CYGPATH_W) 'rrcollator_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrcollator_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrcollator_unittest.Tpo $(DEPDIR)/run_unittests-rrcollator_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrcollator_unittest.cc' object='run_unittests-rrcollator_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrcollator_unittest.obj `if test -f 'rrcollator_unittest.cc'; then $(CYGPATH_W) 'rrcollator_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrcollator_unittest.cc'; fi`
+
+run_unittests-opcode_unittest.o: opcode_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-opcode_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-opcode_unittest.Tpo -c -o run_unittests-opcode_unittest.o `test -f 'opcode_unittest.cc' || echo '$(srcdir)/'`opcode_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-opcode_unittest.Tpo $(DEPDIR)/run_unittests-opcode_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='opcode_unittest.cc' object='run_unittests-opcode_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-opcode_unittest.o `test -f 'opcode_unittest.cc' || echo '$(srcdir)/'`opcode_unittest.cc
+
+run_unittests-opcode_unittest.obj: opcode_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-opcode_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-opcode_unittest.Tpo -c -o run_unittests-opcode_unittest.obj `if test -f 'opcode_unittest.cc'; then $(CYGPATH_W) 'opcode_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/opcode_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-opcode_unittest.Tpo $(DEPDIR)/run_unittests-opcode_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='opcode_unittest.cc' object='run_unittests-opcode_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-opcode_unittest.obj `if test -f 'opcode_unittest.cc'; then $(CYGPATH_W) 'opcode_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/opcode_unittest.cc'; fi`
+
+run_unittests-rcode_unittest.o: rcode_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rcode_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rcode_unittest.Tpo -c -o run_unittests-rcode_unittest.o `test -f 'rcode_unittest.cc' || echo '$(srcdir)/'`rcode_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rcode_unittest.Tpo $(DEPDIR)/run_unittests-rcode_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rcode_unittest.cc' object='run_unittests-rcode_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rcode_unittest.o `test -f 'rcode_unittest.cc' || echo '$(srcdir)/'`rcode_unittest.cc
+
+run_unittests-rcode_unittest.obj: rcode_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rcode_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rcode_unittest.Tpo -c -o run_unittests-rcode_unittest.obj `if test -f 'rcode_unittest.cc'; then $(CYGPATH_W) 'rcode_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rcode_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rcode_unittest.Tpo $(DEPDIR)/run_unittests-rcode_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rcode_unittest.cc' object='run_unittests-rcode_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rcode_unittest.obj `if test -f 'rcode_unittest.cc'; then $(CYGPATH_W) 'rcode_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rcode_unittest.cc'; fi`
+
+run_unittests-rdata_unittest.o: rdata_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_unittest.Tpo -c -o run_unittests-rdata_unittest.o `test -f 'rdata_unittest.cc' || echo '$(srcdir)/'`rdata_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_unittest.Tpo $(DEPDIR)/run_unittests-rdata_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_unittest.cc' object='run_unittests-rdata_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_unittest.o `test -f 'rdata_unittest.cc' || echo '$(srcdir)/'`rdata_unittest.cc
+
+run_unittests-rdata_unittest.obj: rdata_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_unittest.Tpo -c -o run_unittests-rdata_unittest.obj `if test -f 'rdata_unittest.cc'; then $(CYGPATH_W) 'rdata_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_unittest.Tpo $(DEPDIR)/run_unittests-rdata_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_unittest.cc' object='run_unittests-rdata_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_unittest.obj `if test -f 'rdata_unittest.cc'; then $(CYGPATH_W) 'rdata_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_unittest.cc'; fi`
+
+run_unittests-rdatafields_unittest.o: rdatafields_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdatafields_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdatafields_unittest.Tpo -c -o run_unittests-rdatafields_unittest.o `test -f 'rdatafields_unittest.cc' || echo '$(srcdir)/'`rdatafields_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdatafields_unittest.Tpo $(DEPDIR)/run_unittests-rdatafields_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdatafields_unittest.cc' object='run_unittests-rdatafields_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdatafields_unittest.o `test -f 'rdatafields_unittest.cc' || echo '$(srcdir)/'`rdatafields_unittest.cc
+
+run_unittests-rdatafields_unittest.obj: rdatafields_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdatafields_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdatafields_unittest.Tpo -c -o run_unittests-rdatafields_unittest.obj `if test -f 'rdatafields_unittest.cc'; then $(CYGPATH_W) 'rdatafields_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdatafields_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdatafields_unittest.Tpo $(DEPDIR)/run_unittests-rdatafields_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdatafields_unittest.cc' object='run_unittests-rdatafields_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdatafields_unittest.obj `if test -f 'rdatafields_unittest.cc'; then $(CYGPATH_W) 'rdatafields_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdatafields_unittest.cc'; fi`
+
+run_unittests-rdata_pimpl_holder_unittest.o: rdata_pimpl_holder_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_pimpl_holder_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Tpo -c -o run_unittests-rdata_pimpl_holder_unittest.o `test -f 'rdata_pimpl_holder_unittest.cc' || echo '$(srcdir)/'`rdata_pimpl_holder_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Tpo $(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_pimpl_holder_unittest.cc' object='run_unittests-rdata_pimpl_holder_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_pimpl_holder_unittest.o `test -f 'rdata_pimpl_holder_unittest.cc' || echo '$(srcdir)/'`rdata_pimpl_holder_unittest.cc
+
+run_unittests-rdata_pimpl_holder_unittest.obj: rdata_pimpl_holder_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_pimpl_holder_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Tpo -c -o run_unittests-rdata_pimpl_holder_unittest.obj `if test -f 'rdata_pimpl_holder_unittest.cc'; then $(CYGPATH_W) 'rdata_pimpl_holder_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_pimpl_holder_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Tpo $(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_pimpl_holder_unittest.cc' object='run_unittests-rdata_pimpl_holder_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_pimpl_holder_unittest.obj `if test -f 'rdata_pimpl_holder_unittest.cc'; then $(CYGPATH_W) 'rdata_pimpl_holder_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_pimpl_holder_unittest.cc'; fi`
+
+run_unittests-rdata_char_string_unittest.o: rdata_char_string_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_char_string_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_char_string_unittest.Tpo -c -o run_unittests-rdata_char_string_unittest.o `test -f 'rdata_char_string_unittest.cc' || echo '$(srcdir)/'`rdata_char_string_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_char_string_unittest.Tpo $(DEPDIR)/run_unittests-rdata_char_string_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_char_string_unittest.cc' object='run_unittests-rdata_char_string_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_char_string_unittest.o `test -f 'rdata_char_string_unittest.cc' || echo '$(srcdir)/'`rdata_char_string_unittest.cc
+
+run_unittests-rdata_char_string_unittest.obj: rdata_char_string_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_char_string_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_char_string_unittest.Tpo -c -o run_unittests-rdata_char_string_unittest.obj `if test -f 'rdata_char_string_unittest.cc'; then $(CYGPATH_W) 'rdata_char_string_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_char_string_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_char_string_unittest.Tpo $(DEPDIR)/run_unittests-rdata_char_string_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_char_string_unittest.cc' object='run_unittests-rdata_char_string_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_char_string_unittest.obj `if test -f 'rdata_char_string_unittest.cc'; then $(CYGPATH_W) 'rdata_char_string_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_char_string_unittest.cc'; fi`
+
+run_unittests-rdata_char_string_data_unittest.o: rdata_char_string_data_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_char_string_data_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Tpo -c -o run_unittests-rdata_char_string_data_unittest.o `test -f 'rdata_char_string_data_unittest.cc' || echo '$(srcdir)/'`rdata_char_string_data_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Tpo $(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_char_string_data_unittest.cc' object='run_unittests-rdata_char_string_data_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_char_string_data_unittest.o `test -f 'rdata_char_string_data_unittest.cc' || echo '$(srcdir)/'`rdata_char_string_data_unittest.cc
+
+run_unittests-rdata_char_string_data_unittest.obj: rdata_char_string_data_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_char_string_data_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Tpo -c -o run_unittests-rdata_char_string_data_unittest.obj `if test -f 'rdata_char_string_data_unittest.cc'; then $(CYGPATH_W) 'rdata_char_string_data_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_char_string_data_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Tpo $(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_char_string_data_unittest.cc' object='run_unittests-rdata_char_string_data_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_char_string_data_unittest.obj `if test -f 'rdata_char_string_data_unittest.cc'; then $(CYGPATH_W) 'rdata_char_string_data_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_char_string_data_unittest.cc'; fi`
+
+run_unittests-rdata_in_a_unittest.o: rdata_in_a_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_in_a_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_in_a_unittest.Tpo -c -o run_unittests-rdata_in_a_unittest.o `test -f 'rdata_in_a_unittest.cc' || echo '$(srcdir)/'`rdata_in_a_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_in_a_unittest.Tpo $(DEPDIR)/run_unittests-rdata_in_a_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_in_a_unittest.cc' object='run_unittests-rdata_in_a_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_in_a_unittest.o `test -f 'rdata_in_a_unittest.cc' || echo '$(srcdir)/'`rdata_in_a_unittest.cc
+
+run_unittests-rdata_in_a_unittest.obj: rdata_in_a_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_in_a_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_in_a_unittest.Tpo -c -o run_unittests-rdata_in_a_unittest.obj `if test -f 'rdata_in_a_unittest.cc'; then $(CYGPATH_W) 'rdata_in_a_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_in_a_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_in_a_unittest.Tpo $(DEPDIR)/run_unittests-rdata_in_a_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_in_a_unittest.cc' object='run_unittests-rdata_in_a_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_in_a_unittest.obj `if test -f 'rdata_in_a_unittest.cc'; then $(CYGPATH_W) 'rdata_in_a_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_in_a_unittest.cc'; fi`
+
+run_unittests-rdata_in_aaaa_unittest.o: rdata_in_aaaa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_in_aaaa_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Tpo -c -o run_unittests-rdata_in_aaaa_unittest.o `test -f 'rdata_in_aaaa_unittest.cc' || echo '$(srcdir)/'`rdata_in_aaaa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_in_aaaa_unittest.cc' object='run_unittests-rdata_in_aaaa_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_in_aaaa_unittest.o `test -f 'rdata_in_aaaa_unittest.cc' || echo '$(srcdir)/'`rdata_in_aaaa_unittest.cc
+
+run_unittests-rdata_in_aaaa_unittest.obj: rdata_in_aaaa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_in_aaaa_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Tpo -c -o run_unittests-rdata_in_aaaa_unittest.obj `if test -f 'rdata_in_aaaa_unittest.cc'; then $(CYGPATH_W) 'rdata_in_aaaa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_in_aaaa_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_in_aaaa_unittest.cc' object='run_unittests-rdata_in_aaaa_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_in_aaaa_unittest.obj `if test -f 'rdata_in_aaaa_unittest.cc'; then $(CYGPATH_W) 'rdata_in_aaaa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_in_aaaa_unittest.cc'; fi`
+
+run_unittests-rdata_ns_unittest.o: rdata_ns_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_ns_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_ns_unittest.Tpo -c -o run_unittests-rdata_ns_unittest.o `test -f 'rdata_ns_unittest.cc' || echo '$(srcdir)/'`rdata_ns_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_ns_unittest.Tpo $(DEPDIR)/run_unittests-rdata_ns_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_ns_unittest.cc' object='run_unittests-rdata_ns_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_ns_unittest.o `test -f 'rdata_ns_unittest.cc' || echo '$(srcdir)/'`rdata_ns_unittest.cc
+
+run_unittests-rdata_ns_unittest.obj: rdata_ns_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_ns_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_ns_unittest.Tpo -c -o run_unittests-rdata_ns_unittest.obj `if test -f 'rdata_ns_unittest.cc'; then $(CYGPATH_W) 'rdata_ns_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_ns_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_ns_unittest.Tpo $(DEPDIR)/run_unittests-rdata_ns_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_ns_unittest.cc' object='run_unittests-rdata_ns_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_ns_unittest.obj `if test -f 'rdata_ns_unittest.cc'; then $(CYGPATH_W) 'rdata_ns_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_ns_unittest.cc'; fi`
+
+run_unittests-rdata_soa_unittest.o: rdata_soa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_soa_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_soa_unittest.Tpo -c -o run_unittests-rdata_soa_unittest.o `test -f 'rdata_soa_unittest.cc' || echo '$(srcdir)/'`rdata_soa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_soa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_soa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_soa_unittest.cc' object='run_unittests-rdata_soa_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_soa_unittest.o `test -f 'rdata_soa_unittest.cc' || echo '$(srcdir)/'`rdata_soa_unittest.cc
+
+run_unittests-rdata_soa_unittest.obj: rdata_soa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_soa_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_soa_unittest.Tpo -c -o run_unittests-rdata_soa_unittest.obj `if test -f 'rdata_soa_unittest.cc'; then $(CYGPATH_W) 'rdata_soa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_soa_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_soa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_soa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_soa_unittest.cc' object='run_unittests-rdata_soa_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_soa_unittest.obj `if test -f 'rdata_soa_unittest.cc'; then $(CYGPATH_W) 'rdata_soa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_soa_unittest.cc'; fi`
+
+run_unittests-rdata_txt_like_unittest.o: rdata_txt_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_txt_like_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_txt_like_unittest.Tpo -c -o run_unittests-rdata_txt_like_unittest.o `test -f 'rdata_txt_like_unittest.cc' || echo '$(srcdir)/'`rdata_txt_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_txt_like_unittest.Tpo $(DEPDIR)/run_unittests-rdata_txt_like_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_txt_like_unittest.cc' object='run_unittests-rdata_txt_like_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_txt_like_unittest.o `test -f 'rdata_txt_like_unittest.cc' || echo '$(srcdir)/'`rdata_txt_like_unittest.cc
+
+run_unittests-rdata_txt_like_unittest.obj: rdata_txt_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_txt_like_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_txt_like_unittest.Tpo -c -o run_unittests-rdata_txt_like_unittest.obj `if test -f 'rdata_txt_like_unittest.cc'; then $(CYGPATH_W) 'rdata_txt_like_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_txt_like_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_txt_like_unittest.Tpo $(DEPDIR)/run_unittests-rdata_txt_like_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_txt_like_unittest.cc' object='run_unittests-rdata_txt_like_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_txt_like_unittest.obj `if test -f 'rdata_txt_like_unittest.cc'; then $(CYGPATH_W) 'rdata_txt_like_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_txt_like_unittest.cc'; fi`
+
+run_unittests-rdata_mx_unittest.o: rdata_mx_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_mx_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_mx_unittest.Tpo -c -o run_unittests-rdata_mx_unittest.o `test -f 'rdata_mx_unittest.cc' || echo '$(srcdir)/'`rdata_mx_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_mx_unittest.Tpo $(DEPDIR)/run_unittests-rdata_mx_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_mx_unittest.cc' object='run_unittests-rdata_mx_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_mx_unittest.o `test -f 'rdata_mx_unittest.cc' || echo '$(srcdir)/'`rdata_mx_unittest.cc
+
+run_unittests-rdata_mx_unittest.obj: rdata_mx_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_mx_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_mx_unittest.Tpo -c -o run_unittests-rdata_mx_unittest.obj `if test -f 'rdata_mx_unittest.cc'; then $(CYGPATH_W) 'rdata_mx_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_mx_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_mx_unittest.Tpo $(DEPDIR)/run_unittests-rdata_mx_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_mx_unittest.cc' object='run_unittests-rdata_mx_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_mx_unittest.obj `if test -f 'rdata_mx_unittest.cc'; then $(CYGPATH_W) 'rdata_mx_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_mx_unittest.cc'; fi`
+
+run_unittests-rdata_sshfp_unittest.o: rdata_sshfp_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_sshfp_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_sshfp_unittest.Tpo -c -o run_unittests-rdata_sshfp_unittest.o `test -f 'rdata_sshfp_unittest.cc' || echo '$(srcdir)/'`rdata_sshfp_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_sshfp_unittest.Tpo $(DEPDIR)/run_unittests-rdata_sshfp_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_sshfp_unittest.cc' object='run_unittests-rdata_sshfp_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_sshfp_unittest.o `test -f 'rdata_sshfp_unittest.cc' || echo '$(srcdir)/'`rdata_sshfp_unittest.cc
+
+run_unittests-rdata_sshfp_unittest.obj: rdata_sshfp_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_sshfp_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_sshfp_unittest.Tpo -c -o run_unittests-rdata_sshfp_unittest.obj `if test -f 'rdata_sshfp_unittest.cc'; then $(CYGPATH_W) 'rdata_sshfp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_sshfp_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_sshfp_unittest.Tpo $(DEPDIR)/run_unittests-rdata_sshfp_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_sshfp_unittest.cc' object='run_unittests-rdata_sshfp_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_sshfp_unittest.obj `if test -f 'rdata_sshfp_unittest.cc'; then $(CYGPATH_W) 'rdata_sshfp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_sshfp_unittest.cc'; fi`
+
+run_unittests-rdata_ptr_unittest.o: rdata_ptr_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_ptr_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_ptr_unittest.Tpo -c -o run_unittests-rdata_ptr_unittest.o `test -f 'rdata_ptr_unittest.cc' || echo '$(srcdir)/'`rdata_ptr_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_ptr_unittest.Tpo $(DEPDIR)/run_unittests-rdata_ptr_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_ptr_unittest.cc' object='run_unittests-rdata_ptr_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_ptr_unittest.o `test -f 'rdata_ptr_unittest.cc' || echo '$(srcdir)/'`rdata_ptr_unittest.cc
+
+run_unittests-rdata_ptr_unittest.obj: rdata_ptr_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_ptr_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_ptr_unittest.Tpo -c -o run_unittests-rdata_ptr_unittest.obj `if test -f 'rdata_ptr_unittest.cc'; then $(CYGPATH_W) 'rdata_ptr_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_ptr_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_ptr_unittest.Tpo $(DEPDIR)/run_unittests-rdata_ptr_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_ptr_unittest.cc' object='run_unittests-rdata_ptr_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_ptr_unittest.obj `if test -f 'rdata_ptr_unittest.cc'; then $(CYGPATH_W) 'rdata_ptr_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_ptr_unittest.cc'; fi`
+
+run_unittests-rdata_cname_unittest.o: rdata_cname_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_cname_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_cname_unittest.Tpo -c -o run_unittests-rdata_cname_unittest.o `test -f 'rdata_cname_unittest.cc' || echo '$(srcdir)/'`rdata_cname_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_cname_unittest.Tpo $(DEPDIR)/run_unittests-rdata_cname_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_cname_unittest.cc' object='run_unittests-rdata_cname_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_cname_unittest.o `test -f 'rdata_cname_unittest.cc' || echo '$(srcdir)/'`rdata_cname_unittest.cc
+
+run_unittests-rdata_cname_unittest.obj: rdata_cname_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_cname_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_cname_unittest.Tpo -c -o run_unittests-rdata_cname_unittest.obj `if test -f 'rdata_cname_unittest.cc'; then $(CYGPATH_W) 'rdata_cname_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_cname_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_cname_unittest.Tpo $(DEPDIR)/run_unittests-rdata_cname_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_cname_unittest.cc' object='run_unittests-rdata_cname_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_cname_unittest.obj `if test -f 'rdata_cname_unittest.cc'; then $(CYGPATH_W) 'rdata_cname_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_cname_unittest.cc'; fi`
+
+run_unittests-rdata_dname_unittest.o: rdata_dname_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_dname_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_dname_unittest.Tpo -c -o run_unittests-rdata_dname_unittest.o `test -f 'rdata_dname_unittest.cc' || echo '$(srcdir)/'`rdata_dname_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_dname_unittest.Tpo $(DEPDIR)/run_unittests-rdata_dname_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_dname_unittest.cc' object='run_unittests-rdata_dname_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_dname_unittest.o `test -f 'rdata_dname_unittest.cc' || echo '$(srcdir)/'`rdata_dname_unittest.cc
+
+run_unittests-rdata_dname_unittest.obj: rdata_dname_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_dname_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_dname_unittest.Tpo -c -o run_unittests-rdata_dname_unittest.obj `if test -f 'rdata_dname_unittest.cc'; then $(CYGPATH_W) 'rdata_dname_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_dname_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_dname_unittest.Tpo $(DEPDIR)/run_unittests-rdata_dname_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_dname_unittest.cc' object='run_unittests-rdata_dname_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_dname_unittest.obj `if test -f 'rdata_dname_unittest.cc'; then $(CYGPATH_W) 'rdata_dname_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_dname_unittest.cc'; fi`
+
+run_unittests-rdata_afsdb_unittest.o: rdata_afsdb_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_afsdb_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_afsdb_unittest.Tpo -c -o run_unittests-rdata_afsdb_unittest.o `test -f 'rdata_afsdb_unittest.cc' || echo '$(srcdir)/'`rdata_afsdb_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_afsdb_unittest.Tpo $(DEPDIR)/run_unittests-rdata_afsdb_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_afsdb_unittest.cc' object='run_unittests-rdata_afsdb_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_afsdb_unittest.o `test -f 'rdata_afsdb_unittest.cc' || echo '$(srcdir)/'`rdata_afsdb_unittest.cc
+
+run_unittests-rdata_afsdb_unittest.obj: rdata_afsdb_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_afsdb_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_afsdb_unittest.Tpo -c -o run_unittests-rdata_afsdb_unittest.obj `if test -f 'rdata_afsdb_unittest.cc'; then $(CYGPATH_W) 'rdata_afsdb_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_afsdb_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_afsdb_unittest.Tpo $(DEPDIR)/run_unittests-rdata_afsdb_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_afsdb_unittest.cc' object='run_unittests-rdata_afsdb_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_afsdb_unittest.obj `if test -f 'rdata_afsdb_unittest.cc'; then $(CYGPATH_W) 'rdata_afsdb_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_afsdb_unittest.cc'; fi`
+
+run_unittests-rdata_opt_unittest.o: rdata_opt_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_opt_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_opt_unittest.Tpo -c -o run_unittests-rdata_opt_unittest.o `test -f 'rdata_opt_unittest.cc' || echo '$(srcdir)/'`rdata_opt_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_opt_unittest.Tpo $(DEPDIR)/run_unittests-rdata_opt_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_opt_unittest.cc' object='run_unittests-rdata_opt_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_opt_unittest.o `test -f 'rdata_opt_unittest.cc' || echo '$(srcdir)/'`rdata_opt_unittest.cc
+
+run_unittests-rdata_opt_unittest.obj: rdata_opt_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_opt_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_opt_unittest.Tpo -c -o run_unittests-rdata_opt_unittest.obj `if test -f 'rdata_opt_unittest.cc'; then $(CYGPATH_W) 'rdata_opt_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_opt_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_opt_unittest.Tpo $(DEPDIR)/run_unittests-rdata_opt_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_opt_unittest.cc' object='run_unittests-rdata_opt_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_opt_unittest.obj `if test -f 'rdata_opt_unittest.cc'; then $(CYGPATH_W) 'rdata_opt_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_opt_unittest.cc'; fi`
+
+run_unittests-rdata_dhcid_unittest.o: rdata_dhcid_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_dhcid_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_dhcid_unittest.Tpo -c -o run_unittests-rdata_dhcid_unittest.o `test -f 'rdata_dhcid_unittest.cc' || echo '$(srcdir)/'`rdata_dhcid_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_dhcid_unittest.Tpo $(DEPDIR)/run_unittests-rdata_dhcid_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_dhcid_unittest.cc' object='run_unittests-rdata_dhcid_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_dhcid_unittest.o `test -f 'rdata_dhcid_unittest.cc' || echo '$(srcdir)/'`rdata_dhcid_unittest.cc
+
+run_unittests-rdata_dhcid_unittest.obj: rdata_dhcid_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_dhcid_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_dhcid_unittest.Tpo -c -o run_unittests-rdata_dhcid_unittest.obj `if test -f 'rdata_dhcid_unittest.cc'; then $(CYGPATH_W) 'rdata_dhcid_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_dhcid_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_dhcid_unittest.Tpo $(DEPDIR)/run_unittests-rdata_dhcid_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_dhcid_unittest.cc' object='run_unittests-rdata_dhcid_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_dhcid_unittest.obj `if test -f 'rdata_dhcid_unittest.cc'; then $(CYGPATH_W) 'rdata_dhcid_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_dhcid_unittest.cc'; fi`
+
+run_unittests-rdata_dnskey_unittest.o: rdata_dnskey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_dnskey_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_dnskey_unittest.Tpo -c -o run_unittests-rdata_dnskey_unittest.o `test -f 'rdata_dnskey_unittest.cc' || echo '$(srcdir)/'`rdata_dnskey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_dnskey_unittest.Tpo $(DEPDIR)/run_unittests-rdata_dnskey_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_dnskey_unittest.cc' object='run_unittests-rdata_dnskey_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_dnskey_unittest.o `test -f 'rdata_dnskey_unittest.cc' || echo '$(srcdir)/'`rdata_dnskey_unittest.cc
+
+run_unittests-rdata_dnskey_unittest.obj: rdata_dnskey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_dnskey_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_dnskey_unittest.Tpo -c -o run_unittests-rdata_dnskey_unittest.obj `if test -f 'rdata_dnskey_unittest.cc'; then $(CYGPATH_W) 'rdata_dnskey_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_dnskey_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_dnskey_unittest.Tpo $(DEPDIR)/run_unittests-rdata_dnskey_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_dnskey_unittest.cc' object='run_unittests-rdata_dnskey_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_dnskey_unittest.obj `if test -f 'rdata_dnskey_unittest.cc'; then $(CYGPATH_W) 'rdata_dnskey_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_dnskey_unittest.cc'; fi`
+
+run_unittests-rdata_ds_like_unittest.o: rdata_ds_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_ds_like_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_ds_like_unittest.Tpo -c -o run_unittests-rdata_ds_like_unittest.o `test -f 'rdata_ds_like_unittest.cc' || echo '$(srcdir)/'`rdata_ds_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_ds_like_unittest.Tpo $(DEPDIR)/run_unittests-rdata_ds_like_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_ds_like_unittest.cc' object='run_unittests-rdata_ds_like_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_ds_like_unittest.o `test -f 'rdata_ds_like_unittest.cc' || echo '$(srcdir)/'`rdata_ds_like_unittest.cc
+
+run_unittests-rdata_ds_like_unittest.obj: rdata_ds_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_ds_like_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_ds_like_unittest.Tpo -c -o run_unittests-rdata_ds_like_unittest.obj `if test -f 'rdata_ds_like_unittest.cc'; then $(CYGPATH_W) 'rdata_ds_like_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_ds_like_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_ds_like_unittest.Tpo $(DEPDIR)/run_unittests-rdata_ds_like_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_ds_like_unittest.cc' object='run_unittests-rdata_ds_like_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_ds_like_unittest.obj `if test -f 'rdata_ds_like_unittest.cc'; then $(CYGPATH_W) 'rdata_ds_like_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_ds_like_unittest.cc'; fi`
+
+run_unittests-rdata_nsec_unittest.o: rdata_nsec_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec_unittest.Tpo -c -o run_unittests-rdata_nsec_unittest.o `test -f 'rdata_nsec_unittest.cc' || echo '$(srcdir)/'`rdata_nsec_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec_unittest.cc' object='run_unittests-rdata_nsec_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec_unittest.o `test -f 'rdata_nsec_unittest.cc' || echo '$(srcdir)/'`rdata_nsec_unittest.cc
+
+run_unittests-rdata_nsec_unittest.obj: rdata_nsec_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec_unittest.Tpo -c -o run_unittests-rdata_nsec_unittest.obj `if test -f 'rdata_nsec_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec_unittest.cc' object='run_unittests-rdata_nsec_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec_unittest.obj `if test -f 'rdata_nsec_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec_unittest.cc'; fi`
+
+run_unittests-rdata_nsec3_unittest.o: rdata_nsec3_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec3_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec3_unittest.Tpo -c -o run_unittests-rdata_nsec3_unittest.o `test -f 'rdata_nsec3_unittest.cc' || echo '$(srcdir)/'`rdata_nsec3_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec3_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec3_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec3_unittest.cc' object='run_unittests-rdata_nsec3_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec3_unittest.o `test -f 'rdata_nsec3_unittest.cc' || echo '$(srcdir)/'`rdata_nsec3_unittest.cc
+
+run_unittests-rdata_nsec3_unittest.obj: rdata_nsec3_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec3_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec3_unittest.Tpo -c -o run_unittests-rdata_nsec3_unittest.obj `if test -f 'rdata_nsec3_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec3_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec3_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec3_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec3_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec3_unittest.cc' object='run_unittests-rdata_nsec3_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec3_unittest.obj `if test -f 'rdata_nsec3_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec3_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec3_unittest.cc'; fi`
+
+run_unittests-rdata_nsecbitmap_unittest.o: rdata_nsecbitmap_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsecbitmap_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Tpo -c -o run_unittests-rdata_nsecbitmap_unittest.o `test -f 'rdata_nsecbitmap_unittest.cc' || echo '$(srcdir)/'`rdata_nsecbitmap_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsecbitmap_unittest.cc' object='run_unittests-rdata_nsecbitmap_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsecbitmap_unittest.o `test -f 'rdata_nsecbitmap_unittest.cc' || echo '$(srcdir)/'`rdata_nsecbitmap_unittest.cc
+
+run_unittests-rdata_nsecbitmap_unittest.obj: rdata_nsecbitmap_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsecbitmap_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Tpo -c -o run_unittests-rdata_nsecbitmap_unittest.obj `if test -f 'rdata_nsecbitmap_unittest.cc'; then $(CYGPATH_W) 'rdata_nsecbitmap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsecbitmap_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsecbitmap_unittest.cc' object='run_unittests-rdata_nsecbitmap_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsecbitmap_unittest.obj `if test -f 'rdata_nsecbitmap_unittest.cc'; then $(CYGPATH_W) 'rdata_nsecbitmap_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsecbitmap_unittest.cc'; fi`
+
+run_unittests-rdata_nsec3param_unittest.o: rdata_nsec3param_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec3param_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Tpo -c -o run_unittests-rdata_nsec3param_unittest.o `test -f 'rdata_nsec3param_unittest.cc' || echo '$(srcdir)/'`rdata_nsec3param_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec3param_unittest.cc' object='run_unittests-rdata_nsec3param_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec3param_unittest.o `test -f 'rdata_nsec3param_unittest.cc' || echo '$(srcdir)/'`rdata_nsec3param_unittest.cc
+
+run_unittests-rdata_nsec3param_unittest.obj: rdata_nsec3param_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec3param_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Tpo -c -o run_unittests-rdata_nsec3param_unittest.obj `if test -f 'rdata_nsec3param_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec3param_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec3param_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec3param_unittest.cc' object='run_unittests-rdata_nsec3param_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec3param_unittest.obj `if test -f 'rdata_nsec3param_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec3param_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec3param_unittest.cc'; fi`
+
+run_unittests-rdata_nsec3param_like_unittest.o: rdata_nsec3param_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec3param_like_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Tpo -c -o run_unittests-rdata_nsec3param_like_unittest.o `test -f 'rdata_nsec3param_like_unittest.cc' || echo '$(srcdir)/'`rdata_nsec3param_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec3param_like_unittest.cc' object='run_unittests-rdata_nsec3param_like_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec3param_like_unittest.o `test -f 'rdata_nsec3param_like_unittest.cc' || echo '$(srcdir)/'`rdata_nsec3param_like_unittest.cc
+
+run_unittests-rdata_nsec3param_like_unittest.obj: rdata_nsec3param_like_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_nsec3param_like_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Tpo -c -o run_unittests-rdata_nsec3param_like_unittest.obj `if test -f 'rdata_nsec3param_like_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec3param_like_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec3param_like_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Tpo $(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_nsec3param_like_unittest.cc' object='run_unittests-rdata_nsec3param_like_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_nsec3param_like_unittest.obj `if test -f 'rdata_nsec3param_like_unittest.cc'; then $(CYGPATH_W) 'rdata_nsec3param_like_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_nsec3param_like_unittest.cc'; fi`
+
+run_unittests-rdata_rrsig_unittest.o: rdata_rrsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_rrsig_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_rrsig_unittest.Tpo -c -o run_unittests-rdata_rrsig_unittest.o `test -f 'rdata_rrsig_unittest.cc' || echo '$(srcdir)/'`rdata_rrsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_rrsig_unittest.Tpo $(DEPDIR)/run_unittests-rdata_rrsig_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_rrsig_unittest.cc' object='run_unittests-rdata_rrsig_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_rrsig_unittest.o `test -f 'rdata_rrsig_unittest.cc' || echo '$(srcdir)/'`rdata_rrsig_unittest.cc
+
+run_unittests-rdata_rrsig_unittest.obj: rdata_rrsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_rrsig_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_rrsig_unittest.Tpo -c -o run_unittests-rdata_rrsig_unittest.obj `if test -f 'rdata_rrsig_unittest.cc'; then $(CYGPATH_W) 'rdata_rrsig_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_rrsig_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_rrsig_unittest.Tpo $(DEPDIR)/run_unittests-rdata_rrsig_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_rrsig_unittest.cc' object='run_unittests-rdata_rrsig_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_rrsig_unittest.obj `if test -f 'rdata_rrsig_unittest.cc'; then $(CYGPATH_W) 'rdata_rrsig_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_rrsig_unittest.cc'; fi`
+
+run_unittests-rdata_rp_unittest.o: rdata_rp_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_rp_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_rp_unittest.Tpo -c -o run_unittests-rdata_rp_unittest.o `test -f 'rdata_rp_unittest.cc' || echo '$(srcdir)/'`rdata_rp_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_rp_unittest.Tpo $(DEPDIR)/run_unittests-rdata_rp_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_rp_unittest.cc' object='run_unittests-rdata_rp_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_rp_unittest.o `test -f 'rdata_rp_unittest.cc' || echo '$(srcdir)/'`rdata_rp_unittest.cc
+
+run_unittests-rdata_rp_unittest.obj: rdata_rp_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_rp_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_rp_unittest.Tpo -c -o run_unittests-rdata_rp_unittest.obj `if test -f 'rdata_rp_unittest.cc'; then $(CYGPATH_W) 'rdata_rp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_rp_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_rp_unittest.Tpo $(DEPDIR)/run_unittests-rdata_rp_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_rp_unittest.cc' object='run_unittests-rdata_rp_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_rp_unittest.obj `if test -f 'rdata_rp_unittest.cc'; then $(CYGPATH_W) 'rdata_rp_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_rp_unittest.cc'; fi`
+
+run_unittests-rdata_srv_unittest.o: rdata_srv_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_srv_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_srv_unittest.Tpo -c -o run_unittests-rdata_srv_unittest.o `test -f 'rdata_srv_unittest.cc' || echo '$(srcdir)/'`rdata_srv_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_srv_unittest.Tpo $(DEPDIR)/run_unittests-rdata_srv_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_srv_unittest.cc' object='run_unittests-rdata_srv_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_srv_unittest.o `test -f 'rdata_srv_unittest.cc' || echo '$(srcdir)/'`rdata_srv_unittest.cc
+
+run_unittests-rdata_srv_unittest.obj: rdata_srv_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_srv_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_srv_unittest.Tpo -c -o run_unittests-rdata_srv_unittest.obj `if test -f 'rdata_srv_unittest.cc'; then $(CYGPATH_W) 'rdata_srv_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_srv_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_srv_unittest.Tpo $(DEPDIR)/run_unittests-rdata_srv_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_srv_unittest.cc' object='run_unittests-rdata_srv_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_srv_unittest.obj `if test -f 'rdata_srv_unittest.cc'; then $(CYGPATH_W) 'rdata_srv_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_srv_unittest.cc'; fi`
+
+run_unittests-rdata_tlsa_unittest.o: rdata_tlsa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_tlsa_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_tlsa_unittest.Tpo -c -o run_unittests-rdata_tlsa_unittest.o `test -f 'rdata_tlsa_unittest.cc' || echo '$(srcdir)/'`rdata_tlsa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_tlsa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_tlsa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_tlsa_unittest.cc' object='run_unittests-rdata_tlsa_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_tlsa_unittest.o `test -f 'rdata_tlsa_unittest.cc' || echo '$(srcdir)/'`rdata_tlsa_unittest.cc
+
+run_unittests-rdata_tlsa_unittest.obj: rdata_tlsa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_tlsa_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_tlsa_unittest.Tpo -c -o run_unittests-rdata_tlsa_unittest.obj `if test -f 'rdata_tlsa_unittest.cc'; then $(CYGPATH_W) 'rdata_tlsa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_tlsa_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_tlsa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_tlsa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_tlsa_unittest.cc' object='run_unittests-rdata_tlsa_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_tlsa_unittest.obj `if test -f 'rdata_tlsa_unittest.cc'; then $(CYGPATH_W) 'rdata_tlsa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_tlsa_unittest.cc'; fi`
+
+run_unittests-rdata_minfo_unittest.o: rdata_minfo_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_minfo_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_minfo_unittest.Tpo -c -o run_unittests-rdata_minfo_unittest.o `test -f 'rdata_minfo_unittest.cc' || echo '$(srcdir)/'`rdata_minfo_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_minfo_unittest.Tpo $(DEPDIR)/run_unittests-rdata_minfo_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_minfo_unittest.cc' object='run_unittests-rdata_minfo_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_minfo_unittest.o `test -f 'rdata_minfo_unittest.cc' || echo '$(srcdir)/'`rdata_minfo_unittest.cc
+
+run_unittests-rdata_minfo_unittest.obj: rdata_minfo_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_minfo_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_minfo_unittest.Tpo -c -o run_unittests-rdata_minfo_unittest.obj `if test -f 'rdata_minfo_unittest.cc'; then $(CYGPATH_W) 'rdata_minfo_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_minfo_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_minfo_unittest.Tpo $(DEPDIR)/run_unittests-rdata_minfo_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_minfo_unittest.cc' object='run_unittests-rdata_minfo_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_minfo_unittest.obj `if test -f 'rdata_minfo_unittest.cc'; then $(CYGPATH_W) 'rdata_minfo_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_minfo_unittest.cc'; fi`
+
+run_unittests-rdata_tsig_unittest.o: rdata_tsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_tsig_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_tsig_unittest.Tpo -c -o run_unittests-rdata_tsig_unittest.o `test -f 'rdata_tsig_unittest.cc' || echo '$(srcdir)/'`rdata_tsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_tsig_unittest.Tpo $(DEPDIR)/run_unittests-rdata_tsig_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_tsig_unittest.cc' object='run_unittests-rdata_tsig_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_tsig_unittest.o `test -f 'rdata_tsig_unittest.cc' || echo '$(srcdir)/'`rdata_tsig_unittest.cc
+
+run_unittests-rdata_tsig_unittest.obj: rdata_tsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_tsig_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_tsig_unittest.Tpo -c -o run_unittests-rdata_tsig_unittest.obj `if test -f 'rdata_tsig_unittest.cc'; then $(CYGPATH_W) 'rdata_tsig_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_tsig_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_tsig_unittest.Tpo $(DEPDIR)/run_unittests-rdata_tsig_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_tsig_unittest.cc' object='run_unittests-rdata_tsig_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_tsig_unittest.obj `if test -f 'rdata_tsig_unittest.cc'; then $(CYGPATH_W) 'rdata_tsig_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_tsig_unittest.cc'; fi`
+
+run_unittests-rdata_naptr_unittest.o: rdata_naptr_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_naptr_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_naptr_unittest.Tpo -c -o run_unittests-rdata_naptr_unittest.o `test -f 'rdata_naptr_unittest.cc' || echo '$(srcdir)/'`rdata_naptr_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_naptr_unittest.Tpo $(DEPDIR)/run_unittests-rdata_naptr_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_naptr_unittest.cc' object='run_unittests-rdata_naptr_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_naptr_unittest.o `test -f 'rdata_naptr_unittest.cc' || echo '$(srcdir)/'`rdata_naptr_unittest.cc
+
+run_unittests-rdata_naptr_unittest.obj: rdata_naptr_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_naptr_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_naptr_unittest.Tpo -c -o run_unittests-rdata_naptr_unittest.obj `if test -f 'rdata_naptr_unittest.cc'; then $(CYGPATH_W) 'rdata_naptr_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_naptr_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_naptr_unittest.Tpo $(DEPDIR)/run_unittests-rdata_naptr_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_naptr_unittest.cc' object='run_unittests-rdata_naptr_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_naptr_unittest.obj `if test -f 'rdata_naptr_unittest.cc'; then $(CYGPATH_W) 'rdata_naptr_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_naptr_unittest.cc'; fi`
+
+run_unittests-rdata_hinfo_unittest.o: rdata_hinfo_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_hinfo_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_hinfo_unittest.Tpo -c -o run_unittests-rdata_hinfo_unittest.o `test -f 'rdata_hinfo_unittest.cc' || echo '$(srcdir)/'`rdata_hinfo_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_hinfo_unittest.Tpo $(DEPDIR)/run_unittests-rdata_hinfo_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_hinfo_unittest.cc' object='run_unittests-rdata_hinfo_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_hinfo_unittest.o `test -f 'rdata_hinfo_unittest.cc' || echo '$(srcdir)/'`rdata_hinfo_unittest.cc
+
+run_unittests-rdata_hinfo_unittest.obj: rdata_hinfo_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_hinfo_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_hinfo_unittest.Tpo -c -o run_unittests-rdata_hinfo_unittest.obj `if test -f 'rdata_hinfo_unittest.cc'; then $(CYGPATH_W) 'rdata_hinfo_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_hinfo_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_hinfo_unittest.Tpo $(DEPDIR)/run_unittests-rdata_hinfo_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_hinfo_unittest.cc' object='run_unittests-rdata_hinfo_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_hinfo_unittest.obj `if test -f 'rdata_hinfo_unittest.cc'; then $(CYGPATH_W) 'rdata_hinfo_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_hinfo_unittest.cc'; fi`
+
+run_unittests-rdata_caa_unittest.o: rdata_caa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_caa_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_caa_unittest.Tpo -c -o run_unittests-rdata_caa_unittest.o `test -f 'rdata_caa_unittest.cc' || echo '$(srcdir)/'`rdata_caa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_caa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_caa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_caa_unittest.cc' object='run_unittests-rdata_caa_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_caa_unittest.o `test -f 'rdata_caa_unittest.cc' || echo '$(srcdir)/'`rdata_caa_unittest.cc
+
+run_unittests-rdata_caa_unittest.obj: rdata_caa_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_caa_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_caa_unittest.Tpo -c -o run_unittests-rdata_caa_unittest.obj `if test -f 'rdata_caa_unittest.cc'; then $(CYGPATH_W) 'rdata_caa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_caa_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_caa_unittest.Tpo $(DEPDIR)/run_unittests-rdata_caa_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_caa_unittest.cc' object='run_unittests-rdata_caa_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_caa_unittest.obj `if test -f 'rdata_caa_unittest.cc'; then $(CYGPATH_W) 'rdata_caa_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_caa_unittest.cc'; fi`
+
+run_unittests-rdata_tkey_unittest.o: rdata_tkey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_tkey_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rdata_tkey_unittest.Tpo -c -o run_unittests-rdata_tkey_unittest.o `test -f 'rdata_tkey_unittest.cc' || echo '$(srcdir)/'`rdata_tkey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_tkey_unittest.Tpo $(DEPDIR)/run_unittests-rdata_tkey_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_tkey_unittest.cc' object='run_unittests-rdata_tkey_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_tkey_unittest.o `test -f 'rdata_tkey_unittest.cc' || echo '$(srcdir)/'`rdata_tkey_unittest.cc
+
+run_unittests-rdata_tkey_unittest.obj: rdata_tkey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rdata_tkey_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rdata_tkey_unittest.Tpo -c -o run_unittests-rdata_tkey_unittest.obj `if test -f 'rdata_tkey_unittest.cc'; then $(CYGPATH_W) 'rdata_tkey_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_tkey_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rdata_tkey_unittest.Tpo $(DEPDIR)/run_unittests-rdata_tkey_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rdata_tkey_unittest.cc' object='run_unittests-rdata_tkey_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rdata_tkey_unittest.obj `if test -f 'rdata_tkey_unittest.cc'; then $(CYGPATH_W) 'rdata_tkey_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rdata_tkey_unittest.cc'; fi`
+
+run_unittests-rrset_unittest.o: rrset_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrset_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rrset_unittest.Tpo -c -o run_unittests-rrset_unittest.o `test -f 'rrset_unittest.cc' || echo '$(srcdir)/'`rrset_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrset_unittest.Tpo $(DEPDIR)/run_unittests-rrset_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrset_unittest.cc' object='run_unittests-rrset_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrset_unittest.o `test -f 'rrset_unittest.cc' || echo '$(srcdir)/'`rrset_unittest.cc
+
+run_unittests-rrset_unittest.obj: rrset_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrset_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rrset_unittest.Tpo -c -o run_unittests-rrset_unittest.obj `if test -f 'rrset_unittest.cc'; then $(CYGPATH_W) 'rrset_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrset_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrset_unittest.Tpo $(DEPDIR)/run_unittests-rrset_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrset_unittest.cc' object='run_unittests-rrset_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrset_unittest.obj `if test -f 'rrset_unittest.cc'; then $(CYGPATH_W) 'rrset_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrset_unittest.cc'; fi`
+
+run_unittests-qid_gen_unittest.o: qid_gen_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-qid_gen_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-qid_gen_unittest.Tpo -c -o run_unittests-qid_gen_unittest.o `test -f 'qid_gen_unittest.cc' || echo '$(srcdir)/'`qid_gen_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-qid_gen_unittest.Tpo $(DEPDIR)/run_unittests-qid_gen_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='qid_gen_unittest.cc' object='run_unittests-qid_gen_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-qid_gen_unittest.o `test -f 'qid_gen_unittest.cc' || echo '$(srcdir)/'`qid_gen_unittest.cc
+
+run_unittests-qid_gen_unittest.obj: qid_gen_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-qid_gen_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-qid_gen_unittest.Tpo -c -o run_unittests-qid_gen_unittest.obj `if test -f 'qid_gen_unittest.cc'; then $(CYGPATH_W) 'qid_gen_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/qid_gen_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-qid_gen_unittest.Tpo $(DEPDIR)/run_unittests-qid_gen_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='qid_gen_unittest.cc' object='run_unittests-qid_gen_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-qid_gen_unittest.obj `if test -f 'qid_gen_unittest.cc'; then $(CYGPATH_W) 'qid_gen_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/qid_gen_unittest.cc'; fi`
+
+run_unittests-question_unittest.o: question_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-question_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-question_unittest.Tpo -c -o run_unittests-question_unittest.o `test -f 'question_unittest.cc' || echo '$(srcdir)/'`question_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-question_unittest.Tpo $(DEPDIR)/run_unittests-question_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='question_unittest.cc' object='run_unittests-question_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-question_unittest.o `test -f 'question_unittest.cc' || echo '$(srcdir)/'`question_unittest.cc
+
+run_unittests-question_unittest.obj: question_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-question_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-question_unittest.Tpo -c -o run_unittests-question_unittest.obj `if test -f 'question_unittest.cc'; then $(CYGPATH_W) 'question_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/question_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-question_unittest.Tpo $(DEPDIR)/run_unittests-question_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='question_unittest.cc' object='run_unittests-question_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-question_unittest.obj `if test -f 'question_unittest.cc'; then $(CYGPATH_W) 'question_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/question_unittest.cc'; fi`
+
+run_unittests-rrparamregistry_unittest.o: rrparamregistry_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrparamregistry_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rrparamregistry_unittest.Tpo -c -o run_unittests-rrparamregistry_unittest.o `test -f 'rrparamregistry_unittest.cc' || echo '$(srcdir)/'`rrparamregistry_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrparamregistry_unittest.Tpo $(DEPDIR)/run_unittests-rrparamregistry_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrparamregistry_unittest.cc' object='run_unittests-rrparamregistry_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrparamregistry_unittest.o `test -f 'rrparamregistry_unittest.cc' || echo '$(srcdir)/'`rrparamregistry_unittest.cc
+
+run_unittests-rrparamregistry_unittest.obj: rrparamregistry_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrparamregistry_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rrparamregistry_unittest.Tpo -c -o run_unittests-rrparamregistry_unittest.obj `if test -f 'rrparamregistry_unittest.cc'; then $(CYGPATH_W) 'rrparamregistry_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrparamregistry_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrparamregistry_unittest.Tpo $(DEPDIR)/run_unittests-rrparamregistry_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrparamregistry_unittest.cc' object='run_unittests-rrparamregistry_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrparamregistry_unittest.obj `if test -f 'rrparamregistry_unittest.cc'; then $(CYGPATH_W) 'rrparamregistry_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrparamregistry_unittest.cc'; fi`
+
+run_unittests-masterload_unittest.o: masterload_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-masterload_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-masterload_unittest.Tpo -c -o run_unittests-masterload_unittest.o `test -f 'masterload_unittest.cc' || echo '$(srcdir)/'`masterload_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-masterload_unittest.Tpo $(DEPDIR)/run_unittests-masterload_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='masterload_unittest.cc' object='run_unittests-masterload_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-masterload_unittest.o `test -f 'masterload_unittest.cc' || echo '$(srcdir)/'`masterload_unittest.cc
+
+run_unittests-masterload_unittest.obj: masterload_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-masterload_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-masterload_unittest.Tpo -c -o run_unittests-masterload_unittest.obj `if test -f 'masterload_unittest.cc'; then $(CYGPATH_W) 'masterload_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/masterload_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-masterload_unittest.Tpo $(DEPDIR)/run_unittests-masterload_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='masterload_unittest.cc' object='run_unittests-masterload_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-masterload_unittest.obj `if test -f 'masterload_unittest.cc'; then $(CYGPATH_W) 'masterload_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/masterload_unittest.cc'; fi`
+
+run_unittests-message_unittest.o: message_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-message_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-message_unittest.Tpo -c -o run_unittests-message_unittest.o `test -f 'message_unittest.cc' || echo '$(srcdir)/'`message_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-message_unittest.Tpo $(DEPDIR)/run_unittests-message_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_unittest.cc' object='run_unittests-message_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-message_unittest.o `test -f 'message_unittest.cc' || echo '$(srcdir)/'`message_unittest.cc
+
+run_unittests-message_unittest.obj: message_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-message_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-message_unittest.Tpo -c -o run_unittests-message_unittest.obj `if test -f 'message_unittest.cc'; then $(CYGPATH_W) 'message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-message_unittest.Tpo $(DEPDIR)/run_unittests-message_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='message_unittest.cc' object='run_unittests-message_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-message_unittest.obj `if test -f 'message_unittest.cc'; then $(CYGPATH_W) 'message_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/message_unittest.cc'; fi`
+
+run_unittests-serial_unittest.o: serial_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-serial_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-serial_unittest.Tpo -c -o run_unittests-serial_unittest.o `test -f 'serial_unittest.cc' || echo '$(srcdir)/'`serial_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-serial_unittest.Tpo $(DEPDIR)/run_unittests-serial_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='serial_unittest.cc' object='run_unittests-serial_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-serial_unittest.o `test -f 'serial_unittest.cc' || echo '$(srcdir)/'`serial_unittest.cc
+
+run_unittests-serial_unittest.obj: serial_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-serial_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-serial_unittest.Tpo -c -o run_unittests-serial_unittest.obj `if test -f 'serial_unittest.cc'; then $(CYGPATH_W) 'serial_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/serial_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-serial_unittest.Tpo $(DEPDIR)/run_unittests-serial_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='serial_unittest.cc' object='run_unittests-serial_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-serial_unittest.obj `if test -f 'serial_unittest.cc'; then $(CYGPATH_W) 'serial_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/serial_unittest.cc'; fi`
+
+run_unittests-tsig_unittest.o: tsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsig_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-tsig_unittest.Tpo -c -o run_unittests-tsig_unittest.o `test -f 'tsig_unittest.cc' || echo '$(srcdir)/'`tsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsig_unittest.Tpo $(DEPDIR)/run_unittests-tsig_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsig_unittest.cc' object='run_unittests-tsig_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsig_unittest.o `test -f 'tsig_unittest.cc' || echo '$(srcdir)/'`tsig_unittest.cc
+
+run_unittests-tsig_unittest.obj: tsig_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsig_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-tsig_unittest.Tpo -c -o run_unittests-tsig_unittest.obj `if test -f 'tsig_unittest.cc'; then $(CYGPATH_W) 'tsig_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsig_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsig_unittest.Tpo $(DEPDIR)/run_unittests-tsig_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsig_unittest.cc' object='run_unittests-tsig_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsig_unittest.obj `if test -f 'tsig_unittest.cc'; then $(CYGPATH_W) 'tsig_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsig_unittest.cc'; fi`
+
+run_unittests-tsigerror_unittest.o: tsigerror_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsigerror_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-tsigerror_unittest.Tpo -c -o run_unittests-tsigerror_unittest.o `test -f 'tsigerror_unittest.cc' || echo '$(srcdir)/'`tsigerror_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsigerror_unittest.Tpo $(DEPDIR)/run_unittests-tsigerror_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsigerror_unittest.cc' object='run_unittests-tsigerror_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsigerror_unittest.o `test -f 'tsigerror_unittest.cc' || echo '$(srcdir)/'`tsigerror_unittest.cc
+
+run_unittests-tsigerror_unittest.obj: tsigerror_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsigerror_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-tsigerror_unittest.Tpo -c -o run_unittests-tsigerror_unittest.obj `if test -f 'tsigerror_unittest.cc'; then $(CYGPATH_W) 'tsigerror_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsigerror_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsigerror_unittest.Tpo $(DEPDIR)/run_unittests-tsigerror_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsigerror_unittest.cc' object='run_unittests-tsigerror_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsigerror_unittest.obj `if test -f 'tsigerror_unittest.cc'; then $(CYGPATH_W) 'tsigerror_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsigerror_unittest.cc'; fi`
+
+run_unittests-tsigkey_unittest.o: tsigkey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsigkey_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-tsigkey_unittest.Tpo -c -o run_unittests-tsigkey_unittest.o `test -f 'tsigkey_unittest.cc' || echo '$(srcdir)/'`tsigkey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsigkey_unittest.Tpo $(DEPDIR)/run_unittests-tsigkey_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsigkey_unittest.cc' object='run_unittests-tsigkey_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsigkey_unittest.o `test -f 'tsigkey_unittest.cc' || echo '$(srcdir)/'`tsigkey_unittest.cc
+
+run_unittests-tsigkey_unittest.obj: tsigkey_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsigkey_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-tsigkey_unittest.Tpo -c -o run_unittests-tsigkey_unittest.obj `if test -f 'tsigkey_unittest.cc'; then $(CYGPATH_W) 'tsigkey_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsigkey_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsigkey_unittest.Tpo $(DEPDIR)/run_unittests-tsigkey_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsigkey_unittest.cc' object='run_unittests-tsigkey_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsigkey_unittest.obj `if test -f 'tsigkey_unittest.cc'; then $(CYGPATH_W) 'tsigkey_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsigkey_unittest.cc'; fi`
+
+run_unittests-tsigrecord_unittest.o: tsigrecord_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsigrecord_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-tsigrecord_unittest.Tpo -c -o run_unittests-tsigrecord_unittest.o `test -f 'tsigrecord_unittest.cc' || echo '$(srcdir)/'`tsigrecord_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsigrecord_unittest.Tpo $(DEPDIR)/run_unittests-tsigrecord_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsigrecord_unittest.cc' object='run_unittests-tsigrecord_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsigrecord_unittest.o `test -f 'tsigrecord_unittest.cc' || echo '$(srcdir)/'`tsigrecord_unittest.cc
+
+run_unittests-tsigrecord_unittest.obj: tsigrecord_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-tsigrecord_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-tsigrecord_unittest.Tpo -c -o run_unittests-tsigrecord_unittest.obj `if test -f 'tsigrecord_unittest.cc'; then $(CYGPATH_W) 'tsigrecord_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsigrecord_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-tsigrecord_unittest.Tpo $(DEPDIR)/run_unittests-tsigrecord_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tsigrecord_unittest.cc' object='run_unittests-tsigrecord_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-tsigrecord_unittest.obj `if test -f 'tsigrecord_unittest.cc'; then $(CYGPATH_W) 'tsigrecord_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/tsigrecord_unittest.cc'; fi`
+
+run_unittests-master_loader_callbacks_test.o: master_loader_callbacks_test.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_loader_callbacks_test.o -MD -MP -MF $(DEPDIR)/run_unittests-master_loader_callbacks_test.Tpo -c -o run_unittests-master_loader_callbacks_test.o `test -f 'master_loader_callbacks_test.cc' || echo '$(srcdir)/'`master_loader_callbacks_test.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_loader_callbacks_test.Tpo $(DEPDIR)/run_unittests-master_loader_callbacks_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_loader_callbacks_test.cc' object='run_unittests-master_loader_callbacks_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_loader_callbacks_test.o `test -f 'master_loader_callbacks_test.cc' || echo '$(srcdir)/'`master_loader_callbacks_test.cc
+
+run_unittests-master_loader_callbacks_test.obj: master_loader_callbacks_test.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-master_loader_callbacks_test.obj -MD -MP -MF $(DEPDIR)/run_unittests-master_loader_callbacks_test.Tpo -c -o run_unittests-master_loader_callbacks_test.obj `if test -f 'master_loader_callbacks_test.cc'; then $(CYGPATH_W) 'master_loader_callbacks_test.cc'; else $(CYGPATH_W) '$(srcdir)/master_loader_callbacks_test.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-master_loader_callbacks_test.Tpo $(DEPDIR)/run_unittests-master_loader_callbacks_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='master_loader_callbacks_test.cc' object='run_unittests-master_loader_callbacks_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-master_loader_callbacks_test.obj `if test -f 'master_loader_callbacks_test.cc'; then $(CYGPATH_W) 'master_loader_callbacks_test.cc'; else $(CYGPATH_W) '$(srcdir)/master_loader_callbacks_test.cc'; fi`
+
+run_unittests-rrset_collection_unittest.o: rrset_collection_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrset_collection_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-rrset_collection_unittest.Tpo -c -o run_unittests-rrset_collection_unittest.o `test -f 'rrset_collection_unittest.cc' || echo '$(srcdir)/'`rrset_collection_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrset_collection_unittest.Tpo $(DEPDIR)/run_unittests-rrset_collection_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrset_collection_unittest.cc' object='run_unittests-rrset_collection_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrset_collection_unittest.o `test -f 'rrset_collection_unittest.cc' || echo '$(srcdir)/'`rrset_collection_unittest.cc
+
+run_unittests-rrset_collection_unittest.obj: rrset_collection_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-rrset_collection_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-rrset_collection_unittest.Tpo -c -o run_unittests-rrset_collection_unittest.obj `if test -f 'rrset_collection_unittest.cc'; then $(CYGPATH_W) 'rrset_collection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrset_collection_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-rrset_collection_unittest.Tpo $(DEPDIR)/run_unittests-rrset_collection_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rrset_collection_unittest.cc' object='run_unittests-rrset_collection_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-rrset_collection_unittest.obj `if test -f 'rrset_collection_unittest.cc'; then $(CYGPATH_W) 'rrset_collection_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/rrset_collection_unittest.cc'; fi`
+
+run_unittests-zone_checker_unittest.o: zone_checker_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-zone_checker_unittest.o -MD -MP -MF $(DEPDIR)/run_unittests-zone_checker_unittest.Tpo -c -o run_unittests-zone_checker_unittest.o `test -f 'zone_checker_unittest.cc' || echo '$(srcdir)/'`zone_checker_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-zone_checker_unittest.Tpo $(DEPDIR)/run_unittests-zone_checker_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='zone_checker_unittest.cc' object='run_unittests-zone_checker_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-zone_checker_unittest.o `test -f 'zone_checker_unittest.cc' || echo '$(srcdir)/'`zone_checker_unittest.cc
+
+run_unittests-zone_checker_unittest.obj: zone_checker_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-zone_checker_unittest.obj -MD -MP -MF $(DEPDIR)/run_unittests-zone_checker_unittest.Tpo -c -o run_unittests-zone_checker_unittest.obj `if test -f 'zone_checker_unittest.cc'; then $(CYGPATH_W) 'zone_checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/zone_checker_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-zone_checker_unittest.Tpo $(DEPDIR)/run_unittests-zone_checker_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='zone_checker_unittest.cc' object='run_unittests-zone_checker_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-zone_checker_unittest.obj `if test -f 'zone_checker_unittest.cc'; then $(CYGPATH_W) 'zone_checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/zone_checker_unittest.cc'; fi`
+
+run_unittests-run_unittests.o: run_unittests.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.o -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_unittests-run_unittests.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.o `test -f 'run_unittests.cc' || echo '$(srcdir)/'`run_unittests.cc
+
+run_unittests-run_unittests.obj: run_unittests.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT run_unittests-run_unittests.obj -MD -MP -MF $(DEPDIR)/run_unittests-run_unittests.Tpo -c -o run_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_unittests-run_unittests.Tpo $(DEPDIR)/run_unittests-run_unittests.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='run_unittests.cc' object='run_unittests-run_unittests.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_unittests_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o run_unittests-run_unittests.obj `if test -f 'run_unittests.cc'; then $(CYGPATH_W) 'run_unittests.cc'; else $(CYGPATH_W) '$(srcdir)/run_unittests.cc'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f ./$(DEPDIR)/run_unittests-dns_exceptions_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-edns_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-labelsequence_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_state_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_token_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_loader_callbacks_test.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_loader_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-masterload_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-message_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-messagerenderer_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-name_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-nsec3hash_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-opcode_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-qid_gen_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-question_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rcode_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_afsdb_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_caa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_char_string_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_cname_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_dhcid_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_dname_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_dnskey_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_ds_like_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_hinfo_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_in_a_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_minfo_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_mx_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_naptr_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_ns_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec3_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_opt_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_ptr_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_rp_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_rrsig_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_soa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_srv_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_sshfp_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_tkey_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_tlsa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_tsig_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_txt_like_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdatafields_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrclass_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrcollator_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrparamregistry_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrset_collection_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrset_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrttl_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrtype_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po
+ -rm -f ./$(DEPDIR)/run_unittests-serial_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsig_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsigerror_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsigkey_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsigrecord_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-unittest_util.Po
+ -rm -f ./$(DEPDIR)/run_unittests-zone_checker_unittest.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f ./$(DEPDIR)/run_unittests-dns_exceptions_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-edns_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-labelsequence_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_inputsource_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_state_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_token_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_lexer_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_loader_callbacks_test.Po
+ -rm -f ./$(DEPDIR)/run_unittests-master_loader_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-masterload_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-message_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-messagerenderer_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-name_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-nsec3hash_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-opcode_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-qid_gen_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-question_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rcode_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_afsdb_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_caa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_char_string_data_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_char_string_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_cname_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_dhcid_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_dname_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_dnskey_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_ds_like_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_hinfo_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_in_a_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_in_aaaa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_minfo_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_mx_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_naptr_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_ns_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec3_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec3param_like_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec3param_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsec_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_nsecbitmap_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_opt_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_pimpl_holder_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_ptr_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_rp_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_rrsig_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_soa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_srv_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_sshfp_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_tkey_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_tlsa_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_tsig_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_txt_like_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdata_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rdatafields_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrclass_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrcollator_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrparamregistry_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrset_collection_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrset_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrttl_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-rrtype_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-run_unittests.Po
+ -rm -f ./$(DEPDIR)/run_unittests-serial_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsig_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsigerror_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsigkey_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-tsigrecord_unittest.Po
+ -rm -f ./$(DEPDIR)/run_unittests-unittest_util.Po
+ -rm -f ./$(DEPDIR)/run_unittests-zone_checker_unittest.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--depfiles check check-TESTS check-am clean clean-generic \
+ clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/lib/dns/tests/dns_exceptions_unittest.cc b/src/lib/dns/tests/dns_exceptions_unittest.cc
new file mode 100644
index 0000000..a8d2590
--- /dev/null
+++ b/src/lib/dns/tests/dns_exceptions_unittest.cc
@@ -0,0 +1,65 @@
+// Copyright (C) 2014-2015,2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/exceptions.h>
+
+#include <gtest/gtest.h>
+
+namespace { // begin unnamed namespace
+
+TEST(DNSExceptionsTest, checkExceptionsHierarchy) {
+ EXPECT_NO_THROW({
+ const isc::dns::Exception exception("", 0, "");
+ const isc::Exception& exception_cast =
+ dynamic_cast<const isc::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::DNSTextError exception("", 0, "");
+ const isc::dns::Exception& exception_cast =
+ dynamic_cast<const isc::dns::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::NameParserException exception("", 0, "");
+ const isc::dns::DNSTextError& exception_cast =
+ dynamic_cast<const isc::dns::DNSTextError&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::DNSMessageFORMERR exception("", 0, "");
+ const isc::dns::DNSProtocolError& exception_cast =
+ dynamic_cast<const isc::dns::DNSProtocolError&>(exception);
+ const isc::dns::Exception& exception_cast2 =
+ dynamic_cast<const isc::dns::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.getRcode();
+ exception_cast.what();
+ exception_cast2.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::DNSMessageBADVERS exception("", 0, "");
+ const isc::dns::DNSProtocolError& exception_cast =
+ dynamic_cast<const isc::dns::DNSProtocolError&>(exception);
+ const isc::dns::Exception& exception_cast2 =
+ dynamic_cast<const isc::dns::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.getRcode();
+ exception_cast.what();
+ exception_cast2.what();
+ });
+}
+
+} // end unnamed namespace
diff --git a/src/lib/dns/tests/edns_unittest.cc b/src/lib/dns/tests/edns_unittest.cc
new file mode 100644
index 0000000..dfc68cc
--- /dev/null
+++ b/src/lib/dns/tests/edns_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <sstream>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/edns.h>
+#include <dns/exceptions.h>
+#include <dns/message.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rcode.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrttl.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+const uint8_t EDNS::SUPPORTED_VERSION;
+
+namespace {
+class EDNSTest : public ::testing::Test {
+protected:
+ EDNSTest() : rrtype(RRType::OPT()), buffer(NULL, 0), obuffer(0), rcode(0) {
+ opt_rdata = ConstRdataPtr(new generic::OPT());
+ edns_base.setUDPSize(4096);
+ }
+ RRType rrtype;
+ EDNS edns_base;
+ ConstEDNSPtr edns;
+ InputBuffer buffer;
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+ ConstRdataPtr opt_rdata;
+ Rcode rcode;
+ vector<unsigned char> wiredata;
+};
+
+// RRClass of EDNS OPT means UDP buffer size
+const RRClass rrclass(4096);
+// RRTTL of EDNS OPT encodes extended-rcode, version, and DO bit
+const RRTTL rrttl_do_on(0x00008000); // DO=on
+const RRTTL rrttl_do_off(0); // DO=off
+const RRTTL rrttl_badver(0x00018000); // version=1, DO=on
+
+TEST_F(EDNSTest, badVerConstruct) {
+ EXPECT_THROW(EDNS(1), isc::InvalidParameter);
+}
+
+TEST_F(EDNSTest, DNSSECDOBit) {
+ // tests for EDNS from RR
+
+ // DO bit is on, so DNSSEC should be considered to be supported.
+ EXPECT_TRUE(EDNS(Name::ROOT_NAME(), rrclass, rrtype,
+ rrttl_do_on, *opt_rdata).getDNSSECAwareness());
+
+ // DO bit is off. DNSSEC should be considered to be unsupported.
+ EXPECT_FALSE(EDNS(Name::ROOT_NAME(), rrclass, rrtype,
+ rrttl_do_off, *opt_rdata).getDNSSECAwareness());
+
+ // tests for EDNS constructed by hand
+ EXPECT_FALSE(edns_base.getDNSSECAwareness()); // false by default
+ edns_base.setDNSSECAwareness(true); // enable by hand
+ EXPECT_TRUE(edns_base.getDNSSECAwareness());
+ edns_base.setDNSSECAwareness(false); // disable by hand
+ EXPECT_FALSE(edns_base.getDNSSECAwareness());
+}
+
+TEST_F(EDNSTest, UDPSize) {
+ EXPECT_EQ(4096, EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_on,
+ *opt_rdata).getUDPSize());
+
+ // EDNS UDP size smaller than the traditional max, 512. Unusual, but
+ // not prohibited.
+ edns_base.setUDPSize(511);
+ EXPECT_EQ(511, edns_base.getUDPSize());
+
+ // Even 0 is okay.
+ edns_base.setUDPSize(0);
+ EXPECT_EQ(0, edns_base.getUDPSize());
+
+ // Possible max value is also okay, although the higher layer app may
+ // adjust it to a reasonably lower value
+ edns_base.setUDPSize(65535);
+ EXPECT_EQ(65535, edns_base.getUDPSize());
+}
+
+TEST_F(EDNSTest, getVersion) {
+ // Constructed by hand
+ EXPECT_EQ(EDNS::SUPPORTED_VERSION, EDNS().getVersion());
+
+ // From RR
+ EXPECT_EQ(EDNS::SUPPORTED_VERSION,
+ EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_on,
+ *opt_rdata).getVersion());
+}
+
+TEST_F(EDNSTest, BadWireData) {
+ // Incompatible RR type
+ EXPECT_THROW(EDNS(Name::ROOT_NAME(), rrclass, RRType::A(),
+ rrttl_do_on, *opt_rdata), isc::InvalidParameter);
+
+ // OPT RR of a non root name
+ EXPECT_THROW(EDNS(Name("example.com"), rrclass, rrtype,
+ rrttl_do_on, *opt_rdata), DNSMessageFORMERR);
+
+ // Unsupported Version
+ EXPECT_THROW(EDNS(Name::ROOT_NAME(), rrclass, rrtype,
+ rrttl_badver, *opt_rdata), DNSMessageBADVERS);
+}
+
+TEST_F(EDNSTest, toText) {
+ // Typical case, disabling DNSSEC
+ EXPECT_EQ("; EDNS: version: 0, flags:; udp: 4096\n",
+ EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_off,
+ *opt_rdata).toText());
+
+ // Typical case, enabling DNSSEC
+ EXPECT_EQ("; EDNS: version: 0, flags: do; udp: 4096\n",
+ EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_on,
+ *opt_rdata).toText());
+
+ // Non-0 extended Rcode: ignored in the toText() output.
+ EXPECT_EQ("; EDNS: version: 0, flags: do; udp: 4096\n",
+ EDNS(Name::ROOT_NAME(), rrclass, rrtype,
+ RRTTL(0x01008000), *opt_rdata).toText());
+
+ // Unknown flag: ignored in the toText() output.
+ EXPECT_EQ("; EDNS: version: 0, flags: do; udp: 4096\n",
+ EDNS(Name::ROOT_NAME(), rrclass, rrtype,
+ RRTTL(0x00008001), *opt_rdata).toText());
+}
+
+TEST_F(EDNSTest, toWireRenderer) {
+ // Typical case, (explicitly) disabling DNSSEC
+ edns_base.setDNSSECAwareness(false);
+ EXPECT_EQ(1, edns_base.toWire(renderer,
+ Rcode::NOERROR().getExtendedCode()));
+ UnitTestUtil::readWireData("edns_toWire1.wire", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+
+ // Typical case, enabling DNSSEC
+ renderer.clear();
+ wiredata.clear();
+ edns_base.setDNSSECAwareness(true);
+ EXPECT_EQ(1, edns_base.toWire(renderer,
+ Rcode::NOERROR().getExtendedCode()));
+ UnitTestUtil::readWireData("edns_toWire2.wire", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+
+ // Non-0 extended Rcode
+ renderer.clear();
+ wiredata.clear();
+ edns_base.setDNSSECAwareness(true);
+ EXPECT_EQ(1, edns_base.toWire(renderer,
+ Rcode::BADVERS().getExtendedCode()));
+ UnitTestUtil::readWireData("edns_toWire3.wire", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+
+ // Uncommon UDP buffer size
+ renderer.clear();
+ wiredata.clear();
+ edns_base.setDNSSECAwareness(true);
+ edns_base.setUDPSize(511);
+ EXPECT_EQ(1, edns_base.toWire(renderer,
+ Rcode::NOERROR().getExtendedCode()));
+ UnitTestUtil::readWireData("edns_toWire4.wire", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+
+ // From RR with unknown flag. If used for toWire(), the unknown flag
+ // should disappear.
+ renderer.clear();
+ wiredata.clear();
+ EXPECT_EQ(1, EDNS(Name::ROOT_NAME(), rrclass, rrtype, RRTTL(0x00008001),
+ *opt_rdata).toWire(renderer,
+ Rcode::NOERROR().getExtendedCode()));
+ UnitTestUtil::readWireData("edns_toWire2.wire", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+
+ // If the available length in the renderer is not sufficient for the OPT
+ // RR, it shouldn't be inserted.
+ renderer.clear();
+ renderer.setLengthLimit(10); // 10 = minimum length of OPT RR - 1
+ edns_base.setDNSSECAwareness(true);
+ edns_base.setUDPSize(4096);
+ EXPECT_EQ(0, edns_base.toWire(renderer,
+ Rcode::NOERROR().getExtendedCode()));
+ // renderer should be intact
+ EXPECT_EQ(0, renderer.getLength());
+}
+
+TEST_F(EDNSTest, toWireBuffer) {
+ // "to renderer" and "to buffer" should generally produce the same result.
+ // for simplicity we only check one typical case to confirm that.
+ EXPECT_EQ(1, edns_base.toWire(obuffer,
+ Rcode::NOERROR().getExtendedCode()));
+ UnitTestUtil::readWireData("edns_toWire1.wire", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(EDNSTest, createFromRR) {
+ uint8_t extended_rcode;
+
+ // normal case
+ edns = ConstEDNSPtr(createEDNSFromRR(Name::ROOT_NAME(), rrclass, rrtype,
+ rrttl_do_on, *opt_rdata,
+ extended_rcode));
+ EXPECT_EQ(EDNS::SUPPORTED_VERSION, edns->getVersion());
+ EXPECT_TRUE(edns->getDNSSECAwareness());
+ EXPECT_EQ(4096, edns->getUDPSize());
+ EXPECT_EQ(0, static_cast<int>(extended_rcode));
+
+ // non-0 extended rcode
+ extended_rcode = 0;
+ ConstEDNSPtr(createEDNSFromRR(Name::ROOT_NAME(), rrclass, rrtype,
+ RRTTL(0x01008000), *opt_rdata,
+ extended_rcode));
+ EXPECT_EQ(1, static_cast<int>(extended_rcode));
+
+ // creation triggers an exception. extended_rcode must be intact.
+ extended_rcode = 0;
+ EXPECT_THROW(createEDNSFromRR(Name::ROOT_NAME(), rrclass, rrtype,
+ rrttl_badver, *opt_rdata, extended_rcode),
+ DNSMessageBADVERS);
+ EXPECT_EQ(0, static_cast<int>(extended_rcode));
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(EDNSTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << edns_base;
+ EXPECT_EQ(edns_base.toText(), oss.str());
+}
+}
diff --git a/src/lib/dns/tests/labelsequence_unittest.cc b/src/lib/dns/tests/labelsequence_unittest.cc
new file mode 100644
index 0000000..15650fa
--- /dev/null
+++ b/src/lib/dns/tests/labelsequence_unittest.cc
@@ -0,0 +1,1243 @@
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+
+#include <dns/labelsequence.h>
+#include <dns/name.h>
+#include <exceptions/exceptions.h>
+
+#include <gtest/gtest.h>
+
+#include <boost/functional/hash.hpp>
+
+#include <string>
+#include <vector>
+#include <utility>
+#include <set>
+
+using namespace isc::dns;
+using namespace std;
+
+// XXX: this is defined as class static constants, but some compilers
+// seemingly cannot find the symbols when used in the EXPECT_xxx macros.
+const size_t LabelSequence::MAX_SERIALIZED_LENGTH;
+
+namespace {
+
+// Common check that two labelsequences are equal
+void check_equal(const LabelSequence& ls1, const LabelSequence& ls2) {
+ NameComparisonResult result = ls1.compare(ls2);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation()) << ls1.toText() << " != " << ls2.toText();
+ EXPECT_EQ(0, result.getOrder()) << ls1.toText() << " != " << ls2.toText();
+ EXPECT_EQ(ls1.getLabelCount(), result.getCommonLabels());
+}
+
+// Common check for general comparison of two labelsequences
+void check_compare(const LabelSequence& ls1, const LabelSequence& ls2,
+ isc::dns::NameComparisonResult::NameRelation relation,
+ size_t common_labels, bool check_order, int order=0) {
+ NameComparisonResult result = ls1.compare(ls2);
+ EXPECT_EQ(relation, result.getRelation());
+ EXPECT_EQ(common_labels, result.getCommonLabels());
+ if (check_order) {
+ EXPECT_EQ(order, result.getOrder());
+ }
+}
+
+class LabelSequenceTest : public ::testing::Test {
+public:
+ LabelSequenceTest() : n1("example.org"), n2("example.com"),
+ n3("example.org"), n4("foo.bar.test.example"),
+ n5("example.ORG"), n6("ExAmPlE.org"),
+ n7("."), n8("foo.example.org.bar"),
+ n9("\\000xample.org"),
+ n10("\\000xample.org"),
+ n11("\\000xample.com"),
+ n12("\\000xamplE.com"),
+ n_maxlabel("0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6"),
+ ls1(n1), ls2(n2), ls3(n3), ls4(n4), ls5(n5),
+ ls6(n6), ls7(n7), ls8(n8),
+ ls9(n9), ls10(n10), ls11(n11), ls12(n12)
+ {};
+ // Need to keep names in scope for at least the lifetime of
+ // the labelsequences
+ Name n1, n2, n3, n4, n5, n6, n7, n8;
+ Name n9, n10, n11, n12;
+ const Name n_maxlabel;
+
+ LabelSequence ls1, ls2, ls3, ls4, ls5, ls6, ls7, ls8;
+ LabelSequence ls9, ls10, ls11, ls12;
+};
+
+// Check the assignment operator.
+TEST_F(LabelSequenceTest, assign) {
+ // Create the label sequence with example.org (n1 name).
+ LabelSequence ls(n1);
+ EXPECT_TRUE(ls == ls1);
+
+ // Assign the label sequence to example.com (n2 name).
+ ls = ls2;
+ EXPECT_FALSE(ls == ls1);
+ EXPECT_TRUE(ls == ls2);
+}
+
+// Basic equality tests
+TEST_F(LabelSequenceTest, equals_sensitive) {
+ EXPECT_TRUE(ls1.equals(ls1, true));
+ EXPECT_FALSE(ls1.equals(ls2, true));
+ EXPECT_TRUE(ls1.equals(ls3, true));
+ EXPECT_FALSE(ls1.equals(ls4, true));
+ EXPECT_FALSE(ls1.equals(ls5, true));
+ EXPECT_FALSE(ls1.equals(ls6, true));
+ EXPECT_FALSE(ls1.equals(ls7, true));
+ EXPECT_FALSE(ls1.equals(ls8, true));
+
+ EXPECT_FALSE(ls2.equals(ls1, true));
+ EXPECT_TRUE(ls2.equals(ls2, true));
+ EXPECT_FALSE(ls2.equals(ls3, true));
+ EXPECT_FALSE(ls2.equals(ls4, true));
+ EXPECT_FALSE(ls2.equals(ls5, true));
+ EXPECT_FALSE(ls2.equals(ls6, true));
+ EXPECT_FALSE(ls2.equals(ls7, true));
+ EXPECT_FALSE(ls2.equals(ls8, true));
+
+ EXPECT_FALSE(ls4.equals(ls1, true));
+ EXPECT_FALSE(ls4.equals(ls2, true));
+ EXPECT_FALSE(ls4.equals(ls3, true));
+ EXPECT_TRUE(ls4.equals(ls4, true));
+ EXPECT_FALSE(ls4.equals(ls5, true));
+ EXPECT_FALSE(ls4.equals(ls6, true));
+ EXPECT_FALSE(ls4.equals(ls7, true));
+ EXPECT_FALSE(ls4.equals(ls8, true));
+
+ EXPECT_FALSE(ls5.equals(ls1, true));
+ EXPECT_FALSE(ls5.equals(ls2, true));
+ EXPECT_FALSE(ls5.equals(ls3, true));
+ EXPECT_FALSE(ls5.equals(ls4, true));
+ EXPECT_TRUE(ls5.equals(ls5, true));
+ EXPECT_FALSE(ls5.equals(ls6, true));
+ EXPECT_FALSE(ls5.equals(ls7, true));
+ EXPECT_FALSE(ls5.equals(ls8, true));
+
+ EXPECT_TRUE(ls9.equals(ls10, true));
+ EXPECT_FALSE(ls9.equals(ls11, true));
+ EXPECT_FALSE(ls9.equals(ls12, true));
+ EXPECT_FALSE(ls11.equals(ls12, true));
+}
+
+TEST_F(LabelSequenceTest, equals_insensitive) {
+ EXPECT_TRUE(ls1.equals(ls1));
+ EXPECT_FALSE(ls1.equals(ls2));
+ EXPECT_TRUE(ls1.equals(ls3));
+ EXPECT_FALSE(ls1.equals(ls4));
+ EXPECT_TRUE(ls1.equals(ls5));
+ EXPECT_TRUE(ls1.equals(ls6));
+ EXPECT_FALSE(ls1.equals(ls7));
+
+ EXPECT_FALSE(ls2.equals(ls1));
+ EXPECT_TRUE(ls2.equals(ls2));
+ EXPECT_FALSE(ls2.equals(ls3));
+ EXPECT_FALSE(ls2.equals(ls4));
+ EXPECT_FALSE(ls2.equals(ls5));
+ EXPECT_FALSE(ls2.equals(ls6));
+ EXPECT_FALSE(ls2.equals(ls7));
+
+ EXPECT_TRUE(ls3.equals(ls1));
+ EXPECT_FALSE(ls3.equals(ls2));
+ EXPECT_TRUE(ls3.equals(ls3));
+ EXPECT_FALSE(ls3.equals(ls4));
+ EXPECT_TRUE(ls3.equals(ls5));
+ EXPECT_TRUE(ls3.equals(ls6));
+ EXPECT_FALSE(ls3.equals(ls7));
+
+ EXPECT_FALSE(ls4.equals(ls1));
+ EXPECT_FALSE(ls4.equals(ls2));
+ EXPECT_FALSE(ls4.equals(ls3));
+ EXPECT_TRUE(ls4.equals(ls4));
+ EXPECT_FALSE(ls4.equals(ls5));
+ EXPECT_FALSE(ls4.equals(ls6));
+ EXPECT_FALSE(ls4.equals(ls7));
+
+ EXPECT_TRUE(ls5.equals(ls1));
+ EXPECT_FALSE(ls5.equals(ls2));
+ EXPECT_TRUE(ls5.equals(ls3));
+ EXPECT_FALSE(ls5.equals(ls4));
+ EXPECT_TRUE(ls5.equals(ls5));
+ EXPECT_TRUE(ls5.equals(ls6));
+ EXPECT_FALSE(ls5.equals(ls7));
+
+ EXPECT_TRUE(ls9.equals(ls10));
+ EXPECT_FALSE(ls9.equals(ls11));
+ EXPECT_FALSE(ls9.equals(ls12));
+ EXPECT_TRUE(ls11.equals(ls12));
+}
+
+// operator==(). This is mostly trivial wrapper, so it should suffice to
+// check some basic cases.
+TEST_F(LabelSequenceTest, operatorEqual) {
+ // cppcheck-suppress duplicateExpression
+ EXPECT_TRUE(ls1 == ls1); // self equivalence
+ EXPECT_TRUE(ls1 == LabelSequence(n1)); // equivalent two different objects
+ EXPECT_FALSE(ls1 == ls2); // non equivalent objects
+ EXPECT_TRUE(ls1 == ls5); // it's always case insensitive
+}
+
+// Compare tests
+TEST_F(LabelSequenceTest, compare) {
+ // "example.org." and "example.org.", case sensitive
+ NameComparisonResult result = ls1.compare(ls3, true);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation());
+ EXPECT_EQ(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ // "example.org." and "example.ORG.", case sensitive
+ result = ls3.compare(ls5, true);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(1, result.getCommonLabels());
+
+ // "example.org." and "example.ORG.", case in-sensitive
+ result = ls3.compare(ls5);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation());
+ EXPECT_EQ(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ Name na("a.example.org");
+ Name nb("b.example.org");
+ LabelSequence lsa(na);
+ LabelSequence lsb(nb);
+
+ // "a.example.org." and "b.example.org.", case in-sensitive
+ result = lsa.compare(lsb);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ // "example.org." and "b.example.org.", case in-sensitive
+ lsa.stripLeft(1);
+ result = lsa.compare(lsb);
+ EXPECT_EQ(isc::dns::NameComparisonResult::SUPERDOMAIN,
+ result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ Name nc("g.f.e.d.c.example.org");
+ LabelSequence lsc(nc);
+
+ // "g.f.e.d.c.example.org." and "b.example.org" (not absolute), case
+ // in-sensitive; the absolute one is always smaller.
+ lsb.stripRight(1);
+ result = lsc.compare(lsb);
+ EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(0, result.getCommonLabels());
+
+ // "g.f.e.d.c.example.org." and "example.org.", case in-sensitive
+ result = lsc.compare(ls1);
+ EXPECT_EQ(isc::dns::NameComparisonResult::SUBDOMAIN,
+ result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ // "e.d.c.example.org." and "example.org.", case in-sensitive
+ lsc.stripLeft(2);
+ result = lsc.compare(ls1);
+ EXPECT_EQ(isc::dns::NameComparisonResult::SUBDOMAIN,
+ result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ // "example.org." and "example.org.", case in-sensitive
+ lsc.stripLeft(3);
+ result = lsc.compare(ls1);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation());
+ EXPECT_EQ(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ // "." and "example.org.", case in-sensitive
+ lsc.stripLeft(2);
+ result = lsc.compare(ls1);
+ EXPECT_EQ(isc::dns::NameComparisonResult::SUPERDOMAIN,
+ result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(1, result.getCommonLabels());
+
+ Name nd("a.b.c.isc.example.org");
+ LabelSequence lsd(nd);
+ Name ne("w.x.y.isc.EXAMPLE.org");
+ LabelSequence lse(ne);
+
+ // "a.b.c.isc.example.org." and "w.x.y.isc.EXAMPLE.org.",
+ // case sensitive
+ result = lsd.compare(lse, true);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(2, result.getCommonLabels());
+
+ // "a.b.c.isc.example.org." and "w.x.y.isc.EXAMPLE.org.",
+ // case in-sensitive
+ result = lsd.compare(lse);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(4, result.getCommonLabels());
+
+ // "isc.example.org." and "isc.EXAMPLE.org.", case sensitive
+ lsd.stripLeft(3);
+ lse.stripLeft(3);
+ result = lsd.compare(lse, true);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(2, result.getCommonLabels());
+
+ // "isc.example.org." and "isc.EXAMPLE.org.", case in-sensitive
+ result = lsd.compare(lse);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation());
+ EXPECT_EQ(0, result.getOrder());
+ EXPECT_EQ(4, result.getCommonLabels());
+
+ Name nf("a.b.c.isc.example.org");
+ LabelSequence lsf(nf);
+ Name ng("w.x.y.isc.EXAMPLE.org");
+ LabelSequence lsg(ng);
+
+ // lsf: "a.b.c.isc.example.org."
+ // lsg: "w.x.y.isc.EXAMPLE.org" (not absolute), case in-sensitive.
+ // the absolute one is always smaller.
+ lsg.stripRight(1);
+ result = lsg.compare(lsf); // lsg > lsf
+ EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(0, result.getCommonLabels());
+
+ // "a.b.c.isc.example.org" (not absolute) and
+ // "w.x.y.isc.EXAMPLE.org" (not absolute), case in-sensitive
+ lsf.stripRight(1);
+ result = lsg.compare(lsf);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(3, result.getCommonLabels());
+
+ // "a.b.c.isc.example" (not absolute) and
+ // "w.x.y.isc.EXAMPLE" (not absolute), case in-sensitive
+ lsf.stripRight(1);
+ lsg.stripRight(1);
+ result = lsg.compare(lsf);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_LT(0, result.getOrder());
+ EXPECT_EQ(2, result.getCommonLabels());
+
+ // lsf: "a.b.c" (not absolute) and
+ // lsg: "w.x.y" (not absolute), case in-sensitive; a.b.c < w.x.y;
+ // no common labels.
+ lsf.stripRight(2);
+ lsg.stripRight(2);
+ result = lsf.compare(lsg);
+ EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(0, result.getCommonLabels());
+
+ // lsf2: a.b.cc (not absolute); a.b.c < a.b.cc, no common labels.
+ const Name nf2("a.b.cc");
+ LabelSequence lsf2(nf2);
+ lsf2.stripRight(1);
+ result = lsf.compare(lsf2);
+ EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(0, result.getCommonLabels());
+
+ Name nh("aexample.org");
+ LabelSequence lsh(nh);
+ Name ni("bexample.org");
+ LabelSequence lsi(ni);
+
+ // "aexample.org" (not absolute) and
+ // "bexample.org" (not absolute), case in-sensitive
+ lsh.stripRight(1);
+ lsi.stripRight(1);
+ result = lsh.compare(lsi);
+ EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR,
+ result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(1, result.getCommonLabels());
+
+ // "aexample" (not absolute) and
+ // "bexample" (not absolute), case in-sensitive;
+ // aexample < bexample; no common labels.
+ lsh.stripRight(1);
+ lsi.stripRight(1);
+ result = lsh.compare(lsi);
+ EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation());
+ EXPECT_GT(0, result.getOrder());
+ EXPECT_EQ(0, result.getCommonLabels());
+
+ Name nj("example.org");
+ LabelSequence lsj(nj);
+ Name nk("example.org");
+ LabelSequence lsk(nk);
+
+ // "example.org" (not absolute) and
+ // "example.org" (not absolute), case in-sensitive
+ lsj.stripRight(1);
+ lsk.stripRight(1);
+ result = lsj.compare(lsk);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation());
+ EXPECT_EQ(0, result.getOrder());
+ EXPECT_EQ(2, result.getCommonLabels());
+
+ // "example" (not absolute) and
+ // "example" (not absolute), case in-sensitive
+ lsj.stripRight(1);
+ lsk.stripRight(1);
+ result = lsj.compare(lsk);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation());
+ EXPECT_EQ(0, result.getOrder());
+ EXPECT_EQ(1, result.getCommonLabels());
+}
+
+void
+getDataCheck(const uint8_t* expected_data, size_t expected_len,
+ const LabelSequence& ls)
+{
+ size_t len;
+ const uint8_t* data = ls.getData(&len);
+ ASSERT_EQ(expected_len, len) << "Expected data: " << expected_data <<
+ ", label sequence: " << ls;
+ EXPECT_EQ(expected_len, ls.getDataLength()) <<
+ "Expected data: " << expected_data <<
+ ", label sequence: " << ls;
+ for (size_t i = 0; i < len; ++i) {
+ EXPECT_EQ(expected_data[i], data[i]) <<
+ "Difference at pos " << i << ": Expected data: " << expected_data <<
+ ", label sequence: " << ls;
+ }
+}
+
+// Convenient data converter for expected data. Label data must be of
+// uint8_t*, while it's convenient if we can specify some test data in
+// plain string (which is of char*). This wrapper converts the latter to
+// the former in a safer way.
+void
+getDataCheck(const char* expected_char_data, size_t expected_len,
+ const LabelSequence& ls)
+{
+ const vector<uint8_t> expected_data(expected_char_data,
+ expected_char_data + expected_len);
+ getDataCheck(&expected_data[0], expected_len, ls);
+}
+
+TEST_F(LabelSequenceTest, getData) {
+ getDataCheck("\007example\003org\000", 13, ls1);
+ getDataCheck("\007example\003com\000", 13, ls2);
+ getDataCheck("\007example\003org\000", 13, ls3);
+ getDataCheck("\003foo\003bar\004test\007example\000", 22, ls4);
+ getDataCheck("\007example\003ORG\000", 13, ls5);
+ getDataCheck("\007ExAmPlE\003org\000", 13, ls6);
+ getDataCheck("\000", 1, ls7);
+};
+
+TEST_F(LabelSequenceTest, stripLeft) {
+ EXPECT_TRUE(ls1.equals(ls3));
+ ls1.stripLeft(0);
+ getDataCheck("\007example\003org\000", 13, ls1);
+ EXPECT_TRUE(ls1.equals(ls3));
+ ls1.stripLeft(1);
+ getDataCheck("\003org\000", 5, ls1);
+ EXPECT_FALSE(ls1.equals(ls3));
+ ls1.stripLeft(1);
+ getDataCheck("\000", 1, ls1);
+ EXPECT_TRUE(ls1.equals(ls7));
+
+ ls2.stripLeft(2);
+ getDataCheck("\000", 1, ls2);
+ EXPECT_TRUE(ls2.equals(ls7));
+}
+
+TEST_F(LabelSequenceTest, stripRight) {
+ EXPECT_TRUE(ls1.equals(ls3));
+ ls1.stripRight(1);
+ getDataCheck("\007example\003org", 12, ls1);
+ EXPECT_FALSE(ls1.equals(ls3));
+ ls1.stripRight(1);
+ getDataCheck("\007example", 8, ls1);
+ EXPECT_FALSE(ls1.equals(ls3));
+
+ ASSERT_FALSE(ls1.equals(ls2));
+ ls2.stripRight(2);
+ getDataCheck("\007example", 8, ls2);
+ EXPECT_TRUE(ls1.equals(ls2));
+}
+
+TEST_F(LabelSequenceTest, stripOutOfRange) {
+ EXPECT_THROW(ls1.stripLeft(100), isc::OutOfRange);
+ EXPECT_THROW(ls1.stripLeft(5), isc::OutOfRange);
+ EXPECT_THROW(ls1.stripLeft(4), isc::OutOfRange);
+ EXPECT_THROW(ls1.stripLeft(3), isc::OutOfRange);
+ getDataCheck("\007example\003org\000", 13, ls1);
+
+ EXPECT_THROW(ls1.stripRight(100), isc::OutOfRange);
+ EXPECT_THROW(ls1.stripRight(5), isc::OutOfRange);
+ EXPECT_THROW(ls1.stripRight(4), isc::OutOfRange);
+ EXPECT_THROW(ls1.stripRight(3), isc::OutOfRange);
+ getDataCheck("\007example\003org\000", 13, ls1);
+}
+
+TEST_F(LabelSequenceTest, getLabelCount) {
+ EXPECT_EQ(3, ls1.getLabelCount());
+ ls1.stripLeft(0);
+ EXPECT_EQ(3, ls1.getLabelCount());
+ ls1.stripLeft(1);
+ EXPECT_EQ(2, ls1.getLabelCount());
+ ls1.stripLeft(1);
+ EXPECT_EQ(1, ls1.getLabelCount());
+
+ EXPECT_EQ(3, ls2.getLabelCount());
+ ls2.stripRight(1);
+ EXPECT_EQ(2, ls2.getLabelCount());
+ ls2.stripRight(1);
+ EXPECT_EQ(1, ls2.getLabelCount());
+
+ EXPECT_EQ(3, ls3.getLabelCount());
+ ls3.stripRight(2);
+ EXPECT_EQ(1, ls3.getLabelCount());
+
+ EXPECT_EQ(5, ls4.getLabelCount());
+ ls4.stripRight(3);
+ EXPECT_EQ(2, ls4.getLabelCount());
+
+ EXPECT_EQ(3, ls5.getLabelCount());
+ ls5.stripLeft(2);
+ EXPECT_EQ(1, ls5.getLabelCount());
+}
+
+TEST_F(LabelSequenceTest, comparePart) {
+ EXPECT_FALSE(ls1.equals(ls8));
+
+ // strip root label from example.org.
+ ls1.stripRight(1);
+ // strip foo from foo.example.org.bar.
+ ls8.stripLeft(1);
+ // strip bar. (i.e. bar and root) too
+ ls8.stripRight(2);
+
+ EXPECT_TRUE(ls1.equals(ls8));
+
+ // Data comparison
+ size_t len;
+ const uint8_t* data = ls1.getData(&len);
+ getDataCheck(data, len, ls8);
+}
+
+TEST_F(LabelSequenceTest, isAbsolute) {
+ ASSERT_TRUE(ls1.isAbsolute());
+
+ ls1.stripLeft(1);
+ ASSERT_TRUE(ls1.isAbsolute());
+ ls1.stripRight(1);
+ ASSERT_FALSE(ls1.isAbsolute());
+
+ ASSERT_TRUE(ls2.isAbsolute());
+ ls2.stripRight(1);
+ ASSERT_FALSE(ls2.isAbsolute());
+
+ ASSERT_TRUE(ls3.isAbsolute());
+ ls3.stripLeft(2);
+ ASSERT_TRUE(ls3.isAbsolute());
+}
+
+TEST_F(LabelSequenceTest, toText) {
+ EXPECT_EQ(".", ls7.toText());
+
+ EXPECT_EQ("example.org.", ls1.toText());
+ ls1.stripLeft(1);
+ EXPECT_EQ("org.", ls1.toText());
+ ls1.stripLeft(1);
+ EXPECT_EQ(".", ls1.toText());
+
+ EXPECT_EQ("example.com.", ls2.toText());
+ ls2.stripRight(1);
+ EXPECT_EQ("example.com", ls2.toText());
+ ls2.stripRight(1);
+ EXPECT_EQ("example", ls2.toText());
+
+ EXPECT_EQ("foo.example.org.bar.", ls8.toText());
+ ls8.stripRight(2);
+ EXPECT_EQ("foo.example.org", ls8.toText());
+
+ EXPECT_EQ(".", ls7.toText());
+ EXPECT_THROW(ls7.stripLeft(1), isc::OutOfRange);
+
+ Name n_long1("012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "0123456789012345678901234567890");
+ LabelSequence ls_long1(n_long1);
+
+ EXPECT_EQ("012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "0123456789012345678901234567890.", ls_long1.toText());
+ ls_long1.stripRight(1);
+ EXPECT_EQ("012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "012345678901234567890123456789012."
+ "012345678901234567890123456789"
+ "0123456789012345678901234567890", ls_long1.toText());
+
+ LabelSequence ls_long2(n_maxlabel);
+
+ EXPECT_EQ("0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.", ls_long2.toText());
+ ls_long2.stripRight(1);
+ EXPECT_EQ("0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9."
+ "0.1.2.3.4.5.6", ls_long2.toText());
+ ls_long2.stripRight(125);
+ EXPECT_EQ("0.1", ls_long2.toText());
+}
+
+// The following verifies that toRawText() returns a string
+// actual characters in place of escape sequences. We do not
+// bother with an exhaustive set of tests here as this is
+// not a primary use case.
+TEST_F(LabelSequenceTest, toRawText) {
+ Name n("a bc.$exa(m)ple.@org");
+ LabelSequence l(n);
+ EXPECT_EQ("a bc.$exa(m)ple.@org", l.toRawText(true));
+ EXPECT_EQ("a bc.$exa(m)ple.@org.", l.toRawText(false));
+
+ // toRawText is not supposed to do any sanity checks.
+ // Let's try with a very weird name.
+ Name n2("xtra\tchars\n.in.name");
+ LabelSequence l2(n2);
+ EXPECT_EQ("xtra\tchars\n.in.name.", l2.toRawText(false));
+}
+
+// The following are test data used in the getHash test below. Normally
+// we use example/documentation domain names for testing, but in this case
+// we'd specifically like to use more realistic data, and are intentionally
+// using real-world samples: They are the NS names of root and some top level
+// domains as of this test.
+const char* const root_servers[] = {
+ "a.root-servers.net", "b.root-servers.net", "c.root-servers.net",
+ "d.root-servers.net", "e.root-servers.net", "f.root-servers.net",
+ "g.root-servers.net", "h.root-servers.net", "i.root-servers.net",
+ "j.root-servers.net", "k.root-servers.net", "l.root-servers.net",
+ "m.root-servers.net", NULL
+};
+
+const char* const jp_servers[] = {
+ "a.dns.jp", "b.dns.jp", "c.dns.jp", "d.dns.jp", "e.dns.jp",
+ "f.dns.jp", "g.dns.jp", NULL
+};
+const char* const cn_servers[] = {
+ "a.dns.cn", "b.dns.cn", "c.dns.cn", "d.dns.cn", "e.dns.cn",
+ "ns.cernet.net", NULL
+};
+const char* const ca_servers[] = {
+ "k.ca-servers.ca", "e.ca-servers.ca", "a.ca-servers.ca", "z.ca-servers.ca",
+ "tld.isc-sns.net", "c.ca-servers.ca", "j.ca-servers.ca", "l.ca-servers.ca",
+ "sns-pb.isc.org", "f.ca-servers.ca", NULL
+};
+
+// A helper function used in the getHash test below.
+void
+hashDistributionCheck(const char* const* servers) {
+ const size_t BUCKETS = 64; // constant used in the MessageRenderer
+ set<Name> names;
+ vector<size_t> hash_counts(BUCKETS);
+
+ // Store all test names and their super domain names (excluding the
+ // "root" label) in the set, calculates their hash values, and increments
+ // the counter for the corresponding hash "bucket".
+ for (size_t i = 0; servers[i] != NULL; ++i) {
+ const Name name(servers[i]);
+ for (size_t l = 0; l < name.getLabelCount() - 1; ++l) {
+ pair<set<Name>::const_iterator, bool> ret =
+ names.insert(name.split(l));
+ if (ret.second) {
+ hash_counts[LabelSequence((*ret.first)).getHash(false) %
+ BUCKETS]++;
+ }
+ }
+ }
+
+ // See how many conflicts we have in the buckets. For the testing purpose
+ // we expect there's at most 2 conflicts in each set, which is an
+ // arbitrary choice (it should happen to succeed with the hash function
+ // and data we are using; if it's not the case, maybe with an update to
+ // the hash implementation, we should revise the test).
+ for (size_t i = 0; i < BUCKETS; ++i) {
+ EXPECT_GE(3, hash_counts[i]);
+ }
+}
+
+TEST_F(LabelSequenceTest, getHash) {
+ // Trivial case. The same sequence should have the same hash.
+ EXPECT_EQ(ls1.getHash(true), ls1.getHash(true));
+
+ // Check the case-insensitive mode behavior.
+ EXPECT_EQ(ls1.getHash(false), ls5.getHash(false));
+
+ // Check that the distribution of hash values is "not too bad" (such as
+ // everything has the same hash value due to a stupid bug). It's
+ // difficult to check such things reliably. We do some ad hoc tests here.
+ hashDistributionCheck(root_servers);
+ hashDistributionCheck(jp_servers);
+ hashDistributionCheck(cn_servers);
+ hashDistributionCheck(ca_servers);
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(LabelSequenceTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << ls1;
+ EXPECT_EQ(ls1.toText(), oss.str());
+}
+
+TEST_F(LabelSequenceTest, serialize) {
+ // placeholder for serialized data. We use a sufficiently large space
+ // for testing the overwrapping cases below.
+ uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH * 3];
+
+ // vector to store expected and actual data
+ vector<LabelSequence> actual_labelseqs;
+ typedef pair<size_t, const uint8_t*> DataPair;
+ vector<DataPair> expected;
+
+ // An absolute sequence directly constructed from a valid name.
+ // labels = 3, offset sequence = 0, 8, 12, data = "example.com."
+ actual_labelseqs.push_back(ls1);
+ const uint8_t expected_data1[] = {
+ 3, 0, 8, 12, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
+ 3, 'o', 'r', 'g', 0 };
+ expected.push_back(DataPair(sizeof(expected_data1), expected_data1));
+
+ // Strip the original one from right.
+ // labels = 2, offset sequence = 0, 8, data = "example.com" (non absolute)
+ LabelSequence ls_rstripped = ls1;
+ ls_rstripped.stripRight(1);
+ actual_labelseqs.push_back(ls_rstripped);
+ const uint8_t expected_data2[] = {
+ 2, 0, 8, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
+ 3, 'o', 'r', 'g'};
+ expected.push_back(DataPair(sizeof(expected_data2), expected_data2));
+
+ // Strip the original one from left.
+ // labels = 2, offset sequence = 0, 4, data = "com."
+ // Note that offsets are adjusted so that they begin with 0.
+ LabelSequence ls_lstripped = ls1;
+ ls_lstripped.stripLeft(1);
+ actual_labelseqs.push_back(ls_lstripped);
+ const uint8_t expected_data3[] = { 2, 0, 4, 3, 'o', 'r', 'g', 0 };
+ expected.push_back(DataPair(sizeof(expected_data3), expected_data3));
+
+ // Root label.
+ LabelSequence ls_root(Name::ROOT_NAME());
+ actual_labelseqs.push_back(ls_root);
+ const uint8_t expected_data4[] = { 1, 0, 0 };
+ expected.push_back(DataPair(sizeof(expected_data4), expected_data4));
+
+ // Non absolute single-label.
+ LabelSequence ls_single = ls_rstripped;
+ ls_single.stripRight(1);
+ actual_labelseqs.push_back(ls_single);
+ const uint8_t expected_data5[] = {
+ 1, 0, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e' };
+ expected.push_back(DataPair(sizeof(expected_data5), expected_data5));
+
+ // Labels containing a longest possible label
+ const Name name_longlabel(std::string(63, 'x')); // 63 'x's
+ LabelSequence ls_longlabel(name_longlabel);
+ actual_labelseqs.push_back(ls_longlabel);
+ vector<uint8_t> expected_data6;
+ expected_data6.push_back(2); // 2 labels
+ expected_data6.push_back(0); // 1st offset
+ expected_data6.push_back(64); // 2nd offset
+ expected_data6.push_back(63); // 1st label length
+ expected_data6.insert(expected_data6.end(), 63, 'x'); // 1st label: 63 'x's
+ expected_data6.push_back(0); // 2nd label: trailing 0
+ expected.push_back(DataPair(expected_data6.size(), &expected_data6[0]));
+
+ // Max number of labels and longest possible name
+ EXPECT_EQ(Name::MAX_WIRE, n_maxlabel.getLength());
+ LabelSequence ls_maxlabel(n_maxlabel);
+ actual_labelseqs.push_back(ls_maxlabel);
+ vector<uint8_t> expected_data7;
+ expected_data7.push_back(Name::MAX_LABELS); // number of labels
+ for (size_t i = 0; i < Name::MAX_LABELS; ++i) {
+ expected_data7.push_back(i * 2); // each label has length and 1 byte
+ }
+ // Copy wire data of the name
+ isc::util::OutputBuffer ob(0);
+ n_maxlabel.toWire(ob);
+ expected_data7.insert(expected_data7.end(),
+ static_cast<const uint8_t*>(ob.getData()),
+ static_cast<const uint8_t*>(ob.getData()) +
+ ob.getLength());
+ expected.push_back(DataPair(expected_data7.size(), &expected_data7[0]));
+
+ // For each data set, serialize the labels and compare the data to the
+ // expected one.
+ vector<DataPair>::const_iterator it = expected.begin();
+ vector<LabelSequence>::const_iterator itl = actual_labelseqs.begin();
+ for (; it != expected.end(); ++it, ++itl) {
+ SCOPED_TRACE(itl->toText());
+
+ const size_t serialized_len = itl->getSerializedLength();
+
+ ASSERT_GE(LabelSequence::MAX_SERIALIZED_LENGTH, serialized_len);
+ itl->serialize(labels_buf, serialized_len);
+ EXPECT_EQ(it->first, serialized_len);
+ EXPECT_EQ(0, memcmp(it->second, labels_buf, serialized_len));
+
+ EXPECT_EQ(NameComparisonResult::EQUAL,
+ LabelSequence(labels_buf).compare(*itl).getRelation());
+
+ // Shift the data to the middle of the buffer for overwrap check
+ uint8_t* const bp = labels_buf;
+ std::memcpy(bp + serialized_len, bp, serialized_len);
+ // Memory layout is now as follows:
+ // <- ser_len -> <- ser_len ------>
+ // bp bp+ser_len bp+(ser_len*2)
+ // olen,odata,ndata
+
+ // end of buffer would be the first byte of offsets: invalid.
+ EXPECT_THROW(LabelSequence(bp + serialized_len).
+ serialize(bp + 2, serialized_len),
+ isc::BadValue);
+ // begin of buffer would be the last byte of ndata: invalid.
+ EXPECT_THROW(LabelSequence(bp + serialized_len).
+ serialize(bp + (2 * serialized_len) - 1, serialized_len),
+ isc::BadValue);
+ // A boundary safe case: buffer is placed after the sequence data.
+ // should cause no disruption.
+ LabelSequence(bp + serialized_len).
+ serialize(bp + 2 * serialized_len, serialized_len);
+ // A boundary safe case: buffer is placed before the sequence data
+ // should cause no disruption. (but the original serialized data will
+ // be overridden, so it can't be used any more)
+ LabelSequence(bp + serialized_len).
+ serialize(bp + 1, serialized_len);
+ }
+
+ EXPECT_THROW(ls1.serialize(labels_buf, ls1.getSerializedLength() - 1),
+ isc::BadValue);
+}
+
+#ifdef ENABLE_DEBUG
+
+// These checks are enabled only in debug mode in the LabelSequence
+// class.
+TEST_F(LabelSequenceTest, badDeserialize) {
+ EXPECT_THROW(LabelSequence(NULL), isc::BadValue);
+ const uint8_t zero_offsets[] = { 0 };
+ EXPECT_THROW(LabelSequence ls(zero_offsets), isc::BadValue);
+ const uint8_t toomany_offsets[] = { Name::MAX_LABELS + 1 };
+ EXPECT_THROW(LabelSequence ls(toomany_offsets), isc::BadValue);
+
+ // (second) offset does not match actual label length
+ const uint8_t offsets_wrongoffset[] = { 2, 0, 64, 1 };
+ EXPECT_THROW(LabelSequence ls(offsets_wrongoffset), isc::BadValue);
+
+ // offset matches, but exceeds MAX_LABEL_LEN
+ const uint8_t offsets_toolonglabel[] = { 2, 0, 64, 64 };
+ EXPECT_THROW(LabelSequence ls(offsets_toolonglabel), isc::BadValue);
+
+ // Inconsistent data: an offset is lower than the previous offset
+ const uint8_t offsets_lower[] = { 3, // # of offsets
+ 0, 2, 1, // offsets
+ 1, 'a', 1, 'b', 0};
+ EXPECT_THROW(LabelSequence ls(offsets_lower), isc::BadValue);
+
+ // Inconsistent data: an offset is equal to the previous offset
+ const uint8_t offsets_noincrease[] = { 2, 0, 0, 0, 0 };
+ EXPECT_THROW(LabelSequence ls(offsets_noincrease), isc::BadValue);
+}
+
+#endif
+
+namespace {
+
+// Helper function; repeatedly calls
+// - Initially, all three labelsequences should be the same
+// - repeatedly performs:
+// - checks all three are equal
+// - stripLeft on ls1
+// - checks ls1 and ls2 are different, and ls2 and ls3 are equal
+// - stripLeft on ls2
+// - checks ls1 and ls2 are equal, and ls2 and ls3 are different
+// - stripLeft on ls3
+//
+// (this test makes sure the stripLeft of one has no effect on the other
+// two, and that the strip properties hold regardless of how they were
+// constructed)
+//
+void stripLeftCheck(LabelSequence ls1, LabelSequence ls2, LabelSequence ls3) {
+ ASSERT_LT(1, ls1.getLabelCount());
+ while (ls1.getLabelCount() > 1) {
+ check_equal(ls1, ls2);
+ check_equal(ls2, ls3);
+
+ ls1.stripLeft(1);
+ check_compare(ls1, ls2, isc::dns::NameComparisonResult::SUPERDOMAIN,
+ ls1.getLabelCount(), true, -1);
+ check_equal(ls2, ls3);
+
+ ls2.stripLeft(1);
+ check_equal(ls1, ls2);
+ check_compare(ls2, ls3, isc::dns::NameComparisonResult::SUPERDOMAIN,
+ ls1.getLabelCount(), true, -1);
+
+ ls3.stripLeft(1);
+ }
+}
+
+// Similar to stripLeftCheck, but using stripRight()
+void stripRightCheck(LabelSequence ls1, LabelSequence ls2, LabelSequence ls3) {
+ ASSERT_LT(1, ls1.getLabelCount());
+ while (ls1.getLabelCount() > 1) {
+ check_equal(ls1, ls2);
+ check_equal(ls2, ls3);
+
+ ls1.stripRight(1);
+ check_compare(ls1, ls2, isc::dns::NameComparisonResult::NONE, 0,
+ false);
+ check_equal(ls2, ls3);
+
+ ls2.stripRight(1);
+ check_equal(ls1, ls2);
+ check_compare(ls2, ls3, isc::dns::NameComparisonResult::NONE, 0,
+ false);
+
+ ls3.stripRight(1);
+ }
+}
+
+} // end anonymous namespace
+
+class ExtendableLabelSequenceTest : public ::testing::Test {
+public:
+ ExtendableLabelSequenceTest() : bar("bar."),
+ example_org("example.org"),
+ foo("foo."),
+ foo_bar("foo.bar."),
+ foo_bar_example_org("foo.bar.example.org."),
+ foo_bar_foo_bar("foo.bar.foo.bar."),
+ foo_example("foo.example."),
+ org("org")
+ {
+ // explicitly set to non-zero data, to make sure
+ // we don't try to use data we don't set
+ memset(buf, 0xff, LabelSequence::MAX_SERIALIZED_LENGTH);
+ }
+
+ Name bar;
+ Name example_org;
+ Name foo;
+ Name foo_bar;
+ Name foo_bar_example_org;
+ Name foo_bar_foo_bar;
+ Name foo_example;
+ Name org;
+
+ uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
+};
+
+// Test that 'extendable' labelsequences behave correctly when using
+// stripLeft() and stripRight()
+TEST_F(ExtendableLabelSequenceTest, extendableLabelSequence) {
+ LabelSequence ls1(example_org);
+ LabelSequence ls2(example_org);
+
+ LabelSequence els(ls1, buf);
+ // ls1 is absolute, so els should be too
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(ls1, els);
+
+ ASSERT_EQ(ls1.getDataLength(), els.getDataLength());
+ stripLeftCheck(ls1, els, ls2);
+ stripRightCheck(ls1, els, ls2);
+
+ // Creating an extendable labelsequence from a non-absolute
+ // label sequence should result in a non-absolute label sequence
+ ls1.stripRight(1);
+ els = LabelSequence(ls1, buf);
+ EXPECT_FALSE(els.isAbsolute());
+ check_equal(ls1, els);
+
+ // and extending with the root label should make it absolute again
+ els.extend(LabelSequence(Name(".")), buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(ls2, els);
+}
+
+// Test that 'extendable' LabelSequences behave correctly when initialized
+// with a stripped source LabelSequence
+TEST_F(ExtendableLabelSequenceTest, extendableLabelSequenceLeftStrippedSource) {
+ LabelSequence ls1(foo_bar_example_org);
+ LabelSequence ls2(foo_bar_example_org);
+
+ while (ls1.getLabelCount() > 2) {
+ ls1.stripLeft(1);
+ ls2.stripLeft(1);
+
+ LabelSequence els(ls1, buf);
+
+ ASSERT_EQ(ls1.getDataLength(), els.getDataLength());
+ stripLeftCheck(ls1, els, ls2);
+ stripRightCheck(ls1, els, ls2);
+ }
+}
+
+TEST_F(ExtendableLabelSequenceTest, extendableLabelSequenceRightStrippedSource) {
+ LabelSequence ls1(foo_bar_example_org);
+ LabelSequence ls2(foo_bar_example_org);
+
+ while (ls1.getLabelCount() > 2) {
+ ls1.stripRight(1);
+ ls2.stripRight(1);
+
+ LabelSequence els(ls1, buf);
+
+ ASSERT_EQ(ls1.getDataLength(), els.getDataLength());
+ stripLeftCheck(ls1, els, ls2);
+ stripRightCheck(ls1, els, ls2);
+ }
+}
+
+// Check some basic 'extend' functionality
+TEST_F(ExtendableLabelSequenceTest, extend) {
+ LabelSequence ls1(foo_bar);
+ LabelSequence ls2(foo);
+ LabelSequence ls3(bar);
+ LabelSequence ls4(foo_bar);
+
+ LabelSequence els(ls2, buf);
+
+ check_compare(ls1, els, isc::dns::NameComparisonResult::COMMONANCESTOR, 1,
+ true, -4);
+ els.extend(ls3, buf);
+ EXPECT_TRUE(els.isAbsolute());
+
+ check_equal(ls1, els);
+ stripLeftCheck(ls1, els, ls4);
+ stripRightCheck(ls1, els, ls4);
+
+ // strip, then extend again
+ els.stripRight(2); // (2, 1 for root label, 1 for last label)
+ els.extend(ls3, buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(ls1, els);
+
+ // Extending again should make it different
+ els.extend(ls3, buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_compare(ls1, els, isc::dns::NameComparisonResult::COMMONANCESTOR, 2,
+ true, 4);
+
+ // Extending with a non-absolute name should make it non-absolute as well
+ ls3.stripRight(1);
+ els.extend(ls3, buf);
+ EXPECT_FALSE(els.isAbsolute());
+
+ Name check_name("foo.bar.bar.bar");
+ LabelSequence check_ls(check_name);
+ check_ls.stripRight(1);
+ check_equal(check_ls, els);
+
+ // And try extending when both are not absolute
+ els.stripRight(3);
+ ls1.stripRight(1);
+ EXPECT_FALSE(els.isAbsolute());
+ els.extend(ls3, buf);
+ EXPECT_FALSE(els.isAbsolute());
+ check_equal(ls1, els);
+
+ // Extending non-absolute with absolute should make it absolute again
+ EXPECT_FALSE(els.isAbsolute());
+ els.extend(LabelSequence(Name("absolute.")), buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(LabelSequence(Name("foo.bar.absolute")), els);
+}
+
+TEST_F(ExtendableLabelSequenceTest, extendLeftStripped) {
+ LabelSequence ls1(foo_example);
+ LabelSequence ls2(example_org);
+ LabelSequence ls3(org);
+
+ LabelSequence els(ls1, buf);
+
+ els.stripLeft(1);
+ els.extend(ls3, buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(ls2, els);
+}
+
+// Check that when extending with itself, it does not cause horrible failures
+TEST_F(ExtendableLabelSequenceTest, extendWithItself) {
+ LabelSequence ls1(foo_bar);
+ LabelSequence ls2(foo_bar_foo_bar);
+
+ LabelSequence els(ls1, buf);
+
+ els.extend(els, buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(ls2, els);
+
+ // Also try for non-absolute names
+ ls2.stripRight(1);
+ els = LabelSequence(ls1, buf);
+ els.stripRight(1);
+ els.extend(els, buf);
+ EXPECT_FALSE(els.isAbsolute());
+ check_equal(ls2, els);
+
+ // Once more, now start out with non-absolute labelsequence
+ ls1.stripRight(1);
+ els = LabelSequence(ls1, buf);
+ els.extend(els, buf);
+ EXPECT_FALSE(els.isAbsolute());
+ check_equal(ls2, els);
+}
+
+// Test that 'extending' with just a root label is a no-op, iff the original
+// was already absolute
+TEST_F(ExtendableLabelSequenceTest, extendWithRoot) {
+ LabelSequence ls1(example_org);
+
+ LabelSequence els(LabelSequence(ls1, buf));
+ check_equal(ls1, els);
+ els.extend(LabelSequence(Name(".")), buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(ls1, els);
+
+ // but not if the original was not absolute (it will be equal to
+ // the original labelsequence used above, but not the one it was based
+ // on).
+ LabelSequence ls2(example_org);
+ ls2.stripRight(1);
+ els = LabelSequence(ls2, buf);
+ EXPECT_FALSE(els.isAbsolute());
+ els.extend(LabelSequence(Name(".")), buf);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(ls1, els);
+ check_compare(ls2, els, isc::dns::NameComparisonResult::NONE, 0, true, 3);
+}
+
+// Check possible failure modes of extend()
+TEST_F(ExtendableLabelSequenceTest, extendBadData) {
+ LabelSequence ls1(example_org);
+
+ LabelSequence els(ls1, buf);
+
+ // try use with unrelated labelsequence
+ EXPECT_THROW(ls1.extend(ls1, buf), isc::BadValue);
+
+ // Create a long name, but so that we can still extend once
+ Name longlabel("1234567890123456789012345678901234567890"
+ "12345678901234567890");
+ LabelSequence long_ls(longlabel);
+ els = LabelSequence(long_ls, buf);
+ els.extend(els, buf);
+ els.extend(long_ls, buf);
+ els.extend(long_ls, buf);
+ ASSERT_EQ(245, els.getDataLength());
+ // Extending once more with 10 bytes should still work
+ els.extend(LabelSequence(Name("123456789")), buf);
+ EXPECT_TRUE(els.isAbsolute());
+
+ // Extended label sequence should now look like
+ const Name full_name(
+ "123456789012345678901234567890123456789012345678901234567890."
+ "123456789012345678901234567890123456789012345678901234567890."
+ "123456789012345678901234567890123456789012345678901234567890."
+ "123456789012345678901234567890123456789012345678901234567890."
+ "123456789.");
+ const LabelSequence full_ls(full_name);
+ check_equal(full_ls, els);
+
+ // But now, even the shortest extension should fail
+ EXPECT_THROW(els.extend(LabelSequence(Name("1")), buf), isc::BadValue);
+
+ // Check it hasn't been changed
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(full_ls, els);
+
+ // Also check that extending past MAX_LABELS is not possible
+ Name shortname("1.");
+ LabelSequence short_ls(shortname);
+ els = LabelSequence(short_ls, buf);
+ for (size_t i=0; i < 126; ++i) {
+ els.extend(short_ls, buf);
+ }
+
+ // Should now look like this
+ const Name full_name2(
+ "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1."
+ "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1."
+ "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1."
+ "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1."
+ "1.1.1.1.1.1.1.");
+ const LabelSequence full_ls2(full_name2);
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(full_ls2, els);
+
+ EXPECT_THROW(els.extend(short_ls, buf), isc::BadValue);
+
+ EXPECT_TRUE(els.isAbsolute());
+ check_equal(full_ls2, els);
+}
+
+// Check the static fixed 'wildcard' LabelSequence
+TEST(WildCardLabelSequence, wildcard) {
+ ASSERT_FALSE(LabelSequence::WILDCARD().isAbsolute());
+ ASSERT_EQ("*", LabelSequence::WILDCARD().toText());
+}
+
+}
diff --git a/src/lib/dns/tests/master_lexer_inputsource_unittest.cc b/src/lib/dns/tests/master_lexer_inputsource_unittest.cc
new file mode 100644
index 0000000..c5f618a
--- /dev/null
+++ b/src/lib/dns/tests/master_lexer_inputsource_unittest.cc
@@ -0,0 +1,368 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/master_lexer_inputsource.h>
+#include <dns/master_lexer.h>
+#include <exceptions/exceptions.h>
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <string.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::master_lexer_internal;
+
+namespace {
+
+const char* const test_input =
+ "Line1 to scan.\nLine2 to scan.\nLine3 to scan.\n";
+
+class InputSourceTest : public ::testing::Test {
+protected:
+ InputSourceTest() :
+ str_(test_input),
+ str_length_(strlen(str_)),
+ iss_(str_),
+ source_(iss_)
+ {}
+
+ const char* str_;
+ const size_t str_length_;
+ stringstream iss_;
+ InputSource source_;
+};
+
+// Test the default return values set during InputSource construction.
+TEST_F(InputSourceTest, defaults) {
+ EXPECT_EQ(1, source_.getCurrentLine());
+ EXPECT_FALSE(source_.atEOF());
+}
+
+// getName() on file and stream sources
+TEST_F(InputSourceTest, getName) {
+ EXPECT_EQ(0, source_.getName().find("stream-"));
+
+ // Use some file; doesn't really matter what.
+ InputSource source2(TEST_DATA_SRCDIR "/masterload.txt");
+ EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", source2.getName());
+}
+
+TEST_F(InputSourceTest, nonExistentFile) {
+ EXPECT_THROW({
+ InputSource source(TEST_DATA_SRCDIR "/does-not-exist");
+ }, InputSource::OpenError);
+}
+
+// getChar() should return characters from the input stream in
+// sequence. ungetChar() should skip backwards.
+void
+checkGetAndUngetChar(InputSource& source,
+ const char* str, const size_t str_length)
+{
+ for (size_t i = 0; i < str_length; ++i) {
+ EXPECT_EQ(str[i], source.getChar());
+ EXPECT_EQ(i + 1, source.getPosition());
+ EXPECT_FALSE(source.atEOF());
+ }
+
+ // At this point, we still have not reached EOF.
+ EXPECT_FALSE(source.atEOF());
+
+ // This should cause EOF to be set.
+ EXPECT_EQ(InputSource::END_OF_STREAM, source.getChar());
+
+ // Now, EOF should be set.
+ EXPECT_TRUE(source.atEOF());
+
+ // It doesn't increase the position count.
+ EXPECT_EQ(str_length, source.getPosition());
+ EXPECT_EQ(str_length, source.getSize()); // this should be == getSize().
+
+ // Now, let's go backwards. This should cause the EOF to be set to
+ // false.
+ source.ungetChar();
+
+ // Now, EOF should be false.
+ EXPECT_FALSE(source.atEOF());
+
+ // But the position shouldn't change.
+ EXPECT_EQ(str_length, source.getPosition());
+
+ // This should cause EOF to be set again.
+ EXPECT_EQ(InputSource::END_OF_STREAM, source.getChar());
+
+ // Now, EOF should be set.
+ EXPECT_TRUE(source.atEOF());
+
+ // Now, let's go backwards in a loop. Start by skipping the EOF.
+ source.ungetChar();
+
+ for (size_t i = 0; i < str_length; ++i) {
+ const size_t index = str_length - 1 - i;
+ // Skip one character.
+ source.ungetChar();
+ EXPECT_EQ(str[index], source.getChar());
+ EXPECT_EQ(index + 1, source.getPosition());
+ // Skip the character we received again.
+ source.ungetChar();
+ }
+
+ // Skipping past the start of buffer should throw.
+ EXPECT_THROW(source.ungetChar(), InputSource::UngetBeforeBeginning);
+}
+
+TEST_F(InputSourceTest, stream) {
+ checkGetAndUngetChar(source_, str_, str_length_);
+}
+
+TEST_F(InputSourceTest, file) {
+ std::ifstream fs(TEST_DATA_SRCDIR "/masterload.txt");
+ const std::string str((std::istreambuf_iterator<char>(fs)),
+ std::istreambuf_iterator<char>());
+ fs.close();
+
+ InputSource source(TEST_DATA_SRCDIR "/masterload.txt");
+ checkGetAndUngetChar(source, str.c_str(), str.size());
+}
+
+// ungetAll() should skip back to the place where the InputSource
+// started at construction, or the last saved start of line.
+TEST_F(InputSourceTest, ungetAll) {
+ while (!source_.atEOF()) {
+ source_.getChar();
+ }
+
+ // Now, we are at EOF.
+ EXPECT_TRUE(source_.atEOF());
+ EXPECT_EQ(4, source_.getCurrentLine());
+
+ source_.ungetAll();
+
+ // Now we are back to where we started.
+ EXPECT_EQ(1, source_.getCurrentLine());
+ EXPECT_FALSE(source_.atEOF());
+ EXPECT_EQ(0, source_.getPosition());
+}
+
+TEST_F(InputSourceTest, compact) {
+ // Compact at the start
+ source_.compact();
+
+ // Ungetting here must throw.
+ EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
+
+ for (size_t i = 0; i < str_length_; ++i) {
+ EXPECT_EQ(str_[i], source_.getChar());
+ EXPECT_FALSE(source_.atEOF());
+ }
+
+ // At this point, we still have not reached EOF.
+ EXPECT_FALSE(source_.atEOF());
+
+ // This should cause EOF to be set.
+ EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
+
+ // Now, EOF should be set.
+ EXPECT_TRUE(source_.atEOF());
+ EXPECT_EQ(4, source_.getCurrentLine());
+
+ // Compact again
+ source_.compact();
+
+ // We are still at EOF.
+ EXPECT_TRUE(source_.atEOF());
+ EXPECT_EQ(4, source_.getCurrentLine());
+
+ // compact shouldn't change the position count.
+ EXPECT_EQ(source_.getSize(), source_.getPosition());
+
+ // Skip the EOF.
+ source_.ungetChar();
+
+ // Ungetting here must throw.
+ EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
+
+ EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
+ EXPECT_TRUE(source_.atEOF());
+}
+
+TEST_F(InputSourceTest, markDuring) {
+ // First, skip to line 2.
+ while (!source_.atEOF() &&
+ (source_.getCurrentLine() != 2)) {
+ source_.getChar();
+ }
+ EXPECT_FALSE(source_.atEOF());
+ EXPECT_EQ(2, source_.getCurrentLine());
+
+ // Now, unget a couple of characters. This should cause the
+ // buffer_pos_ to be not equal to the size of the buffer.
+ source_.ungetChar();
+ source_.ungetChar();
+
+ // Now "mark" the source, meaning that we save line number and also
+ // compact the internal buffer at this stage.
+ source_.mark();
+
+ // Ungetting here must throw.
+ EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
+
+ for (size_t i = 13; i < str_length_; ++i) {
+ EXPECT_EQ(str_[i], source_.getChar());
+ EXPECT_FALSE(source_.atEOF());
+ }
+
+ // At this point, we still have not reached EOF.
+ EXPECT_FALSE(source_.atEOF());
+
+ // This should cause EOF to be set.
+ EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
+
+ // Now, EOF should be set.
+ EXPECT_TRUE(source_.atEOF());
+
+ // Now, ungetAll() and check where it goes back.
+ source_.ungetAll();
+
+ // Ungetting here must throw.
+ EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
+
+ for (size_t i = 13; i < str_length_; ++i) {
+ EXPECT_EQ(str_[i], source_.getChar());
+ EXPECT_FALSE(source_.atEOF());
+ }
+
+ // At this point, we still have not reached EOF.
+ EXPECT_FALSE(source_.atEOF());
+
+ // This should cause EOF to be set.
+ EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
+
+ // Now, EOF should be set.
+ EXPECT_TRUE(source_.atEOF());
+}
+
+// Test line counters.
+TEST_F(InputSourceTest, lines) {
+ size_t line = 1;
+ while (!source_.atEOF()) {
+ if (source_.getChar() == '\n') {
+ ++line;
+ }
+ EXPECT_EQ(line, source_.getCurrentLine());
+ }
+
+ // Now, we are at EOF.
+ EXPECT_TRUE(source_.atEOF());
+ EXPECT_EQ(4, source_.getCurrentLine());
+
+ // Go backwards 2 characters, skipping the last EOF and '\n'.
+ source_.ungetChar();
+ source_.ungetChar();
+
+ EXPECT_FALSE(source_.atEOF());
+ EXPECT_EQ(3, source_.getCurrentLine());
+
+ source_.ungetAll();
+
+ // Now we are back to where we started.
+ EXPECT_EQ(1, source_.getCurrentLine());
+ EXPECT_FALSE(source_.atEOF());
+
+ // Now check that line numbers are decremented properly (as much as
+ // possible using the available API).
+ while (!source_.atEOF()) {
+ source_.getChar();
+ }
+ line = source_.getCurrentLine();
+
+ // Now, we are at EOF.
+ EXPECT_TRUE(source_.atEOF());
+ EXPECT_EQ(4, line);
+
+ EXPECT_THROW({
+ while (true) {
+ source_.ungetChar();
+ EXPECT_TRUE(((line == source_.getCurrentLine()) ||
+ ((line - 1) == source_.getCurrentLine())));
+ line = source_.getCurrentLine();
+ }
+ }, InputSource::UngetBeforeBeginning);
+
+ // Now we are back to where we started.
+ EXPECT_EQ(1, source_.getCurrentLine());
+}
+
+// ungetAll() after saveLine() should skip back to the last-saved place.
+TEST_F(InputSourceTest, saveLine) {
+ // First, skip to line 2.
+ while (!source_.atEOF() &&
+ (source_.getCurrentLine() != 2)) {
+ source_.getChar();
+ }
+ EXPECT_FALSE(source_.atEOF());
+ EXPECT_EQ(2, source_.getCurrentLine());
+
+ // Now, save the line.
+ source_.saveLine();
+
+ // Now, go to EOF
+ while (!source_.atEOF()) {
+ source_.getChar();
+ }
+
+ // Now, we are at EOF.
+ EXPECT_TRUE(source_.atEOF());
+ EXPECT_EQ(4, source_.getCurrentLine());
+
+ // Now, ungetAll() and check where it goes back.
+ source_.ungetAll();
+
+ // Now we are back to where we last-saved.
+ EXPECT_EQ(2, source_.getCurrentLine());
+ EXPECT_FALSE(source_.atEOF());
+}
+
+TEST_F(InputSourceTest, getSize) {
+ // A simple case using string stream
+ EXPECT_EQ(strlen(test_input), source_.getSize());
+
+ // Check it works with an empty input
+ istringstream iss("");
+ EXPECT_EQ(0, InputSource(iss).getSize());
+
+ // Pretend there's an error in seeking in the stream. It will be
+ // considered a seek specific error, and getSize() returns "unknown".
+ iss.setstate(std::ios_base::failbit);
+ EXPECT_EQ(MasterLexer::SOURCE_SIZE_UNKNOWN, InputSource(iss).getSize());
+ // The fail bit should have been cleared.
+ EXPECT_FALSE(iss.fail());
+
+ // Pretend there's a *critical* error in the stream. The constructor will
+ // throw in the attempt of getting the input size.
+ iss.setstate(std::ios_base::badbit);
+ EXPECT_THROW(InputSource isrc(iss), InputSource::OpenError);
+
+ // Check with input source from file name. We hardcode the file size
+ // for simplicity. It won't change too often.
+ EXPECT_EQ(143, InputSource(TEST_DATA_SRCDIR "/masterload.txt").getSize());
+}
+
+TEST_F(InputSourceTest, getPosition) {
+ // Initially the position is set to 0. Other cases are tested in tests
+ // for get and unget.
+ EXPECT_EQ(0, source_.getPosition());
+ EXPECT_EQ(0, InputSource(TEST_DATA_SRCDIR "/masterload.txt").getPosition());
+}
+
+} // end namespace
diff --git a/src/lib/dns/tests/master_lexer_state_unittest.cc b/src/lib/dns/tests/master_lexer_state_unittest.cc
new file mode 100644
index 0000000..e810136
--- /dev/null
+++ b/src/lib/dns/tests/master_lexer_state_unittest.cc
@@ -0,0 +1,607 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/master_lexer.h>
+#include <dns/master_lexer_inputsource.h>
+#include <dns/master_lexer_state.h>
+
+#include <gtest/gtest.h>
+
+#include <sstream>
+
+using namespace isc::dns;
+using namespace master_lexer_internal;
+
+namespace {
+typedef MasterToken Token; // shortcut
+
+class MasterLexerStateTest : public ::testing::Test {
+protected:
+ MasterLexerStateTest() : common_options(MasterLexer::INITIAL_WS),
+ s_null(NULL),
+ s_crlf(State::getInstance(State::CRLF)),
+ s_string(State::getInstance(State::String)),
+ s_qstring(State::getInstance(State::QString)),
+ s_number(State::getInstance(State::Number)),
+ options(MasterLexer::NONE),
+ orig_options(options)
+ {}
+
+ // Specify INITIAL_WS as common initial options.
+ const MasterLexer::Options common_options;
+ MasterLexer lexer;
+ const State* const s_null;
+ const State& s_crlf;
+ const State& s_string;
+ const State& s_qstring;
+ const State& s_number;
+ std::stringstream ss;
+ MasterLexer::Options options, orig_options;
+};
+
+// Common check for the end-of-file condition.
+// Token is set to END_OF_FILE, and the lexer was NOT last eol state.
+// Passed state can be any valid one; they are stateless, just providing the
+// interface for inspection.
+void
+eofCheck(const State& state, MasterLexer& lexer) {
+ EXPECT_EQ(Token::END_OF_FILE, state.getToken(lexer).getType());
+ EXPECT_FALSE(state.wasLastEOL(lexer));
+}
+
+TEST_F(MasterLexerStateTest, startAndEnd) {
+ // A simple case: the input is empty, so we begin with start and
+ // are immediately done.
+ lexer.pushSource(ss);
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ eofCheck(s_crlf, lexer);
+}
+
+TEST_F(MasterLexerStateTest, startToEOL) {
+ ss << "\n";
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_TRUE(s_crlf.wasLastEOL(lexer));
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+
+ // The next lexer session will reach EOF. Same eof check should pass.
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ eofCheck(s_crlf, lexer);
+}
+
+TEST_F(MasterLexerStateTest, space) {
+ // repeat '\t\n' twice (see below), then space after EOL
+ ss << " \t\n\t\n ";
+ lexer.pushSource(ss);
+
+ // by default space characters and tabs will be ignored. We check this
+ // twice; at the second iteration, it's a white space at the beginning
+ // of line, but since we don't specify INITIAL_WS option, it's treated as
+ // normal space and ignored.
+ for (size_t i = 0; i < 2; ++i) {
+ EXPECT_EQ(s_null, State::start(lexer, MasterLexer::NONE));
+ EXPECT_TRUE(s_crlf.wasLastEOL(lexer));
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+ }
+
+ // Now we specify the INITIAL_WS option. It will be recognized and the
+ // corresponding token will be returned.
+ EXPECT_EQ(s_null, State::start(lexer, MasterLexer::INITIAL_WS));
+ EXPECT_FALSE(s_crlf.wasLastEOL(lexer));
+ EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType());
+}
+
+TEST_F(MasterLexerStateTest, parentheses) {
+ ss << "\n(\na\n )\n "; // 1st \n is to check if 'was EOL' is set to false
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // handle \n
+
+ // Now handle '('. It skips \n and recognize 'a' as string
+ EXPECT_EQ(0, s_crlf.getParenCount(lexer)); // check pre condition
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ EXPECT_EQ(1, s_crlf.getParenCount(lexer)); // check post condition
+ EXPECT_FALSE(s_crlf.wasLastEOL(lexer));
+
+ // skip 'a'
+ s_string.handle(lexer);
+
+ // Then handle ')'. '\n' before ')' isn't recognized because
+ // it's canceled due to the '('. Likewise, the space after the '\n'
+ // shouldn't be recognized but should be just ignored.
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(0, s_crlf.getParenCount(lexer));
+
+ // Now, temporarily disabled options are restored: Both EOL and the
+ // initial WS are recognized
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType());
+}
+
+TEST_F(MasterLexerStateTest, nestedParentheses) {
+ // This is an unusual, but allowed (in this implementation) case.
+ ss << "(a(b)\n c)\n ";
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume '('
+ s_string.handle(lexer); // consume 'a'
+ EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume '('
+ s_string.handle(lexer); // consume 'b'
+ EXPECT_EQ(2, s_crlf.getParenCount(lexer)); // now the count is 2
+
+ // Close the inner most parentheses. count will be decreased, but option
+ // shouldn't be restored yet, so the intermediate EOL or initial WS won't
+ // be recognized.
+ EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume ')'
+ s_string.handle(lexer); // consume 'c'
+ EXPECT_EQ(1, s_crlf.getParenCount(lexer));
+
+ // Close the outermost parentheses. count will be reset to 0, and original
+ // options are restored.
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+
+ // Now, temporarily disabled options are restored: Both EOL and the
+ // initial WS are recognized
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType());
+}
+
+TEST_F(MasterLexerStateTest, unbalancedParentheses) {
+ // Only closing paren is provided. We prepend a \n to check if it's
+ // correctly canceled after detecting the error.
+ ss << "\n)";
+ ss << "(a";
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // consume '\n'
+ EXPECT_TRUE(s_crlf.wasLastEOL(lexer)); // this \n was remembered
+
+ // Now checking ')'. The result should be error, count shouldn't be
+ // changed. "last EOL" should be canceled.
+ EXPECT_EQ(0, s_crlf.getParenCount(lexer));
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(0, s_crlf.getParenCount(lexer));
+ ASSERT_EQ(Token::ERROR, s_crlf.getToken(lexer).getType());
+ EXPECT_EQ(Token::UNBALANCED_PAREN, s_crlf.getToken(lexer).getErrorCode());
+ EXPECT_FALSE(s_crlf.wasLastEOL(lexer));
+
+ // Reach EOF with a dangling open parenthesis.
+ EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume '('
+ s_string.handle(lexer); // consume 'a'
+ EXPECT_EQ(1, s_crlf.getParenCount(lexer));
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // reach EOF
+ ASSERT_EQ(Token::ERROR, s_crlf.getToken(lexer).getType());
+ EXPECT_EQ(Token::UNBALANCED_PAREN, s_crlf.getToken(lexer).getErrorCode());
+ EXPECT_EQ(0, s_crlf.getParenCount(lexer)); // should be reset to 0
+}
+
+TEST_F(MasterLexerStateTest, startToComment) {
+ // Begin with 'start', detect space, then encounter a comment. Skip
+ // the rest of the line, and recognize the new line. Note that the
+ // second ';' is simply ignored.
+ ss << " ;a;\n";
+ ss << ";a;"; // Likewise, but the comment ends with EOF.
+ lexer.pushSource(ss);
+
+ // Initial whitespace (asked for in common_options)
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType());
+ // Comment ending with EOL
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+
+ // Comment ending with EOF
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType());
+}
+
+TEST_F(MasterLexerStateTest, commentAfterParen) {
+ // comment after an opening parenthesis. The code that is tested by
+ // other tests should also ensure that it works correctly, but we
+ // check it explicitly.
+ ss << "( ;this is a comment\na)\n";
+ lexer.pushSource(ss);
+
+ // consume '(', skip comments, consume 'a', then consume ')'
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer);
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+}
+
+TEST_F(MasterLexerStateTest, crlf) {
+ ss << "\r\n"; // case 1
+ ss << "\r "; // case 2
+ ss << "\r;comment\na"; // case 3
+ ss << "\r"; // case 4
+ lexer.pushSource(ss);
+
+ // 1. A sequence of \r, \n is recognized as a single 'end-of-line'
+ EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r'
+ s_crlf.handle(lexer); // recognize '\n'
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+ EXPECT_TRUE(s_crlf.wasLastEOL(lexer));
+
+ // 2. Single '\r' (not followed by \n) is recognized as a single
+ // 'end-of-line'. then there will be "initial WS"
+ EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r'
+ // see ' ', "unget" it
+ s_crlf.handle(lexer);
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // recognize ' '
+ EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType());
+
+ // 3. comment between \r and \n
+ EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r'
+ // skip comments, recognize '\n'
+ s_crlf.handle(lexer);
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // skip 'a'
+
+ // 4. \r then EOF
+ EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r'
+ // see EOF, then "unget" it
+ s_crlf.handle(lexer);
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // recognize EOF
+ EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType());
+}
+
+// Commonly used check for string related test cases, checking if the given
+// token has expected values.
+void
+stringTokenCheck(const std::string& expected, const MasterToken& token,
+ bool quoted = false)
+{
+ EXPECT_EQ(quoted ? Token::QSTRING : Token::STRING, token.getType());
+ EXPECT_EQ(expected, token.getString());
+ const std::string actual(token.getStringRegion().beg,
+ token.getStringRegion().beg +
+ token.getStringRegion().len);
+ EXPECT_EQ(expected, actual);
+
+ // There should be "hidden" nul-terminator after the string data.
+ ASSERT_NE(static_cast<const char*>(NULL), token.getStringRegion().beg);
+ EXPECT_EQ(0, *(token.getStringRegion().beg + token.getStringRegion().len));
+}
+
+TEST_F(MasterLexerStateTest, string) {
+ // Check with simple strings followed by separate characters
+ ss << "followed-by-EOL\n";
+ ss << "followed-by-CR\r";
+ ss << "followed-by-space ";
+ ss << "followed-by-tab\t";
+ ss << "followed-by-comment;this is comment and ignored\n";
+ ss << "followed-by-paren(closing)";
+ ss << "followed-by-EOF";
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see \n
+ EXPECT_FALSE(s_string.wasLastEOL(lexer));
+ stringTokenCheck("followed-by-EOL", s_string.getToken(lexer));
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // skip \n
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see \r
+ stringTokenCheck("followed-by-CR", s_string.getToken(lexer));
+ EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // handle \r...
+ s_crlf.handle(lexer); // ...and skip it
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' '
+ stringTokenCheck("followed-by-space", s_string.getToken(lexer));
+
+ // skip ' ', then recognize the next string
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see \t
+ stringTokenCheck("followed-by-tab", s_string.getToken(lexer));
+
+ // skip \t, then recognize the next string
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see comment
+ stringTokenCheck("followed-by-comment", s_string.getToken(lexer));
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // skip \n after it
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see '('
+ stringTokenCheck("followed-by-paren", s_string.getToken(lexer));
+ EXPECT_EQ(&s_string, State::start(lexer, common_options)); // str in ()
+ s_string.handle(lexer); // recognize the str, see ')'
+ stringTokenCheck("closing", s_string.getToken(lexer));
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see EOF
+ stringTokenCheck("followed-by-EOF", s_string.getToken(lexer));
+}
+
+TEST_F(MasterLexerStateTest, stringEscape) {
+ // some of the separate characters should be considered part of the
+ // string if escaped.
+ ss << "escaped\\ space ";
+ ss << "escaped\\\ttab ";
+ ss << "escaped\\(paren ";
+ ss << "escaped\\)close ";
+ ss << "escaped\\;comment ";
+ ss << "escaped\\\\ backslash "; // second '\' shouldn't escape ' '
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("escaped\\ space", s_string.getToken(lexer));
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("escaped\\\ttab", s_string.getToken(lexer));
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("escaped\\(paren", s_string.getToken(lexer));
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("escaped\\)close", s_string.getToken(lexer));
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("escaped\\;comment", s_string.getToken(lexer));
+
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' ' in mid
+ stringTokenCheck("escaped\\\\", s_string.getToken(lexer));
+
+ // Confirm the word that follows the escaped '\' is correctly recognized.
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("backslash", s_string.getToken(lexer));
+}
+
+TEST_F(MasterLexerStateTest, quotedString) {
+ ss << "\"ignore-quotes\"\n";
+ ss << "\"quoted string\" "; // space is part of the qstring
+ ss << "\"\" "; // empty quoted string
+ // also check other separator characters. note that \r doesn't cause
+ // UNBALANCED_QUOTES. Not sure if it's intentional, but that's how the
+ // BIND 9 version works, so we follow it (it should be too minor to matter
+ // in practice anyway)
+ ss << "\"quoted()\t\rstring\" ";
+ ss << "\"escape\\ in quote\" ";
+ ss << "\"escaped\\\"\" ";
+ ss << "\"escaped backslash\\\\\" ";
+ ss << "\"no;comment\"";
+ lexer.pushSource(ss);
+
+ // by default, '"' is unexpected (when QSTRING is not specified),
+ // and it returns MasterToken::UNEXPECTED_QUOTES.
+ EXPECT_EQ(s_null, State::start(lexer, common_options));
+ EXPECT_EQ(Token::UNEXPECTED_QUOTES, s_string.getToken(lexer).getErrorCode());
+ // Read it as a QSTRING.
+ s_qstring.handle(lexer); // recognize quoted str, see \n
+ stringTokenCheck("ignore-quotes", s_qstring.getToken(lexer), true);
+ EXPECT_EQ(s_null, State::start(lexer, common_options)); // skip \n after it
+ EXPECT_TRUE(s_string.wasLastEOL(lexer));
+
+ // If QSTRING is specified in option, '"' is regarded as a beginning of
+ // a quoted string.
+ const MasterLexer::Options options = common_options | MasterLexer::QSTRING;
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ EXPECT_FALSE(s_string.wasLastEOL(lexer)); // EOL is canceled due to '"'
+ s_qstring.handle(lexer);
+ stringTokenCheck("quoted string", s_string.getToken(lexer), true);
+
+ // Empty string is okay as qstring
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ stringTokenCheck("", s_string.getToken(lexer), true);
+
+ // Also checks other separator characters within a qstring
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ stringTokenCheck("quoted()\t\rstring", s_string.getToken(lexer), true);
+
+ // escape character mostly doesn't have any effect in the qstring
+ // processing
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ stringTokenCheck("escape\\ in quote", s_string.getToken(lexer), true);
+
+ // The only exception is the quotation mark itself. Note that the escape
+ // only works on the quotation mark immediately after it.
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ stringTokenCheck("escaped\"", s_string.getToken(lexer), true);
+
+ // quoted '\' then '"'. Unlike the previous case '"' shouldn't be
+ // escaped.
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ stringTokenCheck("escaped backslash\\\\", s_string.getToken(lexer), true);
+
+ // ';' has no meaning in a quoted string (not indicating a comment)
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ stringTokenCheck("no;comment", s_string.getToken(lexer), true);
+}
+
+TEST_F(MasterLexerStateTest, brokenQuotedString) {
+ ss << "\"unbalanced-quote\n";
+ ss << "\"quoted\\\n\" ";
+ ss << "\"unclosed quote and EOF";
+ lexer.pushSource(ss);
+
+ // EOL is encountered without closing the quote
+ const MasterLexer::Options options = common_options | MasterLexer::QSTRING;
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ ASSERT_EQ(Token::ERROR, s_qstring.getToken(lexer).getType());
+ EXPECT_EQ(Token::UNBALANCED_QUOTES,
+ s_qstring.getToken(lexer).getErrorCode());
+ // We can resume after the error from the '\n'
+ EXPECT_EQ(s_null, State::start(lexer, options));
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+
+ // \n is okay in a quoted string if escaped
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ stringTokenCheck("quoted\\\n", s_string.getToken(lexer), true);
+
+ // EOF is encountered without closing the quote
+ EXPECT_EQ(&s_qstring, State::start(lexer, options));
+ s_qstring.handle(lexer);
+ ASSERT_EQ(Token::ERROR, s_qstring.getToken(lexer).getType());
+ EXPECT_EQ(Token::UNEXPECTED_END, s_qstring.getToken(lexer).getErrorCode());
+ // If we continue we'll simply see the EOF
+ EXPECT_EQ(s_null, State::start(lexer, options));
+ EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType());
+}
+
+TEST_F(MasterLexerStateTest, basicNumbers) {
+ ss << "0 ";
+ ss << "1 ";
+ ss << "12345 ";
+ ss << "4294967295 "; // 2^32-1
+ ss << "4294967296 "; // Out of range
+ ss << "340282366920938463463374607431768211456 ";
+ // Very much out of range (2^128)
+ ss << "005 "; // Leading zeroes are ignored
+ ss << "42;asdf\n"; // Number with comment
+ ss << "37"; // Simple number again, here to make
+ // sure none of the above messed up
+ // the tokenizer
+ lexer.pushSource(ss);
+
+ // Ask the lexer to recognize numbers as well
+ const MasterLexer::Options options = common_options | MasterLexer::NUMBER;
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(0, s_number.getToken(lexer).getNumber());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(1, s_number.getToken(lexer).getNumber());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(12345, s_number.getToken(lexer).getNumber());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(4294967295u, s_number.getToken(lexer).getNumber());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(Token::NUMBER_OUT_OF_RANGE,
+ s_number.getToken(lexer).getErrorCode());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(Token::NUMBER_OUT_OF_RANGE,
+ s_number.getToken(lexer).getErrorCode());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(5, s_number.getToken(lexer).getNumber());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(42, s_number.getToken(lexer).getNumber());
+
+ EXPECT_EQ(s_null, State::start(lexer, options));
+ EXPECT_TRUE(s_crlf.wasLastEOL(lexer));
+ EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType());
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ EXPECT_EQ(37, s_number.getToken(lexer).getNumber());
+
+ // If we continue we'll simply see the EOF
+ EXPECT_EQ(s_null, State::start(lexer, options));
+ EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType());
+}
+
+// Test tokens that look like (or start out as) numbers,
+// but turn out to be strings. Tests include escaped characters.
+TEST_F(MasterLexerStateTest, stringNumbers) {
+ ss << "123 "; // Should be read as a string if the
+ // NUMBER option is not given
+ ss << "-1 "; // Negative numbers are interpreted
+ // as strings (unsigned integers only)
+ ss << "123abc456 "; // 'Numbers' containing non-digits should
+ // be interpreted as strings
+ ss << "123\\456 "; // Numbers containing escaped digits are
+ // interpreted as strings
+ ss << "3scaped\\ space ";
+ ss << "3scaped\\\ttab ";
+ ss << "3scaped\\(paren ";
+ ss << "3scaped\\)close ";
+ ss << "3scaped\\;comment ";
+ ss << "3scaped\\\\ 8ackslash "; // second '\' shouldn't escape ' '
+
+ lexer.pushSource(ss);
+
+ // Note that common_options does not include MasterLexer::NUMBER,
+ // so the token should be recognized as a string
+ EXPECT_EQ(&s_string, State::start(lexer, common_options));
+ s_string.handle(lexer);
+ stringTokenCheck("123", s_string.getToken(lexer), false);
+
+ // Ask the lexer to recognize numbers as well
+ const MasterLexer::Options options = common_options | MasterLexer::NUMBER;
+
+ EXPECT_EQ(&s_string, State::start(lexer, options));
+ s_string.handle(lexer);
+ stringTokenCheck("-1", s_string.getToken(lexer), false);
+
+ // Starts out as a number, but ends up being a string
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ stringTokenCheck("123abc456", s_number.getToken(lexer), false);
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer);
+ stringTokenCheck("123\\456", s_number.getToken(lexer), false);
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("3scaped\\ space", s_number.getToken(lexer));
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("3scaped\\\ttab", s_number.getToken(lexer));
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("3scaped\\(paren", s_number.getToken(lexer));
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("3scaped\\)close", s_number.getToken(lexer));
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("3scaped\\;comment", s_number.getToken(lexer));
+
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer); // recognize str, see ' ' in mid
+ stringTokenCheck("3scaped\\\\", s_number.getToken(lexer));
+
+ // Confirm the word that follows the escaped '\' is correctly recognized.
+ EXPECT_EQ(&s_number, State::start(lexer, options));
+ s_number.handle(lexer); // recognize str, see ' ' at end
+ stringTokenCheck("8ackslash", s_number.getToken(lexer));
+
+ // If we continue we'll simply see the EOF
+ EXPECT_EQ(s_null, State::start(lexer, options));
+ EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType());
+}
+
+} // end anonymous namespace
+
diff --git a/src/lib/dns/tests/master_lexer_token_unittest.cc b/src/lib/dns/tests/master_lexer_token_unittest.cc
new file mode 100644
index 0000000..2167a9f
--- /dev/null
+++ b/src/lib/dns/tests/master_lexer_token_unittest.cc
@@ -0,0 +1,162 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/master_lexer.h>
+
+#include <gtest/gtest.h>
+
+#include <string>
+
+using namespace isc::dns;
+
+namespace {
+
+const char TEST_STRING[] = "string token";
+// This excludes the ending \0 character
+const size_t TEST_STRING_LEN = sizeof(TEST_STRING) - 1;
+
+class MasterLexerTokenTest : public ::testing::Test {
+protected:
+ MasterLexerTokenTest() :
+ token_eof(MasterToken::END_OF_FILE),
+ token_str(TEST_STRING, TEST_STRING_LEN),
+ token_num(42),
+ token_err(MasterToken::UNEXPECTED_END)
+ {}
+
+ const MasterToken token_eof; // an example of non-value type token
+ const MasterToken token_str;
+ const MasterToken token_num;
+ const MasterToken token_err;
+};
+
+
+TEST_F(MasterLexerTokenTest, strings) {
+ // basic construction and getter checks
+ EXPECT_EQ(MasterToken::STRING, token_str.getType());
+ EXPECT_EQ(std::string("string token"), token_str.getString());
+ std::string strval = "dummy"; // this should be replaced
+ token_str.getString(strval);
+ EXPECT_EQ(std::string("string token"), strval);
+ const MasterToken::StringRegion str_region =
+ token_str.getStringRegion();
+ EXPECT_EQ(TEST_STRING, str_region.beg);
+ EXPECT_EQ(TEST_STRING_LEN, str_region.len);
+
+ // Even if the stored string contains a nul character (in this case,
+ // it happens to be at the end of the string, but could be in the middle),
+ // getString() should return a string object containing the nul.
+ std::string expected_str("string token");
+ expected_str.push_back('\0');
+ EXPECT_EQ(expected_str,
+ MasterToken(TEST_STRING, TEST_STRING_LEN + 1).getString());
+ MasterToken(TEST_STRING, TEST_STRING_LEN + 1).getString(strval);
+ EXPECT_EQ(expected_str, strval);
+
+ // Construct type of qstring
+ EXPECT_EQ(MasterToken::QSTRING,
+ MasterToken(TEST_STRING, sizeof(TEST_STRING), true).
+ getType());
+ // if we explicitly set 'quoted' to false, it should be normal string
+ EXPECT_EQ(MasterToken::STRING,
+ MasterToken(TEST_STRING, sizeof(TEST_STRING), false).
+ getType());
+
+ // getString/StringRegion() aren't allowed for non string(-variant) types
+ EXPECT_THROW(token_eof.getString(), isc::InvalidOperation);
+ EXPECT_THROW(token_eof.getString(strval), isc::InvalidOperation);
+ EXPECT_THROW(token_num.getString(), isc::InvalidOperation);
+ EXPECT_THROW(token_num.getString(strval), isc::InvalidOperation);
+ EXPECT_THROW(token_eof.getStringRegion(), isc::InvalidOperation);
+ EXPECT_THROW(token_num.getStringRegion(), isc::InvalidOperation);
+}
+
+TEST_F(MasterLexerTokenTest, numbers) {
+ EXPECT_EQ(42, token_num.getNumber());
+ EXPECT_EQ(MasterToken::NUMBER, token_num.getType());
+
+ // It's copyable and assignable.
+ MasterToken token(token_num);
+ EXPECT_EQ(42, token.getNumber());
+ EXPECT_EQ(MasterToken::NUMBER, token.getType());
+
+ token = token_num;
+ EXPECT_EQ(42, token.getNumber());
+ EXPECT_EQ(MasterToken::NUMBER, token.getType());
+
+ // it's okay to replace it with a different type of token
+ token = token_eof;
+ EXPECT_EQ(MasterToken::END_OF_FILE, token.getType());
+
+ // Possible max value
+ token = MasterToken(0xffffffff);
+ EXPECT_EQ(4294967295u, token.getNumber());
+
+ // getNumber() isn't allowed for non number types
+ EXPECT_THROW(token_eof.getNumber(), isc::InvalidOperation);
+ EXPECT_THROW(token_str.getNumber(), isc::InvalidOperation);
+}
+
+TEST_F(MasterLexerTokenTest, novalues) {
+ // Just checking we can construct them and getType() returns correct value.
+ EXPECT_EQ(MasterToken::END_OF_FILE, token_eof.getType());
+ EXPECT_EQ(MasterToken::END_OF_LINE,
+ MasterToken(MasterToken::END_OF_LINE).getType());
+ EXPECT_EQ(MasterToken::INITIAL_WS,
+ MasterToken(MasterToken::INITIAL_WS).getType());
+
+ // Special types of tokens cannot have value-based types
+ EXPECT_THROW(MasterToken t(MasterToken::STRING), isc::InvalidParameter);
+ EXPECT_THROW(MasterToken t(MasterToken::QSTRING), isc::InvalidParameter);
+ EXPECT_THROW(MasterToken t(MasterToken::NUMBER), isc::InvalidParameter);
+ EXPECT_THROW(MasterToken t(MasterToken::ERROR), isc::InvalidParameter);
+}
+
+TEST_F(MasterLexerTokenTest, errors) {
+ EXPECT_EQ(MasterToken::ERROR, token_err.getType());
+ EXPECT_EQ(MasterToken::UNEXPECTED_END, token_err.getErrorCode());
+ EXPECT_EQ("unexpected end of input", token_err.getErrorText());
+ EXPECT_EQ("lexer not started", MasterToken(MasterToken::NOT_STARTED).
+ getErrorText());
+ EXPECT_EQ("unbalanced parentheses",
+ MasterToken(MasterToken::UNBALANCED_PAREN).
+ getErrorText());
+ EXPECT_EQ("unbalanced quotes", MasterToken(MasterToken::UNBALANCED_QUOTES).
+ getErrorText());
+ EXPECT_EQ("no token produced", MasterToken(MasterToken::NO_TOKEN_PRODUCED).
+ getErrorText());
+ EXPECT_EQ("number out of range",
+ MasterToken(MasterToken::NUMBER_OUT_OF_RANGE).
+ getErrorText());
+ EXPECT_EQ("not a valid number",
+ MasterToken(MasterToken::BAD_NUMBER).getErrorText());
+ EXPECT_EQ("unexpected quotes",
+ MasterToken(MasterToken::UNEXPECTED_QUOTES).getErrorText());
+
+ // getErrorCode/Text() isn't allowed for non number types
+ EXPECT_THROW(token_num.getErrorCode(), isc::InvalidOperation);
+ EXPECT_THROW(token_num.getErrorText(), isc::InvalidOperation);
+
+ // Only the pre-defined error code is accepted. Hardcoding '8' (max code
+ // + 1) is intentional; it'd be actually better if we notice it when we
+ // update the enum list (which shouldn't happen too often).
+ //
+ // Note: if you fix this testcase, you probably want to update the
+ // getErrorText() tests above too.
+ EXPECT_THROW(MasterToken(MasterToken::ErrorCode(8)),
+ isc::InvalidParameter);
+
+ // Check the coexistence of "from number" and "from error-code"
+ // constructors won't cause confusion.
+ EXPECT_EQ(MasterToken::NUMBER,
+ MasterToken(static_cast<uint32_t>(MasterToken::NOT_STARTED)).
+ getType());
+}
+}
diff --git a/src/lib/dns/tests/master_lexer_unittest.cc b/src/lib/dns/tests/master_lexer_unittest.cc
new file mode 100644
index 0000000..7bebb48
--- /dev/null
+++ b/src/lib/dns/tests/master_lexer_unittest.cc
@@ -0,0 +1,521 @@
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/master_lexer.h>
+#include <dns/master_lexer_state.h>
+
+#include <gtest/gtest.h>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include <string>
+#include <sstream>
+
+using namespace isc::dns;
+using std::string;
+using std::stringstream;
+using boost::lexical_cast;
+using boost::scoped_ptr;
+using master_lexer_internal::State;
+
+namespace {
+
+class MasterLexerTest : public ::testing::Test {
+protected:
+ MasterLexerTest() :
+ expected_stream_name("stream-" + lexical_cast<string>(&ss))
+ {}
+
+ MasterLexer lexer;
+ stringstream ss;
+ const string expected_stream_name;
+};
+
+// Commonly used check case where the input sources stack is empty.
+void
+checkEmptySource(const MasterLexer& lexer) {
+ EXPECT_TRUE(lexer.getSourceName().empty());
+ EXPECT_EQ(0, lexer.getSourceLine());
+ EXPECT_EQ(0, lexer.getPosition());
+}
+
+TEST_F(MasterLexerTest, preOpen) {
+ // Initially sources stack is empty.
+ checkEmptySource(lexer);
+}
+
+TEST_F(MasterLexerTest, pushStream) {
+ EXPECT_EQ(0, lexer.getSourceCount());
+ ss << "test";
+ lexer.pushSource(ss);
+ EXPECT_EQ(expected_stream_name, lexer.getSourceName());
+ EXPECT_EQ(1, lexer.getSourceCount());
+ EXPECT_EQ(4, lexer.getTotalSourceSize()); // 4 = len("test")
+
+ // From the point of view of this test, we only have to check (though
+ // indirectly) getSourceLine calls InputSource::getCurrentLine. It should
+ // return 1 initially.
+ EXPECT_EQ(1, lexer.getSourceLine());
+
+ // By popping it the stack will be empty again.
+ lexer.popSource();
+ EXPECT_EQ(0, lexer.getSourceCount());
+ checkEmptySource(lexer);
+ EXPECT_EQ(4, lexer.getTotalSourceSize()); // this shouldn't change
+}
+
+TEST_F(MasterLexerTest, pushStreamFail) {
+ // Pretend a "bad" thing happened in the stream. This will make the
+ // initialization throw an exception.
+ ss << "test";
+ ss.setstate(std::ios_base::badbit);
+
+ EXPECT_THROW(lexer.pushSource(ss), isc::Unexpected);
+}
+
+TEST_F(MasterLexerTest, pushFile) {
+ // We use zone file (-like) data, but in this test that actually doesn't
+ // matter.
+ EXPECT_EQ(0, lexer.getSourceCount());
+ EXPECT_TRUE(lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt"));
+ EXPECT_EQ(1, lexer.getSourceCount());
+ EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", lexer.getSourceName());
+ EXPECT_EQ(1, lexer.getSourceLine());
+
+ // 143 = size of the test zone file. hardcode it assuming it won't change
+ // too often.
+ EXPECT_EQ(143, lexer.getTotalSourceSize());
+
+ lexer.popSource();
+ checkEmptySource(lexer);
+ EXPECT_EQ(0, lexer.getSourceCount());
+ EXPECT_EQ(143, lexer.getTotalSourceSize()); // this shouldn't change
+
+ // If we give a non NULL string pointer, its content will be intact
+ // if pushSource succeeds.
+ std::string error_txt = "dummy";
+ EXPECT_TRUE(lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt",
+ &error_txt));
+ EXPECT_EQ("dummy", error_txt);
+}
+
+TEST_F(MasterLexerTest, pushBadFileName) {
+ EXPECT_THROW(lexer.pushSource(NULL), isc::InvalidParameter);
+}
+
+TEST_F(MasterLexerTest, pushFileFail) {
+ // The file to be pushed doesn't exist. pushSource() fails and
+ // some non empty error string should be set.
+ std::string error_txt;
+ EXPECT_TRUE(error_txt.empty());
+ EXPECT_FALSE(lexer.pushSource("no-such-file", &error_txt));
+ EXPECT_FALSE(error_txt.empty());
+
+ // It's safe to pass NULL error_txt (either explicitly or implicitly as
+ // the default)
+ EXPECT_FALSE(lexer.pushSource("no-such-file", NULL));
+ EXPECT_FALSE(lexer.pushSource("no-such-file"));
+}
+
+TEST_F(MasterLexerTest, nestedPush) {
+ const string test_txt = "test";
+ ss << test_txt;
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(test_txt.size(), lexer.getTotalSourceSize());
+ EXPECT_EQ(0, lexer.getPosition());
+
+ EXPECT_EQ(expected_stream_name, lexer.getSourceName());
+
+ // Read the string; getPosition() should reflect that.
+ EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType());
+ EXPECT_EQ(test_txt.size(), lexer.getPosition());
+
+ // We can push another source without popping the previous one.
+ lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt");
+ EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", lexer.getSourceName());
+ EXPECT_EQ(143 + test_txt.size(),
+ lexer.getTotalSourceSize()); // see above for magic nums
+
+ // the next token should be the EOL (skipping a comment line), its
+ // position in the file is 35 (hardcoded).
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ EXPECT_EQ(test_txt.size() + 35, lexer.getPosition());
+
+ // popSource() works on the "topmost" (last-pushed) source
+ lexer.popSource();
+ EXPECT_EQ(expected_stream_name, lexer.getSourceName());
+
+ // pop shouldn't change the total size and the current position
+ EXPECT_EQ(143 + test_txt.size(), lexer.getTotalSourceSize());
+ EXPECT_EQ(test_txt.size() + 35, lexer.getPosition());
+
+ lexer.popSource();
+ EXPECT_TRUE(lexer.getSourceName().empty());
+
+ // size and position still shouldn't change
+ EXPECT_EQ(143 + test_txt.size(), lexer.getTotalSourceSize());
+ EXPECT_EQ(test_txt.size() + 35, lexer.getPosition());
+}
+
+TEST_F(MasterLexerTest, unknownSourceSize) {
+ // Similar to the previous case, but the size of the second source
+ // will be considered "unknown" (by emulating an error).
+ ss << "test";
+ lexer.pushSource(ss);
+ EXPECT_EQ(4, lexer.getTotalSourceSize());
+
+ stringstream ss2;
+ ss2.setstate(std::ios_base::failbit); // this will make the size unknown
+ lexer.pushSource(ss2);
+ // Then the total size is also unknown.
+ EXPECT_EQ(MasterLexer::SOURCE_SIZE_UNKNOWN, lexer.getTotalSourceSize());
+
+ // Even if we pop that source, the size is still unknown.
+ lexer.popSource();
+ EXPECT_EQ(MasterLexer::SOURCE_SIZE_UNKNOWN, lexer.getTotalSourceSize());
+}
+
+TEST_F(MasterLexerTest, invalidPop) {
+ // popSource() cannot be called if the sources stack is empty.
+ EXPECT_THROW(lexer.popSource(), isc::InvalidOperation);
+}
+
+// Test it is not possible to get token when no source is available.
+TEST_F(MasterLexerTest, noSource) {
+ EXPECT_THROW(lexer.getNextToken(), isc::InvalidOperation);
+}
+
+// Test getting some tokens. It also check basic behavior of getPosition().
+TEST_F(MasterLexerTest, getNextToken) {
+ ss << "\n \n\"STRING\"\n";
+ lexer.pushSource(ss);
+
+ // First, the newline should get out.
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ EXPECT_EQ(1, lexer.getPosition());
+ // Then the whitespace, if we specify the option.
+ EXPECT_EQ(MasterToken::INITIAL_WS,
+ lexer.getNextToken(MasterLexer::INITIAL_WS).getType());
+ EXPECT_EQ(2, lexer.getPosition());
+ // The newline
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ EXPECT_EQ(5, lexer.getPosition()); // 1st \n + 3 spaces, then 2nd \n
+ // The (quoted) string
+ EXPECT_EQ(MasterToken::QSTRING,
+ lexer.getNextToken(MasterLexer::QSTRING).getType());
+ EXPECT_EQ(5 + 8, lexer.getPosition()); // 8 = len("STRING') + quotes
+
+ // And the end of line and file
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ EXPECT_EQ(5 + 8 + 1, lexer.getPosition()); // previous + 3rd \n
+ EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType());
+ EXPECT_EQ(5 + 8 + 1, lexer.getPosition()); // position doesn't change
+}
+
+// Test we correctly find end of file.
+TEST_F(MasterLexerTest, eof) {
+ // Let the ss empty.
+ lexer.pushSource(ss);
+
+ // The first one is found to be EOF
+ EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType());
+ // And it stays on EOF for any following attempts
+ EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType());
+ // And we can step back one token, but that is the EOF too.
+ lexer.ungetToken();
+ EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType());
+}
+
+// Check we properly return error when there's an opened parentheses and no
+// closing one
+TEST_F(MasterLexerTest, getUnbalancedParen) {
+ ss << "(string";
+ lexer.pushSource(ss);
+
+ // The string gets out first
+ EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType());
+ // Then an unbalanced parenthesis
+ EXPECT_EQ(MasterToken::UNBALANCED_PAREN,
+ lexer.getNextToken().getErrorCode());
+ // And then EOF
+ EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType());
+}
+
+// Check we properly return error when there's an opened quoted string and no
+// closing one
+TEST_F(MasterLexerTest, getUnbalancedString) {
+ ss << "\"string";
+ lexer.pushSource(ss);
+
+ // Then an unbalanced qstring (reported as an unexpected end)
+ EXPECT_EQ(MasterToken::UNEXPECTED_END,
+ lexer.getNextToken(MasterLexer::QSTRING).getErrorCode());
+ // And then EOF
+ EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType());
+}
+
+// Test ungetting tokens works. Also check getPosition() is adjusted
+TEST_F(MasterLexerTest, ungetToken) {
+ ss << "\n (\"string\"\n) more";
+ lexer.pushSource(ss);
+
+ // Try getting the newline
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ EXPECT_EQ(1, lexer.getPosition());
+ // Return it and get again
+ lexer.ungetToken();
+ EXPECT_EQ(0, lexer.getPosition());
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ EXPECT_EQ(1, lexer.getPosition());
+ // Get the string and return it back
+ EXPECT_EQ(MasterToken::QSTRING,
+ lexer.getNextToken(MasterLexer::QSTRING).getType());
+ EXPECT_EQ(string("\n (\"string\"").size(), lexer.getPosition());
+ lexer.ungetToken();
+ EXPECT_EQ(1, lexer.getPosition()); // back to just after 1st \n
+ // But if we change the options, it honors them
+ EXPECT_EQ(MasterToken::INITIAL_WS,
+ lexer.getNextToken(MasterLexer::QSTRING |
+ MasterLexer::INITIAL_WS).getType());
+ // Get to the "more" string
+ EXPECT_EQ(MasterToken::QSTRING,
+ lexer.getNextToken(MasterLexer::QSTRING).getType());
+ EXPECT_EQ(MasterToken::STRING,
+ lexer.getNextToken(MasterLexer::QSTRING).getType());
+ // Return it back. It should get inside the parentheses.
+ // Upon next attempt to get it again, the newline inside the parentheses
+ // should be still ignored.
+ lexer.ungetToken();
+ EXPECT_EQ(MasterToken::STRING,
+ lexer.getNextToken(MasterLexer::QSTRING).getType());
+}
+
+// Check ungetting token without overriding the start method. We also
+// check it works well with changing options between the calls.
+TEST_F(MasterLexerTest, ungetRealOptions) {
+ ss << " \n";
+ lexer.pushSource(ss);
+
+ // If we call it the usual way, it skips up to the newline and returns
+ // it
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+
+ // Now we return it. If we call it again, but with different options,
+ // we get the initial whitespace.
+ lexer.ungetToken();
+ EXPECT_EQ(MasterToken::INITIAL_WS,
+ lexer.getNextToken(MasterLexer::INITIAL_WS).getType());
+}
+
+// Check the initial whitespace is found even in the first line of included
+// file. It also confirms getPosition() works for multiple sources, each
+// of which is partially parsed.
+TEST_F(MasterLexerTest, includeAndInitialWS) {
+ ss << " \n";
+ lexer.pushSource(ss);
+
+ stringstream ss2;
+ ss2 << " \n";
+
+ EXPECT_EQ(MasterToken::INITIAL_WS,
+ lexer.getNextToken(MasterLexer::INITIAL_WS).getType());
+ EXPECT_EQ(1, lexer.getPosition());
+ lexer.pushSource(ss2);
+ EXPECT_EQ(MasterToken::INITIAL_WS,
+ lexer.getNextToken(MasterLexer::INITIAL_WS).getType());
+ EXPECT_EQ(2, lexer.getPosition()); // should be sum of pushed positions.
+}
+
+// Test only one token can be ungotten
+TEST_F(MasterLexerTest, ungetTwice) {
+ ss << "\n";
+ lexer.pushSource(ss);
+
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ // Unget the token. It can be done once
+ lexer.ungetToken();
+ // But not twice
+ EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation);
+}
+
+// Test we can't unget a token before we get one
+TEST_F(MasterLexerTest, ungetBeforeGet) {
+ lexer.pushSource(ss); // Just to eliminate the missing source problem
+ EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation);
+}
+
+// Test we can't unget a token after a source switch, even when we got
+// something before.
+TEST_F(MasterLexerTest, ungetAfterSwitch) {
+ ss << "\n\n";
+ lexer.pushSource(ss);
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ // Switch the source
+ std::stringstream ss2;
+ ss2 << "\n\n";
+ lexer.pushSource(ss2);
+ EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation);
+ // We can get from the new source
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+ // And when we drop the current source, we can't unget again
+ lexer.popSource();
+ EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation);
+}
+
+// Common checks for the case when getNextToken() should result in LexerError
+void
+lexerErrorCheck(MasterLexer& lexer, MasterToken::Type expect,
+ MasterToken::ErrorCode expected_error)
+{
+ bool thrown = false;
+ try {
+ lexer.getNextToken(expect);
+ } catch (const MasterLexer::LexerError& error) {
+ EXPECT_EQ(expected_error, error.token_.getErrorCode());
+ thrown = true;
+ }
+ EXPECT_TRUE(thrown);
+}
+
+// Common checks regarding expected/unexpected end-of-line
+//
+// The 'lexer' should be at a position before two consecutive '\n's.
+// The first one will be recognized, and the second one will be considered an
+// unexpected token. Then this helper consumes the second '\n', so the caller
+// can continue the test after these '\n's.
+void
+eolCheck(MasterLexer& lexer, MasterToken::Type expect) {
+ // If EOL is found and eol_ok is true, we get it.
+ EXPECT_EQ(MasterToken::END_OF_LINE,
+ lexer.getNextToken(expect, true).getType());
+ // We'll see the second '\n'; by default it will fail.
+ EXPECT_THROW(lexer.getNextToken(expect), MasterLexer::LexerError);
+ // Same if eol_ok is explicitly set to false. This also checks the
+ // offending '\n' was "ungotten".
+ EXPECT_THROW(lexer.getNextToken(expect, false), MasterLexer::LexerError);
+
+ // And also check the error token set in the exception object.
+ lexerErrorCheck(lexer, expect, MasterToken::UNEXPECTED_END);
+
+ // Then skip the 2nd '\n'
+ EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
+}
+
+// Common checks regarding expected/unexpected end-of-file
+//
+// The 'lexer' should be at a position just before an end-of-file.
+void
+eofCheck(MasterLexer& lexer, MasterToken::Type expect) {
+ EXPECT_EQ(MasterToken::END_OF_FILE,
+ lexer.getNextToken(expect, true).getType());
+ EXPECT_THROW(lexer.getNextToken(expect), MasterLexer::LexerError);
+ EXPECT_THROW(lexer.getNextToken(expect, false), MasterLexer::LexerError);
+}
+
+TEST_F(MasterLexerTest, getNextTokenString) {
+ ss << "normal-string\n";
+ ss << "\n";
+ ss << "another-string";
+ lexer.pushSource(ss);
+
+ // Normal successful case: Expecting a string and get one.
+ EXPECT_EQ("normal-string",
+ lexer.getNextToken(MasterToken::STRING).getString());
+ eolCheck(lexer, MasterToken::STRING);
+
+ // Same set of tests but for end-of-file
+ EXPECT_EQ("another-string",
+ lexer.getNextToken(MasterToken::STRING, true).getString());
+ eofCheck(lexer, MasterToken::STRING);
+}
+
+TEST_F(MasterLexerTest, getNextTokenQString) {
+ ss << "\"quoted-string\"\n";
+ ss << "\n";
+ ss << "normal-string";
+ lexer.pushSource(ss);
+
+ // Expecting a quoted string and get one.
+ EXPECT_EQ("quoted-string",
+ lexer.getNextToken(MasterToken::QSTRING).getString());
+ eolCheck(lexer, MasterToken::QSTRING);
+
+ // Expecting a quoted string but see a normal string. It's okay.
+ EXPECT_EQ("normal-string",
+ lexer.getNextToken(MasterToken::QSTRING).getString());
+ eofCheck(lexer, MasterToken::QSTRING);
+}
+
+TEST_F(MasterLexerTest, getNextTokenNumber) {
+ ss << "3600\n";
+ ss << "\n";
+ ss << "4294967296 "; // =2^32, out of range
+ ss << "not-a-number ";
+ ss << "123abc "; // starting with digits, but resulting in a string
+ ss << "86400";
+ lexer.pushSource(ss);
+
+ // Expecting a number string and get one.
+ EXPECT_EQ(3600,
+ lexer.getNextToken(MasterToken::NUMBER).getNumber());
+ eolCheck(lexer, MasterToken::NUMBER);
+
+ // Expecting a number, but it's too big for uint32.
+ lexerErrorCheck(lexer, MasterToken::NUMBER,
+ MasterToken::NUMBER_OUT_OF_RANGE);
+ // The token should have been "ungotten". Re-read and skip it.
+ EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType());
+
+ // Expecting a number, but see a string.
+ lexerErrorCheck(lexer, MasterToken::NUMBER, MasterToken::BAD_NUMBER);
+ // The unexpected string should have been "ungotten". Re-read and skip it.
+ EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType());
+
+ // Expecting a number, but see a string.
+ lexerErrorCheck(lexer, MasterToken::NUMBER, MasterToken::BAD_NUMBER);
+ // The unexpected string should have been "ungotten". Re-read and skip it.
+ EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType());
+
+ // Unless we specify NUMBER, decimal number string should be recognized
+ // as a string.
+ EXPECT_EQ("86400",
+ lexer.getNextToken(MasterToken::STRING).getString());
+ eofCheck(lexer, MasterToken::NUMBER);
+}
+
+TEST_F(MasterLexerTest, getNextTokenErrors) {
+ // Check miscellaneous error cases
+
+ ss << ") "; // unbalanced parenthesis
+ ss << "string-after-error ";
+ lexer.pushSource(ss);
+
+ // Only string/qstring/number can be "expected".
+ EXPECT_THROW(lexer.getNextToken(MasterToken::END_OF_LINE),
+ isc::InvalidParameter);
+ EXPECT_THROW(lexer.getNextToken(MasterToken::END_OF_FILE),
+ isc::InvalidParameter);
+ EXPECT_THROW(lexer.getNextToken(MasterToken::INITIAL_WS),
+ isc::InvalidParameter);
+ EXPECT_THROW(lexer.getNextToken(MasterToken::ERROR),
+ isc::InvalidParameter);
+
+ // If it encounters a syntax error, it results in LexerError exception.
+ lexerErrorCheck(lexer, MasterToken::STRING, MasterToken::UNBALANCED_PAREN);
+
+ // Unlike the NUMBER_OUT_OF_RANGE case, the error part has been skipped
+ // within getNextToken(). We should be able to get the next token.
+ EXPECT_EQ("string-after-error",
+ lexer.getNextToken(MasterToken::STRING).getString());
+}
+
+}
diff --git a/src/lib/dns/tests/master_loader_callbacks_test.cc b/src/lib/dns/tests/master_loader_callbacks_test.cc
new file mode 100644
index 0000000..9d23802
--- /dev/null
+++ b/src/lib/dns/tests/master_loader_callbacks_test.cc
@@ -0,0 +1,79 @@
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/master_loader_callbacks.h>
+#include <dns/rrset.h>
+#include <dns/name.h>
+#include <dns/rrttl.h>
+#include <dns/rrclass.h>
+
+#include <exceptions/exceptions.h>
+
+#include <gtest/gtest.h>
+#include <functional>
+
+namespace {
+
+using std::string;
+using namespace isc::dns;
+namespace ph = std::placeholders;
+
+class MasterLoaderCallbacksTest : public ::testing::Test {
+protected:
+ MasterLoaderCallbacksTest() :
+ last_was_error_(false), // Not needed, but then cppcheck complains
+ issue_called_(false),
+ rrset_(new RRset(Name("example.org"), RRClass::IN(), RRType::A(),
+ RRTTL(3600))),
+ error_(std::bind(&MasterLoaderCallbacksTest::checkCallback, this,
+ true, ph::_1, ph::_2, ph::_3)),
+ warning_(std::bind(&MasterLoaderCallbacksTest::checkCallback, this,
+ false, ph::_1, ph::_2, ph::_3)),
+ callbacks_(error_, warning_)
+ {}
+
+ void checkCallback(bool error, const string& source, size_t line,
+ const string& reason)
+ {
+ issue_called_ = true;
+ last_was_error_ = error;
+ EXPECT_EQ("source", source);
+ EXPECT_EQ(1, line);
+ EXPECT_EQ("reason", reason);
+ }
+ bool last_was_error_;
+ bool issue_called_;
+ const RRsetPtr rrset_;
+ const MasterLoaderCallbacks::IssueCallback error_, warning_;
+ MasterLoaderCallbacks callbacks_;
+};
+
+// Check the constructor rejects empty callbacks, but accepts non-empty ones
+TEST_F(MasterLoaderCallbacksTest, constructor) {
+ EXPECT_THROW(MasterLoaderCallbacks(MasterLoaderCallbacks::IssueCallback(),
+ warning_), isc::InvalidParameter);
+ EXPECT_THROW(MasterLoaderCallbacks(error_,
+ MasterLoaderCallbacks::IssueCallback()),
+ isc::InvalidParameter);
+ EXPECT_NO_THROW(MasterLoaderCallbacks(error_, warning_));
+}
+
+// Call the issue callbacks
+TEST_F(MasterLoaderCallbacksTest, issueCall) {
+ callbacks_.error("source", 1, "reason");
+ EXPECT_TRUE(last_was_error_);
+ EXPECT_TRUE(issue_called_);
+
+ issue_called_ = false;
+
+ callbacks_.warning("source", 1, "reason");
+ EXPECT_FALSE(last_was_error_);
+ EXPECT_TRUE(issue_called_);
+}
+
+}
diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc
new file mode 100644
index 0000000..74300d3
--- /dev/null
+++ b/src/lib/dns/tests/master_loader_unittest.cc
@@ -0,0 +1,1445 @@
+// Copyright (C) 2012-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/master_loader_callbacks.h>
+#include <dns/master_loader.h>
+#include <dns/rrtype.h>
+#include <dns/rrset.h>
+#include <dns/rrclass.h>
+#include <dns/rrttl.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+#include <gtest/gtest.h>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include <functional>
+#include <string>
+#include <vector>
+#include <list>
+#include <sstream>
+
+using namespace isc::dns;
+using std::vector;
+using std::string;
+using std::list;
+using std::stringstream;
+using std::endl;
+using boost::lexical_cast;
+namespace ph = std::placeholders;
+
+namespace {
+class MasterLoaderTest : public ::testing::Test {
+public:
+ MasterLoaderTest() :
+ callbacks_(std::bind(&MasterLoaderTest::callback, this,
+ &errors_, ph::_1, ph::_2, ph::_3),
+ std::bind(&MasterLoaderTest::callback, this,
+ &warnings_, ph::_1, ph::_2, ph::_3))
+ {}
+
+ void TearDown() {
+ // Check there are no more RRs we didn't expect
+ EXPECT_TRUE(rrsets_.empty());
+ }
+
+ /// Concatenate file, line, and reason, and add it to either errors
+ /// or warnings
+ void callback(vector<string>* target, const std::string& file, size_t line,
+ const std::string& reason)
+ {
+ std::stringstream ss;
+ ss << reason << " [" << file << ":" << line << "]";
+ target->push_back(ss.str());
+ }
+
+ void addRRset(const Name& name, const RRClass& rrclass,
+ const RRType& rrtype, const RRTTL& rrttl,
+ const rdata::RdataPtr& data) {
+ const RRsetPtr rrset(new BasicRRset(name, rrclass, rrtype, rrttl));
+ rrset->addRdata(data);
+ rrsets_.push_back(rrset);
+ }
+
+ void setLoader(const char* file, const Name& origin,
+ const RRClass& rrclass, const MasterLoader::Options options)
+ {
+ loader_.reset(new MasterLoader(file, origin, rrclass, callbacks_,
+ std::bind(&MasterLoaderTest::addRRset,
+ this, ph::_1, ph::_2, ph::_3,
+ ph::_4, ph::_5),
+ options));
+ }
+
+ void setLoader(std::istream& stream, const Name& origin,
+ const RRClass& rrclass, const MasterLoader::Options options)
+ {
+ loader_.reset(new MasterLoader(stream, origin, rrclass, callbacks_,
+ std::bind(&MasterLoaderTest::addRRset,
+ this, ph::_1, ph::_2, ph::_3,
+ ph::_4, ph::_5),
+ options));
+ }
+
+ static string prepareZone(const string& line, bool include_last) {
+ string result;
+ result += "example.org. 3600 IN SOA ns1.example.org. "
+ "admin.example.org. 1234 3600 1800 2419200 7200\n";
+ result += line;
+ if (include_last) {
+ result += "\n";
+ result += "correct 3600 IN A 192.0.2.2\n";
+ }
+ return (result);
+ }
+
+ void clear() {
+ warnings_.clear();
+ errors_.clear();
+ rrsets_.clear();
+ }
+
+ // Check the next RR in the ones produced by the loader
+ // Other than passed arguments are checked to be the default for the tests
+ void checkRR(const string& name, const RRType& type, const string& data,
+ const RRTTL& rrttl = RRTTL(3600)) {
+ ASSERT_FALSE(rrsets_.empty());
+ RRsetPtr current = rrsets_.front();
+ rrsets_.pop_front();
+
+ EXPECT_EQ(Name(name), current->getName());
+ EXPECT_EQ(type, current->getType());
+ EXPECT_EQ(RRClass::IN(), current->getClass());
+ EXPECT_EQ(rrttl, current->getTTL());
+ ASSERT_EQ(1, current->getRdataCount());
+ EXPECT_EQ(0, isc::dns::rdata::createRdata(type, RRClass::IN(), data)->
+ compare(current->getRdataIterator()->getCurrent()))
+ << data << " vs. "
+ << current->getRdataIterator()->getCurrent().toText();
+ }
+
+ void checkBasicRRs() {
+ checkRR("example.org", RRType::SOA(),
+ "ns1.example.org. admin.example.org. "
+ "1234 3600 1800 2419200 7200");
+ checkRR("example.org", RRType::NS(), "ns1.example.org.");
+ checkRR("www.example.org", RRType::A(), "192.0.2.1");
+ checkRR("www.example.org", RRType::AAAA(), "2001:db8::1");
+ }
+
+ void checkARR(const string& name) {
+ checkRR(name, RRType::A(), "192.0.2.1");
+ }
+
+ MasterLoaderCallbacks callbacks_;
+ boost::scoped_ptr<MasterLoader> loader_;
+ vector<string> errors_;
+ vector<string> warnings_;
+ list<RRsetPtr> rrsets_;
+};
+
+// Test simple loading. The zone file contains no tricky things, and nothing is
+// omitted. No RRset contains more than one RR Also no errors or warnings.
+TEST_F(MasterLoaderTest, basicLoad) {
+ setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."),
+ RRClass::IN(), MasterLoader::MANY_ERRORS);
+
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+
+ // The following three should be set to 0 initially in case the loader
+ // is constructed from a file name.
+ EXPECT_EQ(0, loader_->getSize());
+ EXPECT_EQ(0, loader_->getPosition());
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+
+ // Hardcode expected values taken from the test data file, assuming it
+ // won't change too often.
+ EXPECT_EQ(550, loader_->getSize());
+ EXPECT_EQ(550, loader_->getPosition());
+
+ checkBasicRRs();
+}
+
+// Test the $INCLUDE directive
+TEST_F(MasterLoaderTest, include) {
+ // Test various cases of include
+ const char* includes[] = {
+ "$include",
+ "$INCLUDE",
+ "$Include",
+ "$InCluDe",
+ "\"$INCLUDE\"",
+ NULL
+ };
+ for (const char** include = includes; *include != NULL; ++include) {
+ SCOPED_TRACE(*include);
+
+ clear();
+ // Prepare input source that has the include and some more data
+ // below (to see it returns back to the original source).
+ const string include_str = string(*include) + " " +
+ TEST_DATA_SRCDIR + "/example.org\nwww 3600 IN AAAA 2001:db8::1\n";
+ stringstream ss(include_str);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+
+ checkBasicRRs();
+ checkRR("www.example.org", RRType::AAAA(), "2001:db8::1");
+ }
+}
+
+TEST_F(MasterLoaderTest, includeAndIncremental) {
+ // Check getSize() and getPosition() are adjusted before and after
+ // $INCLUDE.
+ const string first_rr = "before.example.org. 0 A 192.0.2.1\n";
+ const string include_str = "$INCLUDE " TEST_DATA_SRCDIR "/example.org";
+ const string zone_data = first_rr + include_str + "\n" +
+ "www 3600 IN AAAA 2001:db8::1\n";
+ stringstream ss(zone_data);
+ setLoader(ss, Name("example.org."), RRClass::IN(), MasterLoader::DEFAULT);
+
+ // On construction, getSize() returns the size of the data (exclude the
+ // the file to be included); position is set to 0.
+ EXPECT_EQ(zone_data.size(), loader_->getSize());
+ EXPECT_EQ(0, loader_->getPosition());
+
+ // Read the first RR. getSize() doesn't change; position should be
+ // at the end of the first line.
+ loader_->loadIncremental(1);
+ EXPECT_EQ(zone_data.size(), loader_->getSize());
+ EXPECT_EQ(first_rr.size(), loader_->getPosition());
+
+ // Read next 4. It includes $INCLUDE processing. Magic number of 550
+ // is the size of the test zone file (see above); 507 is the position in
+ // the file at the end of 4th RR (due to extra comments it's smaller than
+ // the file size).
+ loader_->loadIncremental(4);
+ EXPECT_EQ(zone_data.size() + 550, loader_->getSize());
+ EXPECT_EQ(first_rr.size() + include_str.size() + 507,
+ loader_->getPosition());
+
+ // Read the last one. At this point getSize and getPosition return
+ // the same value, indicating progress of 100%.
+ loader_->loadIncremental(1);
+ EXPECT_EQ(zone_data.size() + 550, loader_->getSize());
+ EXPECT_EQ(zone_data.size() + 550, loader_->getPosition());
+
+ // we were not interested in checking RRs in this test. clear them to
+ // not confuse TearDown().
+ rrsets_.clear();
+}
+
+// A commonly used helper to check callback message.
+void
+checkCallbackMessage(const string& actual_msg, const string& expected_msg,
+ size_t expected_line) {
+ // The actual message should begin with the expected message.
+ EXPECT_EQ(0, actual_msg.find(expected_msg)) << "actual message: " <<
+ actual_msg << " expected: " <<
+ expected_msg;
+
+ // and it should end with "...:<line_num>]"
+ const string line_desc = ":" + lexical_cast<string>(expected_line) + "]";
+ EXPECT_EQ(actual_msg.size() - line_desc.size(),
+ actual_msg.find(line_desc)) << "Expected on line " <<
+ expected_line;
+}
+
+TEST_F(MasterLoaderTest, origin) {
+ // Various forms of the directive
+ const char* origins[] = {
+ "$origin",
+ "$ORIGIN",
+ "$Origin",
+ "$OrigiN",
+ "\"$ORIGIN\"",
+ NULL
+ };
+ for (const char** origin = origins; *origin != NULL; ++origin) {
+ SCOPED_TRACE(*origin);
+
+ clear();
+ const string directive = *origin;
+ const string input =
+ "@ 1H IN A 192.0.2.1\n" +
+ directive + " sub.example.org.\n"
+ "\"www\" 1H IN A 192.0.2.1\n" +
+ // Relative name in the origin
+ directive + " relative\n"
+ "@ 1H IN A 192.0.2.1\n"
+ // Origin is _not_ used here (absolute name)
+ "noorigin.example.org. 60M IN A 192.0.2.1\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ // There's a relative origin in it, we warn about that.
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0),
+ "The new origin is relative, did you really mean "
+ "relative.sub.example.org.?", 4);
+
+ checkARR("example.org");
+ checkARR("www.sub.example.org");
+ checkARR("relative.sub.example.org");
+ checkARR("noorigin.example.org");
+ }
+}
+
+TEST_F(MasterLoaderTest, generate) {
+ // Various forms of the directive
+ const char* generates[] = {
+ "$generate",
+ "$GENERATE",
+ "$Generate",
+ "$GeneratE",
+ "\"$GENERATE\"",
+ NULL
+ };
+ for (const char** generate = generates; *generate != NULL; ++generate) {
+ SCOPED_TRACE(*generate);
+
+ clear();
+ const string directive = *generate;
+ const string input =
+ "$ORIGIN example.org.\n"
+ "before.example.org. 3600 IN A 192.0.2.0\n" +
+ directive + " 3-5 host$ A 192.0.2.$\n" +
+ "after.example.org. 3600 IN A 192.0.2.255\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ // The "before" and "after" scaffolding below checks that no
+ // extra records are added by $GENERATE outside the requested
+ // range.
+ checkRR("before.example.org", RRType::A(), "192.0.2.0");
+ checkRR("host3.example.org", RRType::A(), "192.0.2.3");
+ checkRR("host4.example.org", RRType::A(), "192.0.2.4");
+ checkRR("host5.example.org", RRType::A(), "192.0.2.5");
+ checkRR("after.example.org", RRType::A(), "192.0.2.255");
+ }
+}
+
+TEST_F(MasterLoaderTest, generateRelativeLHS) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 @ 3600 NS ns$.example.org.\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("example.org", RRType::NS(), "ns1.example.org.");
+ checkRR("example.org", RRType::NS(), "ns2.example.org.");
+}
+
+TEST_F(MasterLoaderTest, generateInFront) {
+ // $ is in the front
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 $host 3600 TXT \"$ pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("9host.example.org", RRType::TXT(), "9 pomegranate");
+ checkRR("10host.example.org", RRType::TXT(), "10 pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateInMiddle) {
+ // $ is in the middle
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 num$-host 3600 TXT \"This is $ pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("num9-host.example.org", RRType::TXT(), "This is 9 pomegranate");
+ checkRR("num10-host.example.org", RRType::TXT(), "This is 10 pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateAtEnd) {
+ // $ is at the end
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 num$-host 3600 TXT Pomegranate$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("num9-host.example.org", RRType::TXT(), "Pomegranate9");
+ checkRR("num10-host.example.org", RRType::TXT(), "Pomegranate10");
+}
+
+TEST_F(MasterLoaderTest, generateStripsQuotes) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 @ 3600 MX \"$ mx$.example.org.\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("example.org", RRType::MX(), "1 mx1.example.org.");
+ checkRR("example.org", RRType::MX(), "2 mx2.example.org.");
+}
+
+TEST_F(MasterLoaderTest, generateWithDoublePlaceholder) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 host$ 3600 TXT \"This is $$ pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host9.example.org", RRType::TXT(), "This is $ pomegranate");
+ checkRR("host10.example.org", RRType::TXT(), "This is $ pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateWithEscape) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 host$ 3600 TXT \"This is \\$\\pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host9.example.org", RRType::TXT(), "This is \\$\\pomegranate");
+ checkRR("host10.example.org", RRType::TXT(), "This is \\$\\pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateWithParams) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+ "$GENERATE 2-3 host$ A 192.0.2.$\n"
+ "$GENERATE 5-6 host$ 3600 A 192.0.2.$\n"
+ "$GENERATE 8-9 host$ IN A 192.0.2.$\n"
+ "$GENERATE 11-12 host$ IN 3600 A 192.0.2.$\n"
+ "$GENERATE 14-15 host$ 3600 IN A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host2.example.org", RRType::A(), "192.0.2.2");
+ checkRR("host3.example.org", RRType::A(), "192.0.2.3");
+
+ checkRR("host5.example.org", RRType::A(), "192.0.2.5");
+ checkRR("host6.example.org", RRType::A(), "192.0.2.6");
+
+ checkRR("host8.example.org", RRType::A(), "192.0.2.8");
+ checkRR("host9.example.org", RRType::A(), "192.0.2.9");
+
+ checkRR("host11.example.org", RRType::A(), "192.0.2.11");
+ checkRR("host12.example.org", RRType::A(), "192.0.2.12");
+
+ checkRR("host14.example.org", RRType::A(), "192.0.2.14");
+ checkRR("host15.example.org", RRType::A(), "192.0.2.15");
+}
+
+TEST_F(MasterLoaderTest, generateWithStep) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-9/2 host$ 3600 A 192.0.2.$\n"
+ "$GENERATE 12-21/3 host$ 3600 A 192.0.2.$\n"
+ "$GENERATE 30-31/1 host$ 3600 A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host2.example.org", RRType::A(), "192.0.2.2");
+ checkRR("host4.example.org", RRType::A(), "192.0.2.4");
+ checkRR("host6.example.org", RRType::A(), "192.0.2.6");
+ checkRR("host8.example.org", RRType::A(), "192.0.2.8");
+
+ checkRR("host12.example.org", RRType::A(), "192.0.2.12");
+ checkRR("host15.example.org", RRType::A(), "192.0.2.15");
+ checkRR("host18.example.org", RRType::A(), "192.0.2.18");
+ checkRR("host21.example.org", RRType::A(), "192.0.2.21");
+
+ checkRR("host30.example.org", RRType::A(), "192.0.2.30");
+ checkRR("host31.example.org", RRType::A(), "192.0.2.31");
+}
+
+TEST_F(MasterLoaderTest, generateWithModifiers) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+
+ // Use a positive delta of 1 in the LHS and a negative delta of
+ // -1 in the RHS
+ "$GENERATE 2-9/2 host${1} A 192.0.2.${-1}\n"
+
+ "$GENERATE 10-12 host${0,4} A 192.0.2.$\n"
+ "$GENERATE 14-15 host${0,4,d} A 192.0.2.$\n"
+
+ // Names are case-insensitive, so we use TXT's RDATA to check
+ // case with hex representation.
+ "$GENERATE 30-31 host$ TXT \"Value ${0,4,x}\"\n"
+ "$GENERATE 42-43 host$ TXT \"Value ${0,4,X}\"\n"
+
+ // Octal does not use any alphabets
+ "$GENERATE 45-46 host${0,4,o} A 192.0.2.$\n"
+
+ // Here, the LHS has a trailing dot (which would result in an
+ // out-of-zone name), but that should be handled as a relative
+ // name.
+ "$GENERATE 90-92 ${0,8,n} A 192.0.2.$\n"
+
+ // Here, the LHS has no trailing dot, and results in the same
+ // number of labels as width=8 above.
+ "$GENERATE 94-96 ${0,7,n} A 192.0.2.$\n"
+
+ // Names are case-insensitive, so we use TXT's RDATA to check
+ // case with nibble representation.
+ "$GENERATE 106-107 host$ TXT \"Value ${0,9,n}\"\n"
+ "$GENERATE 109-110 host$ TXT \"Value ${0,9,N}\"\n"
+
+ // Junk type will not parse and 'd' is assumed. No error is
+ // generated (this is to match BIND 9 behavior).
+ "$GENERATE 200-201 host${0,4,j} A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host3.example.org", RRType::A(), "192.0.2.1");
+ checkRR("host5.example.org", RRType::A(), "192.0.2.3");
+ checkRR("host7.example.org", RRType::A(), "192.0.2.5");
+ checkRR("host9.example.org", RRType::A(), "192.0.2.7");
+
+ checkRR("host0010.example.org", RRType::A(), "192.0.2.10");
+ checkRR("host0011.example.org", RRType::A(), "192.0.2.11");
+ checkRR("host0012.example.org", RRType::A(), "192.0.2.12");
+
+ checkRR("host0014.example.org", RRType::A(), "192.0.2.14");
+ checkRR("host0015.example.org", RRType::A(), "192.0.2.15");
+
+ checkRR("host30.example.org", RRType::TXT(), "Value 001e");
+ checkRR("host31.example.org", RRType::TXT(), "Value 001f");
+
+ checkRR("host42.example.org", RRType::TXT(), "Value 002A");
+ checkRR("host43.example.org", RRType::TXT(), "Value 002B");
+
+ checkRR("host0055.example.org", RRType::A(), "192.0.2.45");
+ checkRR("host0056.example.org", RRType::A(), "192.0.2.46");
+
+ checkRR("a.5.0.0.example.org", RRType::A(), "192.0.2.90");
+ checkRR("b.5.0.0.example.org", RRType::A(), "192.0.2.91");
+ checkRR("c.5.0.0.example.org", RRType::A(), "192.0.2.92");
+
+ checkRR("e.5.0.0.example.org", RRType::A(), "192.0.2.94");
+ checkRR("f.5.0.0.example.org", RRType::A(), "192.0.2.95");
+ checkRR("0.6.0.0.example.org", RRType::A(), "192.0.2.96");
+
+ checkRR("host106.example.org", RRType::TXT(), "Value a.6.0.0.0");
+ checkRR("host107.example.org", RRType::TXT(), "Value b.6.0.0.0");
+ checkRR("host109.example.org", RRType::TXT(), "Value D.6.0.0.0");
+ checkRR("host110.example.org", RRType::TXT(), "Value E.6.0.0.0");
+
+ checkRR("host0200.example.org", RRType::A(), "192.0.2.200");
+ checkRR("host0201.example.org", RRType::A(), "192.0.2.201");
+}
+
+TEST_F(MasterLoaderTest, generateWithNoModifiers) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+ "$GENERATE 10-12 host${} A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ ASSERT_EQ(2, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "Invalid $GENERATE format modifiers", 3);
+ checkCallbackMessage(errors_.at(1),
+ "$GENERATE error", 3);
+}
+
+TEST_F(MasterLoaderTest, generateWithBadModifiers) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+ "$GENERATE 10-12 host${GARBAGE} A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ ASSERT_EQ(2, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "Invalid $GENERATE format modifiers", 3);
+ checkCallbackMessage(errors_.at(1),
+ "$GENERATE error", 3);
+}
+
+TEST_F(MasterLoaderTest, generateMissingRange) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateMissingLHS) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-4\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateMissingType) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-4 host$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateMissingRHS) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-4 host$ A\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithBadRangeSyntax) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE ABCD host$ 3600 A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "$GENERATE: invalid range: ABCD", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithInvalidRange) {
+ // start > stop
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-1 host$ 3600 A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "$GENERATE: invalid range: 2-1", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithInvalidClass) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 host$ 3600 CH A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "Class mismatch: CH vs. IN", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithNoAvailableTTL) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 host$ A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "no TTL specified; load rejected", 2);
+}
+
+// Test the source is correctly popped even after error
+TEST_F(MasterLoaderTest, popAfterError) {
+ const string include_str = "$include " TEST_DATA_SRCDIR
+ "/broken.zone\nwww 3600 IN AAAA 2001:db8::1\n";
+ stringstream ss(include_str);
+ // We perform the test with MANY_ERRORS, we want to see what happens
+ // after the error.
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken RR
+ EXPECT_EQ(1, warnings_.size()); // For missing EOLN
+
+ // The included file doesn't contain anything usable, but the
+ // line after the include should be there.
+ checkRR("www.example.org", RRType::AAAA(), "2001:db8::1");
+}
+
+// Check it works the same when created based on a stream, not filename
+TEST_F(MasterLoaderTest, streamConstructor) {
+ const string zone_data(prepareZone("", true));
+ stringstream zone_stream(zone_data);
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+
+ // Unlike the basicLoad test, if we construct the loader from a stream
+ // getSize() returns the data size in the stream immediately after the
+ // construction.
+ EXPECT_EQ(zone_data.size(), loader_->getSize());
+ EXPECT_EQ(0, loader_->getPosition());
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+ checkRR("example.org", RRType::SOA(), "ns1.example.org. "
+ "admin.example.org. 1234 3600 1800 2419200 7200");
+ checkRR("correct.example.org", RRType::A(), "192.0.2.2");
+
+ // On completion of the load, both getSize() and getPosition() return the
+ // size of the data.
+ EXPECT_EQ(zone_data.size(), loader_->getSize());
+ EXPECT_EQ(zone_data.size(), loader_->getPosition());
+}
+
+// Try loading data incrementally.
+TEST_F(MasterLoaderTest, incrementalLoad) {
+ setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."),
+ RRClass::IN(), MasterLoader::MANY_ERRORS);
+
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_FALSE(loader_->loadIncremental(2));
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+
+ checkRR("example.org", RRType::SOA(),
+ "ns1.example.org. admin.example.org. "
+ "1234 3600 1800 2419200 7200");
+ checkRR("example.org", RRType::NS(), "ns1.example.org.");
+
+ // The third one is not loaded yet
+ EXPECT_TRUE(rrsets_.empty());
+
+ // Load the rest.
+ EXPECT_TRUE(loader_->loadIncremental(20));
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+
+ checkRR("www.example.org", RRType::A(), "192.0.2.1");
+ checkRR("www.example.org", RRType::AAAA(), "2001:db8::1");
+}
+
+// Try loading from file that doesn't exist. There should be single error
+// saying so.
+TEST_F(MasterLoaderTest, invalidFile) {
+ setLoader("This file doesn't exist at all",
+ Name("example.org."), RRClass::IN(), MasterLoader::MANY_ERRORS);
+
+ // Nothing yet. The loader is dormant until invoked.
+ // Is it really what we want?
+ EXPECT_TRUE(errors_.empty());
+
+ loader_->load();
+
+ EXPECT_TRUE(warnings_.empty());
+ EXPECT_TRUE(rrsets_.empty());
+ ASSERT_EQ(1, errors_.size());
+ EXPECT_EQ(0, errors_[0].find("Error opening the input source file: ")) <<
+ "Different error: " << errors_[0];
+}
+
+struct ErrorCase {
+ const char* const line; // The broken line in master file
+ const char* const reason; // If non NULL, the reason string
+ const char* const problem; // Description of the problem for SCOPED_TRACE
+} const error_cases[] = {
+ { "www... 3600 IN A 192.0.2.1", NULL, "Invalid name" },
+ { "www FORTNIGHT IN A 192.0.2.1", NULL, "Invalid TTL" },
+ { "www 3600 XX A 192.0.2.1", NULL, "Invalid class" },
+ { "www 3600 IN A bad_ip", NULL, "Invalid Rdata" },
+
+ // Parameter ordering errors
+ { "www IN A 3600 192.168.2.7",
+ "createRdata from text failed: Bad IN/A RDATA text: '3600'",
+ "Incorrect order of class, TTL and type" },
+ { "www A IN 3600 192.168.2.8",
+ "createRdata from text failed: Bad IN/A RDATA text: 'IN'",
+ "Incorrect order of class, TTL and type" },
+ { "www 3600 A IN 192.168.2.7",
+ "createRdata from text failed: Bad IN/A RDATA text: 'IN'",
+ "Incorrect order of class, TTL and type" },
+ { "www A 3600 IN 192.168.2.8",
+ "createRdata from text failed: Bad IN/A RDATA text: '3600'",
+ "Incorrect order of class, TTL and type" },
+
+ // Missing type and Rdata
+ { "www", "unexpected end of input", "Missing type and Rdata" },
+ { "www 3600", "unexpected end of input", "Missing type and Rdata" },
+ { "www IN", "unexpected end of input", "Missing type and Rdata" },
+ { "www 3600 IN", "unexpected end of input", "Missing type and Rdata" },
+ { "www IN 3600", "unexpected end of input", "Missing type and Rdata" },
+
+ // Missing Rdata
+ { "www A",
+ "createRdata from text failed: unexpected end of input",
+ "Missing Rdata" },
+ { "www 3600 A",
+ "createRdata from text failed: unexpected end of input",
+ "Missing Rdata" },
+ { "www IN A",
+ "createRdata from text failed: unexpected end of input",
+ "Missing Rdata" },
+ { "www 3600 IN A",
+ "createRdata from text failed: unexpected end of input",
+ "Missing Rdata" },
+ { "www IN 3600 A",
+ "createRdata from text failed: unexpected end of input",
+ "Missing Rdata" },
+
+ { "www 3600 IN", NULL, "Unexpected EOLN" },
+ { "www 3600 CH TXT nothing", "Class mismatch: CH vs. IN",
+ "Class mismatch" },
+ { "www \"3600\" IN A 192.0.2.1", NULL, "Quoted TTL" },
+ { "www 3600 \"IN\" A 192.0.2.1", NULL, "Quoted class" },
+ { "www 3600 IN \"A\" 192.0.2.1", NULL, "Quoted type" },
+ { "unbalanced)paren 3600 IN A 192.0.2.1", NULL, "Token error 1" },
+ { "www 3600 unbalanced)paren A 192.0.2.1", NULL,
+ "Token error 2" },
+ // Check the unknown directive. The rest looks like ordinary RR,
+ // so we see the $ is actually special.
+ { "$UNKNOWN 3600 IN A 192.0.2.1", NULL, "Unknown $ directive" },
+ { "$INCLUD " TEST_DATA_SRCDIR "/example.org", "Unknown directive 'INCLUD'",
+ "Include too short" },
+ { "$INCLUDES " TEST_DATA_SRCDIR "/example.org",
+ "Unknown directive 'INCLUDES'", "Include too long" },
+ { "$INCLUDE", "unexpected end of input", "Missing include path" },
+ // The following two error messages are system dependent, omitting
+ { "$INCLUDE /file/not/found", NULL, "Include file not found" },
+ { "$INCLUDE /file/not/found example.org. and here goes bunch of garbage",
+ NULL, "Include file not found and garbage at the end of line" },
+ { "$ORIGIN", "unexpected end of input", "Missing origin name" },
+ { "$ORIGIN invalid...name", "duplicate period in invalid...name",
+ "Invalid name for origin" },
+ { "$ORIGIN )brokentoken", "unbalanced parentheses",
+ "Broken token in origin" },
+ { "$ORIGIN example.org. garbage", "Extra tokens at the end of line",
+ "Garbage after origin" },
+ { "$ORIGI name.", "Unknown directive 'ORIGI'", "$ORIGIN too short" },
+ { "$ORIGINAL name.", "Unknown directive 'ORIGINAL'", "$ORIGIN too long" },
+ { "$TTL 100 extra-garbage", "Extra tokens at the end of line",
+ "$TTL with extra token" },
+ { "$TTL", "unexpected end of input", "missing TTL" },
+ { "$TTL No-ttl", "Unknown unit used: N in: No-ttl", "bad TTL" },
+ { "$TTL \"100\"", "unexpected quotes", "bad TTL, quoted" },
+ { "$TT 100", "Unknown directive 'TT'", "bad directive, too short" },
+ { "$TTLLIKE 100", "Unknown directive 'TTLLIKE'", "bad directive, extra" },
+ { NULL, NULL, NULL }
+};
+
+// Test a broken zone is handled properly. We test several problems,
+// both in strict and lenient mode.
+TEST_F(MasterLoaderTest, brokenZone) {
+ for (const ErrorCase* ec = error_cases; ec->line != NULL; ++ec) {
+ SCOPED_TRACE(ec->problem);
+ const string zone(prepareZone(ec->line, true));
+
+ {
+ SCOPED_TRACE("Strict mode");
+ clear();
+ stringstream zone_stream(zone);
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_THROW(loader_->load(), MasterLoaderError);
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size());
+ if (ec->reason != NULL) {
+ checkCallbackMessage(errors_.at(0), ec->reason, 2);
+ }
+ EXPECT_TRUE(warnings_.empty());
+
+ checkRR("example.org", RRType::SOA(), "ns1.example.org. "
+ "admin.example.org. 1234 3600 1800 2419200 7200");
+ // In the strict mode, it is aborted. The last RR is not
+ // even attempted.
+ EXPECT_TRUE(rrsets_.empty());
+ }
+
+ {
+ SCOPED_TRACE("Lenient mode");
+ clear();
+ stringstream zone_stream(zone);
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_NO_THROW(loader_->load());
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size());
+ EXPECT_TRUE(warnings_.empty());
+ checkRR("example.org", RRType::SOA(), "ns1.example.org. "
+ "admin.example.org. 1234 3600 1800 2419200 7200");
+ // This one is below the error one.
+ checkRR("correct.example.org", RRType::A(), "192.0.2.2");
+ EXPECT_TRUE(rrsets_.empty());
+ }
+
+ {
+ SCOPED_TRACE("Error at EOF");
+ // This case is interesting only in the lenient mode.
+ clear();
+ const string zoneEOF(prepareZone(ec->line, false));
+ stringstream zone_stream(zoneEOF);
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_NO_THROW(loader_->load());
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size()) << errors_[0] << "\n" << errors_[1];
+ // The unexpected EOF warning
+ EXPECT_EQ(1, warnings_.size());
+ checkRR("example.org", RRType::SOA(), "ns1.example.org. "
+ "admin.example.org. 1234 3600 1800 2419200 7200");
+ EXPECT_TRUE(rrsets_.empty());
+ }
+ }
+}
+
+// Check that a garbage after the include generates an error, but not fatal
+// one (in lenient mode) and we can recover.
+TEST_F(MasterLoaderTest, includeWithGarbage) {
+ // Include an origin (example.org) because we expect it to be handled
+ // soon and we don't want it to break here.
+ const string include_str("$INCLUDE " TEST_DATA_SRCDIR
+ "/example.org example.org. bunch of other stuff\n"
+ "www 3600 IN AAAA 2001:db8::1\n");
+ stringstream zone_stream(include_str);
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ EXPECT_NO_THROW(loader_->load());
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ ASSERT_EQ(1, errors_.size());
+ checkCallbackMessage(errors_.at(0), "Extra tokens at the end of line", 1);
+ // It says something about extra tokens at the end
+ EXPECT_NE(string::npos, errors_[0].find("Extra"));
+ EXPECT_TRUE(warnings_.empty());
+ checkBasicRRs();
+ checkRR("www.example.org", RRType::AAAA(), "2001:db8::1");
+}
+
+// Check we error about garbage at the end of $ORIGIN line (but the line
+// works).
+TEST_F(MasterLoaderTest, originWithGarbage) {
+ const string origin_str = "$ORIGIN www.example.org. More garbage here\n"
+ "@ 1H IN A 192.0.2.1\n";
+ stringstream ss(origin_str);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ EXPECT_NO_THROW(loader_->load());
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ ASSERT_EQ(1, errors_.size());
+ checkCallbackMessage(errors_.at(0), "Extra tokens at the end of line", 1);
+ EXPECT_TRUE(warnings_.empty());
+ checkARR("www.example.org");
+}
+
+// Test we can pass both file to include and the origin to switch
+TEST_F(MasterLoaderTest, includeAndOrigin) {
+ // First, switch origin to something else, so we can check it is
+ // switched back.
+ const string include_string = "$ORIGIN www.example.org.\n"
+ "@ 1H IN A 192.0.2.1\n"
+ // Then include the file with data and switch origin back
+ "$INCLUDE " TEST_DATA_SRCDIR "/example.org example.org.\n"
+ // Another RR to see we fall back to the previous origin.
+ "www 1H IN A 192.0.2.1\n";
+ stringstream ss(include_string);
+ setLoader(ss, Name("example.org"), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ // Successfully load the data
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+ // And check it's the correct data
+ checkARR("www.example.org");
+ checkBasicRRs();
+ checkARR("www.www.example.org");
+}
+
+// Like above, but the origin after include is bogus. The whole line should
+// be rejected.
+TEST_F(MasterLoaderTest, includeAndBadOrigin) {
+ const string include_string =
+ "$INCLUDE " TEST_DATA_SRCDIR "/example.org example..org.\n"
+ // Another RR to see the switch survives after we exit include
+ "www 1H IN A 192.0.2.1\n";
+ stringstream ss(include_string);
+ setLoader(ss, Name("example.org"), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size());
+ checkCallbackMessage(errors_.at(0), "duplicate period in example..org.",
+ 1);
+ EXPECT_TRUE(warnings_.empty());
+ // And check it's the correct data
+ checkARR("www.example.org");
+}
+
+// Check the origin doesn't get outside of the included file.
+TEST_F(MasterLoaderTest, includeOriginRestore) {
+ const string include_string =
+ "$INCLUDE " TEST_DATA_SRCDIR "/origincheck.txt\n"
+ "@ 1H IN A 192.0.2.1\n";
+ stringstream ss(include_string);
+ setLoader(ss, Name("example.org"), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ // Successfully load the data
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+ // And check it's the correct data
+ checkARR("www.example.org");
+ checkARR("example.org");
+}
+
+// Check we restore the last name for initial whitespace when returning from
+// include. But we do produce a warning if there's one just ofter the include.
+TEST_F(MasterLoaderTest, includeAndInitialWS) {
+ const string include_string = "xyz 1H IN A 192.0.2.1\n"
+ "$INCLUDE " TEST_DATA_SRCDIR "/example.org\n"
+ " 1H IN A 192.0.2.1\n";
+ stringstream ss(include_string);
+ setLoader(ss, Name("example.org"), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ // Successfully load the data
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0),
+ "Owner name omitted around $INCLUDE, the result might "
+ "not be as expected", 3);
+ checkARR("xyz.example.org");
+ checkBasicRRs();
+ checkARR("xyz.example.org");
+}
+
+// Test for "$TTL"
+TEST_F(MasterLoaderTest, ttlDirective) {
+ stringstream zone_stream;
+
+ // Set the default TTL with $TTL followed by an RR omitting the TTL
+ zone_stream << "$TTL 1800\nexample.org. IN A 192.0.2.1\n";
+ // $TTL can be quoted. Also testing the case of $TTL being changed.
+ zone_stream << "\"$TTL\" 100\na.example.org. IN A 192.0.2.2\n";
+ // Extended TTL form is accepted.
+ zone_stream << "$TTL 1H\nb.example.org. IN A 192.0.2.3\n";
+ // Matching is case insensitive.
+ zone_stream << "$tTl 360\nc.example.org. IN A 192.0.2.4\n";
+ // Maximum allowable TTL
+ zone_stream << "$TTL 2147483647\nd.example.org. IN A 192.0.2.5\n";
+
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ checkRR("example.org", RRType::A(), "192.0.2.1", RRTTL(1800));
+ checkRR("a.example.org", RRType::A(), "192.0.2.2", RRTTL(100));
+ checkRR("b.example.org", RRType::A(), "192.0.2.3", RRTTL(3600));
+ checkRR("c.example.org", RRType::A(), "192.0.2.4", RRTTL(360));
+ checkRR("d.example.org", RRType::A(), "192.0.2.5", RRTTL(2147483647));
+}
+
+TEST_F(MasterLoaderTest, ttlFromSOA) {
+ // No $TTL, and the SOA doesn't have an explicit TTL field. Its minimum
+ // TTL field will be used as the RR's TTL, and it'll be used as the
+ // default TTL for others.
+ stringstream zone_stream("example.org. IN SOA . . 0 0 0 0 1800\n"
+ "a.example.org. IN A 192.0.2.1\n");
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ checkRR("example.org", RRType::SOA(), ". . 0 0 0 0 1800", RRTTL(1800));
+ checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800));
+
+ // The use of SOA minimum TTL should have caused a warning.
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0),
+ "no TTL specified; using SOA MINTTL instead", 1);
+}
+
+TEST_F(MasterLoaderTest, ttlFromPrevious) {
+ // No available default TTL. 2nd and 3rd RR will use the TTL of the
+ // 1st RR. This will result in a warning, but only for the first time.
+ stringstream zone_stream("a.example.org. 1800 IN A 192.0.2.1\n"
+ "b.example.org. IN A 192.0.2.2\n"
+ "c.example.org. IN A 192.0.2.3\n");
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800));
+ checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(1800));
+ checkRR("c.example.org", RRType::A(), "192.0.2.3", RRTTL(1800));
+
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2);
+}
+
+TEST_F(MasterLoaderTest, RRParamsOrdering) {
+ // We test the order and existence of TTL, class and type. See
+ // MasterLoader::MasterLoaderImpl::parseRRParams() for ordering.
+
+ stringstream zone_stream;
+ // <TTL> <class> <type> <RDATA>
+ zone_stream << "a.example.org. 1800 IN A 192.0.2.1\n";
+ // <type> <RDATA>
+ zone_stream << "b.example.org. A 192.0.2.2\n";
+ // <class> <TTL> <type> <RDATA>
+ zone_stream << "c.example.org. IN 3600 A 192.0.2.3\n";
+ // <TTL> <type> <RDATA>
+ zone_stream << "d.example.org. 7200 A 192.0.2.4\n";
+ // <class> <type> <RDATA>
+ zone_stream << "e.example.org. IN A 192.0.2.5\n";
+
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800));
+ checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(1800));
+ checkRR("c.example.org", RRType::A(), "192.0.2.3", RRTTL(3600));
+ checkRR("d.example.org", RRType::A(), "192.0.2.4", RRTTL(7200));
+ checkRR("e.example.org", RRType::A(), "192.0.2.5", RRTTL(7200));
+
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2);
+}
+
+TEST_F(MasterLoaderTest, ttlFromPreviousSOA) {
+ // Mixture of the previous two cases: SOA has explicit TTL, followed by
+ // an RR without an explicit TTL. In this case the minimum TTL won't be
+ // recognized as the "default TTL".
+ stringstream zone_stream("example.org. 100 IN SOA . . 0 0 0 0 1800\n"
+ "a.example.org. IN A 192.0.2.1\n");
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+
+ checkRR("example.org", RRType::SOA(), ". . 0 0 0 0 1800", RRTTL(100));
+ checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(100));
+
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2);
+}
+
+TEST_F(MasterLoaderTest, ttlUnknown) {
+ // No available TTL is known for the first RR.
+ stringstream zone_stream("a.example.org. IN A 192.0.2.1\n");
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ EXPECT_THROW(loader_->load(), MasterLoaderError);
+}
+
+TEST_F(MasterLoaderTest, ttlUnknownAndContinue) {
+ stringstream zone_stream("a.example.org. IN A 192.0.2.1\n"
+ "b.example.org. 1800 IN A 192.0.2.2\n");
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(1800));
+
+ EXPECT_TRUE(warnings_.empty());
+ EXPECT_EQ(1, errors_.size());
+ checkCallbackMessage(errors_.at(0), "no TTL specified; load rejected", 1);
+}
+
+TEST_F(MasterLoaderTest, ttlUnknownAndEOF) {
+ // Similar to the previous case, but the input will be abruptly terminated
+ // after the offending RR. This will cause an additional warning.
+ stringstream zone_stream("a.example.org. IN A 192.0.2.1");
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(rrsets_.empty());
+
+ EXPECT_EQ(1, errors_.size());
+ checkCallbackMessage(errors_.at(0), "no TTL specified; load rejected", 1);
+
+ // RDATA implementation can complain about it, too. To be independent of
+ // its details, we focus on the very last warning.
+ EXPECT_FALSE(warnings_.empty());
+ checkCallbackMessage(*warnings_.rbegin(), "File does not end with newline",
+ 1);
+}
+
+TEST_F(MasterLoaderTest, ttlOverflow) {
+ stringstream zone_stream;
+ zone_stream << "example.org. IN SOA . . 0 0 0 0 2147483648\n";
+ zone_stream << "$TTL 3600\n"; // reset to an in-range value
+ zone_stream << "$TTL 2147483649\n";
+ zone_stream << "a.example.org. IN A 192.0.2.1\n";
+ zone_stream << "$TTL 3600\n"; // reset to an in-range value
+ zone_stream << "b.example.org. 2147483650 IN A 192.0.2.2\n";
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_EQ(3, rrsets_.size());
+
+ checkRR("example.org", RRType::SOA(), ". . 0 0 0 0 2147483648", RRTTL(0));
+ checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(0));
+ checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(0));
+
+ EXPECT_EQ(4, warnings_.size());
+ checkCallbackMessage(warnings_.at(1),
+ "TTL 2147483648 > MAXTTL, setting to 0 per RFC2181",
+ 1);
+ checkCallbackMessage(warnings_.at(2),
+ "TTL 2147483649 > MAXTTL, setting to 0 per RFC2181",
+ 3);
+ checkCallbackMessage(warnings_.at(3),
+ "TTL 2147483650 > MAXTTL, setting to 0 per RFC2181",
+ 6);
+}
+
+// Test the constructor rejects empty add callback.
+TEST_F(MasterLoaderTest, emptyCallback) {
+ EXPECT_THROW(MasterLoader(TEST_DATA_SRCDIR "/example.org",
+ Name("example.org"), RRClass::IN(), callbacks_,
+ AddRRCallback()), isc::InvalidParameter);
+ // And the same with the second constructor
+ stringstream ss("");
+ EXPECT_THROW(MasterLoader(ss, Name("example.org"), RRClass::IN(),
+ callbacks_, AddRRCallback()),
+ isc::InvalidParameter);
+}
+
+// Check it throws when we try to load after loading was complete.
+TEST_F(MasterLoaderTest, loadTwice) {
+ setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."),
+ RRClass::IN(), MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_THROW(loader_->load(), isc::InvalidOperation);
+ // Don't check them, they are not interesting, so suppress the error
+ // at TearDown
+ rrsets_.clear();
+}
+
+// Load 0 items should be rejected
+TEST_F(MasterLoaderTest, loadZero) {
+ setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."),
+ RRClass::IN(), MasterLoader::MANY_ERRORS);
+ EXPECT_THROW(loader_->loadIncremental(0), isc::InvalidParameter);
+}
+
+// Test there's a warning when the file terminates without end of
+// line.
+TEST_F(MasterLoaderTest, noEOLN) {
+ // No \n at the end
+ const string input("example.org. 3600 IN SOA ns1.example.org. "
+ "admin.example.org. 1234 3600 1800 2419200 7200");
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ // There should be one warning about the EOLN
+ EXPECT_EQ(1, warnings_.size());
+ checkRR("example.org", RRType::SOA(), "ns1.example.org. "
+ "admin.example.org. 1234 3600 1800 2419200 7200");
+}
+
+// Test it rejects when we don't have the previous name to use in place of
+// initial whitespace
+TEST_F(MasterLoaderTest, noPreviousName) {
+ const string input(" 1H IN A 192.0.2.1\n");
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSuccessfully());
+ EXPECT_EQ(1, errors_.size());
+ checkCallbackMessage(errors_.at(0), "No previous name to use in place of "
+ "initial whitespace", 1);
+ EXPECT_TRUE(warnings_.empty());
+}
+
+// Check we warn if the first RR in an included file has omitted name
+TEST_F(MasterLoaderTest, previousInInclude) {
+ const string input("www 1H IN A 192.0.2.1\n"
+ "$INCLUDE " TEST_DATA_SRCDIR "/omitcheck.txt\n");
+ stringstream ss(input);
+ setLoader(ss, Name("example.org"), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ // There should be one warning about the EOLN
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0), "Owner name omitted around "
+ "$INCLUDE, the result might not be as expected", 1);
+ checkARR("www.example.org");
+ checkARR("www.example.org");
+}
+
+TEST_F(MasterLoaderTest, numericOwnerName) {
+ const string input("$ORIGIN example.org.\n"
+ "1 3600 IN A 192.0.2.1\n");
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSuccessfully());
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+
+ checkRR("1.example.org", RRType::A(), "192.0.2.1");
+}
+
+}
diff --git a/src/lib/dns/tests/masterload_unittest.cc b/src/lib/dns/tests/masterload_unittest.cc
new file mode 100644
index 0000000..e412de0
--- /dev/null
+++ b/src/lib/dns/tests/masterload_unittest.cc
@@ -0,0 +1,397 @@
+// Copyright (C) 2010-2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <functional>
+#include <ios>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <dns/masterload.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rrclass.h>
+#include <dns/rrset.h>
+
+using namespace std;
+using namespace isc::dns;
+namespace ph = std::placeholders;
+
+namespace {
+// A callback functor for masterLoad() commonly used for the following tests.
+class TestCallback {
+public:
+ TestCallback(vector<ConstRRsetPtr>& rrsets) : rrsets_(rrsets) {}
+ void operator()(ConstRRsetPtr rrset) {
+ rrsets_.push_back(rrset);
+ }
+private:
+ vector<ConstRRsetPtr>& rrsets_;
+};
+
+// A function version of TestCallback.
+void
+testCallback(ConstRRsetPtr rrset, vector<ConstRRsetPtr>* rrsets) {
+ rrsets->push_back(rrset);
+}
+
+class MasterLoadTest : public ::testing::Test {
+protected:
+ MasterLoadTest() : origin("example.com"), zclass(RRClass::IN()),
+ callback(results) {}
+public:
+ void rrsetCallback(ConstRRsetPtr rrset) {
+ results.push_back(rrset);
+ }
+protected:
+ Name origin;
+ RRClass zclass;
+ stringstream rr_stream;
+ vector<ConstRRsetPtr> results;
+ TestCallback callback;
+};
+
+// Commonly used test RRs
+const char* const txt_rr = "example.com. 3600 IN TXT \"test data\"\n";
+const char* const a_rr1 = "www.example.com. 60 IN A 192.0.2.1\n";
+const char* const a_rr2 = "www.example.com. 60 IN A 192.0.2.2\n";
+const char* const a_rr3 = "ftp.example.com. 60 IN A 192.0.2.3\n";
+// multi-field RR case
+const char* const soa_rr = "example.com. 7200 IN SOA . . 0 0 0 0 0\n";
+// A couple of RRSIGs, different type covered
+const char* const rrsig_rr1 =
+ "www.example.com. 60 IN RRSIG A 5 3 3600 20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE\n";
+const char* const rrsig_rr2 =
+ "www.example.com. 60 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE\n";
+
+// Commonly used for some tests to check the constructed RR content.
+const char* const dnskey_rdata =
+ "256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
+ "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=\n";
+
+TEST_F(MasterLoadTest, loadRRs) {
+ // a simple case: loading 3 RRs, each consists of a single RRset.
+ rr_stream << txt_rr << a_rr1 << soa_rr;
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(3, results.size());
+ EXPECT_EQ(txt_rr, results[0]->toText());
+ EXPECT_EQ(a_rr1, results[1]->toText());
+ EXPECT_EQ(soa_rr, results[2]->toText());
+}
+
+TEST_F(MasterLoadTest, loadWithFunctionCallback) {
+ // The same test as loadRRs but using a normal function (not a functor
+ // object)
+ rr_stream << txt_rr << a_rr1 << soa_rr;
+ masterLoad(rr_stream, origin, zclass,
+ std::bind(&testCallback, ph::_1, &results));
+ ASSERT_EQ(3, results.size());
+ EXPECT_EQ(txt_rr, results[0]->toText());
+ EXPECT_EQ(a_rr1, results[1]->toText());
+ EXPECT_EQ(soa_rr, results[2]->toText());
+}
+
+TEST_F(MasterLoadTest, loadWithMemFunctionCallback) {
+ // The same test as loadRRs but using a class member function (with a
+ // help of std.bind)
+ rr_stream << txt_rr << a_rr1 << soa_rr;
+ masterLoad(rr_stream, origin, zclass,
+ std::bind(&MasterLoadTest::rrsetCallback, this, ph::_1));
+ ASSERT_EQ(3, results.size());
+ EXPECT_EQ(txt_rr, results[0]->toText());
+ EXPECT_EQ(a_rr1, results[1]->toText());
+ EXPECT_EQ(soa_rr, results[2]->toText());
+}
+
+TEST_F(MasterLoadTest, loadComments) {
+ rr_stream << ";; comment line, should be skipped\n"
+ << "\n" // blank line (should be skipped)
+ << txt_rr;
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(txt_rr, results[0]->toText());
+}
+
+TEST_F(MasterLoadTest, loadRRset) {
+ // load an RRset containing two RRs
+ rr_stream << a_rr1 << a_rr2;
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(string(a_rr1) + string(a_rr2), results[0]->toText());
+}
+
+TEST_F(MasterLoadTest, loadRRsetsOfSameType) {
+ // load two RRsets with the same RR type and different owner names.
+ // the loader must distinguish them as separate RRsets.
+ rr_stream << a_rr1 << a_rr3;
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(2, results.size());
+ EXPECT_EQ(a_rr1, results[0]->toText());
+ EXPECT_EQ(a_rr3, results[1]->toText());
+}
+
+TEST_F(MasterLoadTest, loadRRsetsInterleaved) {
+ // two RRs that belongs to the same RRset (rr1 and rr2) are interleaved
+ // by another. This is an unexpected case for this loader, but it's
+ // not considered an error. The loader will simply treat them separate
+ // RRsets.
+ rr_stream << a_rr1 << a_rr3 << a_rr2;
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(3, results.size());
+ EXPECT_EQ(a_rr1, results[0]->toText());
+ EXPECT_EQ(a_rr3, results[1]->toText());
+ EXPECT_EQ(a_rr2, results[2]->toText());
+}
+
+TEST_F(MasterLoadTest, loadRRsigs) {
+ // RRSIGs of different types covered should be separated
+ rr_stream << rrsig_rr1 << rrsig_rr2;
+ masterLoad(rr_stream, origin, zclass, callback);
+ EXPECT_EQ(2, results.size());
+}
+
+// This test was disabled by #2387, because the test data has trailing
+// comments and it (eventually) uses the string RDATA constructor which
+// doesn't support them. This test should be fixed and re-enabled by
+// #2381, or deleted.
+TEST_F(MasterLoadTest, DISABLED_loadRRWithComment) {
+ // Comment at the end of line should be ignored and the RR should be
+ // accepted.
+ rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 "
+ "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
+ "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE= ; key id = 40430\n";
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::DNSKEY(), zclass,
+ dnskey_rdata)));
+}
+
+// This test was disabled by #2387, because the test data has trailing
+// comments and it (eventually) uses the string RDATA constructor which
+// doesn't support them. This test should be fixed and re-enabled by
+// #2381, or deleted.
+TEST_F(MasterLoadTest, DISABLED_loadRRWithCommentNoSpace) {
+ // Similar to the previous one, but there's no space before comments.
+ // It should still work.
+ rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 "
+ "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
+ "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=; key id = 40430\n";
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::DNSKEY(), zclass,
+ dnskey_rdata)));
+}
+
+// This test was disabled by #2387, because the test data has trailing
+// comments and it (eventually) uses the string RDATA constructor which
+// doesn't support them. This test should be fixed and re-enabled by
+// #2381, or deleted.
+TEST_F(MasterLoadTest, DISABLED_loadRRWithCommentEmptyComment) {
+ // Similar to the previous one, but there's no data after the ;
+ // It should still work.
+ rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 "
+ "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
+ "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE= ;\n";
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::DNSKEY(), zclass,
+ dnskey_rdata)));
+}
+
+// This test was disabled by #2387, because the test data has trailing
+// comments and it (eventually) uses the string RDATA constructor which
+// doesn't support them. This test should be fixed and re-enabled by
+// #2381, or deleted.
+TEST_F(MasterLoadTest, DISABLED_loadRRWithCommentEmptyCommentNoSpace) {
+ // Similar to the previous one, but there's no space before or after ;
+ // It should still work.
+ rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 "
+ "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
+ "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=;\n";
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::DNSKEY(), zclass,
+ dnskey_rdata)));
+}
+
+TEST_F(MasterLoadTest, loadRRWithEOLWhitespace) {
+ // Test with whitespace after rdata
+ // It should still work.
+ rr_stream << "example.com. 3600 IN NSEC3PARAM 1 0 1 beef \n";
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::NSEC3PARAM(), zclass,
+ "1 0 1 beef")));
+}
+
+TEST_F(MasterLoadTest, loadRRWithEOLWhitespaceTab) {
+ // Similar to the previous one, tab instead of space.
+ // It should still work.
+ rr_stream << "example.com. 3600 IN NSEC3PARAM 1 0 1 beef\t\n";
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::NSEC3PARAM(), zclass,
+ "1 0 1 beef")));
+}
+
+TEST_F(MasterLoadTest, loadRRNoComment) {
+ // A semicolon in a character-string shouldn't confuse the parser.
+ rr_stream << "example.com. 3600 IN TXT \"aaa;bbb\"\n";
+ masterLoad(rr_stream, origin, zclass, callback);
+ EXPECT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::TXT(), zclass,
+ "\"aaa;bbb\"")));
+}
+
+TEST_F(MasterLoadTest, nonAbsoluteOwner) {
+ // If the owner name is not absolute, the zone origin is assumed to be
+ // its origin.
+ rr_stream << "example.com 3600 IN A 192.0.2.1";
+ masterLoad(rr_stream, origin, zclass, callback);
+ EXPECT_EQ(1, results.size());
+ EXPECT_EQ(results[0]->getName(), Name("example.com.example.com"));
+}
+
+TEST_F(MasterLoadTest, loadRREmptyAndComment) {
+ // There's no RDATA (invalid in this case) but a comment. This position
+ // shouldn't cause any disruption and should be treated as a normal error.
+ rr_stream << "example.com. 3600 IN A ;\n";
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
+ MasterLoadError);
+}
+
+TEST_F(MasterLoadTest, loadWithNoEOF) {
+ // the input stream doesn't end with a new line (and the following blank
+ // line). It should be accepted.
+ string rr_string(a_rr1);
+ rr_string.erase(rr_string.end() - 1);
+ rr_stream << rr_string;
+ masterLoad(rr_stream, origin, zclass, callback);
+ ASSERT_EQ(1, results.size());
+ EXPECT_EQ(a_rr1, results[0]->toText());
+}
+
+TEST_F(MasterLoadTest, loadEmpty) {
+ // an unusual case: empty input. load must succeed with an empty result.
+ masterLoad(rr_stream, origin, zclass, callback);
+ EXPECT_EQ(0, results.size());
+}
+
+TEST_F(MasterLoadTest, loadWithBeginningSpace) {
+ rr_stream << " " << a_rr1;
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
+ MasterLoadError);
+}
+
+TEST_F(MasterLoadTest, loadWithBeginningTab) {
+ rr_stream << "\t" << a_rr1;
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
+ MasterLoadError);
+}
+
+TEST_F(MasterLoadTest, loadInvalidRRClass) {
+ rr_stream << "example.com. 3600 CH TXT \"test text\"";
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
+ MasterLoadError);
+}
+
+TEST_F(MasterLoadTest, loadOutOfZoneData) {
+ rr_stream << "example.org. 3600 IN A 192.0.2.255";
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
+ MasterLoadError);
+}
+
+TEST_F(MasterLoadTest, loadNonAtopSOA) {
+ // SOA's owner name must be zone's origin.
+ rr_stream << "soa.example.com. 3600 IN SOA . . 0 0 0 0 0";
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
+ MasterLoadError);
+}
+
+// Load TTL with units
+TEST_F(MasterLoadTest, loadUnitTTL) {
+ stringstream rr_stream2("example.com. 1D IN A 192.0.2.1");
+ masterLoad(rr_stream2, origin, zclass, callback);
+ EXPECT_EQ(1, results.size());
+ EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
+ *rdata::createRdata(RRType::A(), zclass, "192.0.2.1")));
+}
+
+TEST_F(MasterLoadTest, loadBadRRText) {
+ rr_stream << "example..com. 3600 IN A 192.0.2.1"; // bad owner name
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
+ MasterLoadError);
+
+ // bad RR class text
+ stringstream rr_stream3("example.com. 3600 BAD A 192.0.2.1");
+ EXPECT_THROW(masterLoad(rr_stream3, origin, zclass, callback),
+ MasterLoadError);
+
+ // bad RR type text
+ stringstream rr_stream4("example.com. 3600 IN BAD 192.0.2.1");
+ EXPECT_THROW(masterLoad(rr_stream4, origin, zclass, callback),
+ MasterLoadError);
+
+ // bad RDATA text
+ stringstream rr_stream5("example.com. 3600 IN A 2001:db8::1");
+ EXPECT_THROW(masterLoad(rr_stream5, origin, zclass, callback),
+ MasterLoadError);
+
+ // incomplete RR text
+ stringstream rr_stream6("example.com. 3600 IN A");
+ EXPECT_THROW(masterLoad(rr_stream6, origin, zclass, callback),
+ MasterLoadError);
+}
+
+// This is a helper callback to test the case the input stream becomes bad
+// in the middle of processing.
+class StreamInvalidator {
+public:
+ StreamInvalidator(stringstream& ss) : ss_(ss) {}
+ void operator()(ConstRRsetPtr) {
+ ss_.setstate(ios::badbit);
+ }
+private:
+ stringstream& ss_;
+};
+
+TEST_F(MasterLoadTest, loadBadStream) {
+ rr_stream << txt_rr << a_rr1;
+ StreamInvalidator invalidator(rr_stream);
+ EXPECT_THROW(masterLoad(rr_stream, origin, zclass, invalidator),
+ MasterLoadError);
+}
+
+TEST_F(MasterLoadTest, loadFromFile) {
+ // The main parser is shared with the stream version, so we simply test
+ // file I/O specific parts.
+ masterLoad(TEST_DATA_SRCDIR "/masterload.txt", origin, zclass, callback);
+ ASSERT_EQ(2, results.size());
+ EXPECT_EQ(txt_rr, results[0]->toText());
+ EXPECT_EQ(string(a_rr1) + string(a_rr2), results[1]->toText());
+
+ // NULL file name. Should result in exception.
+ EXPECT_THROW(masterLoad(NULL, origin, zclass, callback), MasterLoadError);
+
+ // Non existent file name. Ditto.
+ EXPECT_THROW(masterLoad(TEST_DATA_BUILDDIR "/nonexistent.txt", origin,
+ zclass, callback), MasterLoadError);
+}
+} // end namespace
diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc
new file mode 100644
index 0000000..8b6832b
--- /dev/null
+++ b/src/lib/dns/tests/message_unittest.cc
@@ -0,0 +1,1162 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <fstream>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/time_utilities.h>
+
+#include <util/unittests/testdata.h>
+#include <util/unittests/textdata.h>
+
+#include <dns/edns.h>
+#include <dns/exceptions.h>
+#include <dns/message.h>
+#include <dns/messagerenderer.h>
+#include <dns/question.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrttl.h>
+#include <dns/rrtype.h>
+#include <dns/tsig.h>
+#include <dns/tsigkey.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+//
+// Note: we need more tests, including:
+// parsing malformed headers
+// more complete tests about parsing/rendering header flags, opcode, rcode, etc.
+// tests for adding RRsets
+// tests for RRset/Question iterators
+// But, we'll ship with the current set of tests for now, partly because many
+// of the above are covered as part of other tests, and partly due to time
+// limitation. We also expect to revisit the fundamental design of the Message
+// class, at which point we'll also revise the tests including more cases.
+//
+
+const uint16_t Message::DEFAULT_MAX_UDPSIZE;
+
+namespace isc {
+namespace util {
+namespace detail {
+extern int64_t (*gettimeFunction)();
+}
+}
+}
+
+// XXX: this is defined as class static constants, but some compilers
+// seemingly cannot find the symbol when used in the EXPECT_xxx macros.
+const uint16_t TSIGContext::DEFAULT_FUDGE;
+
+namespace {
+class MessageTest : public ::testing::Test {
+protected:
+ MessageTest() : test_name("test.example.com"), obuffer(0),
+ message_parse(Message::PARSE),
+ message_render(Message::RENDER),
+ bogus_section(static_cast<Message::Section>(
+ Message::SECTION_ADDITIONAL + 1)),
+ tsig_ctx(TSIGKey("www.example.com:"
+ "SFuWd/q99SzF8Yzd1QbB9g=="))
+ {
+ rrset_a = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::A(), RRTTL(3600)));
+ rrset_a->addRdata(in::A("192.0.2.1"));
+ rrset_a->addRdata(in::A("192.0.2.2"));
+
+ rrset_aaaa = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::AAAA(), RRTTL(3600)));
+ rrset_aaaa->addRdata(in::AAAA("2001:db8::1234"));
+
+ rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ rrset_rrsig->addRdata(generic::RRSIG("AAAA 5 3 7200 20100322084538 "
+ "20100220084538 1 example.com. "
+ "FAKEFAKEFAKEFAKE"));
+ rrset_aaaa->addRRsig(rrset_rrsig);
+ }
+
+ static Question factoryFromFile(const char* datafile);
+ const Name test_name;
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+ Message message_parse;
+ Message message_render;
+ const Message::Section bogus_section;
+ RRsetPtr rrset_a; // A RRset with two RDATAs
+ RRsetPtr rrset_aaaa; // AAAA RRset with one RDATA with RRSIG
+ RRsetPtr rrset_rrsig; // RRSIG for the AAAA RRset
+ TSIGContext tsig_ctx;
+ vector<unsigned char> received_data;
+ vector<unsigned char> expected_data;
+
+ void factoryFromFile(Message& message, const char* datafile,
+ Message::ParseOptions options =
+ Message::PARSE_DEFAULT);
+};
+
+void
+MessageTest::factoryFromFile(Message& message, const char* datafile,
+ Message::ParseOptions options)
+{
+ received_data.clear();
+ UnitTestUtil::readWireData(datafile, received_data);
+
+ InputBuffer buffer(&received_data[0], received_data.size());
+ message.fromWire(buffer, options);
+}
+
+TEST_F(MessageTest, headerFlag) {
+ // by default no flag is set
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_QR));
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_AA));
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_TC));
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_RD));
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_RA));
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_AD));
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_CD));
+
+ // set operation: by default it will be on
+ message_render.setHeaderFlag(Message::HEADERFLAG_QR);
+ EXPECT_TRUE(message_render.getHeaderFlag(Message::HEADERFLAG_QR));
+
+ // it can be set to on explicitly, too
+ message_render.setHeaderFlag(Message::HEADERFLAG_AA, true);
+ EXPECT_TRUE(message_render.getHeaderFlag(Message::HEADERFLAG_AA));
+
+ // the bit can also be cleared
+ message_render.setHeaderFlag(Message::HEADERFLAG_AA, false);
+ EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_AA));
+
+ // Invalid flag values
+ EXPECT_THROW(message_render.setHeaderFlag(
+ static_cast<Message::HeaderFlag>(0)), InvalidParameter);
+ EXPECT_THROW(message_render.setHeaderFlag(
+ static_cast<Message::HeaderFlag>(0x7000)),
+ InvalidParameter);
+ EXPECT_THROW(message_render.setHeaderFlag(
+ static_cast<Message::HeaderFlag>(0x0800)),
+ InvalidParameter);
+ EXPECT_THROW(message_render.setHeaderFlag(
+ static_cast<Message::HeaderFlag>(0x0040)),
+ InvalidParameter);
+ EXPECT_THROW(message_render.setHeaderFlag(
+ static_cast<Message::HeaderFlag>(0x10000)),
+ InvalidParameter);
+ EXPECT_THROW(message_render.setHeaderFlag(
+ static_cast<Message::HeaderFlag>(0x80000000)),
+ InvalidParameter);
+
+ // set operation isn't allowed in the parse mode.
+ EXPECT_THROW(message_parse.setHeaderFlag(Message::HEADERFLAG_QR),
+ InvalidMessageOperation);
+}
+TEST_F(MessageTest, getEDNS) {
+ EXPECT_FALSE(message_parse.getEDNS()); // by default EDNS isn't set
+
+ factoryFromFile(message_parse, "message_fromWire10.wire");
+ EXPECT_TRUE(message_parse.getEDNS());
+ EXPECT_EQ(0, message_parse.getEDNS()->getVersion());
+ EXPECT_EQ(4096, message_parse.getEDNS()->getUDPSize());
+ EXPECT_TRUE(message_parse.getEDNS()->getDNSSECAwareness());
+}
+
+TEST_F(MessageTest, setEDNS) {
+ // setEDNS() isn't allowed in the parse mode
+ EXPECT_THROW(message_parse.setEDNS(EDNSPtr(new EDNS())),
+ InvalidMessageOperation);
+
+ EDNSPtr edns = EDNSPtr(new EDNS());
+ message_render.setEDNS(edns);
+ EXPECT_EQ(edns, message_render.getEDNS());
+}
+
+TEST_F(MessageTest, fromWireWithTSIG) {
+ // Initially there should be no TSIG
+ EXPECT_EQ(static_cast<void*>(NULL), message_parse.getTSIGRecord());
+
+ // getTSIGRecord() is only valid in the parse mode.
+ EXPECT_THROW(message_render.getTSIGRecord(), InvalidMessageOperation);
+
+ factoryFromFile(message_parse, "message_toWire2.wire");
+ const uint8_t expected_mac[] = {
+ 0x22, 0x70, 0x26, 0xad, 0x29, 0x7b, 0xee, 0xe7,
+ 0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3
+ };
+ const TSIGRecord* tsig_rr = message_parse.getTSIGRecord();
+ ASSERT_NE(static_cast<void*>(NULL), tsig_rr);
+ EXPECT_EQ(Name("www.example.com"), tsig_rr->getName());
+ EXPECT_EQ(85, tsig_rr->getLength()); // see TSIGRecordTest.getLength
+ EXPECT_EQ(TSIGKey::HMACMD5_NAME(), tsig_rr->getRdata().getAlgorithm());
+ EXPECT_EQ(0x4da8877a, tsig_rr->getRdata().getTimeSigned());
+ EXPECT_EQ(TSIGContext::DEFAULT_FUDGE, tsig_rr->getRdata().getFudge());
+ matchWireData(expected_mac, sizeof(expected_mac),
+ tsig_rr->getRdata().getMAC(),
+ tsig_rr->getRdata().getMACSize());
+ EXPECT_EQ(0, tsig_rr->getRdata().getError());
+ EXPECT_EQ(0, tsig_rr->getRdata().getOtherLen());
+ EXPECT_EQ(static_cast<void*>(NULL), tsig_rr->getRdata().getOtherData());
+
+ // If we clear the message for reuse, the recorded TSIG will be cleared.
+ message_parse.clear(Message::PARSE);
+ EXPECT_EQ(static_cast<void*>(NULL), message_parse.getTSIGRecord());
+}
+
+TEST_F(MessageTest, fromWireWithTSIGCompressed) {
+ // Mostly same as fromWireWithTSIG, but the TSIG owner name is compressed.
+ factoryFromFile(message_parse, "message_fromWire12.wire");
+ const TSIGRecord* tsig_rr = message_parse.getTSIGRecord();
+ ASSERT_NE(static_cast<void*>(NULL), tsig_rr);
+ EXPECT_EQ(Name("www.example.com"), tsig_rr->getName());
+ // len(www.example.com) = 17, but when fully compressed, the length is
+ // 2 bytes. So the length of the record should be 15 bytes shorter.
+ EXPECT_EQ(70, tsig_rr->getLength());
+}
+
+TEST_F(MessageTest, fromWireWithBadTSIG) {
+ // Multiple TSIG RRs
+ EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire13.wire"),
+ DNSMessageFORMERR);
+ message_parse.clear(Message::PARSE);
+
+ // TSIG in the answer section (must be in additional)
+ EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire14.wire"),
+ DNSMessageFORMERR);
+ message_parse.clear(Message::PARSE);
+
+ // TSIG is not the last record.
+ EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire15.wire"),
+ DNSMessageFORMERR);
+ message_parse.clear(Message::PARSE);
+
+ // Unexpected RR Class (this will fail in constructing TSIGRecord)
+ EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire16.wire"),
+ DNSMessageFORMERR);
+}
+
+TEST_F(MessageTest, getRRCount) {
+ // by default all counters should be 0
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+
+ message_render.addQuestion(Question(Name("test.example.com"),
+ RRClass::IN(), RRType::A()));
+ EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION));
+
+ // rrset_a contains two RRs
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+ EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER));
+
+ // parse a message containing a Question and EDNS OPT RR.
+ // OPT shouldn't be counted as normal RR, so result of getRRCount
+ // shouldn't change.
+ factoryFromFile(message_parse, "message_fromWire11.wire");
+ EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+
+ // out-of-band section ID
+ EXPECT_THROW(message_parse.getRRCount(bogus_section), OutOfRange);
+}
+
+TEST_F(MessageTest, addRRset) {
+ // initially, we have 0
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ANSWER));
+
+ // add two A RRs (unsigned)
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+ EXPECT_EQ(rrset_a,
+ *message_render.beginSection(Message::SECTION_ANSWER));
+ EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER));
+
+ message_render.clear(Message::RENDER);
+
+ // add one AAAA RR (signed)
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_aaaa);
+ EXPECT_EQ(rrset_aaaa,
+ *message_render.beginSection(Message::SECTION_ANSWER));
+ EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER));
+}
+
+TEST_F(MessageTest, badAddRRset) {
+ // addRRset() isn't allowed in the parse mode.
+ EXPECT_THROW(message_parse.addRRset(Message::SECTION_ANSWER,
+ rrset_a), InvalidMessageOperation);
+ // out-of-band section ID
+ EXPECT_THROW(message_render.addRRset(bogus_section, rrset_a), OutOfRange);
+
+ // NULL RRset
+ EXPECT_THROW(message_render.addRRset(Message::SECTION_ANSWER, RRsetPtr()),
+ InvalidParameter);
+}
+
+TEST_F(MessageTest, hasRRset) {
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+ EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::A()));
+ // section doesn't match
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+ RRClass::IN(), RRType::A()));
+ // name doesn't match
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER,
+ Name("nomatch.example"),
+ RRClass::IN(), RRType::A()));
+ // RR class doesn't match
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::CH(), RRType::A()));
+ // RR type doesn't match
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::AAAA()));
+
+ // out-of-band section ID
+ EXPECT_THROW(message_render.hasRRset(bogus_section, test_name,
+ RRClass::IN(), RRType::A()),
+ OutOfRange);
+
+ // Repeat the checks having created an RRset of the appropriate type.
+
+ RRsetPtr rrs1(new RRset(test_name, RRClass::IN(), RRType::A(), RRTTL(60)));
+ EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, rrs1));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, rrs1));
+
+ RRsetPtr rrs2(new RRset(Name("nomatch.example"), RRClass::IN(), RRType::A(),
+ RRTTL(5)));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs2));
+
+ RRsetPtr rrs3(new RRset(test_name, RRClass::CH(), RRType::A(), RRTTL(60)));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs3));
+
+ RRsetPtr rrs4(new RRset(test_name, RRClass::IN(), RRType::AAAA(), RRTTL(5)));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs4));
+
+ RRsetPtr rrs5(new RRset(test_name, RRClass::IN(), RRType::AAAA(), RRTTL(5)));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs4));
+
+ EXPECT_THROW(message_render.hasRRset(bogus_section, rrs1), OutOfRange);
+}
+
+TEST_F(MessageTest, removeRRset) {
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_aaaa);
+ EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::A()));
+ EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ EXPECT_EQ(4, message_render.getRRCount(Message::SECTION_ANSWER));
+
+ // Locate the AAAA RRset and remove it and any associated RRSIGs
+ RRsetIterator i = message_render.beginSection(Message::SECTION_ANSWER);
+ if ((*i)->getType() == RRType::A()) {
+ ++i;
+ }
+ EXPECT_EQ(RRType::AAAA(), (*i)->getType());
+ message_render.removeRRset(Message::SECTION_ANSWER, i);
+
+ EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::A()));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER));
+}
+
+TEST_F(MessageTest, clearQuestionSection) {
+ QuestionPtr q(new Question(Name("www.example.com"), RRClass::IN(),
+ RRType::A()));
+ message_render.addQuestion(q);
+ ASSERT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION));
+
+ message_render.clearSection(Message::SECTION_QUESTION);
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_TRUE(message_render.beginQuestion() ==
+ message_render.endQuestion());
+}
+
+
+TEST_F(MessageTest, clearAnswerSection) {
+ // Add two RRsets, check they are present, clear the section,
+ // check if they are gone.
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_aaaa);
+ ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::A()));
+ ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ ASSERT_EQ(4, message_render.getRRCount(Message::SECTION_ANSWER));
+
+ message_render.clearSection(Message::SECTION_ANSWER);
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::A()));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ANSWER));
+}
+
+TEST_F(MessageTest, clearAuthoritySection) {
+ // Add two RRsets, check they are present, clear the section,
+ // check if they are gone.
+ message_render.addRRset(Message::SECTION_AUTHORITY, rrset_a);
+ message_render.addRRset(Message::SECTION_AUTHORITY, rrset_aaaa);
+ ASSERT_TRUE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+ RRClass::IN(), RRType::A()));
+ ASSERT_TRUE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ ASSERT_EQ(4, message_render.getRRCount(Message::SECTION_AUTHORITY));
+
+ message_render.clearSection(Message::SECTION_AUTHORITY);
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+ RRClass::IN(), RRType::A()));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY));
+}
+
+TEST_F(MessageTest, clearAdditionalSection) {
+ // Add two RRsets, check they are present, clear the section,
+ // check if they are gone.
+ message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_a);
+ message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_aaaa);
+ ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+ RRClass::IN(), RRType::A()));
+ ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ ASSERT_EQ(4, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+
+ message_render.clearSection(Message::SECTION_ADDITIONAL);
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+ RRClass::IN(), RRType::A()));
+ EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+ RRClass::IN(), RRType::AAAA()));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+}
+
+TEST_F(MessageTest, badClearSection) {
+ // attempt of clearing a message in the parse mode.
+ EXPECT_THROW(message_parse.clearSection(Message::SECTION_QUESTION),
+ InvalidMessageOperation);
+ // attempt of clearing out-of-range section
+ EXPECT_THROW(message_render.clearSection(bogus_section), OutOfRange);
+}
+
+TEST_F(MessageTest, badBeginSection) {
+ // valid cases are tested via other tests
+ EXPECT_THROW(message_render.beginSection(Message::SECTION_QUESTION),
+ InvalidMessageSection);
+ EXPECT_THROW(message_render.beginSection(bogus_section), OutOfRange);
+}
+
+TEST_F(MessageTest, badEndSection) {
+ // valid cases are tested via other tests
+ EXPECT_THROW(message_render.endSection(Message::SECTION_QUESTION),
+ InvalidMessageSection);
+ EXPECT_THROW(message_render.endSection(bogus_section), OutOfRange);
+}
+
+TEST_F(MessageTest, appendSection) {
+ Message target(Message::RENDER);
+
+ // Section check
+ EXPECT_THROW(target.appendSection(bogus_section, message_render),
+ OutOfRange);
+
+ // Make sure nothing is copied if there is nothing to copy
+ target.appendSection(Message::SECTION_QUESTION, message_render);
+ EXPECT_EQ(0, target.getRRCount(Message::SECTION_QUESTION));
+ target.appendSection(Message::SECTION_ANSWER, message_render);
+ EXPECT_EQ(0, target.getRRCount(Message::SECTION_ANSWER));
+ target.appendSection(Message::SECTION_AUTHORITY, message_render);
+ EXPECT_EQ(0, target.getRRCount(Message::SECTION_AUTHORITY));
+ target.appendSection(Message::SECTION_ADDITIONAL, message_render);
+ EXPECT_EQ(0, target.getRRCount(Message::SECTION_ADDITIONAL));
+
+ // Now add some data, copy again, and see if it got added
+ message_render.addQuestion(Question(Name("test.example.com"),
+ RRClass::IN(), RRType::A()));
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+ message_render.addRRset(Message::SECTION_AUTHORITY, rrset_a);
+ message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_a);
+ message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_aaaa);
+
+ target.appendSection(Message::SECTION_QUESTION, message_render);
+ EXPECT_EQ(1, target.getRRCount(Message::SECTION_QUESTION));
+
+ target.appendSection(Message::SECTION_ANSWER, message_render);
+ EXPECT_EQ(2, target.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_TRUE(target.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::A()));
+
+ target.appendSection(Message::SECTION_AUTHORITY, message_render);
+ EXPECT_EQ(2, target.getRRCount(Message::SECTION_AUTHORITY));
+ EXPECT_TRUE(target.hasRRset(Message::SECTION_AUTHORITY, test_name,
+ RRClass::IN(), RRType::A()));
+
+ target.appendSection(Message::SECTION_ADDITIONAL, message_render);
+ EXPECT_EQ(4, target.getRRCount(Message::SECTION_ADDITIONAL));
+ EXPECT_TRUE(target.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+ RRClass::IN(), RRType::A()));
+ EXPECT_TRUE(target.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+ RRClass::IN(), RRType::AAAA()));
+
+ // One more test, test to see if the section gets added, not replaced
+ Message source2(Message::RENDER);
+ source2.addRRset(Message::SECTION_ANSWER, rrset_aaaa);
+ target.appendSection(Message::SECTION_ANSWER, source2);
+ EXPECT_EQ(4, target.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_TRUE(target.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::A()));
+ EXPECT_TRUE(target.hasRRset(Message::SECTION_ANSWER, test_name,
+ RRClass::IN(), RRType::AAAA()));
+
+}
+
+TEST_F(MessageTest, parseHeader) {
+ received_data.clear();
+ UnitTestUtil::readWireData("message_fromWire1", received_data);
+
+ // parseHeader() isn't allowed in the render mode.
+ InputBuffer buffer(&received_data[0], received_data.size());
+ EXPECT_THROW(message_render.parseHeader(buffer), InvalidMessageOperation);
+
+ message_parse.parseHeader(buffer);
+ EXPECT_EQ(0x1035, message_parse.getQid());
+ EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode());
+ EXPECT_EQ(Rcode::NOERROR(), message_parse.getRcode());
+ EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_QR));
+ EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_AA));
+ EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_TC));
+ EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_RD));
+ EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_RA));
+ EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_AD));
+ EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_CD));
+ EXPECT_EQ(1, message_parse.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_EQ(2, message_parse.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_AUTHORITY));
+ EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_ADDITIONAL));
+
+ // Only the header part should have been examined.
+ EXPECT_EQ(12, buffer.getPosition()); // 12 = size of the header section
+ EXPECT_TRUE(message_parse.beginQuestion() == message_parse.endQuestion());
+ EXPECT_TRUE(message_parse.beginSection(Message::SECTION_ANSWER) ==
+ message_parse.endSection(Message::SECTION_ANSWER));
+ EXPECT_TRUE(message_parse.beginSection(Message::SECTION_AUTHORITY) ==
+ message_parse.endSection(Message::SECTION_AUTHORITY));
+ EXPECT_TRUE(message_parse.beginSection(Message::SECTION_ADDITIONAL) ==
+ message_parse.endSection(Message::SECTION_ADDITIONAL));
+}
+
+void
+checkMessageFromWire(const Message& message_parse,
+ const Name& test_name)
+{
+ EXPECT_EQ(0x1035, message_parse.getQid());
+ EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode());
+ EXPECT_EQ(Rcode::NOERROR(), message_parse.getRcode());
+ EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_QR));
+ EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_RD));
+ EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_AA));
+
+ QuestionPtr q = *message_parse.beginQuestion();
+ EXPECT_EQ(test_name, q->getName());
+ EXPECT_EQ(RRType::A(), q->getType());
+ EXPECT_EQ(RRClass::IN(), q->getClass());
+ EXPECT_EQ(1, message_parse.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_EQ(2, message_parse.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_AUTHORITY));
+ EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_ADDITIONAL));
+
+ RRsetPtr rrset = *message_parse.beginSection(Message::SECTION_ANSWER);
+ EXPECT_EQ(test_name, rrset->getName());
+ EXPECT_EQ(RRType::A(), rrset->getType());
+ EXPECT_EQ(RRClass::IN(), rrset->getClass());
+ // TTL should be 3600, even though that of the 2nd RR is 7200
+ EXPECT_EQ(RRTTL(3600), rrset->getTTL());
+ RdataIteratorPtr it = rrset->getRdataIterator();
+ EXPECT_EQ("192.0.2.1", it->getCurrent().toText());
+ it->next();
+ EXPECT_EQ("192.0.2.2", it->getCurrent().toText());
+ it->next();
+ EXPECT_TRUE(it->isLast());
+}
+
+
+TEST_F(MessageTest, fromWire) {
+ // fromWire() isn't allowed in the render mode.
+ EXPECT_THROW(factoryFromFile(message_render, "message_fromWire1"),
+ InvalidMessageOperation);
+
+ factoryFromFile(message_parse, "message_fromWire1");
+ checkMessageFromWire(message_parse, test_name);
+}
+
+TEST_F(MessageTest, fromWireMultiple) {
+ // Parse from wire multiple times.
+ factoryFromFile(message_parse, "message_fromWire1");
+ factoryFromFile(message_parse, "message_fromWire1");
+ factoryFromFile(message_parse, "message_fromWire1");
+ factoryFromFile(message_parse, "message_fromWire1");
+ checkMessageFromWire(message_parse, test_name);
+
+ // Calling parseHeader() directly before fromWire() should not cause
+ // any problems.
+ received_data.clear();
+ UnitTestUtil::readWireData("message_fromWire1", received_data);
+
+ InputBuffer buffer(&received_data[0], received_data.size());
+ message_parse.parseHeader(buffer);
+ message_parse.fromWire(buffer);
+ message_parse.parseHeader(buffer);
+ message_parse.fromWire(buffer);
+ checkMessageFromWire(message_parse, test_name);
+}
+
+TEST_F(MessageTest, fromWireShortBuffer) {
+ // We trim a valid message (ending with an SOA RR) for one byte.
+ // fromWire() should throw an exception while parsing the trimmed RR.
+ UnitTestUtil::readWireData("message_fromWire22.wire", received_data);
+ InputBuffer buffer(&received_data[0], received_data.size() - 1);
+ EXPECT_THROW(message_parse.fromWire(buffer), InvalidBufferPosition);
+}
+
+TEST_F(MessageTest, fromWireCombineRRs) {
+ // This message contains 3 RRs in the answer section in the order of
+ // A, AAAA, A types. fromWire() should combine the two A RRs into a
+ // single RRset by default.
+ factoryFromFile(message_parse, "message_fromWire19.wire");
+
+ RRsetIterator it = message_parse.beginSection(Message::SECTION_ANSWER);
+ RRsetIterator it_end = message_parse.endSection(Message::SECTION_ANSWER);
+ ASSERT_TRUE(it != it_end);
+ EXPECT_EQ(RRType::A(), (*it)->getType());
+ EXPECT_EQ(2, (*it)->getRdataCount());
+
+ ++it;
+ ASSERT_TRUE(it != it_end);
+ EXPECT_EQ(RRType::AAAA(), (*it)->getType());
+ EXPECT_EQ(1, (*it)->getRdataCount());
+}
+
+// A helper function for a test pattern commonly used in several tests below.
+void
+preserveRRCheck(const Message& message, Message::Section section) {
+ RRsetIterator it = message.beginSection(section);
+ RRsetIterator it_end = message.endSection(section);
+ ASSERT_TRUE(it != it_end);
+ EXPECT_EQ(RRType::A(), (*it)->getType());
+ EXPECT_EQ(1, (*it)->getRdataCount());
+ EXPECT_EQ("192.0.2.1", (*it)->getRdataIterator()->getCurrent().toText());
+
+ ++it;
+ ASSERT_TRUE(it != it_end);
+ EXPECT_EQ(RRType::AAAA(), (*it)->getType());
+ EXPECT_EQ(1, (*it)->getRdataCount());
+ EXPECT_EQ("2001:db8::1", (*it)->getRdataIterator()->getCurrent().toText());
+
+ ++it;
+ ASSERT_TRUE(it != it_end);
+ EXPECT_EQ(RRType::A(), (*it)->getType());
+ EXPECT_EQ(1, (*it)->getRdataCount());
+ EXPECT_EQ("192.0.2.2", (*it)->getRdataIterator()->getCurrent().toText());
+}
+
+TEST_F(MessageTest, fromWirePreserveAnswer) {
+ // Using the same data as the previous test, but specify the PRESERVE_ORDER
+ // option. The received order of RRs should be preserved, and each RR
+ // should be stored in a single RRset.
+ factoryFromFile(message_parse, "message_fromWire19.wire",
+ Message::PRESERVE_ORDER);
+ {
+ SCOPED_TRACE("preserve answer RRs");
+ preserveRRCheck(message_parse, Message::SECTION_ANSWER);
+ }
+}
+
+TEST_F(MessageTest, fromWirePreserveAuthority) {
+ // Same for the previous test, but for the authority section.
+ factoryFromFile(message_parse, "message_fromWire20.wire",
+ Message::PRESERVE_ORDER);
+ {
+ SCOPED_TRACE("preserve authority RRs");
+ preserveRRCheck(message_parse, Message::SECTION_AUTHORITY);
+ }
+}
+
+TEST_F(MessageTest, fromWirePreserveAdditional) {
+ // Same for the previous test, but for the additional section.
+ factoryFromFile(message_parse, "message_fromWire21.wire",
+ Message::PRESERVE_ORDER);
+ {
+ SCOPED_TRACE("preserve additional RRs");
+ preserveRRCheck(message_parse, Message::SECTION_ADDITIONAL);
+ }
+}
+
+TEST_F(MessageTest, EDNS0ExtRcode) {
+ // Extended Rcode = BADVERS
+ factoryFromFile(message_parse, "message_fromWire10.wire");
+ EXPECT_EQ(Rcode::BADVERS(), message_parse.getRcode());
+
+ // Maximum extended Rcode
+ message_parse.clear(Message::PARSE);
+ factoryFromFile(message_parse, "message_fromWire11.wire");
+ EXPECT_EQ(0xfff, message_parse.getRcode().getCode());
+}
+
+TEST_F(MessageTest, BadEDNS0) {
+ // OPT RR in the answer section
+ EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire4"),
+ DNSMessageFORMERR);
+ // multiple OPT RRs (in the additional section)
+ message_parse.clear(Message::PARSE);
+ EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire5"),
+ DNSMessageFORMERR);
+}
+
+TEST_F(MessageTest, toWire) {
+ message_render.setQid(0x1035);
+ message_render.setOpcode(Opcode::QUERY());
+ message_render.setRcode(Rcode::NOERROR());
+ message_render.setHeaderFlag(Message::HEADERFLAG_QR, true);
+ message_render.setHeaderFlag(Message::HEADERFLAG_RD, true);
+ message_render.setHeaderFlag(Message::HEADERFLAG_AA, true);
+ message_render.addQuestion(Question(Name("test.example.com"), RRClass::IN(),
+ RRType::A()));
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+
+ EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+
+ message_render.toWire(renderer);
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("message_toWire1", data);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageTest, toWireSigned) {
+ message_render.setQid(0x75c1);
+ message_render.setOpcode(Opcode::QUERY());
+ message_render.setRcode(Rcode::NOERROR());
+ message_render.setHeaderFlag(Message::HEADERFLAG_QR, true);
+ message_render.setHeaderFlag(Message::HEADERFLAG_RD, true);
+ message_render.setHeaderFlag(Message::HEADERFLAG_AA, true);
+ message_render.addQuestion(Question(Name("test.example.com"), RRClass::IN(),
+ RRType::A()));
+
+ rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ // one signature algorithm (5 = RSA/SHA-1)
+ rrset_rrsig->addRdata(generic::RRSIG("A 5 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ // another signature algorithm (3 = DSA/SHA-1)
+ rrset_rrsig->addRdata(generic::RRSIG("A 3 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ rrset_a->addRRsig(rrset_rrsig);
+ EXPECT_EQ(2, rrset_a->getRRsigDataCount());
+
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+
+ EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_EQ(4, message_render.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+
+ message_render.toWire(renderer);
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("message_toWire6", data);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageTest, toWireSignedAndTruncated) {
+ message_render.setQid(0x75c1);
+ message_render.setOpcode(Opcode::QUERY());
+ message_render.setRcode(Rcode::NOERROR());
+ message_render.setHeaderFlag(Message::HEADERFLAG_QR, true);
+ message_render.setHeaderFlag(Message::HEADERFLAG_RD, true);
+ message_render.setHeaderFlag(Message::HEADERFLAG_AA, true);
+ message_render.addQuestion(Question(Name("test.example.com"), RRClass::IN(),
+ RRType::TXT()));
+
+ RRsetPtr rrset_txt = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::TXT(), RRTTL(3600)));
+ rrset_txt->addRdata(generic::TXT(string(255, 'a')));
+ rrset_txt->addRdata(generic::TXT(string(255, 'b')));
+ rrset_txt->addRdata(generic::TXT(string(255, 'c')));
+ rrset_txt->addRdata(generic::TXT(string(255, 'd')));
+ rrset_txt->addRdata(generic::TXT(string(255, 'e')));
+ rrset_txt->addRdata(generic::TXT(string(255, 'f')));
+ rrset_txt->addRdata(generic::TXT(string(255, 'g')));
+ rrset_txt->addRdata(generic::TXT(string(255, 'h')));
+
+ rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ // one signature algorithm (5 = RSA/SHA-1)
+ rrset_rrsig->addRdata(generic::RRSIG("TXT 5 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ rrset_txt->addRRsig(rrset_rrsig);
+ EXPECT_EQ(1, rrset_txt->getRRsigDataCount());
+
+ message_render.addRRset(Message::SECTION_ANSWER, rrset_txt);
+
+ EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_EQ(9, message_render.getRRCount(Message::SECTION_ANSWER));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY));
+ EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+
+ message_render.toWire(renderer);
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("message_toWire7", data);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageTest, toWireInParseMode) {
+ // toWire() isn't allowed in the parse mode.
+ EXPECT_THROW(message_parse.toWire(renderer), InvalidMessageOperation);
+}
+
+// See dnssectime_unittest.cc
+template <int64_t NOW>
+int64_t
+testGetTime() {
+ return (NOW);
+}
+
+// bit-wise constant flags to configure DNS header flags for test
+// messages.
+const unsigned int QR_FLAG = 0x1;
+const unsigned int AA_FLAG = 0x2;
+const unsigned int RD_FLAG = 0x4;
+
+void
+commonTSIGToWireCheck(Message& message, MessageRenderer& renderer,
+ TSIGContext& tsig_ctx, const char* const expected_file,
+ unsigned int message_flags = RD_FLAG,
+ RRType qtype = RRType::A(),
+ const vector<const char*>* answer_data = NULL)
+{
+ message.setOpcode(Opcode::QUERY());
+ message.setRcode(Rcode::NOERROR());
+ if ((message_flags & QR_FLAG) != 0) {
+ message.setHeaderFlag(Message::HEADERFLAG_QR);
+ }
+ if ((message_flags & AA_FLAG) != 0) {
+ message.setHeaderFlag(Message::HEADERFLAG_AA);
+ }
+ if ((message_flags & RD_FLAG) != 0) {
+ message.setHeaderFlag(Message::HEADERFLAG_RD);
+ }
+ message.addQuestion(Question(Name("www.example.com"), RRClass::IN(),
+ qtype));
+
+ if (answer_data != NULL) {
+ RRsetPtr ans_rrset(new RRset(Name("www.example.com"), RRClass::IN(),
+ qtype, RRTTL(86400)));
+ for (vector<const char*>::const_iterator it = answer_data->begin();
+ it != answer_data->end();
+ ++it) {
+ ans_rrset->addRdata(createRdata(qtype, RRClass::IN(), *it));
+ }
+ message.addRRset(Message::SECTION_ANSWER, ans_rrset);
+ }
+
+ message.toWire(renderer, &tsig_ctx);
+ vector<unsigned char> expected_data;
+ UnitTestUtil::readWireData(expected_file, expected_data);
+ matchWireData(&expected_data[0], expected_data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageTest, toWireWithTSIG) {
+ // Rendering a message with TSIG. Various special cases specific to
+ // TSIG are tested in the tsig tests. We only check the message contains
+ // a TSIG at the end and the ARCOUNT of the header is updated.
+
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ message_render.setQid(0x2d65);
+
+ {
+ SCOPED_TRACE("Message sign with TSIG");
+ commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+ "message_toWire2.wire");
+ }
+}
+
+TEST_F(MessageTest, toWireWithEDNSAndTSIG) {
+ // Similar to the previous test, but with an EDNS before TSIG.
+ // The wire data check will confirm the ordering.
+ isc::util::detail::gettimeFunction = testGetTime<0x4db60d1f>;
+
+ message_render.setQid(0x6cd);
+
+ EDNSPtr edns(new EDNS());
+ edns->setUDPSize(4096);
+ message_render.setEDNS(edns);
+
+ {
+ SCOPED_TRACE("Message sign with TSIG and EDNS");
+ commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+ "message_toWire3.wire");
+ }
+}
+
+// Some of the following tests involve truncation. We use the query name
+// "www.example.com" and some TXT question/answers. The length of the
+// header and question will be 33 bytes. If we also try to include a
+// TSIG of the same key name (not compressed) with HMAC-MD5, the TSIG RR
+// will be 85 bytes.
+
+// A long TXT RDATA. With a fully compressed owner name, the corresponding
+// RR will be 268 bytes.
+const char* const long_txt1 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde";
+
+// With a fully compressed owner name, the corresponding RR will be 212 bytes.
+// It should result in truncation even without TSIG (33 + 268 + 212 = 513)
+const char* const long_txt2 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456";
+
+// With a fully compressed owner name, the corresponding RR will be 127 bytes.
+// So, it can fit in the standard 512 bytes with txt1 and without TSIG, but
+// adding a TSIG would result in truncation (33 + 268 + 127 + 85 = 513)
+const char* const long_txt3 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01";
+
+// This is 1 byte shorter than txt3, which will result in a possible longest
+// message containing answer RRs and TSIG.
+const char* const long_txt4 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0";
+
+// Example output generated by
+// "dig -y www.example.com:SFuWd/q99SzF8Yzd1QbB9g== www.example.com txt
+// QID: 0x22c2
+// Time Signed: 0x00004e179212
+TEST_F(MessageTest, toWireTSIGTruncation) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4e179212>;
+
+ // Verify a validly signed query so that we can use the TSIG context
+
+ factoryFromFile(message_parse, "message_fromWire17.wire");
+ EXPECT_EQ(TSIGError::NOERROR(),
+ tsig_ctx.verify(message_parse.getTSIGRecord(),
+ &received_data[0], received_data.size()));
+
+ message_render.setQid(0x22c2);
+ vector<const char*> answer_data;
+ answer_data.push_back(long_txt1);
+ answer_data.push_back(long_txt2);
+ {
+ SCOPED_TRACE("Message sign with TSIG and TC bit on");
+ commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+ "message_toWire4.wire",
+ QR_FLAG|AA_FLAG|RD_FLAG,
+ RRType::TXT(), &answer_data);
+ }
+}
+
+TEST_F(MessageTest, toWireTSIGTruncation2) {
+ // Similar to the previous test, but without TSIG it wouldn't cause
+ // truncation.
+ isc::util::detail::gettimeFunction = testGetTime<0x4e179212>;
+ factoryFromFile(message_parse, "message_fromWire17.wire");
+ EXPECT_EQ(TSIGError::NOERROR(),
+ tsig_ctx.verify(message_parse.getTSIGRecord(),
+ &received_data[0], received_data.size()));
+
+ message_render.setQid(0x22c2);
+ vector<const char*> answer_data;
+ answer_data.push_back(long_txt1);
+ answer_data.push_back(long_txt3);
+ {
+ SCOPED_TRACE("Message sign with TSIG and TC bit on (2)");
+ commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+ "message_toWire4.wire",
+ QR_FLAG|AA_FLAG|RD_FLAG,
+ RRType::TXT(), &answer_data);
+ }
+}
+
+TEST_F(MessageTest, toWireTSIGTruncation3) {
+ // Similar to previous ones, but truncation occurs due to too many
+ // Questions (very unusual, but not necessarily illegal).
+
+ // We are going to create a message starting with a standard
+ // header (12 bytes) and multiple questions in the Question
+ // section of the same owner name (changing the RRType, just so
+ // that it would be the form that would be accepted by the BIND 9
+ // parser). The first Question is 21 bytes in length, and the subsequent
+ // ones are 6 bytes. We'll also use a TSIG whose size is 85 bytes.
+ // Up to 66 questions can fit in the standard 512-byte buffer
+ // (12 + 21 + 6 * 65 + 85 = 508). If we try to add one more it would
+ // result in truncation.
+ message_render.setOpcode(Opcode::QUERY());
+ message_render.setRcode(Rcode::NOERROR());
+ for (int i = 1; i <= 67; ++i) {
+ message_render.addQuestion(Question(Name("www.example.com"),
+ RRClass::IN(), RRType(i)));
+ }
+ message_render.toWire(renderer, &tsig_ctx);
+
+ // Check the rendered data by parsing it. We only check it has the
+ // TC bit on, has the correct number of questions, and has a TSIG RR.
+ // Checking the signature wouldn't be necessary for this rare case
+ // scenario.
+ InputBuffer buffer(renderer.getData(), renderer.getLength());
+ message_parse.fromWire(buffer);
+ EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_TC));
+ // Note that the number of questions are 66, not 67 as we tried to add.
+ EXPECT_EQ(66, message_parse.getRRCount(Message::SECTION_QUESTION));
+ EXPECT_TRUE(message_parse.getTSIGRecord() != NULL);
+}
+
+TEST_F(MessageTest, toWireTSIGNoTruncation) {
+ // A boundary case that shouldn't cause truncation: the resulting
+ // response message with a TSIG will be 512 bytes long.
+ isc::util::detail::gettimeFunction = testGetTime<0x4e17b38d>;
+ factoryFromFile(message_parse, "message_fromWire18.wire");
+ EXPECT_EQ(TSIGError::NOERROR(),
+ tsig_ctx.verify(message_parse.getTSIGRecord(),
+ &received_data[0], received_data.size()));
+
+ message_render.setQid(0xd6e2);
+ vector<const char*> answer_data;
+ answer_data.push_back(long_txt1);
+ answer_data.push_back(long_txt4);
+ {
+ SCOPED_TRACE("Message sign with TSIG, no truncation");
+ commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+ "message_toWire5.wire",
+ QR_FLAG|AA_FLAG|RD_FLAG,
+ RRType::TXT(), &answer_data);
+ }
+}
+
+// This is a buggy renderer for testing. It behaves like the straightforward
+// MessageRenderer, but once it has some data, its setLengthLimit() ignores
+// the given parameter and resets the limit to the current length, making
+// subsequent insertion result in truncation, which would make TSIG RR
+// rendering fail unexpectedly in the test that follows.
+class BadRenderer : public MessageRenderer {
+public:
+ virtual void setLengthLimit(size_t len) {
+ if (getLength() > 0) {
+ MessageRenderer::setLengthLimit(getLength());
+ } else {
+ MessageRenderer::setLengthLimit(len);
+ }
+ }
+};
+
+TEST_F(MessageTest, toWireTSIGLengthErrors) {
+ // specify an unusual short limit that wouldn't be able to hold
+ // the TSIG.
+ renderer.setLengthLimit(tsig_ctx.getTSIGLength() - 1);
+ // Use commonTSIGToWireCheck() only to call toWire() with otherwise valid
+ // conditions. The checks inside it don't matter because we expect an
+ // exception before any of the checks.
+ EXPECT_THROW(commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+ "message_toWire2.wire"),
+ InvalidParameter);
+
+ // This one is large enough for TSIG, but the remaining limit isn't
+ // even enough for the Header section.
+ renderer.clear();
+ message_render.clear(Message::RENDER);
+ renderer.setLengthLimit(tsig_ctx.getTSIGLength() + 1);
+ EXPECT_THROW(commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
+ "message_toWire2.wire"),
+ InvalidParameter);
+
+ // Trying to render a message with TSIG using a buggy renderer.
+ BadRenderer bad_renderer;
+ bad_renderer.setLengthLimit(512);
+ message_render.clear(Message::RENDER);
+ EXPECT_THROW(commonTSIGToWireCheck(message_render, bad_renderer, tsig_ctx,
+ "message_toWire2.wire"),
+ Unexpected);
+}
+
+TEST_F(MessageTest, toWireWithoutOpcode) {
+ message_render.setRcode(Rcode::NOERROR());
+ EXPECT_THROW(message_render.toWire(renderer), InvalidMessageOperation);
+}
+
+TEST_F(MessageTest, toWireWithoutRcode) {
+ message_render.setOpcode(Opcode::QUERY());
+ EXPECT_THROW(message_render.toWire(renderer), InvalidMessageOperation);
+}
+
+TEST_F(MessageTest, toText) {
+ // Check toText() output for a typical DNS response with records in
+ // all sections
+
+ factoryFromFile(message_parse, "message_toText1.wire");
+ {
+ SCOPED_TRACE("Message toText test (basic case)");
+ ifstream ifs;
+ unittests::openTestData("message_toText1.txt", ifs);
+ unittests::matchTextData(ifs, message_parse.toText());
+ }
+
+ // Another example with EDNS. The expected data was slightly modified
+ // from the dig output (other than replacing tabs with a space): adding
+ // a newline after the "OPT PSEUDOSECTION". This is an intentional change
+ // in our version for better readability.
+ message_parse.clear(Message::PARSE);
+ factoryFromFile(message_parse, "message_toText2.wire");
+ {
+ SCOPED_TRACE("Message toText test with EDNS");
+ ifstream ifs;
+ unittests::openTestData("message_toText2.txt", ifs);
+ unittests::matchTextData(ifs, message_parse.toText());
+ }
+
+ // Another example with TSIG. The expected data was slightly modified
+ // from the dig output (other than replacing tabs with a space): removing
+ // a redundant white space at the end of TSIG RDATA. We'd rather consider
+ // it a dig's defect than a feature.
+ message_parse.clear(Message::PARSE);
+ factoryFromFile(message_parse, "message_toText3.wire");
+ {
+ SCOPED_TRACE("Message toText test with TSIG");
+ ifstream ifs;
+ unittests::openTestData("message_toText3.txt", ifs);
+ unittests::matchTextData(ifs, message_parse.toText());
+ }
+}
+
+TEST_F(MessageTest, toTextWithoutOpcode) {
+ message_render.setRcode(Rcode::NOERROR());
+ EXPECT_THROW(message_render.toText(), InvalidMessageOperation);
+}
+
+TEST_F(MessageTest, toTextWithoutRcode) {
+ message_render.setOpcode(Opcode::QUERY());
+ EXPECT_THROW(message_render.toText(), InvalidMessageOperation);
+}
+}
diff --git a/src/lib/dns/tests/messagerenderer_unittest.cc b/src/lib/dns/tests/messagerenderer_unittest.cc
new file mode 100644
index 0000000..c3a53eb
--- /dev/null
+++ b/src/lib/dns/tests/messagerenderer_unittest.cc
@@ -0,0 +1,292 @@
+// Copyright (C) 2009-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/labelsequence.h>
+#include <dns/messagerenderer.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+#include <gtest/gtest.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <string>
+#include <vector>
+
+using isc::UnitTestUtil;
+using isc::dns::Name;
+using isc::dns::LabelSequence;
+using isc::dns::MessageRenderer;
+using isc::util::OutputBuffer;
+using boost::lexical_cast;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class MessageRendererTest : public ::testing::Test {
+protected:
+ MessageRendererTest() : expected_size(0) {
+ data16 = (2 << 8) | 3;
+ data32 = (4 << 24) | (5 << 16) | (6 << 8) | 7;
+ }
+ size_t expected_size;
+ uint16_t data16;
+ uint32_t data32;
+ MessageRenderer renderer;
+ std::vector<unsigned char> data;
+ static const uint8_t testdata[5];
+};
+
+const uint8_t MessageRendererTest::testdata[5] = {1, 2, 3, 4, 5};
+
+// The test cases are borrowed from those for the OutputBuffer class.
+TEST_F(MessageRendererTest, writeInteger) {
+ renderer.writeUint16(data16);
+ expected_size += sizeof(data16);
+
+ matchWireData(&testdata[1], sizeof(data16),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeName) {
+ UnitTestUtil::readWireData("name_toWire1", data);
+ renderer.writeName(Name("a.example.com."));
+ renderer.writeName(Name("b.example.com."));
+ renderer.writeName(Name("a.example.org."));
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeNameInLargeBuffer) {
+ size_t offset = 0x3fff;
+ renderer.skip(offset);
+
+ UnitTestUtil::readWireData("name_toWire2", data);
+ renderer.writeName(Name("a.example.com."));
+ renderer.writeName(Name("a.example.com."));
+ renderer.writeName(Name("b.example.com."));
+ matchWireData(&data[0], data.size(),
+ static_cast<const uint8_t*>(renderer.getData()) + offset,
+ renderer.getLength() - offset);
+}
+
+TEST_F(MessageRendererTest, writeNameWithUncompressed) {
+ UnitTestUtil::readWireData("name_toWire3", data);
+ renderer.writeName(Name("a.example.com."));
+ renderer.writeName(Name("b.example.com."), false);
+ renderer.writeName(Name("b.example.com."));
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeNamePointerChain) {
+ UnitTestUtil::readWireData("name_toWire4", data);
+ renderer.writeName(Name("a.example.com."));
+ renderer.writeName(Name("b.example.com."));
+ renderer.writeName(Name("b.example.com."));
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, compressMode) {
+ // By default the render performs case insensitive compression.
+ EXPECT_EQ(MessageRenderer::CASE_INSENSITIVE, renderer.getCompressMode());
+
+ // The mode can be explicitly changed.
+ renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE);
+ EXPECT_EQ(MessageRenderer::CASE_SENSITIVE, renderer.getCompressMode());
+ renderer.setCompressMode(MessageRenderer::CASE_INSENSITIVE);
+ EXPECT_EQ(MessageRenderer::CASE_INSENSITIVE, renderer.getCompressMode());
+
+ // The clear() method resets the mode to the default.
+ renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE);
+ renderer.clear();
+ EXPECT_EQ(MessageRenderer::CASE_INSENSITIVE, renderer.getCompressMode());
+}
+
+TEST_F(MessageRendererTest, writeNameCaseCompress) {
+ // By default MessageRenderer performs case insensitive compression.
+
+ UnitTestUtil::readWireData("name_toWire1", data);
+ renderer.writeName(Name("a.example.com."));
+ // this should match the first name in terms of compression:
+ renderer.writeName(Name("b.exAmple.CoM."));
+ renderer.writeName(Name("a.example.org."));
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeNameCaseSensitiveCompress) {
+ // name compression in case sensitive manner. See the data file
+ // description for details.
+ renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE);
+ UnitTestUtil::readWireData("name_toWire5.wire", data);
+ renderer.writeName(Name("a.example.com."));
+ renderer.writeName(Name("b.eXample.com."));
+ renderer.writeName(Name("c.eXample.com."));
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeNameMixedCaseCompress) {
+ renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE);
+ UnitTestUtil::readWireData("name_toWire6.wire", data);
+ renderer.writeName(Name("a.example.com."));
+ renderer.writeName(Name("b.eXample.com."));
+
+ // Change the compression mode in the middle of rendering. This is not
+ // allowed in this implementation.
+ EXPECT_THROW(renderer.setCompressMode(MessageRenderer::CASE_INSENSITIVE),
+ isc::InvalidParameter);
+
+ // Once the renderer is cleared, it's okay again.
+ renderer.clear();
+ EXPECT_NO_THROW(renderer.setCompressMode(
+ MessageRenderer::CASE_INSENSITIVE));
+}
+
+TEST_F(MessageRendererTest, writeRootName) {
+ // root name is special: it never causes compression or can (reasonably)
+ // be a compression pointer. So it makes sense to check this case
+ // explicitly.
+ Name example_name = Name("www.example.com");
+
+ OutputBuffer expected(0);
+ expected.writeUint8(0); // root name
+ example_name.toWire(expected);
+
+ renderer.writeName(Name("."));
+ renderer.writeName(example_name);
+ matchWireData(static_cast<const uint8_t*>(expected.getData()),
+ expected.getLength(),
+ static_cast<const uint8_t*>(renderer.getData()),
+ renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeNameLabelSequence1) {
+ UnitTestUtil::readWireData("name_toWire7", data);
+
+ Name n1("a.example.com");
+ LabelSequence ls1(n1);
+
+ // a.example.com.
+ renderer.writeName(ls1);
+
+ ls1.stripLeft(1);
+
+ // example.com.
+ renderer.writeName(ls1);
+
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeNameLabelSequence2) {
+ UnitTestUtil::readWireData("name_toWire8", data);
+
+ Name n1("a.example.com");
+ LabelSequence ls1(n1);
+
+ ls1.stripRight(1);
+
+ // a.example.com (without root .)
+ renderer.writeName(ls1);
+
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, writeNameLabelSequence3) {
+ UnitTestUtil::readWireData("name_toWire9", data);
+
+ Name n1("a.example.com");
+ LabelSequence ls1(n1);
+
+ // a.example.com.
+ renderer.writeName(ls1);
+
+ ls1.stripRight(1);
+
+ // a.example.com (without root .)
+ renderer.writeName(ls1);
+
+ ls1.stripRight(1);
+
+ // a.example
+ renderer.writeName(ls1);
+
+ ls1.stripLeft(1);
+
+ // example
+ renderer.writeName(ls1);
+
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(MessageRendererTest, setBuffer) {
+ OutputBuffer new_buffer(0);
+ renderer.setBuffer(&new_buffer);
+ EXPECT_EQ(0, new_buffer.getLength()); // the buffer should be still empty
+ renderer.writeUint32(42);
+ EXPECT_EQ(sizeof(uint32_t), new_buffer.getLength());
+ EXPECT_EQ(sizeof(uint32_t), renderer.getLength());
+
+ // Change some other internal state for the reset test below.
+ EXPECT_EQ(512, renderer.getLengthLimit());
+ renderer.setLengthLimit(4096);
+ EXPECT_EQ(4096, renderer.getLengthLimit());
+
+ // Reset the buffer to the default again. Other internal states and
+ // resources should be cleared. The used buffer should be intact.
+ renderer.setBuffer(NULL);
+ EXPECT_EQ(sizeof(uint32_t), new_buffer.getLength());
+ EXPECT_EQ(0, renderer.getLength());
+ EXPECT_EQ(512, renderer.getLengthLimit());
+}
+
+TEST_F(MessageRendererTest, setBufferErrors) {
+ OutputBuffer new_buffer(0);
+
+ // Buffer cannot be reset when the renderer is in use.
+ renderer.writeUint32(10);
+ EXPECT_THROW(renderer.setBuffer(&new_buffer), isc::InvalidParameter);
+
+ renderer.clear();
+ renderer.setBuffer(&new_buffer);
+ renderer.writeUint32(10);
+ EXPECT_THROW(renderer.setBuffer(&new_buffer), isc::InvalidParameter);
+
+ // Resetting the buffer isn't allowed for the default buffer.
+ renderer.setBuffer(NULL);
+ EXPECT_THROW(renderer.setBuffer(NULL), isc::InvalidParameter);
+
+ // It's okay to reset a temporary buffer without using it.
+ renderer.setBuffer(&new_buffer);
+ EXPECT_NO_THROW(renderer.setBuffer(NULL));
+}
+
+TEST_F(MessageRendererTest, manyRRs) {
+ // Render a large number of names, and the confirm the resulting wire
+ // data store the expected names in the correct order (1000 is an
+ // arbitrary choice).
+ for (size_t i = 0; i < 1000; ++i) {
+ renderer.writeName(Name(lexical_cast<std::string>(i) + ".example"));
+ }
+ isc::util::InputBuffer b(renderer.getData(), renderer.getLength());
+ for (size_t i = 0; i < 1000; ++i) {
+ EXPECT_EQ(Name(lexical_cast<std::string>(i) + ".example"), Name(b));
+ }
+ // This will trigger trimming excessive hash items. It shouldn't cause
+ // any disruption.
+ EXPECT_NO_THROW(renderer.clear());
+}
+}
diff --git a/src/lib/dns/tests/name_unittest.cc b/src/lib/dns/tests/name_unittest.cc
new file mode 100644
index 0000000..caf1f12
--- /dev/null
+++ b/src/lib/dns/tests/name_unittest.cc
@@ -0,0 +1,797 @@
+// Copyright (C) 2009-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <vector>
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <stdexcept>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using isc::util::unittests::matchWireData;
+
+//
+// XXX: these are defined as class static constants, but some compilers
+// seemingly cannot find the symbols when used in the EXPECT_xxx macros.
+//
+const size_t Name::MAX_WIRE;
+const size_t Name::MAX_LABELS;
+
+// This is a name of maximum allowed number of labels
+const char* max_labels_str = "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 40
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 80
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 120
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 160
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 200
+ "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 240
+ "0.1.2.3.4.5.6";
+// This is a name of maximum allowed length
+const char* max_len_str = "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789."
+ "123";
+
+namespace {
+class NameTest : public ::testing::Test {
+protected:
+ NameTest() : example_name("www.example.com"),
+ example_name_upper("WWW.EXAMPLE.COM"),
+ small_name("aaa.example.com"),
+ large_name("zzz.example.com"),
+ origin_name("example.com."),
+ origin_name_upper("EXAMPLE.COM"),
+ buffer_actual(0), buffer_expected(0)
+ {}
+
+ const Name example_name;
+ Name example_name_upper; // this will be modified and cannot be const
+ const Name small_name;
+ const Name large_name;
+ const Name origin_name;
+ const Name origin_name_upper;
+ OutputBuffer buffer_actual, buffer_expected;
+
+ //
+ // helper methods
+ //
+ static Name nameFactoryFromWire(const char* datafile, size_t position,
+ bool downcase = false);
+ // construct a name including all non-upper-case-alphabet characters.
+ static Name nameFactoryLowerCase();
+ void compareInWireFormat(const Name& name_actual,
+ const Name& name_expected);
+};
+
+const Name downcased_global("\\255.EXAMPLE.COM", true);
+
+Name
+NameTest::nameFactoryFromWire(const char* datafile, size_t position,
+ bool downcase)
+{
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData(datafile, data);
+
+ InputBuffer buffer(&data[0], data.size());
+ buffer.setPosition(position);
+
+ return (Name(buffer, downcase));
+}
+
+Name
+NameTest::nameFactoryLowerCase() {
+ string lowercase_namestr;
+ lowercase_namestr.reserve(Name::MAX_WIRE);
+
+ unsigned int ch = 0;
+ unsigned int labelcount = 0;
+ do {
+ if (ch < 'A' || ch > 'Z') {
+ ostringstream ss;
+ ss.setf(ios_base::right, ios_base::adjustfield);
+ ss.width(3);
+ ss << setfill('0') << ch;
+ lowercase_namestr += '\\' + ss.str();
+
+ if (++labelcount == Name::MAX_LABELLEN) {
+ lowercase_namestr.push_back('.');
+ labelcount = 0;
+ }
+ }
+ } while (++ch <= Name::MAX_WIRE);
+
+ return (Name(lowercase_namestr));
+}
+
+void
+NameTest::compareInWireFormat(const Name& name_actual,
+ const Name& name_expected)
+{
+ buffer_actual.clear();
+ buffer_expected.clear();
+
+ name_actual.toWire(buffer_actual);
+ name_expected.toWire(buffer_expected);
+
+ matchWireData(buffer_expected.getData(), buffer_expected.getLength(),
+ buffer_actual.getData(), buffer_actual.getLength());
+}
+
+TEST_F(NameTest, nonlocalObject) {
+ // A previous version of code relied on a non local static object for
+ // name construction, so a non local static Name object defined outside
+ // the name module might not be initialized correctly. This test detects
+ // that kind of bug.
+ EXPECT_EQ("\\255.example.com.", downcased_global.toText());
+}
+
+template <typename ExceptionType>
+void
+checkBadTextName(const string& txt) {
+ // Check it results in the specified type of exception as well as
+ // NameParserException.
+ EXPECT_THROW(Name(txt, false), ExceptionType);
+ EXPECT_THROW(Name(txt, false), NameParserException);
+ // The same is thrown when constructing by the master-file constructor
+ EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()),
+ ExceptionType);
+ EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()),
+ NameParserException);
+}
+
+TEST_F(NameTest, checkExceptionsHierarchy) {
+ EXPECT_NO_THROW({
+ const isc::dns::EmptyLabel exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::TooLongName exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::TooLongLabel exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::BadLabelType exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::BadEscape exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::IncompleteName exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::MissingNameOrigin exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+}
+
+TEST_F(NameTest, fromText) {
+ vector<string> strnames;
+ strnames.push_back("www.example.com");
+ strnames.push_back("www.example.com."); // with a trailing dot
+ strnames.push_back("wWw.exAmpLe.com"); // mixed cases
+ strnames.push_back("\\wWw.exAmpLe.com"); // escape with a backslash
+ // decimal representation for "WWW"
+ strnames.push_back("\\087\\087\\087.example.com");
+
+ vector<string>::const_iterator it;
+ for (it = strnames.begin(); it != strnames.end(); ++it) {
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name, Name(*it));
+ }
+
+ // root names
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, Name("@"), Name("."));
+
+ // downcase
+ EXPECT_EQ(Name("Www.eXample.coM", true).toText(), example_name.toText());
+
+ //
+ // Tests for bogus names. These should trigger exceptions.
+ //
+ // empty label cannot be followed by another label
+ checkBadTextName<EmptyLabel>(".a");
+ // duplicate period
+ checkBadTextName<EmptyLabel>("a..");
+ // label length must be < 64
+ checkBadTextName<TooLongLabel>("012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "0123");
+ // now-unsupported bitstring labels
+ checkBadTextName<BadLabelType>("\\[b11010000011101]");
+ // label length must be < 64
+ checkBadTextName<TooLongLabel>("012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012\\x");
+ // but okay as long as resulting len < 64 even if the original string is
+ // "too long"
+ EXPECT_NO_THROW(Name("012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "01\\x"));
+ // incomplete \DDD pattern (exactly 3 D's must appear)
+ checkBadTextName<BadEscape>("\\12abc");
+ // \DDD must not exceed 255
+ checkBadTextName<BadEscape>("\\256");
+ // Same tests for \111 as for \\x above
+ checkBadTextName<TooLongLabel>("012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012\\111");
+ EXPECT_NO_THROW(Name("012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "01\\111"));
+ // A domain name must be 255 octets or less
+ checkBadTextName<TooLongName>("123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789."
+ "123456789.1234");
+ // This is a possible longest name and should be accepted
+ EXPECT_NO_THROW(Name(string(max_len_str)));
+ // \DDD must consist of 3 digits.
+ checkBadTextName<IncompleteName>("\\12");
+
+ // a name with the max number of labels. should be constructed without
+ // an error, and its length should be the max value.
+ Name maxlabels = Name(string(max_labels_str));
+ EXPECT_EQ(Name::MAX_LABELS, maxlabels.getLabelCount());
+}
+
+// The following test uses a name data that was produced by
+// fuzz testing and causes an unexpected condition in stringParser.
+// Formerly this condition was trapped by an assert, but for
+// robustness it has been replaced by a throw.
+TEST_F(NameTest, unexpectedParseError) {
+ std::vector<uint8_t> badname {
+ 0xff,0xff,0x7f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x04,0x63,0x82,0x53,0x63,0x35,0x01,0x01,0x3d,0x07,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x19,0x0c,0x4e,0x01,0x00,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x35,0x01,0x05,0x3a,0x04,0x00,0x00,0x07,0x08,0x3b,0x04,0x00,
+ 0x00,0x2e,0x3b,0x04,0x00,0x19,0x2e,0x00,0x00,0x00,0x0a,0x00,0x12,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x0b,0x82,0x01,0xfc,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x35,0x01,0x05,0x3a,0x04,0x00,0x00,0x07,0x08,0x3b,0x04,
+ 0x00,0x00,0x2e,0x3b,0x04,0x00,0x19,0x2e,0x56,0x00,0x00,0x0a,0x00,0x12,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x0b,0x82,0x01,0xfc,0x42,0x00,0x00,0x00,0x00,0x19,0x0c,
+ 0x4e,0x01,0x05,0x3a,0x04,0xde,0x00,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x35,0x01,0x05,0x3a,0x07,0x08,0x3b,0x04,0x00,0x00,0x2e,0x3b,0x04,
+ 0x00,0x19,0x2e,0x56,0x40,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x12,0x00,0x00,0x00,
+ 0x00,0x00,0x19,0x00,0x0b,0x82,0x01,0xfc,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x35,0x01,0x05,0xff,0xff,0x05,0x00,0x07,0x08,0x3b,0x04,
+ 0x00,0x00,0x2e,0x3b
+ };
+
+ std::string badnamestr(badname.begin(), badname.end());
+ EXPECT_THROW(Name(badnamestr, false), Unexpected);
+}
+
+// on the rest while we prepare it.
+// Check the @ syntax is accepted and it just copies the origin.
+TEST_F(NameTest, copyOrigin) {
+ EXPECT_EQ(origin_name, Name("@", 1, &origin_name));
+ // The downcase works on the origin too. But only when we provide it.
+ EXPECT_EQ(origin_name, Name("@", 1, &origin_name_upper, true));
+ EXPECT_EQ(origin_name_upper, Name("@", 1, &origin_name_upper, true));
+ // If we don't provide the origin, it throws
+ EXPECT_THROW(Name("@", 1, NULL), MissingNameOrigin);
+}
+
+// Test the master-file constructor does not append the origin when the
+// provided name is absolute
+TEST_F(NameTest, dontAppendOrigin) {
+ EXPECT_EQ(example_name, Name("www.example.com.", 16, &origin_name));
+ // The downcase works (only if provided, though)
+ EXPECT_EQ(example_name, Name("WWW.EXAMPLE.COM.", 16, &origin_name, true));
+ EXPECT_EQ(example_name_upper, Name("WWW.EXAMPLE.COM.", 16, &origin_name));
+ // And it does not require the origin to be provided
+ EXPECT_NO_THROW(Name("www.example.com.", 16, NULL));
+}
+
+// Test the master-file constructor properly appends the origin when
+// the provided name is relative.
+TEST_F(NameTest, appendOrigin) {
+ EXPECT_EQ(example_name, Name("www", 3, &origin_name));
+ // Check the downcase works (if provided)
+ EXPECT_EQ(example_name, Name("WWW", 3, &origin_name, true));
+ EXPECT_EQ(example_name, Name("WWW", 3, &origin_name_upper, true));
+ EXPECT_EQ(example_name_upper, Name("WWW", 3, &origin_name_upper));
+ // Check we can prepend more than one label
+ EXPECT_EQ(Name("a.b.c.d.example.com."), Name("a.b.c.d", 7, &origin_name));
+ // When the name is relative, we throw.
+ EXPECT_THROW(Name("www", 3, NULL), MissingNameOrigin);
+}
+
+// When we don't provide the data, it throws
+TEST_F(NameTest, noDataProvided) {
+ EXPECT_THROW(Name(NULL, 10, NULL), isc::InvalidParameter);
+ EXPECT_THROW(Name(NULL, 10, &origin_name), isc::InvalidParameter);
+ EXPECT_THROW(Name("www", 0, NULL), isc::InvalidParameter);
+ EXPECT_THROW(Name("www", 0, &origin_name), isc::InvalidParameter);
+}
+
+// When we combine the first part and the origin together, the resulting name
+// is too long. It should throw. Other test checks this is valid when alone
+// (without the origin appended).
+TEST_F(NameTest, combinedTooLong) {
+ EXPECT_THROW(Name(max_len_str, strlen(max_len_str), &origin_name),
+ TooLongName);
+ EXPECT_THROW(Name(max_labels_str, strlen(max_labels_str), &origin_name),
+ TooLongName);
+ // Appending the root should be OK
+ EXPECT_NO_THROW(Name(max_len_str, strlen(max_len_str),
+ &Name::ROOT_NAME()));
+ EXPECT_NO_THROW(Name(max_labels_str, strlen(max_labels_str),
+ &Name::ROOT_NAME()));
+}
+
+// Test the handling of @ in the name. If it is alone, it is the origin (when
+// it exists) or the root. If it is somewhere else, it has no special meaning.
+TEST_F(NameTest, atSign) {
+ // If it is alone, it is the origin
+ EXPECT_EQ(origin_name, Name("@", 1, &origin_name));
+ EXPECT_THROW(Name("@", 1, NULL), MissingNameOrigin);
+ EXPECT_EQ(Name::ROOT_NAME(), Name("@"));
+
+ // It is not alone. It is taken verbatim. We check the name converted
+ // back to the textual form, since checking it against other name object
+ // may be wrong -- if we create it wrong the same way as the tested
+ // object.
+ EXPECT_EQ("\\@.", Name("@.").toText());
+ EXPECT_EQ("\\@.", Name("@.", 2, NULL).toText());
+ EXPECT_EQ("\\@something.", Name("@something").toText());
+ EXPECT_EQ("something\\@.", Name("something@").toText());
+ EXPECT_EQ("\\@x.example.com.", Name("@x", 2, &origin_name).toText());
+ EXPECT_EQ("x\\@.example.com.", Name("x@", 2, &origin_name).toText());
+
+ // An escaped at-sign isn't active
+ EXPECT_EQ("\\@.", Name("\\@").toText());
+ EXPECT_EQ("\\@.example.com.", Name("\\@", 2, &origin_name).toText());
+}
+
+TEST_F(NameTest, fromWire) {
+ //
+ // test cases derived from BIND9 tests.
+ //
+ // normal case with a compression pointer
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName,
+ nameFactoryFromWire("name_fromWire1", 25),
+ Name("vix.com"));
+ // bogus label character (looks like a local compression pointer)
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire2", 25), DNSMessageFORMERR);
+ // a bad compression pointer (too big)
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire3_1", 25),
+ DNSMessageFORMERR);
+ // forward reference
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire3_2", 25),
+ DNSMessageFORMERR);
+ // invalid name length
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire4", 550), DNSMessageFORMERR);
+
+ // skip test for from Wire5. It's for disabling decompression, but our
+ // implementation always allows it.
+
+ // bad pointer (too big)
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire6", 25), DNSMessageFORMERR);
+ // input ends unexpectedly
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire7", 25), DNSMessageFORMERR);
+ // many hops of compression but valid. should succeed.
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName,
+ nameFactoryFromWire("name_fromWire8", 383),
+ Name("vix.com"));
+
+ //
+ // Additional test cases
+ //
+
+ // large names, a long but valid one, and invalid (too long) one.
+ EXPECT_EQ(Name::MAX_WIRE,
+ nameFactoryFromWire("name_fromWire9", 0).getLength());
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire10", 0).getLength(),
+ DNSMessageFORMERR);
+
+ // A name with possible maximum number of labels; awkward but valid
+ EXPECT_EQ(nameFactoryFromWire("name_fromWire11", 0).getLabelCount(),
+ Name::MAX_LABELS);
+
+ // Wire format including an invalid label length
+ EXPECT_THROW(nameFactoryFromWire("name_fromWire12", 0), DNSMessageFORMERR);
+
+ // converting upper-case letters to down-case
+ EXPECT_EQ("vix.com.",
+ nameFactoryFromWire("name_fromWire1", 25, true).toText());
+ EXPECT_EQ(3, nameFactoryFromWire("name_fromWire1", 25).getLabelCount());
+}
+
+TEST_F(NameTest, copyConstruct) {
+ Name copy(example_name);
+ EXPECT_EQ(copy, example_name);
+
+ // Check the copied data is valid even after the original is deleted
+ Name* copy2 = new Name(example_name);
+ Name copy3(*copy2);
+ delete copy2;
+ EXPECT_EQ(copy3, example_name);
+}
+
+TEST_F(NameTest, assignment) {
+ Name copy(".");
+ copy = example_name;
+ EXPECT_EQ(copy, example_name);
+
+ // Check if the copied data is valid even after the original is deleted
+ Name* copy2 = new Name(example_name);
+ Name copy3(".");
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(copy3, example_name);
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(example_name, copy);
+}
+
+TEST_F(NameTest, toText) {
+ // tests derived from BIND9
+ EXPECT_EQ("a.b.c.d", Name("a.b.c.d").toText(true));
+ EXPECT_EQ("a.\\\\[[.c.d", Name("a.\\\\[\\[.c.d").toText(true));
+ EXPECT_EQ("a.b.C.d.", Name("a.b.C.d").toText(false));
+ EXPECT_EQ("a.b.", Name("a.b.").toText(false));
+
+ // test omit_final_dot. It's false by default.
+ EXPECT_EQ("a.b.c.d", Name("a.b.c.d.").toText(true));
+ EXPECT_EQ(Name("a.b.").toText(false), Name("a.b.").toText());
+
+ // the root name is a special case: omit_final_dot will be ignored.
+ EXPECT_EQ(".", Name(".").toText(true));
+
+ // test all printable characters to see whether special characters are
+ // escaped while the others are intact. note that the conversion is
+ // implementation specific; for example, it's not invalid to escape a
+ // "normal" character such as 'a' with regard to the standard.
+ string all_printable("!\\\"#\\$%&'\\(\\)*+,-\\./0123456789:\\;<=>?\\@"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "[\\\\]^_.`abcdefghijklmnopqrstuvwxyz{|}~.");
+ EXPECT_EQ(all_printable,
+ nameFactoryFromWire("name_fromWire13", 0).toText());
+
+ string all_nonprintable(
+ "\\000\\001\\002\\003\\004\\005\\006\\007\\008\\009"
+ "\\010\\011\\012\\013\\014\\015\\016\\017\\018\\019"
+ "\\020\\021\\022\\023\\024\\025\\026\\027\\028\\029"
+ "\\030\\031\\032\\127\\128\\129"
+ "\\130\\131\\132\\133\\134\\135\\136\\137\\138\\139"
+ "\\140\\141\\142\\143\\144\\145\\146\\147\\148\\149"
+ "\\150\\151\\152\\153\\154\\155\\156."
+ "\\157\\158\\159"
+ "\\160\\161\\162\\163\\164\\165\\166\\167\\168\\169"
+ "\\170\\171\\172\\173\\174\\175\\176\\177\\178\\179"
+ "\\180\\181\\182\\183\\184\\185\\186\\187\\188\\189"
+ "\\190\\191\\192\\193\\194\\195\\196\\197\\198\\199"
+ "\\200\\201\\202\\203\\204\\205\\206\\207\\208\\209"
+ "\\210\\211\\212\\213\\214\\215\\216\\217\\218\\219."
+ "\\220\\221\\222\\223\\224\\225\\226\\227\\228\\229"
+ "\\230\\231\\232\\233\\234\\235\\236\\237\\238\\239"
+ "\\240\\241\\242\\243\\244\\245\\246\\247\\248\\249"
+ "\\250\\251\\252\\253\\254\\255.");
+ EXPECT_EQ(all_nonprintable,
+ nameFactoryFromWire("name_fromWire14", 0).toText());
+}
+
+TEST_F(NameTest, toWireBuffer) {
+ vector<unsigned char> data;
+ OutputBuffer buffer(0);
+
+ UnitTestUtil::readWireData(string("01610376697803636f6d00"), data);
+ Name("a.vix.com.").toWire(buffer);
+ matchWireData(&data[0], data.size(),
+ buffer.getData(), buffer.getLength());
+}
+
+//
+// We test various corner cases in Renderer tests, but add this test case
+// to fill the code coverage gap.
+//
+TEST_F(NameTest, toWireRenderer) {
+ vector<unsigned char> data;
+ MessageRenderer renderer;
+
+ UnitTestUtil::readWireData(string("01610376697803636f6d00"), data);
+ Name("a.vix.com.").toWire(renderer);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+//
+// Helper class to hold comparison test parameters.
+//
+struct CompareParameters {
+ CompareParameters(const Name& n1, const Name& n2,
+ NameComparisonResult::NameRelation r, int o,
+ unsigned int l) :
+ name1(n1), name2(n2), reln(r), order(o), labels(l) {}
+ static int normalizeOrder(int o)
+ {
+ if (o > 0) {
+ return (1);
+ } else if (o < 0) {
+ return (-1);
+ }
+ return (0);
+ }
+ Name name1;
+ Name name2;
+ NameComparisonResult::NameRelation reln;
+ int order;
+ unsigned int labels;
+};
+
+TEST_F(NameTest, compare) {
+ vector<CompareParameters> params;
+ params.push_back(CompareParameters(Name("c.d"), Name("a.b.c.d"),
+ NameComparisonResult::SUPERDOMAIN,
+ -1, 3));
+ params.push_back(CompareParameters(Name("a.b.c.d"), Name("c.d"),
+ NameComparisonResult::SUBDOMAIN, 1, 3));
+ params.push_back(CompareParameters(Name("a.b.c.d"), Name("c.d.e.f"),
+ NameComparisonResult::COMMONANCESTOR,
+ -1, 1));
+ params.push_back(CompareParameters(Name("a.b.c.d"), Name("f.g.c.d"),
+ NameComparisonResult::COMMONANCESTOR,
+ -1, 3));
+ params.push_back(CompareParameters(Name("a.b.c.d"), Name("A.b.C.d."),
+ NameComparisonResult::EQUAL,
+ 0, 5));
+
+ vector<CompareParameters>::const_iterator it;
+ for (it = params.begin(); it != params.end(); ++it) {
+ NameComparisonResult result = (*it).name1.compare((*it).name2);
+ EXPECT_EQ((*it).reln, result.getRelation());
+ EXPECT_EQ((*it).order,
+ CompareParameters::normalizeOrder(result.getOrder()));
+ EXPECT_EQ((*it).labels, result.getCommonLabels());
+ }
+}
+
+TEST_F(NameTest, equal) {
+ EXPECT_TRUE(example_name == Name("WWW.EXAMPLE.COM."));
+ EXPECT_TRUE(example_name.equals(Name("WWW.EXAMPLE.COM.")));
+ EXPECT_TRUE(example_name != Name("www.example.org."));
+ EXPECT_TRUE(example_name.nequals(Name("www.example.org.")));
+ // lengths don't match
+ EXPECT_TRUE(example_name != Name("www2.example.com."));
+ EXPECT_TRUE(example_name.nequals(Name("www2.example.com.")));
+ // lengths are equal, but # of labels don't match (first test checks the
+ // prerequisite).
+ EXPECT_EQ(example_name.getLength(), Name("www\\.example.com.").getLength());
+ EXPECT_TRUE(example_name != Name("www\\.example.com."));
+ EXPECT_TRUE(example_name.nequals(Name("www\\.example.com.")));
+}
+
+TEST_F(NameTest, isWildcard) {
+ EXPECT_FALSE(example_name.isWildcard());
+ EXPECT_TRUE(Name("*.a.example.com").isWildcard());
+ EXPECT_FALSE(Name("a.*.example.com").isWildcard());
+}
+
+TEST_F(NameTest, concatenate) {
+ NameComparisonResult result =
+ Name("aaa.www.example.com.").compare(Name("aaa").concatenate(example_name));
+ EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
+
+ result = example_name.compare(Name(".").concatenate(example_name));
+ EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
+
+ result = example_name.compare(example_name.concatenate(Name(".")));
+ EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
+
+ // concatenating two valid names would result in too long a name.
+ Name n1("123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789.");
+ Name n2("123456789.123456789.123456789.123456789.123456789."
+ "123456789.123456789.123456789.123456789.123456789."
+ "1234.");
+ EXPECT_THROW(n1.concatenate(n2), TooLongName);
+}
+
+TEST_F(NameTest, reverse) {
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.reverse(),
+ Name("com.example.www."));
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, Name(".").reverse(),
+ Name("."));
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName,
+ Name("a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s").reverse(),
+ Name("s.r.q.p.o.n.m.l.k.j.i.h.g.f.e.d.c.b.a"));
+}
+
+TEST_F(NameTest, split) {
+ // normal cases with or without explicitly specifying the trailing dot.
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 2),
+ Name("example.com."));
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 3),
+ Name("example.com."));
+ // edge cases: only the first or last label.
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(0, 1),
+ Name("www."));
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(3, 1),
+ Name("."));
+ // invalid range: an exception should be thrown.
+ EXPECT_THROW(example_name.split(1, 0), OutOfRange);
+ EXPECT_THROW(example_name.split(2, 3), OutOfRange);
+
+ // invalid range: the following parameters would cause overflow,
+ // bypassing naive validation.
+ EXPECT_THROW(example_name.split(1, numeric_limits<unsigned int>::max()),
+ OutOfRange);
+}
+
+TEST_F(NameTest, split_for_suffix) {
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1),
+ Name("example.com"));
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(0),
+ example_name);
+ EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(3),
+ Name("."));
+
+ // Invalid case: the level must be less than the original label count.
+ EXPECT_THROW(example_name.split(4), OutOfRange);
+}
+
+TEST_F(NameTest, downcase) {
+ // usual case: all-upper case name to all-lower case
+ compareInWireFormat(example_name_upper.downcase(), example_name);
+ // confirm that non upper-case characters are intact
+ compareInWireFormat(nameFactoryLowerCase().downcase(),
+ nameFactoryLowerCase());
+ // confirm the calling object is actually modified
+ example_name_upper.downcase();
+ compareInWireFormat(example_name_upper, example_name);
+}
+
+TEST_F(NameTest, at) {
+ // Confirm at() produces the exact sequence of wire-format name data
+ vector<uint8_t> data;
+
+ for (size_t i = 0; i < example_name.getLength(); i++) {
+ data.push_back(example_name.at(i));
+ }
+
+ example_name.toWire(buffer_expected);
+ matchWireData(&data[0], data.size(),
+ buffer_expected.getData(), buffer_expected.getLength());
+
+ // Out-of-range access: should trigger an exception.
+ EXPECT_THROW(example_name.at(example_name.getLength()), OutOfRange);
+}
+
+//
+// The following set of tests confirm the result of <=, <, >=, >
+// The test logic is simple, and all tests are just straightforward variations
+// of the first one.
+//
+TEST_F(NameTest, leq) {
+ // small <= large is true
+ EXPECT_TRUE(small_name.leq(large_name));
+ EXPECT_TRUE(small_name <= large_name);
+
+ // small <= small is true
+ EXPECT_TRUE(small_name.leq(small_name));
+ EXPECT_LE(small_name, small_name);
+
+ // large <= small is false
+ EXPECT_FALSE(large_name.leq(small_name));
+ EXPECT_FALSE(large_name <= small_name);
+}
+
+TEST_F(NameTest, geq) {
+ EXPECT_TRUE(large_name.geq(small_name));
+ EXPECT_TRUE(large_name >= small_name);
+
+ EXPECT_TRUE(large_name.geq(large_name));
+ EXPECT_GE(large_name, large_name);
+
+ EXPECT_FALSE(small_name.geq(large_name));
+ EXPECT_FALSE(small_name >= large_name);
+}
+
+TEST_F(NameTest, lthan) {
+ EXPECT_TRUE(small_name.lthan(large_name));
+ EXPECT_TRUE(small_name < large_name);
+
+ EXPECT_FALSE(small_name.lthan(small_name));
+ // cppcheck-suppress duplicateExpression
+ EXPECT_FALSE(small_name < small_name);
+
+ EXPECT_FALSE(large_name.lthan(small_name));
+ EXPECT_FALSE(large_name < small_name);
+}
+
+TEST_F(NameTest, gthan) {
+ EXPECT_TRUE(large_name.gthan(small_name));
+ EXPECT_TRUE(large_name > small_name);
+
+ EXPECT_FALSE(large_name.gthan(large_name));
+ // cppcheck-suppress duplicateExpression
+ EXPECT_FALSE(large_name > large_name);
+
+ EXPECT_FALSE(small_name.gthan(large_name));
+ EXPECT_FALSE(small_name > large_name);
+}
+
+TEST_F(NameTest, constants) {
+ EXPECT_EQ(Name("."), Name::ROOT_NAME());
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(NameTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << example_name;
+ EXPECT_EQ(example_name.toText(), oss.str());
+}
+
+// The following verifies that toRawText() returns a string
+// actual characters in place of escape sequences. We do not
+// bother with an exhaustive set of tests here as this is
+// not a primary use case.
+TEST_F(NameTest, toRawText) {
+ Name n("a bc.$exa(m)ple.@org");
+ EXPECT_EQ("a bc.$exa(m)ple.@org", n.toRawText(true));
+ EXPECT_EQ("a bc.$exa(m)ple.@org.", n.toRawText(false));
+ // Verify default value of omit parameter is false.
+ EXPECT_EQ("a bc.$exa(m)ple.@org.", n.toRawText());
+}
+
+}
diff --git a/src/lib/dns/tests/nsec3hash_unittest.cc b/src/lib/dns/tests/nsec3hash_unittest.cc
new file mode 100644
index 0000000..b47bb49
--- /dev/null
+++ b/src/lib/dns/tests/nsec3hash_unittest.cc
@@ -0,0 +1,269 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <dns/nsec3hash.h>
+#include <dns/labelsequence.h>
+#include <dns/rdataclass.h>
+#include <util/encode/hex.h>
+
+using boost::scoped_ptr;
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+namespace {
+typedef scoped_ptr<NSEC3Hash> NSEC3HashPtr;
+
+// Commonly used NSEC3 suffix, defined to reduce the amount of typing
+const char* const nsec3_common = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG";
+
+class NSEC3HashTest : public ::testing::Test {
+protected:
+ NSEC3HashTest() :
+ test_hash(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd"))),
+ test_hash_nsec3(NSEC3Hash::create(generic::NSEC3
+ ("1 0 12 aabbccdd " +
+ string(nsec3_common))))
+ {
+ const uint8_t salt[] = {0xaa, 0xbb, 0xcc, 0xdd};
+ test_hash_args.reset(NSEC3Hash::create(1, 12, salt, sizeof(salt)));
+ }
+
+ ~NSEC3HashTest() {
+ // Make sure we reset the hash creator to the default
+ setNSEC3HashCreator(NULL);
+ }
+
+ // An NSEC3Hash object commonly used in tests. Parameters are borrowed
+ // from the RFC5155 example. Construction of this object implicitly
+ // checks a successful case of the creation.
+ NSEC3HashPtr test_hash;
+
+ // Similar to test_hash, but created from NSEC3 RR.
+ NSEC3HashPtr test_hash_nsec3;
+
+ // Similar to test_hash, but created from passed args.
+ NSEC3HashPtr test_hash_args;
+};
+
+TEST_F(NSEC3HashTest, unknownAlgorithm) {
+ EXPECT_THROW(NSEC3HashPtr(
+ NSEC3Hash::create(
+ generic::NSEC3PARAM("2 0 12 aabbccdd"))),
+ UnknownNSEC3HashAlgorithm);
+ EXPECT_THROW(NSEC3HashPtr(
+ NSEC3Hash::create(
+ generic::NSEC3("2 0 12 aabbccdd " +
+ string(nsec3_common)))),
+ UnknownNSEC3HashAlgorithm);
+
+ const uint8_t salt[] = {0xaa, 0xbb, 0xcc, 0xdd};
+ EXPECT_THROW(NSEC3HashPtr(NSEC3Hash::create(2, 12, salt, sizeof(salt))),
+ UnknownNSEC3HashAlgorithm);
+}
+
+// Common checks for NSEC3 hash calculation
+void
+calculateCheck(NSEC3Hash& hash) {
+ // A couple of normal cases from the RFC5155 example.
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ hash.calculate(Name("example")));
+ EXPECT_EQ("35MTHGPGCU1QG68FAB165KLNSNK3DPVL",
+ hash.calculate(Name("a.example")));
+
+ // Check case-insensitiveness
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ hash.calculate(Name("EXAMPLE")));
+
+ // Repeat for the LabelSequence variant.
+
+ // A couple of normal cases from the RFC5155 example.
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ hash.calculate(LabelSequence(Name("example"))));
+ EXPECT_EQ("35MTHGPGCU1QG68FAB165KLNSNK3DPVL",
+ hash.calculate(LabelSequence(Name("a.example"))));
+
+ // Check case-insensitiveness
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ hash.calculate(LabelSequence(Name("EXAMPLE"))));
+}
+
+TEST_F(NSEC3HashTest, calculate) {
+ {
+ SCOPED_TRACE("calculate check with NSEC3PARAM based hash");
+ calculateCheck(*test_hash);
+ }
+ {
+ SCOPED_TRACE("calculate check with NSEC3 based hash");
+ calculateCheck(*test_hash_nsec3);
+ }
+ {
+ SCOPED_TRACE("calculate check with args based hash");
+ calculateCheck(*test_hash_args);
+ }
+
+ // Some boundary cases: 0-iteration and empty salt. Borrowed from the
+ // .com zone data.
+ EXPECT_EQ("CK0POJMG874LJREF7EFN8430QVIT8BSM",
+ NSEC3HashPtr(NSEC3Hash::create(generic::NSEC3PARAM("1 0 0 -")))
+ ->calculate(Name("com")));
+ EXPECT_EQ("CK0POJMG874LJREF7EFN8430QVIT8BSM",
+ NSEC3HashPtr(NSEC3Hash::create(generic::NSEC3PARAM("1 0 0 -")))
+ ->calculate(LabelSequence(Name("com"))));
+
+ // Using unusually large iterations, something larger than the 8-bit range.
+ // (expected hash value generated by BIND 9's dnssec-signzone)
+ EXPECT_EQ("COG6A52MJ96MNMV3QUCAGGCO0RHCC2Q3",
+ NSEC3HashPtr(NSEC3Hash::create(
+ generic::NSEC3PARAM("1 0 256 AABBCCDD")))
+ ->calculate(LabelSequence(Name("example.org"))));
+}
+
+// Common checks for match cases
+template <typename RDATAType>
+void
+matchCheck(NSEC3Hash& hash, const string& postfix) {
+ // If all parameters match, it's considered to be matched.
+ EXPECT_TRUE(hash.match(RDATAType("1 0 12 aabbccdd" + postfix)));
+
+ // Algorithm doesn't match
+ EXPECT_FALSE(hash.match(RDATAType("2 0 12 aabbccdd" + postfix)));
+ // Iterations doesn't match
+ EXPECT_FALSE(hash.match(RDATAType("1 0 1 aabbccdd" + postfix)));
+ // Salt doesn't match
+ EXPECT_FALSE(hash.match(RDATAType("1 0 12 aabbccde" + postfix)));
+ // Salt doesn't match: the other has an empty salt
+ EXPECT_FALSE(hash.match(RDATAType("1 0 12 -" + postfix)));
+ // Flags don't matter
+ EXPECT_TRUE(hash.match(RDATAType("1 1 12 aabbccdd" + postfix)));
+}
+
+TEST_F(NSEC3HashTest, matchWithNSEC3) {
+ {
+ SCOPED_TRACE("match NSEC3PARAM based hash against NSEC3 parameters");
+ matchCheck<generic::NSEC3>(*test_hash, " " + string(nsec3_common));
+ }
+ {
+ SCOPED_TRACE("match NSEC3 based hash against NSEC3 parameters");
+ matchCheck<generic::NSEC3>(*test_hash_nsec3,
+ " " + string(nsec3_common));
+ }
+}
+
+TEST_F(NSEC3HashTest, matchWithNSEC3PARAM) {
+ {
+ SCOPED_TRACE("match NSEC3PARAM based hash against NSEC3 parameters");
+ matchCheck<generic::NSEC3PARAM>(*test_hash, "");
+ }
+ {
+ SCOPED_TRACE("match NSEC3 based hash against NSEC3 parameters");
+ matchCheck<generic::NSEC3PARAM>(*test_hash_nsec3, "");
+ }
+}
+
+// A simple faked hash calculator and a dedicated creator for it.
+class TestNSEC3Hash : public NSEC3Hash {
+ virtual string calculate(const Name&) const {
+ return ("00000000000000000000000000000000");
+ }
+ virtual string calculate(const LabelSequence&) const {
+ return ("00000000000000000000000000000000");
+ }
+ virtual bool match(const generic::NSEC3PARAM&) const {
+ return (true);
+ }
+ virtual bool match(const generic::NSEC3&) const {
+ return (true);
+ }
+};
+
+// This faked creator basically creates the faked calculator regardless of
+// the passed NSEC3PARAM or NSEC3. But if the most significant bit of flags
+// is set, it will behave like the default creator.
+class TestNSEC3HashCreator : public NSEC3HashCreator {
+public:
+ virtual NSEC3Hash* create(const generic::NSEC3PARAM& param) const {
+ if ((param.getFlags() & 0x80) != 0) {
+ return (default_creator_.create(param));
+ }
+ return (new TestNSEC3Hash);
+ }
+ virtual NSEC3Hash* create(const generic::NSEC3& nsec3) const {
+ if ((nsec3.getFlags() & 0x80) != 0) {
+ return (default_creator_.create(nsec3));
+ }
+ return (new TestNSEC3Hash);
+ }
+ virtual NSEC3Hash* create(uint8_t, uint16_t,
+ const uint8_t*, size_t) const {
+ isc_throw(isc::Unexpected,
+ "This method is not implemented here.");
+ }
+private:
+ DefaultNSEC3HashCreator default_creator_;
+};
+
+TEST_F(NSEC3HashTest, setCreator) {
+ // Re-check an existing case using the default creator/hash implementation
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
+
+ // Replace the creator, and confirm the hash values are faked
+ TestNSEC3HashCreator test_creator;
+ setNSEC3HashCreator(&test_creator);
+ // Re-create the hash object with the new creator
+ test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd")));
+ EXPECT_EQ("00000000000000000000000000000000",
+ test_hash->calculate(Name("example")));
+ EXPECT_EQ("00000000000000000000000000000000",
+ test_hash->calculate(LabelSequence(Name("example"))));
+ // Same for hash from NSEC3 RDATA
+ test_hash.reset(NSEC3Hash::create(generic::NSEC3
+ ("1 0 12 aabbccdd " +
+ string(nsec3_common))));
+ EXPECT_EQ("00000000000000000000000000000000",
+ test_hash->calculate(Name("example")));
+ EXPECT_EQ("00000000000000000000000000000000",
+ test_hash->calculate(LabelSequence(Name("example"))));
+
+ // If we set a special flag big (0x80) on creation, it will act like the
+ // default creator.
+ test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM(
+ "1 128 12 aabbccdd")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
+ test_hash.reset(NSEC3Hash::create(generic::NSEC3
+ ("1 128 12 aabbccdd " +
+ string(nsec3_common))));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
+
+ // Reset the creator to default, and confirm that
+ setNSEC3HashCreator(NULL);
+ test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
+}
+
+} // end namespace
diff --git a/src/lib/dns/tests/opcode_unittest.cc b/src/lib/dns/tests/opcode_unittest.cc
new file mode 100644
index 0000000..9bc60b5
--- /dev/null
+++ b/src/lib/dns/tests/opcode_unittest.cc
@@ -0,0 +1,100 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <vector>
+#include <sstream>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/opcode.h>
+
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc::dns;
+
+namespace {
+TEST(OpcodeTest, construct) {
+ // This test also tests getCode()
+ EXPECT_EQ(0, Opcode(0).getCode());
+ EXPECT_EQ(15, Opcode(Opcode::RESERVED15_CODE).getCode());
+
+ EXPECT_THROW(Opcode(16), isc::OutOfRange);
+}
+
+TEST(OpcodeTest, constants) {
+ // We'll only test arbitrarily chosen subsets of the codes.
+ // This class is quite simple, so it should be suffice.
+
+ EXPECT_EQ(Opcode::QUERY_CODE, Opcode(0).getCode());
+ EXPECT_EQ(Opcode::IQUERY_CODE, Opcode(1).getCode());
+ EXPECT_EQ(Opcode::NOTIFY_CODE, Opcode(4).getCode());
+ EXPECT_EQ(Opcode::UPDATE_CODE, Opcode(5).getCode());
+ EXPECT_EQ(Opcode::RESERVED15_CODE, Opcode(15).getCode());
+
+ EXPECT_EQ(Opcode::QUERY_CODE, Opcode::QUERY().getCode());
+ EXPECT_EQ(Opcode::IQUERY_CODE, Opcode::IQUERY().getCode());
+ EXPECT_EQ(Opcode::NOTIFY_CODE, Opcode::NOTIFY().getCode());
+ EXPECT_EQ(Opcode::UPDATE_CODE, Opcode::UPDATE().getCode());
+ EXPECT_EQ(Opcode::RESERVED15_CODE, Opcode::RESERVED15().getCode());
+}
+
+TEST(OpcodeTest, equal) {
+ EXPECT_TRUE(Opcode::QUERY() == Opcode(Opcode::QUERY_CODE));
+ EXPECT_TRUE(Opcode::QUERY().equals(Opcode(Opcode::QUERY_CODE)));
+ EXPECT_TRUE(Opcode::IQUERY() == Opcode(Opcode::IQUERY_CODE));
+ EXPECT_TRUE(Opcode::IQUERY().equals(Opcode(Opcode::IQUERY_CODE)));
+ EXPECT_TRUE(Opcode::NOTIFY() == Opcode(Opcode::NOTIFY_CODE));
+ EXPECT_TRUE(Opcode::NOTIFY().equals(Opcode(Opcode::NOTIFY_CODE)));
+ EXPECT_TRUE(Opcode::UPDATE() == Opcode(Opcode::UPDATE_CODE));
+ EXPECT_TRUE(Opcode::UPDATE().equals(Opcode(Opcode::UPDATE_CODE)));
+ EXPECT_TRUE(Opcode::RESERVED15() == Opcode(Opcode::RESERVED15()));
+ EXPECT_TRUE(Opcode::RESERVED15().equals(Opcode(Opcode::RESERVED15())));
+}
+
+TEST(OpcodeTest, nequal) {
+ EXPECT_TRUE(Opcode::QUERY() != Opcode::IQUERY());
+ EXPECT_TRUE(Opcode::QUERY().nequals(Opcode::IQUERY()));
+ EXPECT_TRUE(Opcode::NOTIFY() != Opcode(1));
+ EXPECT_TRUE(Opcode::NOTIFY().nequals(Opcode(1)));
+ EXPECT_TRUE(Opcode(10) != Opcode(11));
+ EXPECT_TRUE(Opcode(10).nequals(Opcode(11)));
+}
+
+TEST(OpcodeTest, toText) {
+ vector<const char*> expects;
+ expects.resize(Opcode::RESERVED15_CODE + 1);
+ expects[Opcode::QUERY_CODE] = "QUERY";
+ expects[Opcode::IQUERY_CODE] = "IQUERY";
+ expects[Opcode::STATUS_CODE] = "STATUS";
+ expects[Opcode::RESERVED3_CODE] = "RESERVED3";
+ expects[Opcode::NOTIFY_CODE] = "NOTIFY";
+ expects[Opcode::UPDATE_CODE] = "UPDATE";
+ expects[Opcode::RESERVED6_CODE] = "RESERVED6";
+ expects[Opcode::RESERVED7_CODE] = "RESERVED7";
+ expects[Opcode::RESERVED8_CODE] = "RESERVED8";
+ expects[Opcode::RESERVED9_CODE] = "RESERVED9";
+ expects[Opcode::RESERVED10_CODE] = "RESERVED10";
+ expects[Opcode::RESERVED11_CODE] = "RESERVED11";
+ expects[Opcode::RESERVED12_CODE] = "RESERVED12";
+ expects[Opcode::RESERVED13_CODE] = "RESERVED13";
+ expects[Opcode::RESERVED14_CODE] = "RESERVED14";
+ expects[Opcode::RESERVED15_CODE] = "RESERVED15";
+
+ for (unsigned int i = 0; i <= Opcode::RESERVED15_CODE; ++i) {
+ EXPECT_EQ(expects.at(i), Opcode(i).toText());
+ }
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST(OpcodeTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << Opcode::NOTIFY();
+ EXPECT_EQ(Opcode::NOTIFY().toText(), oss.str());
+}
+}
diff --git a/src/lib/dns/tests/qid_gen_unittest.cc b/src/lib/dns/tests/qid_gen_unittest.cc
new file mode 100644
index 0000000..20a2dfa
--- /dev/null
+++ b/src/lib/dns/tests/qid_gen_unittest.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/// \brief Test of QidGenerator
+///
+
+#include <config.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/qid_gen.h>
+
+using namespace isc::dns;
+
+// Tests the operation of the Qid generator
+
+// Check that getInstance returns a singleton
+TEST(QidGenerator, singleton) {
+ QidGenerator& g1 = QidGenerator::getInstance();
+ QidGenerator& g2 = QidGenerator::getInstance();
+
+ EXPECT_TRUE(&g1 == &g2);
+}
+
+TEST(QidGenerator, generate) {
+ // We'll assume that cryptolink's generator is 'good enough', and won't
+ // do full statistical checking here. Let's just call it the xkcd
+ // test (http://xkcd.com/221/), and check if three consecutive
+ // generates are not all the same.
+ uint16_t one, two, three;
+ QidGenerator& gen = QidGenerator::getInstance();
+ one = gen.generateQid();
+ two = gen.generateQid();
+ three = gen.generateQid();
+ ASSERT_FALSE((one == two) && (one == three));
+}
diff --git a/src/lib/dns/tests/question_unittest.cc b/src/lib/dns/tests/question_unittest.cc
new file mode 100644
index 0000000..03d31b1
--- /dev/null
+++ b/src/lib/dns/tests/question_unittest.cc
@@ -0,0 +1,196 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <vector>
+#include <sstream>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/question.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class QuestionTest : public ::testing::Test {
+protected:
+ QuestionTest() : obuffer(0),
+ example_name1(Name("foo.example.com")),
+ example_name2(Name("bar.example.com")),
+ test_question1(example_name1, RRClass::IN(),
+ RRType::NS()),
+ test_question2(example_name2, RRClass::CH(),
+ RRType::A())
+ {}
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+ Name example_name1;
+ Name example_name2;
+ Question test_question1;
+ Question test_question2;
+ vector<unsigned char> wiredata;
+};
+
+Question
+questionFromWire(const char* datafile, size_t position = 0) {
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData(datafile, data);
+
+ InputBuffer buffer(&data[0], data.size());
+ buffer.setPosition(position);
+
+ return (Question(buffer));
+}
+
+TEST_F(QuestionTest, fromWire) {
+ Question q = questionFromWire("question_fromWire");
+
+ EXPECT_EQ(example_name1, q.getName());
+ EXPECT_EQ(RRClass::IN(), q.getClass());
+ EXPECT_EQ(RRType::NS(), q.getType());
+
+ // owner name of the second Question is compressed. It's uncommon
+ // (to have multiple questions), but isn't prohibited by the protocol.
+ q = questionFromWire("question_fromWire", 21);
+ EXPECT_EQ(example_name2, q.getName());
+ EXPECT_EQ(RRClass::CH(), q.getClass());
+ EXPECT_EQ(RRType::A(), q.getType());
+
+ // Pathological cases: Corresponding exceptions will be thrown from
+ // the underlying parser.
+ EXPECT_THROW(questionFromWire("question_fromWire", 31), DNSMessageFORMERR);
+ EXPECT_THROW(questionFromWire("question_fromWire", 36), IncompleteRRClass);
+}
+
+TEST_F(QuestionTest, toText) {
+ EXPECT_EQ("foo.example.com. IN NS", test_question1.toText());
+ EXPECT_EQ("bar.example.com. CH A", test_question2.toText());
+
+ EXPECT_EQ("foo.example.com. IN NS", test_question1.toText(false));
+ EXPECT_EQ("bar.example.com. CH A", test_question2.toText(false));
+
+ EXPECT_EQ("foo.example.com. IN NS\n", test_question1.toText(true));
+ EXPECT_EQ("bar.example.com. CH A\n", test_question2.toText(true));
+}
+
+TEST_F(QuestionTest, toWireBuffer) {
+ test_question1.toWire(obuffer);
+ test_question2.toWire(obuffer);
+ UnitTestUtil::readWireData("question_toWire1", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(QuestionTest, toWireRenderer) {
+ test_question1.toWire(renderer);
+ test_question2.toWire(renderer);
+ UnitTestUtil::readWireData("question_toWire2", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(QuestionTest, toWireTruncated) {
+ // If the available length in the renderer is too small, it would require
+ // truncation. This won't happen in normal cases, but protocol wise it
+ // could still happen if and when we support some (possibly future) opcode
+ // that allows multiple questions.
+
+ // Set the length limit to the qname length so that the whole question
+ // would request truncated
+ renderer.setLengthLimit(example_name1.getLength());
+
+ EXPECT_FALSE(renderer.isTruncated()); // check pre-render condition
+ EXPECT_EQ(0, test_question1.toWire(renderer));
+ EXPECT_TRUE(renderer.isTruncated());
+ EXPECT_EQ(0, renderer.getLength()); // renderer shouldn't have any data
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(QuestionTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << test_question1;
+ EXPECT_EQ(test_question1.toText(), oss.str());
+}
+
+TEST_F(QuestionTest, comparison) {
+ const Name a("a"), b("b");
+ const RRClass in(RRClass::IN()), ch(RRClass::CH());
+ const RRType ns(RRType::NS()), aaaa(RRType::AAAA());
+
+ EXPECT_TRUE(Question(a, in, ns) < Question(a, in, aaaa));
+ EXPECT_FALSE(Question(a, in, aaaa) < Question(a, in, ns));
+
+ EXPECT_TRUE(Question(a, in, ns) < Question(a, ch, ns));
+ EXPECT_FALSE(Question(a, ch, ns) < Question(a, in, ns));
+
+ EXPECT_TRUE(Question(a, in, ns) < Question(a, ch, aaaa));
+ EXPECT_FALSE(Question(a, ch, aaaa) < Question(a, in, ns));
+
+ EXPECT_TRUE(Question(a, in, ns) < Question(b, in, ns));
+ EXPECT_FALSE(Question(a, in, ns) < Question(a, in, ns));
+
+ EXPECT_TRUE(Question(a, in, ns) < Question(b, ch, ns));
+ EXPECT_FALSE(Question(b, ch, ns) < Question(a, in, ns));
+
+ EXPECT_TRUE(Question(a, in, ns) < Question(b, ch, aaaa));
+ EXPECT_FALSE(Question(b, ch, aaaa) < Question(a, in, ns));
+
+ EXPECT_FALSE(Question(a, in, ns) < Question(a, in, ns));
+ EXPECT_FALSE(Question(a, ch, ns) < Question(a, ch, ns));
+ EXPECT_FALSE(Question(b, in, ns) < Question(b, in, ns));
+ EXPECT_FALSE(Question(b, in, aaaa) < Question(b, in, aaaa));
+
+ // Identical questions are equal
+
+ EXPECT_TRUE(Question(a, in, ns) == Question(a, in, ns));
+ EXPECT_FALSE(Question(a, in, ns) != Question(a, in, ns));
+
+ // Components differing by one component are unequal...
+
+ EXPECT_FALSE(Question(b, in, ns) == Question(a, in, ns));
+ EXPECT_TRUE(Question(b, in, ns) != Question(a, in, ns));
+
+ EXPECT_FALSE(Question(a, ch, ns) == Question(a, in, ns));
+ EXPECT_TRUE(Question(a, ch, ns) != Question(a, in, ns));
+
+ EXPECT_FALSE(Question(a, in, aaaa) == Question(a, in, ns));
+ EXPECT_TRUE(Question(a, in, aaaa) != Question(a, in, ns));
+
+ // ... as are those differing by two components
+
+ EXPECT_FALSE(Question(b, ch, ns) == Question(a, in, ns));
+ EXPECT_TRUE(Question(b, ch, ns) != Question(a, in, ns));
+
+ EXPECT_FALSE(Question(b, in, aaaa) == Question(a, in, ns));
+ EXPECT_TRUE(Question(b, in, aaaa) != Question(a, in, ns));
+
+ EXPECT_FALSE(Question(a, ch, aaaa) == Question(a, in, ns));
+ EXPECT_TRUE(Question(a, ch, aaaa) != Question(a, in, ns));
+
+ // ... and question differing by all three
+
+ EXPECT_FALSE(Question(b, ch, aaaa) == Question(a, in, ns));
+ EXPECT_TRUE(Question(b, ch, aaaa) != Question(a, in, ns));
+
+}
+
+}
diff --git a/src/lib/dns/tests/rcode_unittest.cc b/src/lib/dns/tests/rcode_unittest.cc
new file mode 100644
index 0000000..220248f
--- /dev/null
+++ b/src/lib/dns/tests/rcode_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <vector>
+#include <sstream>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/rcode.h>
+
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc::dns;
+
+namespace {
+TEST(RcodeTest, constructFromCode) {
+ // Normal cases. This test also tests getCode()
+ EXPECT_EQ(0, Rcode(0).getCode());
+ EXPECT_EQ(0xfff, Rcode(0xfff).getCode()); // possible max code
+
+ // should fail on attempt of construction with an out of range code
+ EXPECT_THROW(Rcode(0x1000), isc::OutOfRange);
+ EXPECT_THROW(Rcode(0xffff), isc::OutOfRange);
+}
+
+TEST(RcodeTest, constructFromCodePair) {
+ EXPECT_EQ(3, Rcode(Rcode::NXDOMAIN_CODE, 0).getCode());
+ EXPECT_EQ(Rcode::BADVERS_CODE, Rcode(0, 1).getCode());
+ EXPECT_EQ(0xfff, Rcode(0xf, 0xff).getCode());
+ EXPECT_THROW(Rcode(0x10, 0xff), isc::OutOfRange);
+}
+
+TEST(RcodeTest, getExtendedCode) {
+ EXPECT_EQ(0, Rcode::NOERROR().getExtendedCode());
+ EXPECT_EQ(0, Rcode::YXRRSET().getExtendedCode());
+ EXPECT_EQ(1, Rcode::BADVERS().getExtendedCode());
+ EXPECT_EQ(0xab, Rcode(0xabf).getExtendedCode());
+ EXPECT_EQ(0xff, Rcode(0xfff).getExtendedCode());
+}
+
+TEST(RcodeTest, constants) {
+ // We'll only test arbitrarily chosen subsets of the codes.
+ // This class is quite simple, so it should be suffice.
+
+ EXPECT_EQ(Rcode::NOERROR_CODE, Rcode(0).getCode());
+ EXPECT_EQ(Rcode::FORMERR_CODE, Rcode(1).getCode());
+ EXPECT_EQ(Rcode::NOTIMP_CODE, Rcode(4).getCode());
+ EXPECT_EQ(Rcode::REFUSED_CODE, Rcode(5).getCode());
+ EXPECT_EQ(Rcode::RESERVED15_CODE, Rcode(15).getCode());
+ EXPECT_EQ(Rcode::BADVERS_CODE, Rcode(16).getCode());
+
+ EXPECT_EQ(Rcode::NOERROR_CODE, Rcode::NOERROR().getCode());
+ EXPECT_EQ(Rcode::FORMERR_CODE, Rcode::FORMERR().getCode());
+ EXPECT_EQ(Rcode::NOTIMP_CODE, Rcode::NOTIMP().getCode());
+ EXPECT_EQ(Rcode::REFUSED_CODE, Rcode::REFUSED().getCode());
+ EXPECT_EQ(Rcode::RESERVED15_CODE, Rcode::RESERVED15().getCode());
+ EXPECT_EQ(Rcode::BADVERS_CODE, Rcode::BADVERS().getCode());
+}
+
+TEST(RcodeTest, equal) {
+ EXPECT_TRUE(Rcode::NOERROR() == Rcode(Rcode::NOERROR_CODE));
+ EXPECT_TRUE(Rcode::NOERROR().equals(Rcode(Rcode::NOERROR_CODE)));
+ EXPECT_TRUE(Rcode::FORMERR() == Rcode(Rcode::FORMERR_CODE));
+ EXPECT_TRUE(Rcode::FORMERR().equals(Rcode(Rcode::FORMERR_CODE)));
+ EXPECT_TRUE(Rcode::NOTIMP() == Rcode(Rcode::NOTIMP_CODE));
+ EXPECT_TRUE(Rcode::NOTIMP().equals(Rcode(Rcode::NOTIMP_CODE)));
+ EXPECT_TRUE(Rcode::REFUSED() == Rcode(Rcode::REFUSED_CODE));
+ EXPECT_TRUE(Rcode::REFUSED().equals(Rcode(Rcode::REFUSED_CODE)));
+ EXPECT_TRUE(Rcode::RESERVED15() == Rcode(Rcode::RESERVED15()));
+ EXPECT_TRUE(Rcode::RESERVED15().equals(Rcode(Rcode::RESERVED15())));
+ EXPECT_TRUE(Rcode::BADVERS() == Rcode(Rcode::BADVERS_CODE));
+ EXPECT_TRUE(Rcode::BADVERS().equals(Rcode(Rcode::BADVERS_CODE)));
+}
+
+TEST(RcodeTest, nequal) {
+ EXPECT_TRUE(Rcode::NOERROR() != Rcode::FORMERR());
+ EXPECT_TRUE(Rcode::NOERROR().nequals(Rcode::FORMERR()));
+ EXPECT_TRUE(Rcode::NOTIMP() != Rcode(1));
+ EXPECT_TRUE(Rcode::NOTIMP().nequals(Rcode(1)));
+ EXPECT_TRUE(Rcode(10) != Rcode(11));
+ EXPECT_TRUE(Rcode(10).nequals(Rcode(11)));
+}
+
+TEST(RcodeTest, toText) {
+ vector<const char*> expects;
+ expects.resize(Rcode::BADVERS_CODE + 1);
+ expects[Rcode::NOERROR_CODE] = "NOERROR";
+ expects[Rcode::FORMERR_CODE] = "FORMERR";
+ expects[Rcode::SERVFAIL_CODE] = "SERVFAIL";
+ expects[Rcode::NXDOMAIN_CODE] = "NXDOMAIN";
+ expects[Rcode::NOTIMP_CODE] = "NOTIMP";
+ expects[Rcode::REFUSED_CODE] = "REFUSED";
+ expects[Rcode::YXDOMAIN_CODE] = "YXDOMAIN";
+ expects[Rcode::YXRRSET_CODE] = "YXRRSET";
+ expects[Rcode::NXRRSET_CODE] = "NXRRSET";
+ expects[Rcode::NOTAUTH_CODE] = "NOTAUTH";
+ expects[Rcode::NOTZONE_CODE] = "NOTZONE";
+ expects[Rcode::RESERVED11_CODE] = "RESERVED11";
+ expects[Rcode::RESERVED12_CODE] = "RESERVED12";
+ expects[Rcode::RESERVED13_CODE] = "RESERVED13";
+ expects[Rcode::RESERVED14_CODE] = "RESERVED14";
+ expects[Rcode::RESERVED15_CODE] = "RESERVED15";
+ expects[Rcode::BADVERS_CODE] = "BADVERS";
+
+ for (unsigned int i = 0; i <= Rcode::BADVERS_CODE; ++i) {
+ EXPECT_EQ(expects.at(i), Rcode(i).toText());
+ }
+
+ // Non well-known Rcodes
+ EXPECT_EQ("17", Rcode(Rcode::BADVERS().getCode() + 1).toText());
+ EXPECT_EQ("4095", Rcode(Rcode(0xfff)).toText());
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST(RcodeTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << Rcode::SERVFAIL();
+ EXPECT_EQ(Rcode::SERVFAIL().toText(), oss.str());
+}
+}
diff --git a/src/lib/dns/tests/rdata_afsdb_unittest.cc b/src/lib/dns/tests/rdata_afsdb_unittest.cc
new file mode 100644
index 0000000..26c3135
--- /dev/null
+++ b/src/lib/dns/tests/rdata_afsdb_unittest.cc
@@ -0,0 +1,235 @@
+// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+const char* const afsdb_text = "1 afsdb.example.com.";
+const char* const afsdb_text2 = "0 root.example.com.";
+const char* const too_long_label("012345678901234567890123456789"
+ "0123456789012345678901234567890123.");
+
+namespace {
+class Rdata_AFSDB_Test : public RdataTest {
+protected:
+ Rdata_AFSDB_Test() :
+ rdata_afsdb(string(afsdb_text)), rdata_afsdb2(string(afsdb_text2))
+ {}
+
+ const generic::AFSDB rdata_afsdb;
+ const generic::AFSDB rdata_afsdb2;
+ vector<uint8_t> expected_wire;
+};
+
+
+TEST_F(Rdata_AFSDB_Test, createFromText) {
+ EXPECT_EQ(1, rdata_afsdb.getSubtype());
+ EXPECT_EQ(Name("afsdb.example.com."), rdata_afsdb.getServer());
+
+ EXPECT_EQ(0, rdata_afsdb2.getSubtype());
+ EXPECT_EQ(Name("root.example.com."), rdata_afsdb2.getServer());
+}
+
+TEST_F(Rdata_AFSDB_Test, badText) {
+ // subtype is too large
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("99999999 afsdb.example.com."),
+ InvalidRdataText);
+ // incomplete text
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("10"), InvalidRdataText);
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("SPOON"), InvalidRdataText);
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("1root.example.com."), InvalidRdataText);
+ // number of fields (must be 2) is incorrect
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("10 afsdb. example.com."),
+ InvalidRdataText);
+ // No origin and relative
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com"),
+ MissingNameOrigin);
+ // bad name
+ EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com." +
+ string(too_long_label)), TooLongLabel);
+}
+
+TEST_F(Rdata_AFSDB_Test, copy) {
+ const generic::AFSDB rdata_afsdb2(rdata_afsdb);
+ EXPECT_EQ(0, rdata_afsdb.compare(rdata_afsdb2));
+}
+
+TEST_F(Rdata_AFSDB_Test, assignment) {
+ generic::AFSDB copy((string(afsdb_text2)));
+ copy = rdata_afsdb;
+ EXPECT_EQ(0, copy.compare(rdata_afsdb));
+
+ // Check if the copied data is valid even after the original is deleted
+ generic::AFSDB* copy2 = new generic::AFSDB(rdata_afsdb);
+ generic::AFSDB copy3((string(afsdb_text2)));
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_afsdb));
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(0, copy.compare(rdata_afsdb));
+}
+
+TEST_F(Rdata_AFSDB_Test, createFromWire) {
+ // uncompressed names
+ EXPECT_EQ(0, rdata_afsdb.compare(
+ *rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(),
+ "rdata_afsdb_fromWire1.wire")));
+ // compressed name
+ EXPECT_EQ(0, rdata_afsdb.compare(
+ *rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(),
+ "rdata_afsdb_fromWire2.wire", 13)));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(),
+ "rdata_afsdb_fromWire3.wire"),
+ InvalidRdataLength);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(),
+ "rdata_afsdb_fromWire4.wire"),
+ InvalidRdataLength);
+ // bogus server name, the error should be detected in the name
+ // constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(),
+ "rdata_afsdb_fromWire5.wire"),
+ DNSMessageFORMERR);
+}
+
+TEST_F(Rdata_AFSDB_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_afsdb.compare(
+ *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ afsdb_text)));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ generic::AFSDB tmp = generic::AFSDB("1 afsdb2.example.org.");
+ EXPECT_EQ(0, tmp.compare(
+ *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ "1 afsdb2")));
+
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ "1root.example.com."));
+
+ // 65536 is larger than maximum possible subtype
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ "65536 afsdb.example.com."));
+
+ // Extra text at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+ "1 afsdb.example.com. extra."));
+}
+
+TEST_F(Rdata_AFSDB_Test, toWireBuffer) {
+ // construct actual data
+ rdata_afsdb.toWire(obuffer);
+
+ // construct expected data
+ UnitTestUtil::readWireData("rdata_afsdb_toWire1.wire", expected_wire);
+
+ // then compare them
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
+
+ // clear buffer for the next test
+ obuffer.clear();
+
+ // construct actual data
+ Name("example.com.").toWire(obuffer);
+ rdata_afsdb2.toWire(obuffer);
+
+ // construct expected data
+ UnitTestUtil::readWireData("rdata_afsdb_toWire2.wire", expected_wire);
+
+ // then compare them
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_AFSDB_Test, toWireRenderer) {
+ // similar to toWireBuffer, but names in RDATA could be compressed due to
+ // preceding names. Actually they must not be compressed according to
+ // RFC3597, and this test checks that.
+
+ // construct actual data
+ rdata_afsdb.toWire(renderer);
+
+ // construct expected data
+ UnitTestUtil::readWireData("rdata_afsdb_toWire1.wire", expected_wire);
+
+ // then compare them
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
+
+ // clear renderer for the next test
+ renderer.clear();
+
+ // construct actual data
+ renderer.writeName(Name("example.com."));
+ rdata_afsdb2.toWire(renderer);
+
+ // construct expected data
+ UnitTestUtil::readWireData("rdata_afsdb_toWire2.wire", expected_wire);
+
+ // then compare them
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_AFSDB_Test, toText) {
+ EXPECT_EQ(afsdb_text, rdata_afsdb.toText());
+ EXPECT_EQ(afsdb_text2, rdata_afsdb2.toText());
+}
+
+TEST_F(Rdata_AFSDB_Test, compare) {
+ // check reflexivity
+ EXPECT_EQ(0, rdata_afsdb.compare(rdata_afsdb));
+
+ // name must be compared in case-insensitive manner
+ EXPECT_EQ(0, rdata_afsdb.compare(generic::AFSDB("1 "
+ "AFSDB.example.com.")));
+
+ const generic::AFSDB small1("10 afsdb.example.com.");
+ const generic::AFSDB large1("65535 afsdb.example.com.");
+ const generic::AFSDB large2("256 afsdb.example.com.");
+
+ // confirm these are compared as unsigned values
+ EXPECT_GT(0, rdata_afsdb.compare(large1));
+ EXPECT_LT(0, large1.compare(rdata_afsdb));
+
+ // confirm these are compared in network byte order
+ EXPECT_GT(0, small1.compare(large2));
+ EXPECT_LT(0, large2.compare(small1));
+
+ // another AFSDB whose server name is larger than that of rdata_afsdb.
+ const generic::AFSDB large3("256 zzzzz.example.com.");
+ EXPECT_GT(0, large2.compare(large3));
+ EXPECT_LT(0, large3.compare(large2));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_afsdb.compare(*rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc
new file mode 100644
index 0000000..48b9076
--- /dev/null
+++ b/src/lib/dns/tests/rdata_caa_unittest.cc
@@ -0,0 +1,322 @@
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_CAA_Test : public RdataTest {
+protected:
+ Rdata_CAA_Test() :
+ caa_txt("0 issue \"ca.example.net\""),
+ rdata_caa(caa_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::CAA, isc::Exception, isc::Exception>(
+ rdata_str, rdata_caa, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::CAA, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_caa, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::CAA, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_caa, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::CAA, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_caa, true, false);
+ }
+
+ const string caa_txt;
+ const generic::CAA rdata_caa;
+};
+
+const uint8_t rdata_caa_wiredata[] = {
+ // flags
+ 0x00,
+ // tag length
+ 0x5,
+ // tag
+ 'i', 's', 's', 'u', 'e',
+ // value
+ 'c', 'a', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e',
+ '.', 'n', 'e', 't'
+};
+
+TEST_F(Rdata_CAA_Test, createFromText) {
+ // Basic test
+ checkFromText_None(caa_txt);
+
+ // With different spacing
+ checkFromText_None("0 issue \"ca.example.net\"");
+
+ // Combination of lowercase and uppercase
+ checkFromText_None("0 IssUE \"ca.example.net\"");
+
+ // string constructor throws if there's extra text,
+ // but lexer constructor doesn't
+ checkFromText_BadString(caa_txt + "\n" + caa_txt);
+
+ // Missing value field
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue"));
+}
+
+TEST_F(Rdata_CAA_Test, fields) {
+ // Some of these may not be RFC conformant, but we relax the check
+ // in our code to work with other field values that may show up in
+ // the future.
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("1 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("2 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("3 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("128 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("255 issue \"ca.example.net\""));
+
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 foo \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 bar \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 12345 \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 w0x1y2z3 \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 relaxed-too \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 RELAXED.too \"ca.example.net\""));
+
+ // No value (this is redundant to the last test case in the
+ // .createFromText test
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue"));
+
+ // > 255 would be broken
+ EXPECT_THROW(const generic::CAA rdata_caa2("256 issue \"ca.example.net\""),
+ InvalidRdataText);
+
+ // Missing tag causes the value to be parsed as the tag field. As
+ // the tag field does not allow quoted strings, this throws.
+ EXPECT_THROW(const generic::CAA rdata_caa2("0 \"ca.example.net\""),
+ InvalidRdataText);
+
+ // Tag is too long
+ const std::string tag(256, 'a');
+ const std::string rdata_txt("0 " + tag + " \"ca.example.net\"");
+ EXPECT_THROW(const generic::CAA rdata_caa2(rdata_txt), InvalidRdataText);
+}
+
+TEST_F(Rdata_CAA_Test, characterStringValue) {
+ const generic::CAA rdata_caa_unquoted("0 issue ca.example.net");
+ EXPECT_EQ(0, rdata_caa_unquoted.compare(rdata_caa));
+
+ const generic::CAA rdata_caa_escape_X("0 issue ca.e\\xample.net");
+ EXPECT_EQ(0, rdata_caa_escape_X.compare(rdata_caa));
+
+ const generic::CAA rdata_caa_escape_DDD("0 issue ca.e\\120ample.net");
+ EXPECT_EQ(0, rdata_caa_escape_DDD.compare(rdata_caa));
+
+ const generic::CAA rdata_caa_multiline("0 issue (\nca.example.net)");
+ EXPECT_EQ(0, rdata_caa_multiline.compare(rdata_caa));
+}
+
+TEST_F(Rdata_CAA_Test, badText) {
+ checkFromText_LexerError("0");
+ checkFromText_LexerError("ZERO issue \"ca.example.net\"");
+ EXPECT_THROW(const generic::CAA rdata_caa2(caa_txt + " extra text"),
+ InvalidRdataText);
+
+ // Yes, this is redundant to the last test cases in the .fields test
+ checkFromText_InvalidText("2345 issue \"ca.example.net\"");
+
+ // negative values are trapped in the lexer rather than the
+ // constructor
+ checkFromText_LexerError("-2 issue \"ca.example.net\"");
+}
+
+TEST_F(Rdata_CAA_Test, copyAndAssign) {
+ // Copy construct
+ generic::CAA rdata_caa2(rdata_caa);
+ EXPECT_EQ(0, rdata_caa.compare(rdata_caa2));
+
+ // Assignment, mainly to confirm it doesn't cause disruption.
+ rdata_caa2 = rdata_caa;
+ EXPECT_EQ(0, rdata_caa.compare(rdata_caa2));
+}
+
+TEST_F(Rdata_CAA_Test, createFromWire) {
+ // Basic test
+ EXPECT_EQ(0, rdata_caa.compare(
+ *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire1.wire")));
+
+ // Combination of lowercase and uppercase
+ EXPECT_EQ(0, rdata_caa.compare(
+ *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire2.wire")));
+
+ // Value field is empty
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire3.wire"));
+
+ // Tag field is empty
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire4.wire"),
+ InvalidRdataText);
+
+ // Value field is shorter than rdata len
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire5"),
+ InvalidBufferPosition);
+
+ // all RDATA is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire6"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_CAA_Test, createFromParams) {
+ const generic::CAA rdata_caa2(0, "issue", "ca.example.net");
+ EXPECT_EQ(0, rdata_caa2.compare(rdata_caa));
+
+ const generic::CAA rdata_caa4(0, "issue", "ca.e\\xample.net");
+ EXPECT_EQ(0, rdata_caa4.compare(rdata_caa));
+
+ const generic::CAA rdata_caa5(0, "issue", "ca.e\\120ample.net");
+ EXPECT_EQ(0, rdata_caa5.compare(rdata_caa));
+
+ // Tag is empty
+ EXPECT_THROW(const generic::CAA rdata_caa3(0, "", "ca.example.net"),
+ isc::InvalidParameter);
+
+ // Tag is too long
+ const std::string tag(256, 'a');
+ EXPECT_THROW(const generic::CAA rdata_caa3(0, tag, "ca.example.net"),
+ isc::InvalidParameter);
+
+ // Value is too long
+ const std::string value(65536, 'a');
+ EXPECT_THROW(const generic::CAA rdata_caa3(0, "issue", value),
+ InvalidRdataLength);
+}
+
+TEST_F(Rdata_CAA_Test, toText) {
+ EXPECT_TRUE(boost::iequals(caa_txt, rdata_caa.toText()));
+
+ const string caa_txt2("1 issue \"\"");
+ const generic::CAA rdata_caa2(caa_txt2);
+ EXPECT_TRUE(boost::iequals(caa_txt2, rdata_caa2.toText()));
+}
+
+TEST_F(Rdata_CAA_Test, toWire) {
+ obuffer.clear();
+ rdata_caa.toWire(obuffer);
+
+ matchWireData(rdata_caa_wiredata, sizeof(rdata_caa_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_CAA_Test, compare) {
+ // Equality test is repeated from createFromWire tests above.
+ EXPECT_EQ(0, rdata_caa.compare(
+ *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire1.wire")));
+
+ const generic::CAA rdata_caa2("1 issue \"ca.example.net\"");
+
+ EXPECT_EQ(1, rdata_caa2.compare(rdata_caa));
+ EXPECT_EQ(-1, rdata_caa.compare(rdata_caa2));
+}
+
+TEST_F(Rdata_CAA_Test, getFlags) {
+ EXPECT_EQ(0, rdata_caa.getFlags());
+}
+
+TEST_F(Rdata_CAA_Test, getTag) {
+ EXPECT_EQ("issue", rdata_caa.getTag());
+}
+
+TEST_F(Rdata_CAA_Test, getValue) {
+ const uint8_t value_data[] = {
+ 'c', 'a', '.',
+ 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.',
+ 'n', 'e', 't'
+ };
+
+ const std::vector<uint8_t>& value = rdata_caa.getValue();
+ matchWireData(value_data, sizeof(value_data),
+ &value[0], value.size());
+}
+
+TEST_F(Rdata_CAA_Test, emptyValueFromWire) {
+ const uint8_t rdf_wiredata[] = {
+ // flags
+ 0x00,
+ // tag length
+ 0x5,
+ // tag
+ 'i', 's', 's', 'u', 'e'
+ };
+
+ const generic::CAA rdf =
+ dynamic_cast<const generic::CAA&>
+ (*rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire3.wire"));
+
+ EXPECT_EQ(0, rdf.getFlags());
+ EXPECT_EQ("issue", rdf.getTag());
+
+ obuffer.clear();
+ rdf.toWire(obuffer);
+
+ matchWireData(rdf_wiredata, sizeof(rdf_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_CAA_Test, emptyValueFromString) {
+ const generic::CAA rdata_caa2("0 issue");
+ const uint8_t rdata_caa2_wiredata[] = {
+ // flags
+ 0x00,
+ // tag length
+ 0x5,
+ // tag
+ 'i', 's', 's', 'u', 'e'
+ };
+
+ EXPECT_EQ(0, rdata_caa2.getFlags());
+ EXPECT_EQ("issue", rdata_caa2.getTag());
+
+ obuffer.clear();
+ rdata_caa2.toWire(obuffer);
+
+ matchWireData(rdata_caa2_wiredata, sizeof(rdata_caa2_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+}
diff --git a/src/lib/dns/tests/rdata_char_string_data_unittest.cc b/src/lib/dns/tests/rdata_char_string_data_unittest.cc
new file mode 100644
index 0000000..4ffeadb
--- /dev/null
+++ b/src/lib/dns/tests/rdata_char_string_data_unittest.cc
@@ -0,0 +1,181 @@
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/unittests/wiredata.h>
+
+#include <dns/exceptions.h>
+#include <dns/rdata.h>
+#include <dns/rdata/generic/detail/char_string.h>
+#include <util/buffer.h>
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using isc::dns::rdata::generic::detail::CharStringData;
+using isc::dns::rdata::generic::detail::stringToCharStringData;
+using isc::dns::rdata::generic::detail::charStringDataToString;
+using isc::dns::rdata::generic::detail::compareCharStringDatas;
+using isc::util::unittests::matchWireData;
+
+namespace {
+const uint8_t test_charstr[] = {
+ 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'
+};
+
+class CharStringDataTest : public ::testing::Test {
+protected:
+ CharStringDataTest() :
+ // char-string representation for test data using two types of escape
+ // ('r' = 114)
+ test_str("Test\\ St\\114ing")
+ {
+ str_region.beg = &test_str[0];
+ str_region.len = test_str.size();
+ }
+ CharStringData chstr; // place holder
+ const std::string test_str;
+ MasterToken::StringRegion str_region;
+};
+
+MasterToken::StringRegion
+createStringRegion(const std::string& str) {
+ MasterToken::StringRegion region;
+ region.beg = &str[0]; // note std ensures this works even if str is empty
+ region.len = str.size();
+ return (region);
+}
+
+TEST_F(CharStringDataTest, normalConversion) {
+ uint8_t tmp[3]; // placeholder for expected sequence
+
+ stringToCharStringData(str_region, chstr);
+ matchWireData(test_charstr, sizeof(test_charstr), &chstr[0], chstr.size());
+
+ // Empty string
+ chstr.clear();
+ stringToCharStringData(createStringRegion(""), chstr);
+ EXPECT_TRUE(chstr.empty());
+
+ // Possible largest char string
+ chstr.clear();
+ std::string long_str(255, 'x');
+ stringToCharStringData(createStringRegion(long_str), chstr);
+ std::vector<uint8_t> expected;
+ expected.insert(expected.end(), long_str.begin(), long_str.end());
+ matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size());
+
+ // Escaped '\'
+ chstr.clear();
+ tmp[0] = '\\';
+ stringToCharStringData(createStringRegion("\\\\"), chstr);
+ matchWireData(tmp, 1, &chstr[0], chstr.size());
+
+ // Boundary values for \DDD
+ chstr.clear();
+ tmp[0] = 0;
+ stringToCharStringData(createStringRegion("\\000"), chstr);
+ matchWireData(tmp, 1, &chstr[0], chstr.size());
+
+ chstr.clear();
+ stringToCharStringData(createStringRegion("\\255"), chstr);
+ tmp[0] = 255;
+ matchWireData(tmp, 1, &chstr[0], chstr.size());
+
+ // Another digit follows DDD; it shouldn't cause confusion
+ chstr.clear();
+ stringToCharStringData(createStringRegion("\\2550"), chstr);
+ tmp[1] = '0';
+ matchWireData(tmp, 2, &chstr[0], chstr.size());
+}
+
+TEST_F(CharStringDataTest, badConversion) {
+ // input string ending with (non escaped) '\'
+ chstr.clear();
+ EXPECT_THROW(stringToCharStringData(createStringRegion("foo\\"), chstr),
+ InvalidRdataText);
+}
+
+TEST_F(CharStringDataTest, badDDD) {
+ // Check various type of bad form of \DDD
+
+ // Not a number
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\1a2"), chstr),
+ InvalidRdataText);
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\12a"), chstr),
+ InvalidRdataText);
+
+ // Not in the range of uint8_t
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\256"), chstr),
+ InvalidRdataText);
+
+ // Short buffer
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\42"), chstr),
+ InvalidRdataText);
+}
+
+const struct TestData {
+ const char *data;
+ const char *expected;
+} conversion_data[] = {
+ {"Test\"Test", "Test\\\"Test"},
+ {"Test;Test", "Test\\;Test"},
+ {"Test\\Test", "Test\\\\Test"},
+ {"Test\x1fTest", "Test\\031Test"},
+ {"Test ~ Test", "Test ~ Test"},
+ {"Test\x7fTest", "Test\\127Test"},
+ {NULL, NULL}
+};
+
+TEST_F(CharStringDataTest, charStringDataToString) {
+ for (const TestData* cur = conversion_data; cur->data != NULL; ++cur) {
+ uint8_t idata[32];
+ size_t length = std::strlen(cur->data);
+ ASSERT_LT(length, sizeof(idata));
+ std::memcpy(idata, cur->data, length);
+ const CharStringData test_data(idata, idata + length);
+ EXPECT_EQ(cur->expected, charStringDataToString(test_data));
+ }
+}
+
+TEST_F(CharStringDataTest, compareCharStringData) {
+ CharStringData charstr;
+ CharStringData charstr2;
+ CharStringData charstr_small1;
+ CharStringData charstr_small2;
+ CharStringData charstr_large1;
+ CharStringData charstr_large2;
+ CharStringData charstr_empty;
+
+ stringToCharStringData(createStringRegion("test string"), charstr);
+ stringToCharStringData(createStringRegion("test string"), charstr2);
+ stringToCharStringData(createStringRegion("test strin"), charstr_small1);
+ stringToCharStringData(createStringRegion("test strina"), charstr_small2);
+ stringToCharStringData(createStringRegion("test stringa"), charstr_large1);
+ stringToCharStringData(createStringRegion("test strinz"), charstr_large2);
+
+ EXPECT_EQ(0, compareCharStringDatas(charstr, charstr2));
+ EXPECT_EQ(0, compareCharStringDatas(charstr2, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_small1));
+ EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_small2));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr, charstr_large1));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr, charstr_large2));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr_small1, charstr));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr_small2, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr_large1, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr_large2, charstr));
+
+ EXPECT_EQ(-1, compareCharStringDatas(charstr_empty, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_empty));
+ EXPECT_EQ(0, compareCharStringDatas(charstr_empty, charstr_empty));
+}
+
+} // unnamed namespace
diff --git a/src/lib/dns/tests/rdata_char_string_unittest.cc b/src/lib/dns/tests/rdata_char_string_unittest.cc
new file mode 100644
index 0000000..f1618b5
--- /dev/null
+++ b/src/lib/dns/tests/rdata_char_string_unittest.cc
@@ -0,0 +1,246 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/unittests/wiredata.h>
+
+#include <dns/exceptions.h>
+#include <dns/rdata.h>
+#include <dns/rdata/generic/detail/char_string.h>
+#include <util/buffer.h>
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using isc::dns::rdata::generic::detail::CharString;
+using isc::dns::rdata::generic::detail::bufferToCharString;
+using isc::dns::rdata::generic::detail::stringToCharString;
+using isc::dns::rdata::generic::detail::charStringToString;
+using isc::dns::rdata::generic::detail::compareCharStrings;
+using isc::util::unittests::matchWireData;
+
+namespace {
+const uint8_t test_charstr[] = {
+ sizeof("Test String") - 1,
+ 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'
+};
+
+class CharStringTest : public ::testing::Test {
+protected:
+ CharStringTest() :
+ // char-string representation for test data using two types of escape
+ // ('r' = 114)
+ test_str("Test\\ St\\114ing")
+ {
+ str_region.beg = &test_str[0];
+ str_region.len = test_str.size();
+ }
+ CharString chstr; // place holder
+ const std::string test_str;
+ MasterToken::StringRegion str_region;
+};
+
+MasterToken::StringRegion
+createStringRegion(const std::string& str) {
+ MasterToken::StringRegion region;
+ region.beg = &str[0]; // note std ensures this works even if str is empty
+ region.len = str.size();
+ return (region);
+}
+
+TEST_F(CharStringTest, normalConversion) {
+ uint8_t tmp[3]; // placeholder for expected sequence
+
+ stringToCharString(str_region, chstr);
+ matchWireData(test_charstr, sizeof(test_charstr), &chstr[0], chstr.size());
+
+ // Empty string
+ chstr.clear();
+ stringToCharString(createStringRegion(""), chstr);
+ tmp[0] = 0;
+ matchWireData(tmp, 1, &chstr[0], chstr.size());
+
+ // Possible largest char string
+ chstr.clear();
+ std::string long_str(255, 'x');
+ stringToCharString(createStringRegion(long_str), chstr);
+ std::vector<uint8_t> expected;
+ expected.push_back(255); // len of char string
+ expected.insert(expected.end(), long_str.begin(), long_str.end());
+ matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size());
+
+ // Same data as the previous case, but the original string is longer than
+ // the max; this shouldn't be rejected
+ chstr.clear();
+ long_str.at(254) = '\\'; // replace the last 'x' with '\'
+ long_str.append("120"); // 'x' = 120
+ stringToCharString(createStringRegion(long_str), chstr);
+ matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size());
+
+ // Escaped '\'
+ chstr.clear();
+ tmp[0] = 1;
+ tmp[1] = '\\';
+ stringToCharString(createStringRegion("\\\\"), chstr);
+ matchWireData(tmp, 2, &chstr[0], chstr.size());
+
+ // Boundary values for \DDD
+ chstr.clear();
+ tmp[0] = 1;
+ tmp[1] = 0;
+ stringToCharString(createStringRegion("\\000"), chstr);
+ matchWireData(tmp, 2, &chstr[0], chstr.size());
+
+ chstr.clear();
+ stringToCharString(createStringRegion("\\255"), chstr);
+ tmp[0] = 1;
+ tmp[1] = 255;
+ matchWireData(tmp, 2, &chstr[0], chstr.size());
+
+ // Another digit follows DDD; it shouldn't cause confusion
+ chstr.clear();
+ stringToCharString(createStringRegion("\\2550"), chstr);
+ tmp[0] = 2; // string len is now 2
+ tmp[2] = '0';
+ matchWireData(tmp, 3, &chstr[0], chstr.size());
+}
+
+TEST_F(CharStringTest, badConversion) {
+ // string cannot exceed 255 bytes
+ EXPECT_THROW(stringToCharString(createStringRegion(std::string(256, 'a')),
+ chstr),
+ CharStringTooLong);
+
+ // input string ending with (non escaped) '\'
+ chstr.clear();
+ EXPECT_THROW(stringToCharString(createStringRegion("foo\\"), chstr),
+ InvalidRdataText);
+}
+
+TEST_F(CharStringTest, badDDD) {
+ // Check various type of bad form of \DDD
+
+ // Not a number
+ EXPECT_THROW(stringToCharString(createStringRegion("\\1a2"), chstr),
+ InvalidRdataText);
+ EXPECT_THROW(stringToCharString(createStringRegion("\\12a"), chstr),
+ InvalidRdataText);
+
+ // Not in the range of uint8_t
+ EXPECT_THROW(stringToCharString(createStringRegion("\\256"), chstr),
+ InvalidRdataText);
+
+ // Short buffer
+ EXPECT_THROW(stringToCharString(createStringRegion("\\42"), chstr),
+ InvalidRdataText);
+}
+
+const struct TestData {
+ const char *data;
+ const char *expected;
+} conversion_data[] = {
+ {"Test\"Test", "Test\\\"Test"},
+ {"Test;Test", "Test\\;Test"},
+ {"Test\\Test", "Test\\\\Test"},
+ {"Test\x1fTest", "Test\\031Test"},
+ {"Test ~ Test", "Test ~ Test"},
+ {"Test\x7fTest", "Test\\127Test"},
+ {NULL, NULL}
+};
+
+TEST_F(CharStringTest, charStringToString) {
+ for (const TestData* cur = conversion_data; cur->data != NULL; ++cur) {
+ uint8_t idata[32];
+ size_t length = std::strlen(cur->data);
+ // length (1 byte) + string (length bytes)
+ assert(sizeof(idata) > length);
+ idata[0] = static_cast<uint8_t>(length);
+ std::memcpy(idata + 1, cur->data, length);
+ const CharString test_data(idata, idata + length + 1);
+ EXPECT_EQ(cur->expected, charStringToString(test_data));
+ }
+}
+
+TEST_F(CharStringTest, bufferToCharString) {
+ const size_t chstr_size = sizeof(test_charstr);
+ isc::util::InputBuffer buf(test_charstr, chstr_size);
+ size_t read = bufferToCharString(buf, chstr_size, chstr);
+
+ EXPECT_EQ(chstr_size, read);
+ EXPECT_EQ("Test String", charStringToString(chstr));
+}
+
+TEST_F(CharStringTest, bufferToCharString_bad) {
+ const size_t chstr_size = sizeof(test_charstr);
+ isc::util::InputBuffer buf(test_charstr, chstr_size);
+ // Set valid data in both so we can make sure the charstr is not
+ // modified
+ bufferToCharString(buf, chstr_size, chstr);
+ ASSERT_EQ("Test String", charStringToString(chstr));
+
+ // Should be at end of buffer now, so it should fail
+ EXPECT_THROW(bufferToCharString(buf, chstr_size - 1, chstr),
+ DNSMessageFORMERR);
+ EXPECT_EQ("Test String", charStringToString(chstr));
+
+ // reset and try to read with too low rdata_len
+ buf.setPosition(0);
+ EXPECT_THROW(bufferToCharString(buf, chstr_size - 1, chstr),
+ DNSMessageFORMERR);
+ EXPECT_EQ("Test String", charStringToString(chstr));
+
+ // set internal charstring len too high
+ const uint8_t test_charstr_err[] = {
+ sizeof("Test String") + 1,
+ 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'
+ };
+ buf = isc::util::InputBuffer(test_charstr_err, sizeof(test_charstr_err));
+ EXPECT_THROW(bufferToCharString(buf, chstr_size, chstr),
+ DNSMessageFORMERR);
+ EXPECT_EQ("Test String", charStringToString(chstr));
+
+}
+
+
+
+TEST_F(CharStringTest, compareCharString) {
+ CharString charstr;
+ CharString charstr2;
+ CharString charstr_small1;
+ CharString charstr_small2;
+ CharString charstr_large1;
+ CharString charstr_large2;
+ CharString charstr_empty;
+
+ stringToCharString(createStringRegion("test string"), charstr);
+ stringToCharString(createStringRegion("test string"), charstr2);
+ stringToCharString(createStringRegion("test strin"), charstr_small1);
+ stringToCharString(createStringRegion("test strina"), charstr_small2);
+ stringToCharString(createStringRegion("test stringa"), charstr_large1);
+ stringToCharString(createStringRegion("test strinz"), charstr_large2);
+
+ EXPECT_EQ(0, compareCharStrings(charstr, charstr2));
+ EXPECT_EQ(0, compareCharStrings(charstr2, charstr));
+ EXPECT_EQ(1, compareCharStrings(charstr, charstr_small1));
+ EXPECT_EQ(1, compareCharStrings(charstr, charstr_small2));
+ EXPECT_EQ(-1, compareCharStrings(charstr, charstr_large1));
+ EXPECT_EQ(-1, compareCharStrings(charstr, charstr_large2));
+ EXPECT_EQ(-1, compareCharStrings(charstr_small1, charstr));
+ EXPECT_EQ(-1, compareCharStrings(charstr_small2, charstr));
+ EXPECT_EQ(1, compareCharStrings(charstr_large1, charstr));
+ EXPECT_EQ(1, compareCharStrings(charstr_large2, charstr));
+
+ EXPECT_EQ(-1, compareCharStrings(charstr_empty, charstr));
+ EXPECT_EQ(1, compareCharStrings(charstr, charstr_empty));
+ EXPECT_EQ(0, compareCharStrings(charstr_empty, charstr_empty));
+}
+
+} // unnamed namespace
diff --git a/src/lib/dns/tests/rdata_cname_unittest.cc b/src/lib/dns/tests/rdata_cname_unittest.cc
new file mode 100644
index 0000000..e666355
--- /dev/null
+++ b/src/lib/dns/tests/rdata_cname_unittest.cc
@@ -0,0 +1,135 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_CNAME_Test : public RdataTest {
+public:
+ Rdata_CNAME_Test() :
+ rdata_cname("cn.example.com."),
+ rdata_cname2("cn2.example.com.")
+ {}
+
+ const generic::CNAME rdata_cname;
+ const generic::CNAME rdata_cname2;
+};
+
+const uint8_t wiredata_cname[] = {
+ 0x02, 0x63, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00 };
+const uint8_t wiredata_cname2[] = {
+ // first name: cn.example.com.
+ 0x02, 0x63, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00,
+ // second name: cn2.example.com. all labels except the first should be
+ // compressed.
+ 0x03, 0x63, 0x6e, 0x32, 0xc0, 0x03 };
+
+TEST_F(Rdata_CNAME_Test, createFromText) {
+ EXPECT_EQ(0, rdata_cname.compare(generic::CNAME("cn.example.com.")));
+ // explicitly add a trailing dot. should be the same RDATA.
+ EXPECT_EQ(0, rdata_cname.compare(generic::CNAME("cn.example.com.")));
+ // should be case sensitive.
+ EXPECT_EQ(0, rdata_cname.compare(generic::CNAME("CN.EXAMPLE.COM.")));
+ // RDATA of a class-independent type should be recognized for any
+ // "unknown" class.
+ EXPECT_EQ(0, rdata_cname.compare(*createRdata(RRType("CNAME"),
+ RRClass(65000),
+ "cn.example.com.")));
+}
+
+TEST_F(Rdata_CNAME_Test, badText) {
+ // Extra text at end of line
+ EXPECT_THROW(generic::CNAME("cname.example.com. extra."), InvalidRdataText);
+}
+
+TEST_F(Rdata_CNAME_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_cname.compare(
+ *rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"),
+ "rdata_cname_fromWire")));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"),
+ "rdata_cname_fromWire", 18),
+ InvalidRdataLength);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"),
+ "rdata_cname_fromWire", 36),
+ InvalidRdataLength);
+ // incomplete name. the error should be detected in the name constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"),
+ "rdata_cname_fromWire", 71),
+ DNSMessageFORMERR);
+
+ EXPECT_EQ(0, generic::CNAME("cn2.example.com.").compare(
+ *rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"),
+ "rdata_cname_fromWire", 55)));
+ EXPECT_THROW(*rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"),
+ "rdata_cname_fromWire", 63),
+ InvalidRdataLength);
+}
+
+TEST_F(Rdata_CNAME_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_cname.compare(
+ *test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(),
+ "cn.example.com.")));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ EXPECT_EQ(0, generic::CNAME("cname10.example.org.").compare(
+ *test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(),
+ "cname10")));
+
+ // Extra text at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(),
+ "cname.example.com. extra."));
+}
+
+TEST_F(Rdata_CNAME_Test, toWireBuffer) {
+ rdata_cname.toWire(obuffer);
+ matchWireData(wiredata_cname, sizeof(wiredata_cname),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_CNAME_Test, toWireRenderer) {
+ rdata_cname.toWire(renderer);
+ matchWireData(wiredata_cname, sizeof(wiredata_cname),
+ renderer.getData(), renderer.getLength());
+
+ rdata_cname2.toWire(renderer);
+ matchWireData(wiredata_cname2, sizeof(wiredata_cname2),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_CNAME_Test, toText) {
+ EXPECT_EQ("cn.example.com.", rdata_cname.toText());
+}
+
+TEST_F(Rdata_CNAME_Test, getCname) {
+ EXPECT_EQ(Name("cn.example.com."), rdata_cname.getCname());
+}
+}
diff --git a/src/lib/dns/tests/rdata_dhcid_unittest.cc b/src/lib/dns/tests/rdata_dhcid_unittest.cc
new file mode 100644
index 0000000..a96c3e4
--- /dev/null
+++ b/src/lib/dns/tests/rdata_dhcid_unittest.cc
@@ -0,0 +1,165 @@
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/rdataclass.h>
+#include <util/encode/base64.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+
+class Rdata_DHCID_Test : public RdataTest {
+protected:
+ Rdata_DHCID_Test() :
+ dhcid_txt("0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA="),
+ rdata_dhcid(dhcid_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<in::DHCID, isc::Exception, isc::Exception>(
+ rdata_str, rdata_dhcid, false, false);
+ }
+
+ void checkFromText_BadValue(const string& rdata_str) {
+ checkFromText<in::DHCID, BadValue, BadValue>(
+ rdata_str, rdata_dhcid, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <in::DHCID, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_dhcid, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <in::DHCID, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_dhcid, true, false);
+ }
+
+ const string dhcid_txt;
+ const in::DHCID rdata_dhcid;
+};
+
+TEST_F(Rdata_DHCID_Test, fromText) {
+ EXPECT_EQ(dhcid_txt, rdata_dhcid.toText());
+
+ // Space in digest data is OK
+ checkFromText_None(
+ "0LIg0LvQtdGB0YMg 0YDQvtC00LjQu9Cw 0YHRjCDRkdC70L7R h9C60LA=");
+
+ // Multi-line digest data is OK, if enclosed in parentheses
+ checkFromText_None(
+ "( 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw\n0YHRjCDRkdC70L7R h9C60LA= )");
+
+ // Trailing garbage. This should cause only the string constructor
+ // to fail, but the lexer constructor must be able to continue
+ // parsing from it.
+ checkFromText_BadString(
+ "0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA="
+ " ; comment\n"
+ "AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=");
+}
+
+TEST_F(Rdata_DHCID_Test, badText) {
+ // missing digest data
+ checkFromText_LexerError("");
+
+ // invalid base64
+ checkFromText_BadValue("EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!=");
+
+ // unterminated multi-line base64
+ checkFromText_LexerError(
+ "( 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw\n0YHRjCDRkdC70L7R h9C60LA=");
+}
+
+TEST_F(Rdata_DHCID_Test, copy) {
+ const in::DHCID rdata_dhcid2(rdata_dhcid);
+ EXPECT_EQ(0, rdata_dhcid.compare(rdata_dhcid2));
+}
+
+TEST_F(Rdata_DHCID_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_dhcid.compare(
+ *rdataFactoryFromFile(RRType("DHCID"), RRClass("IN"),
+ "rdata_dhcid_fromWire")));
+
+ InputBuffer buffer(NULL, 0);
+ EXPECT_THROW(in::DHCID(buffer, 0), InvalidRdataLength);
+
+ // TBD: more tests
+}
+
+TEST_F(Rdata_DHCID_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_dhcid.compare(
+ *test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(),
+ dhcid_txt)));
+}
+
+TEST_F(Rdata_DHCID_Test, toWireRenderer) {
+ rdata_dhcid.toWire(renderer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_dhcid_toWire", data);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_DHCID_Test, toWireBuffer) {
+ rdata_dhcid.toWire(obuffer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_dhcid_toWire", data);
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_DHCID_Test, toText) {
+ EXPECT_EQ(dhcid_txt, rdata_dhcid.toText());
+}
+
+TEST_F(Rdata_DHCID_Test, getDHCIDDigest) {
+ const string dhcid_txt1(encodeBase64(rdata_dhcid.getDigest()));
+
+ EXPECT_EQ(dhcid_txt, dhcid_txt1);
+}
+
+TEST_F(Rdata_DHCID_Test, compare) {
+ // trivial case: self equivalence
+ // cppcheck-suppress uselessCallsCompare
+ EXPECT_EQ(0, rdata_dhcid.compare(rdata_dhcid));
+
+ in::DHCID rdata_dhcid1("0YLQvtC/0L7Qu9GPINC00LLQsCDRgNGD0LHQu9GP");
+ in::DHCID rdata_dhcid2("0YLQvtC/0L7Qu9GPINGC0YDQuCDRgNGD0LHQu9GP");
+ in::DHCID rdata_dhcid3("0YLQvtC/0L7Qu9GPINGH0LXRgtGL0YDQtSDRgNGD0LHQu9GP");
+
+ EXPECT_LT(rdata_dhcid1.compare(rdata_dhcid2), 0);
+ EXPECT_GT(rdata_dhcid2.compare(rdata_dhcid1), 0);
+
+ EXPECT_LT(rdata_dhcid2.compare(rdata_dhcid3), 0);
+ EXPECT_GT(rdata_dhcid3.compare(rdata_dhcid2), 0);
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_dhcid.compare(*rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_dname_unittest.cc b/src/lib/dns/tests/rdata_dname_unittest.cc
new file mode 100644
index 0000000..3bdfb23
--- /dev/null
+++ b/src/lib/dns/tests/rdata_dname_unittest.cc
@@ -0,0 +1,137 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_DNAME_Test : public RdataTest {
+public:
+ Rdata_DNAME_Test() :
+ rdata_dname("dn.example.com."),
+ rdata_dname2("dn2.example.com.")
+ {}
+
+ const generic::DNAME rdata_dname;
+ const generic::DNAME rdata_dname2;
+};
+
+const uint8_t wiredata_dname[] = {
+ 0x02, 0x64, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00 };
+const uint8_t wiredata_dname2[] = {
+ // first name: dn.example.com.
+ 0x02, 0x64, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00,
+ // second name: dn2.example.com. The "example.com" shouldn't be compressed
+ // because DNAME is not a well know type per RFC3597.
+ 0x03, 0x64, 0x6e, 0x32,
+ 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00 };
+
+TEST_F(Rdata_DNAME_Test, createFromText) {
+ EXPECT_EQ(0, rdata_dname.compare(generic::DNAME("dn.example.com.")));
+ // explicitly add a trailing dot. should be the same RDATA.
+ EXPECT_EQ(0, rdata_dname.compare(generic::DNAME("dn.example.com.")));
+ // should be case sensitive.
+ EXPECT_EQ(0, rdata_dname.compare(generic::DNAME("DN.EXAMPLE.COM.")));
+ // RDATA of a class-independent type should be recognized for any
+ // "unknown" class.
+ EXPECT_EQ(0, rdata_dname.compare(*createRdata(RRType("DNAME"),
+ RRClass(65000),
+ "dn.example.com.")));
+}
+
+TEST_F(Rdata_DNAME_Test, badText) {
+ // Extra text at end of line
+ EXPECT_THROW(generic::DNAME("dname.example.com. extra."), InvalidRdataText);
+}
+
+TEST_F(Rdata_DNAME_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_dname.compare(
+ *rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"),
+ "rdata_dname_fromWire")));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"),
+ "rdata_dname_fromWire", 18),
+ InvalidRdataLength);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"),
+ "rdata_dname_fromWire", 36),
+ InvalidRdataLength);
+ // incomplete name. the error should be detected in the name constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"),
+ "rdata_dname_fromWire", 71),
+ DNSMessageFORMERR);
+
+ EXPECT_EQ(0, generic::DNAME("dn2.example.com.").compare(
+ *rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"),
+ "rdata_dname_fromWire", 55)));
+ EXPECT_THROW(*rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"),
+ "rdata_dname_fromWire", 63),
+ InvalidRdataLength);
+}
+
+TEST_F(Rdata_DNAME_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_dname.compare(
+ *test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(),
+ "dn.example.com.")));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ EXPECT_EQ(0, generic::DNAME("dname8.example.org.").compare(
+ *test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(),
+ "dname8")));
+
+ // Extra text at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(),
+ "dname.example.com. extra."));
+}
+
+TEST_F(Rdata_DNAME_Test, toWireBuffer) {
+ rdata_dname.toWire(obuffer);
+ matchWireData(wiredata_dname, sizeof(wiredata_dname),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_DNAME_Test, toWireRenderer) {
+ rdata_dname.toWire(renderer);
+ matchWireData(wiredata_dname, sizeof(wiredata_dname),
+ renderer.getData(), renderer.getLength());
+
+ rdata_dname2.toWire(renderer);
+ matchWireData(wiredata_dname2, sizeof(wiredata_dname2),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_DNAME_Test, toText) {
+ EXPECT_EQ("dn.example.com.", rdata_dname.toText());
+}
+
+TEST_F(Rdata_DNAME_Test, getDname) {
+ EXPECT_EQ(Name("dn.example.com."), rdata_dname.getDname());
+}
+}
diff --git a/src/lib/dns/tests/rdata_dnskey_unittest.cc b/src/lib/dns/tests/rdata_dnskey_unittest.cc
new file mode 100644
index 0000000..6f0866d
--- /dev/null
+++ b/src/lib/dns/tests/rdata_dnskey_unittest.cc
@@ -0,0 +1,200 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_DNSKEY_Test : public RdataTest {
+protected:
+ Rdata_DNSKEY_Test() :
+ dnskey_txt("257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMV"
+ "Fu2hWLDMvoOMRXjGrhhCeFvAZih7yJHf8ZGfW6hd38hXG/x"
+ "ylYCO6Krpbdojwx8YMXLA5/kA+u50WIL8ZR1R6KTbsYVMf/"
+ "Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy347cBB1zMnnz/"
+ "4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQzBkj"
+ "0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ"
+ "7+ysyLKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA"
+ "8lVUgEf/rzeC/bByBNsO70aEFTd"),
+ dnskey_txt2("257 3 5 YmluZDEwLmlzYy5vcmc="),
+ rdata_dnskey(dnskey_txt),
+ rdata_dnskey2(dnskey_txt2)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::DNSKEY, isc::Exception, isc::Exception>(
+ rdata_str, rdata_dnskey2, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::DNSKEY, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_dnskey2, true, true);
+ }
+
+ void checkFromText_InvalidLength(const string& rdata_str) {
+ checkFromText<generic::DNSKEY, InvalidRdataLength, InvalidRdataLength>(
+ rdata_str, rdata_dnskey2, true, true);
+ }
+
+ void checkFromText_BadValue(const string& rdata_str) {
+ checkFromText<generic::DNSKEY, BadValue, BadValue>(
+ rdata_str, rdata_dnskey2, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::DNSKEY, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_dnskey2, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::DNSKEY, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_dnskey2, true, false);
+ }
+
+ const string dnskey_txt;
+ const string dnskey_txt2;
+ const generic::DNSKEY rdata_dnskey;
+ const generic::DNSKEY rdata_dnskey2;
+};
+
+TEST_F(Rdata_DNSKEY_Test, fromText) {
+ EXPECT_EQ(dnskey_txt, rdata_dnskey.toText());
+
+ // Space in key data is OK
+ checkFromText_None("257 3 5 YmluZDEw LmlzYy5vcmc=");
+
+ // Delimited number in key data is OK
+ checkFromText_None("257 3 5 YmluZDEwLmlzYy 5 vcmc=");
+
+ // Missing keydata is OK
+ EXPECT_NO_THROW(const generic::DNSKEY rdata_dnskey3("257 3 5"));
+
+ // Key data too short for RSA/MD5 algorithm is OK when
+ // constructing. But getTag() on this object would throw (see
+ // .getTag tests).
+ EXPECT_NO_THROW(const generic::DNSKEY rdata_dnskey4("1 1 1 YQ=="));
+
+ // Flags field out of range
+ checkFromText_InvalidText("65536 3 5 YmluZDEwLmlzYy5vcmc=");
+
+ // Protocol field out of range
+ checkFromText_InvalidText("257 256 5 YmluZDEwLmlzYy5vcmc=");
+
+ // Algorithm field out of range
+ checkFromText_InvalidText("257 3 256 YmluZDEwLmlzYy5vcmc=");
+
+ // Missing algorithm field
+ checkFromText_LexerError("257 3 YmluZDEwLmlzYy5vcmc=");
+
+ // Invalid key data field (not Base64)
+ checkFromText_BadValue("257 3 5 BAAAAAAAAAAAD");
+
+ // String instead of number
+ checkFromText_LexerError("foo 3 5 YmluZDEwLmlzYy5vcmc=");
+ checkFromText_LexerError("257 foo 5 YmluZDEwLmlzYy5vcmc=");
+ checkFromText_LexerError("257 3 foo YmluZDEwLmlzYy5vcmc=");
+
+ // Trailing garbage. This should cause only the string constructor
+ // to fail, but the lexer constructor must be able to continue
+ // parsing from it.
+ checkFromText_BadString("257 3 5 YmluZDEwLmlzYy5vcmc= ; comment\n"
+ "257 3 4 YmluZDEwLmlzYy5vcmc=");
+
+ // Unmatched parenthesis should cause a lexer error
+ checkFromText_LexerError("257 3 5 )YmluZDEwLmlzYy5vcmc=");
+}
+
+TEST_F(Rdata_DNSKEY_Test, assign) {
+ generic::DNSKEY rdata_dnskey2("257 3 5 YQ==");
+ rdata_dnskey2 = rdata_dnskey;
+ EXPECT_EQ(0, rdata_dnskey.compare(rdata_dnskey2));
+}
+
+TEST_F(Rdata_DNSKEY_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_dnskey.compare(
+ *test::createRdataUsingLexer(RRType::DNSKEY(), RRClass::IN(),
+ dnskey_txt)));
+}
+
+TEST_F(Rdata_DNSKEY_Test, toWireRenderer) {
+ renderer.skip(2);
+ rdata_dnskey.toWire(renderer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_dnskey_fromWire.wire", data);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
+}
+
+TEST_F(Rdata_DNSKEY_Test, toWireBuffer) {
+ rdata_dnskey.toWire(obuffer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_dnskey_fromWire.wire", data);
+ matchWireData(&data[2], data.size() - 2,
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_DNSKEY_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_dnskey.compare(
+ *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"),
+ "rdata_dnskey_fromWire.wire")));
+
+ // Missing keydata is OK
+ const generic::DNSKEY rdata_dnskey_missing_keydata("257 3 5");
+ EXPECT_EQ(0, rdata_dnskey_missing_keydata.compare(
+ *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"),
+ "rdata_dnskey_empty_keydata_fromWire.wire")));
+}
+
+TEST_F(Rdata_DNSKEY_Test, getTag) {
+ EXPECT_EQ(12892, rdata_dnskey.getTag());
+
+ // Short keydata with algorithm RSA/MD5 must throw.
+ const generic::DNSKEY rdata_dnskey_short_keydata1("1 1 1 YQ==");
+ EXPECT_THROW(rdata_dnskey_short_keydata1.getTag(), isc::OutOfRange);
+
+ // Short keydata with algorithm not RSA/MD5 must not throw.
+ const generic::DNSKEY rdata_dnskey_short_keydata2("257 3 5 YQ==");
+ EXPECT_NO_THROW(rdata_dnskey_short_keydata2.getTag());
+}
+
+TEST_F(Rdata_DNSKEY_Test, getAlgorithm) {
+ EXPECT_EQ(5, rdata_dnskey.getAlgorithm());
+}
+
+TEST_F(Rdata_DNSKEY_Test, getFlags) {
+ EXPECT_EQ(257, rdata_dnskey.getFlags());
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_ds_like_unittest.cc b/src/lib/dns/tests/rdata_ds_like_unittest.cc
new file mode 100644
index 0000000..d4ea924
--- /dev/null
+++ b/src/lib/dns/tests/rdata_ds_like_unittest.cc
@@ -0,0 +1,229 @@
+// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+// hacks to make templates work
+template <class T>
+class RRTYPE : public RRType {
+public:
+ RRTYPE();
+};
+
+template<> RRTYPE<generic::DS>::RRTYPE() : RRType(RRType::DS()) {}
+template<> RRTYPE<generic::DLV>::RRTYPE() : RRType(RRType::DLV()) {}
+
+template <class DS_LIKE>
+class Rdata_DS_LIKE_Test : public RdataTest {
+protected:
+ Rdata_DS_LIKE_Test() :
+ ds_like_txt("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5"),
+ rdata_ds_like(ds_like_txt)
+ {}
+ const string ds_like_txt;
+ const DS_LIKE rdata_ds_like;
+};
+
+// The list of types we want to test.
+typedef testing::Types<generic::DS, generic::DLV> Implementations;
+
+#ifdef TYPED_TEST_SUITE
+TYPED_TEST_SUITE(Rdata_DS_LIKE_Test, Implementations);
+#else
+TYPED_TEST_CASE(Rdata_DS_LIKE_Test, Implementations);
+#endif
+
+TYPED_TEST(Rdata_DS_LIKE_Test, createFromText) {
+ // It's valid for the digest's presentation format to contain
+ // spaces. See RFC4034 section 5.3.
+ EXPECT_EQ(0, this->rdata_ds_like.compare(
+ TypeParam("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D5F0EB5"
+ "C777 58 6DE18 \t DA6B5")));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toText_DS_LIKE) {
+ EXPECT_EQ(this->ds_like_txt, this->rdata_ds_like.toText());
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, badText_DS_LIKE) {
+ EXPECT_THROW(const TypeParam ds_like2("99999 5 2 BEEF"), InvalidRdataText);
+ EXPECT_THROW(const TypeParam ds_like2("11111 555 2 BEEF"),
+ InvalidRdataText);
+ EXPECT_THROW(const TypeParam ds_like2("11111 5 22222 BEEF"),
+ InvalidRdataText);
+ EXPECT_THROW(const TypeParam ds_like2("11111 5 2"), InvalidRdataText);
+ EXPECT_THROW(const TypeParam ds_like2("GARBAGE IN"), InvalidRdataText);
+ // no space between the digest type and the digest.
+ EXPECT_THROW(const TypeParam ds_like2(
+ "12892 5 2F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5"), InvalidRdataText);
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, createFromWire_DS_LIKE) {
+ EXPECT_EQ(0, this->rdata_ds_like.compare(
+ *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass::IN(),
+ "rdata_ds_fromWire")));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, createFromLexer_DS_LIKE) {
+ EXPECT_EQ(0, this->rdata_ds_like.compare(
+ *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+ this->ds_like_txt)));
+
+ // Whitespace is okay
+ EXPECT_EQ(0, this->rdata_ds_like.compare(
+ *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+ "12892 5 2 F1E184C0E1D615D20EB3C223ACED3B0"
+ "3C773DD952D5F0EB5C777 58 6DE18 \t DA6B5"
+ )));
+
+ // Exceptions cause NULL to be returned.
+
+ // Bad tag
+ EXPECT_FALSE(test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+ "65536 5 2 BEEF"));
+
+ // Bad algorithm
+ EXPECT_FALSE(test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+ "1024 256 2 BEEF"));
+
+ // Bad digest type
+ EXPECT_FALSE(test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+ "2048 2 256 BEEF"));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, assignment_DS_LIKE) {
+ TypeParam copy(this->ds_like_txt);
+ copy = this->rdata_ds_like;
+ EXPECT_EQ(0, copy.compare(this->rdata_ds_like));
+
+ // Check if the copied data is valid even after the original is deleted
+ TypeParam* copy2 = new TypeParam(this->rdata_ds_like);
+ TypeParam copy3(this->ds_like_txt);
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(this->rdata_ds_like));
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(0, copy.compare(this->rdata_ds_like));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, getTag_DS_LIKE) {
+ EXPECT_EQ(12892, this->rdata_ds_like.getTag());
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toWireRenderer) {
+ Rdata_DS_LIKE_Test<TypeParam>::renderer.skip(2);
+ TypeParam rdata_ds_like(this->ds_like_txt);
+ rdata_ds_like.toWire(this->renderer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_ds_fromWire", data);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t*>(this->renderer.getData()) + 2,
+ this->renderer.getLength() - 2);
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toWireBuffer) {
+ TypeParam rdata_ds_like(this->ds_like_txt);
+ rdata_ds_like.toWire(this->obuffer);
+}
+
+string ds_like_txt1("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+// different tag
+string ds_like_txt2("12893 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+// different algorithm
+string ds_like_txt3("12892 6 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+// different digest type
+string ds_like_txt4("12892 5 3 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+// different digest
+string ds_like_txt5("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+// different digest length
+string ds_like_txt6("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B555");
+
+TYPED_TEST(Rdata_DS_LIKE_Test, compare) {
+ const string ds_like_txt1(
+ "12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+ // different tag
+ const string ds_like_txt2(
+ "12893 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+ // different algorithm
+ const string ds_like_txt3(
+ "12892 6 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+ // different digest type
+ const string ds_like_txt4(
+ "12892 5 3 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+ // different digest
+ const string ds_like_txt5(
+ "12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B5");
+ // different digest length
+ const string ds_like_txt6(
+ "12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+ "5F0EB5C777586DE18DA6B555");
+
+ // trivial case: self equivalence
+ EXPECT_EQ(0, TypeParam(this->ds_like_txt).
+ compare(TypeParam(this->ds_like_txt)));
+
+ // non-equivalence tests
+ EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt2)), 0);
+ EXPECT_GT(TypeParam(ds_like_txt2).compare(TypeParam(ds_like_txt1)), 0);
+
+ EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt3)), 0);
+ EXPECT_GT(TypeParam(ds_like_txt3).compare(TypeParam(ds_like_txt1)), 0);
+
+ EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt4)), 0);
+ EXPECT_GT(TypeParam(ds_like_txt4).compare(TypeParam(ds_like_txt1)), 0);
+
+ EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt5)), 0);
+ EXPECT_GT(TypeParam(ds_like_txt5).compare(TypeParam(ds_like_txt1)), 0);
+
+ EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt6)), 0);
+ EXPECT_GT(TypeParam(ds_like_txt6).compare(TypeParam(ds_like_txt1)), 0);
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(this->rdata_ds_like.compare(*this->rdata_nomatch),
+ bad_cast);
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_hinfo_unittest.cc b/src/lib/dns/tests/rdata_hinfo_unittest.cc
new file mode 100644
index 0000000..1830f05
--- /dev/null
+++ b/src/lib/dns/tests/rdata_hinfo_unittest.cc
@@ -0,0 +1,154 @@
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using namespace isc::dns::rdata::generic;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_HINFO_Test : public RdataTest {
+};
+
+static uint8_t hinfo_rdata[] = {0x07,0x50,0x65,0x6e,0x74,0x69,0x75,0x6d,0x05,
+ 0x4c,0x69,0x6e,0x75,0x78};
+static const char *hinfo_str = "\"Pentium\" \"Linux\"";
+static const char *hinfo_str1 = "\"Pen\\\"tium\" \"Linux\"";
+
+static const char *hinfo_str_equal = "\"Pentium\"\"Linux\"";
+static const char *hinfo_str_small1 = "\"Lentium\" \"Linux\"";
+static const char *hinfo_str_small2 = "\"Pentium\" \"Kinux\"";
+static const char *hinfo_str_large1 = "\"Qentium\" \"Linux\"";
+static const char *hinfo_str_large2 = "\"Pentium\" \"UNIX\"";
+
+TEST_F(Rdata_HINFO_Test, createFromText) {
+ HINFO hinfo(hinfo_str);
+ EXPECT_EQ(string("Pentium"), hinfo.getCPU());
+ EXPECT_EQ(string("Linux"), hinfo.getOS());
+ // Test the text with double quotes in the middle of string
+ HINFO hinfo1(hinfo_str1);
+ EXPECT_EQ(string("Pen\\\"tium"), hinfo1.getCPU());
+}
+
+TEST_F(Rdata_HINFO_Test, badText) {
+ // Only 2 fields must exist
+ EXPECT_THROW(const HINFO hinfo("\"Pentium\"\"Linux\"\"Computer\""),
+ InvalidRdataText);
+ EXPECT_THROW(const HINFO hinfo("\"Pentium\" \"Linux\" \"Computer\""),
+ InvalidRdataText);
+ // Field cannot be missing
+ EXPECT_THROW(const HINFO hinfo("Pentium"), InvalidRdataText);
+ // The <character-string> cannot exceed 255 characters
+ string hinfo_str;
+ for (int i = 0; i < 257; ++i) {
+ hinfo_str += 'A';
+ }
+ hinfo_str += " Linux";
+ EXPECT_THROW(const HINFO hinfo(hinfo_str), CharStringTooLong);
+}
+
+TEST_F(Rdata_HINFO_Test, createFromWire) {
+ InputBuffer input_buffer(hinfo_rdata, sizeof(hinfo_rdata));
+ HINFO hinfo(input_buffer, sizeof(hinfo_rdata));
+ EXPECT_EQ(string("Pentium"), hinfo.getCPU());
+ EXPECT_EQ(string("Linux"), hinfo.getOS());
+}
+
+TEST_F(Rdata_HINFO_Test, createFromLexer) {
+ HINFO rdata_hinfo(hinfo_str);
+ EXPECT_EQ(0, rdata_hinfo.compare(
+ *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+ hinfo_str)));
+ EXPECT_EQ(0, rdata_hinfo.compare(
+ *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+ "\"Pentium\"\"Linux\"")));
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+ "\"Pentium\"\"Linux\""
+ "\"Computer\""));
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+ "\"Pentium\" \"Linux\" "
+ "\"Computer\""));
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+ "\"Pentium\""));
+}
+
+TEST_F(Rdata_HINFO_Test, toText) {
+ HINFO hinfo(hinfo_str);
+ EXPECT_EQ(hinfo_str, hinfo.toText());
+
+ // will add quotes even if they were not in the original input
+ EXPECT_EQ("\"a\" \"b\"", HINFO("a b").toText());
+ // will not add additional quotes
+ EXPECT_EQ("\"a\" \"b\"", HINFO("\"a\" \"b\"").toText());
+ // And make sure escaped quotes and spaces are left intact
+ EXPECT_EQ("\"a\\\"\" \"b c\"", HINFO("\"a\\\"\" \"b c\"").toText());
+}
+
+TEST_F(Rdata_HINFO_Test, toWire) {
+ HINFO hinfo(hinfo_str);
+
+ hinfo.toWire(obuffer);
+ matchWireData(hinfo_rdata, sizeof (hinfo_rdata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_HINFO_Test, toWireRenderer) {
+ HINFO hinfo(hinfo_str);
+
+ hinfo.toWire(renderer);
+ matchWireData(hinfo_rdata, sizeof (hinfo_rdata),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_HINFO_Test, compare) {
+ HINFO hinfo(hinfo_str);
+ HINFO hinfo_small1(hinfo_str_small1);
+ HINFO hinfo_small2(hinfo_str_small2);
+ HINFO hinfo_large1(hinfo_str_large1);
+ HINFO hinfo_large2(hinfo_str_large2);
+
+ EXPECT_EQ(0, hinfo.compare(HINFO(hinfo_str)));
+ EXPECT_EQ(0, hinfo.compare(HINFO(hinfo_str_equal)));
+ EXPECT_EQ(1, hinfo.compare(HINFO(hinfo_str_small1)));
+ EXPECT_EQ(1, hinfo.compare(HINFO(hinfo_str_small2)));
+ EXPECT_EQ(-1, hinfo.compare(HINFO(hinfo_str_large1)));
+ EXPECT_EQ(-1, hinfo.compare(HINFO(hinfo_str_large2)));
+}
+
+// Copy/assign test
+TEST_F(Rdata_HINFO_Test, copy) {
+ HINFO hinfo(hinfo_str);
+ HINFO hinfo2(hinfo);
+ HINFO hinfo3 = hinfo;
+
+ EXPECT_EQ(0, hinfo.compare(hinfo2));
+ EXPECT_EQ(0, hinfo.compare(hinfo3));
+
+ hinfo3 = hinfo;
+ EXPECT_EQ(0, hinfo.compare(hinfo3));
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_in_a_unittest.cc b/src/lib/dns/tests/rdata_in_a_unittest.cc
new file mode 100644
index 0000000..809cfb5
--- /dev/null
+++ b/src/lib/dns/tests/rdata_in_a_unittest.cc
@@ -0,0 +1,159 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/rdataclass.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+#include <dns/rdata.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_IN_A_Test : public RdataTest {
+protected:
+ Rdata_IN_A_Test() : rdata_in_a("192.0.2.1") {}
+
+ void checkFromTextIN_A(const std::string& rdata_txt,
+ bool throw_str_version = true,
+ bool throw_lexer_version = true) {
+ checkFromText<in::A, InvalidRdataText, InvalidRdataText>(
+ rdata_txt, rdata_in_a, throw_str_version, throw_lexer_version);
+ }
+
+ const in::A rdata_in_a;
+};
+
+const uint8_t wiredata_in_a[] = { 192, 0, 2, 1 };
+
+TEST_F(Rdata_IN_A_Test, createFromText) {
+ // Normal case: no exception for either case, so the exception type
+ // doesn't matter.
+ checkFromText<in::A, isc::Exception, isc::Exception>("192.0.2.1",
+ rdata_in_a, false,
+ false);
+
+ // should reject an abbreviated form of IPv4 address
+ checkFromTextIN_A("10.1");
+ // or an IPv6 address
+ checkFromTextIN_A("2001:db8::1234");
+ // or any meaningless text as an IP address
+ checkFromTextIN_A("xxx");
+
+ // NetBSD's inet_pton accepts trailing space after an IPv4 address, which
+ // would confuse some of the tests below. We check the case differently
+ // in these cases depending on the strictness of inet_pton (most
+ // implementations seem to be stricter).
+ uint8_t v4addr_buf[4];
+ const bool reject_extra_space =
+ inet_pton(AF_INET, "192.0.2.1 ", v4addr_buf) == 0;
+
+ // trailing white space: only string version throws
+ checkFromTextIN_A("192.0.2.1 ", reject_extra_space, false);
+ // same for beginning white space.
+ checkFromTextIN_A(" 192.0.2.1", true, false);
+ // same for trailing non-space garbage (note that lexer version still
+ // ignore it; it's expected to be detected at a higher layer).
+ checkFromTextIN_A("192.0.2.1 xxx", reject_extra_space, false);
+
+ // nul character after a valid textual representation.
+ string nul_after_addr = "192.0.2.1";
+ nul_after_addr.push_back(0);
+ checkFromTextIN_A(nul_after_addr, true, true);
+
+ // a valid address surrounded by parentheses; only okay with lexer
+ checkFromTextIN_A("(192.0.2.1)", true, false);
+
+ // input that would cause lexer-specific error; it's bad text as an
+ // address so should result in the string version, too.
+ checkFromText<in::A, InvalidRdataText, MasterLexer::LexerError>(
+ ")192.0.2.1", rdata_in_a);
+}
+
+TEST_F(Rdata_IN_A_Test, createFromWire) {
+ // Valid data
+ EXPECT_EQ(0, rdata_in_a.compare(
+ *rdataFactoryFromFile(RRType::A(), RRClass::IN(),
+ "rdata_in_a_fromWire")));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType::A(), RRClass::IN(),
+ "rdata_in_a_fromWire", 6),
+ DNSMessageFORMERR);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType::A(), RRClass::IN(),
+ "rdata_in_a_fromWire", 12),
+ DNSMessageFORMERR);
+ // buffer too short.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::A(), RRClass::IN(),
+ "rdata_in_a_fromWire", 19),
+ DNSMessageFORMERR);
+}
+
+TEST_F(Rdata_IN_A_Test, toWireBuffer) {
+ rdata_in_a.toWire(obuffer);
+ matchWireData(wiredata_in_a, sizeof (wiredata_in_a),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_IN_A_Test, toWireRenderer) {
+ rdata_in_a.toWire(renderer);
+ matchWireData(wiredata_in_a, sizeof (wiredata_in_a),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_IN_A_Test, toText) {
+ EXPECT_EQ("192.0.2.1", rdata_in_a.toText());
+
+ // this shouldn't make the code crash
+ const string longaddr("255.255.255.255");
+ EXPECT_EQ(longaddr, in::A(longaddr).toText());
+}
+
+TEST_F(Rdata_IN_A_Test, compare) {
+ const in::A small1("1.1.1.1");
+ const in::A small2("1.2.3.4");
+ const in::A large1("255.255.255.255");
+ const in::A large2("4.3.2.1");
+
+ // trivial case: self equivalence
+ // cppcheck-suppress uselessCallsCompare
+ EXPECT_EQ(0, small1.compare(small1));
+
+ // confirm these are compared as unsigned values
+ EXPECT_GT(0, small1.compare(large1));
+ EXPECT_LT(0, large1.compare(small1));
+
+ // confirm these are compared in network byte order
+ EXPECT_GT(0, small2.compare(large2));
+ EXPECT_LT(0, large2.compare(small2));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_in_a.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_in_aaaa_unittest.cc b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
new file mode 100644
index 0000000..cc7b07d
--- /dev/null
+++ b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
@@ -0,0 +1,151 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_IN_AAAA_Test : public RdataTest {
+protected:
+ Rdata_IN_AAAA_Test() : rdata_in_aaaa("2001:db8::1234") {}
+
+ // Common check to see the result of in::A Rdata construction either from
+ // std::string or with MasterLexer object. If it's expected to succeed
+ // the result should be identical to the commonly used test data
+ // (rdata_in_a); otherwise it should result in the exception specified as
+ // the template parameter.
+ void checkFromTextIN_AAAA(const string& in_aaaa_txt,
+ bool throw_str_version = true,
+ bool throw_lexer_version = true)
+ {
+ checkFromText<in::AAAA, InvalidRdataText, InvalidRdataText>(
+ in_aaaa_txt, rdata_in_aaaa, throw_str_version,
+ throw_lexer_version);
+ }
+
+ const in::AAAA rdata_in_aaaa;
+};
+
+const uint8_t wiredata_in_aaaa[] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x12, 0x34 };
+
+TEST_F(Rdata_IN_AAAA_Test, createFromText) {
+ // Normal case: no exception for either case, so the exception type
+ // doesn't matter.
+ checkFromText<in::AAAA, isc::Exception, isc::Exception>(
+ "2001:db8::1234", rdata_in_aaaa, false, false);
+
+ // should reject an IP4 address.
+ checkFromTextIN_AAAA("192.0.2.1");
+ // or any meaningless text as an IPv6 address
+ checkFromTextIN_AAAA("xxx");
+
+ // trailing white space: only string version throws
+ checkFromTextIN_AAAA("2001:db8::1234 ", true, false);
+ // same for beginning white space.
+ checkFromTextIN_AAAA(" 2001:db8::1234", true, false);
+ // same for trailing non-space garbage (note that lexer version still
+ // ignore it; it's expected to be detected at a higher layer).
+ checkFromTextIN_AAAA("2001:db8::1234 xxx", true, false);
+
+ // nul character after a valid textual representation.
+ string nul_after_addr = "2001:db8::1234";
+ nul_after_addr.push_back(0);
+ checkFromTextIN_AAAA(nul_after_addr, true, true);
+
+ // a valid address surrounded by parentheses; only okay with lexer
+ checkFromTextIN_AAAA("(2001:db8::1234)", true, false);
+
+ // input that would cause lexer-specific error; it's bad text as an
+ // address so should result in the string version, too.
+ checkFromText<in::AAAA, InvalidRdataText, MasterLexer::LexerError>(
+ ")2001:db8::1234", rdata_in_aaaa);
+}
+
+TEST_F(Rdata_IN_AAAA_Test, createFromWire) {
+ // Valid data
+ EXPECT_EQ(0, rdata_in_aaaa.compare(
+ *rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(),
+ "rdata_in_aaaa_fromWire")));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(),
+ "rdata_in_aaaa_fromWire", 18),
+ DNSMessageFORMERR);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(),
+ "rdata_in_aaaa_fromWire", 36),
+ DNSMessageFORMERR);
+ // buffer too short.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(),
+ "rdata_in_aaaa_fromWire", 55),
+ DNSMessageFORMERR);
+}
+
+TEST_F(Rdata_IN_AAAA_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_in_aaaa.compare(
+ *test::createRdataUsingLexer(RRType::AAAA(), RRClass::IN(),
+ "2001:db8::1234")));
+}
+
+TEST_F(Rdata_IN_AAAA_Test, toWireBuffer) {
+ rdata_in_aaaa.toWire(obuffer);
+ matchWireData(wiredata_in_aaaa, sizeof (wiredata_in_aaaa),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_IN_AAAA_Test, toWireRenderer) {
+ rdata_in_aaaa.toWire(renderer);
+ matchWireData(wiredata_in_aaaa, sizeof (wiredata_in_aaaa),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_IN_AAAA_Test, toText) {
+ EXPECT_EQ("2001:db8::1234", rdata_in_aaaa.toText());
+}
+
+TEST_F(Rdata_IN_AAAA_Test, compare) {
+ in::AAAA small1("::1");
+ in::AAAA small2("1:2:3:4:5:6:7:8");
+ in::AAAA large1("ffff::");
+ in::AAAA large2("8:7:6:5:4:3:2:1");
+
+ // trivial case: self equivalence
+ // cppcheck-suppress uselessCallsCompare
+ EXPECT_EQ(0, small1.compare(small1));
+
+ // confirm these are compared as unsigned values
+ EXPECT_GT(0, small1.compare(large1));
+ EXPECT_LT(0, large1.compare(small1));
+
+ // confirm these are compared in network byte order
+ EXPECT_GT(0, small2.compare(large2));
+ EXPECT_LT(0, large2.compare(small2));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_in_aaaa.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_minfo_unittest.cc b/src/lib/dns/tests/rdata_minfo_unittest.cc
new file mode 100644
index 0000000..35ff55c
--- /dev/null
+++ b/src/lib/dns/tests/rdata_minfo_unittest.cc
@@ -0,0 +1,230 @@
+// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_MINFO_Test : public RdataTest {
+protected:
+ Rdata_MINFO_Test():
+ minfo_txt("rmailbox.example.com. emailbox.example.com."),
+ minfo_txt2("root.example.com. emailbox.example.com."),
+ too_long_label("01234567890123456789012345678901234567"
+ "89012345678901234567890123."),
+ rdata_minfo(minfo_txt),
+ rdata_minfo2(minfo_txt2)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::MINFO, isc::Exception, isc::Exception>(
+ rdata_str, rdata_minfo, false, false);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::MINFO, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_minfo, true, true);
+ }
+
+ void checkFromText_TooLongLabel(const string& rdata_str) {
+ checkFromText<generic::MINFO, TooLongLabel, TooLongLabel>(
+ rdata_str, rdata_minfo, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText<generic::MINFO, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_minfo, true, false);
+ }
+
+ void checkFromText_EmptyLabel(const string& rdata_str) {
+ checkFromText<generic::MINFO, EmptyLabel, EmptyLabel>(
+ rdata_str, rdata_minfo, true, true);
+ }
+
+ void checkFromText_MissingOrigin(const string& rdata_str) {
+ checkFromText
+ <generic::MINFO, MissingNameOrigin, MissingNameOrigin>(
+ rdata_str, rdata_minfo, true, true);
+ }
+
+ void checkFromText_Origin(const string& rdata_str, const Name* origin) {
+ checkFromText<generic::MINFO, MissingNameOrigin, isc::Exception>(
+ rdata_str, rdata_minfo, true, false, origin);
+ }
+
+ const string minfo_txt;
+ const string minfo_txt2;
+ const string too_long_label;
+ const generic::MINFO rdata_minfo;
+ const generic::MINFO rdata_minfo2;
+};
+
+
+TEST_F(Rdata_MINFO_Test, createFromText) {
+ EXPECT_EQ(Name("rmailbox.example.com."), rdata_minfo.getRmailbox());
+ EXPECT_EQ(Name("emailbox.example.com."), rdata_minfo.getEmailbox());
+
+ EXPECT_EQ(Name("root.example.com."), rdata_minfo2.getRmailbox());
+ EXPECT_EQ(Name("emailbox.example.com."), rdata_minfo2.getEmailbox());
+
+ checkFromText_None(minfo_txt);
+
+ // origin defined for lexer constructor, but not string constructor
+ const Name origin("example.com");
+ checkFromText_Origin("rmailbox emailbox", &origin);
+
+ // lexer constructor accepts extra text, but string constructor doesn't
+ checkFromText_BadString("rmailbox.example.com. emailbox.example.com. "
+ "extra.example.com.");
+}
+
+TEST_F(Rdata_MINFO_Test, badText) {
+ // too long names
+ checkFromText_TooLongLabel("root.example.com." + too_long_label +
+ " emailbox.example.com.");
+ checkFromText_TooLongLabel("root.example.com. emailbox.example.com." +
+ too_long_label);
+
+ // invalid names
+ checkFromText_EmptyLabel("root..example.com. emailbox.example.com.");
+ checkFromText_EmptyLabel("root.example.com. emailbox..example.com.");
+
+ // missing name
+ checkFromText_LexerError("root.example.com.");
+
+ // missing origin
+ checkFromText_MissingOrigin("root.example.com emailbox.example.com.");
+ checkFromText_MissingOrigin("root.example.com. emailbox.example.com");
+}
+
+TEST_F(Rdata_MINFO_Test, createFromWire) {
+ // uncompressed names
+ EXPECT_EQ(0, rdata_minfo.compare(
+ *rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
+ "rdata_minfo_fromWire1.wire")));
+ // compressed names
+ EXPECT_EQ(0, rdata_minfo.compare(
+ *rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
+ "rdata_minfo_fromWire2.wire", 15)));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
+ "rdata_minfo_fromWire3.wire"),
+ InvalidRdataLength);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
+ "rdata_minfo_fromWire4.wire"),
+ InvalidRdataLength);
+ // bogus rmailbox name, the error should be detected in the name
+ // constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
+ "rdata_minfo_fromWire5.wire"),
+ DNSMessageFORMERR);
+ // bogus emailbox name, the error should be detected in the name
+ // constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(),
+ "rdata_minfo_fromWire6.wire"),
+ DNSMessageFORMERR);
+}
+
+TEST_F(Rdata_MINFO_Test, assignment) {
+ generic::MINFO copy((string(minfo_txt2)));
+ copy = rdata_minfo;
+ EXPECT_EQ(0, copy.compare(rdata_minfo));
+
+ // Check if the copied data is valid even after the original is deleted
+ generic::MINFO* copy2 = new generic::MINFO(rdata_minfo);
+ generic::MINFO copy3((string(minfo_txt2)));
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_minfo));
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(0, copy.compare(rdata_minfo));
+}
+
+TEST_F(Rdata_MINFO_Test, toWireBuffer) {
+ rdata_minfo.toWire(obuffer);
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed1.wire", data);
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
+
+ obuffer.clear();
+ rdata_minfo2.toWire(obuffer);
+ vector<unsigned char> data2;
+ UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed2.wire", data2);
+ matchWireData(&data2[0], data2.size(),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_MINFO_Test, toWireRenderer) {
+ rdata_minfo.toWire(renderer);
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_minfo_toWire1.wire", data);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+
+ renderer.clear();
+ rdata_minfo2.toWire(renderer);
+ vector<unsigned char> data2;
+ UnitTestUtil::readWireData("rdata_minfo_toWire2.wire", data2);
+ matchWireData(&data2[0], data2.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_MINFO_Test, toText) {
+ EXPECT_EQ(minfo_txt, rdata_minfo.toText());
+ EXPECT_EQ(minfo_txt2, rdata_minfo2.toText());
+}
+
+TEST_F(Rdata_MINFO_Test, compare) {
+ // check reflexivity
+ EXPECT_EQ(0, rdata_minfo.compare(rdata_minfo));
+
+ // names must be compared in case-insensitive manner
+ EXPECT_EQ(0, rdata_minfo.compare(generic::MINFO("RMAILBOX.example.com. "
+ "emailbox.EXAMPLE.com.")));
+
+ // another MINFO whose rmailbox name is larger than that of rdata_minfo.
+ const generic::MINFO large1_minfo("zzzzzzzz.example.com. "
+ "emailbox.example.com.");
+ EXPECT_GT(0, rdata_minfo.compare(large1_minfo));
+ EXPECT_LT(0, large1_minfo.compare(rdata_minfo));
+
+ // another MINFO whose emailbox name is larger than that of rdata_minfo.
+ const generic::MINFO large2_minfo("rmailbox.example.com. "
+ "zzzzzzzzzzz.example.com.");
+ EXPECT_GT(0, rdata_minfo.compare(large2_minfo));
+ EXPECT_LT(0, large2_minfo.compare(rdata_minfo));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_minfo.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_mx_unittest.cc b/src/lib/dns/tests/rdata_mx_unittest.cc
new file mode 100644
index 0000000..b11411f
--- /dev/null
+++ b/src/lib/dns/tests/rdata_mx_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_MX_Test : public RdataTest {
+public:
+ Rdata_MX_Test() :
+ rdata_mx(10, Name("mx.example.com"))
+ {}
+
+ const generic::MX rdata_mx;
+};
+
+TEST_F(Rdata_MX_Test, createFromText) {
+ const generic::MX rdata_mx2("10 mx.example.com.");
+ EXPECT_EQ(0, rdata_mx2.compare(rdata_mx));
+}
+
+TEST_F(Rdata_MX_Test, badText) {
+ EXPECT_THROW(const generic::MX rdata_mx("99999999 mx."), InvalidRdataText);
+ EXPECT_THROW(const generic::MX rdata_mx("10"), InvalidRdataText);
+ EXPECT_THROW(const generic::MX rdata_mx("SPOON"), InvalidRdataText);
+ EXPECT_THROW(const generic::MX rdata_mx("10 mx. example.com."),
+ InvalidRdataText);
+ // No origin and relative
+ EXPECT_THROW(const generic::MX rdata_mx("10 mx.example.com"),
+ MissingNameOrigin);
+ // Extra text at end of line
+ EXPECT_THROW(const generic::MX rdata_mx("10 mx.example.com. extra."),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_MX_Test, copy) {
+ const generic::MX rdata_mx2(rdata_mx);
+ EXPECT_EQ(0, rdata_mx.compare(rdata_mx2));
+}
+
+TEST_F(Rdata_MX_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_mx.compare(
+ *rdataFactoryFromFile(RRType("MX"), RRClass("IN"),
+ "rdata_mx_fromWire")));
+ // TBD: more tests
+}
+
+TEST_F(Rdata_MX_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_mx.compare(
+ *test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+ "10 mx.example.com.")));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ EXPECT_EQ(0, generic::MX("10 mx2.example.org.").compare(
+ *test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+ "10 mx2")));
+
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+ "10 mx. example.com."));
+
+ // 65536 is larger than maximum possible preference
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+ "65536 mx.example.com."));
+
+ // Extra text at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+ "10 mx.example.com. extra."));
+}
+
+TEST_F(Rdata_MX_Test, toWireRenderer) {
+ renderer.writeName(Name("example.com"));
+ rdata_mx.toWire(renderer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_mx_toWire1", data);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_MX_Test, toWireBuffer) {
+ Name("example.com").toWire(obuffer);
+ rdata_mx.toWire(obuffer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_mx_toWire2", data);
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_MX_Test, toText) {
+ EXPECT_EQ("10 mx.example.com.", rdata_mx.toText());
+}
+
+TEST_F(Rdata_MX_Test, getMXName) {
+ EXPECT_EQ(Name("mx.example.com."), rdata_mx.getMXName());
+}
+
+TEST_F(Rdata_MX_Test, getMXPref) {
+ EXPECT_EQ(10, rdata_mx.getMXPref());
+}
+
+TEST_F(Rdata_MX_Test, compare) {
+ generic::MX small1(1, Name("mx.example.com"));
+ generic::MX small2(10, Name("mx.example.com"));
+ generic::MX large1(65535, Name("mx.example.com"));
+ generic::MX large2(256, Name("mx.example.com"));
+
+ // trivial case: self equivalence
+ // cppcheck-suppress uselessCallsCompare
+ EXPECT_EQ(0, small1.compare(small1));
+
+ // confirm these are compared as unsigned values
+ EXPECT_GT(0, small1.compare(large1));
+ EXPECT_LT(0, large1.compare(small1));
+
+ // confirm these are compared in network byte order
+ EXPECT_GT(0, small2.compare(large2));
+ EXPECT_LT(0, large2.compare(small2));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_mx.compare(*rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_naptr_unittest.cc b/src/lib/dns/tests/rdata_naptr_unittest.cc
new file mode 100644
index 0000000..4ce008e
--- /dev/null
+++ b/src/lib/dns/tests/rdata_naptr_unittest.cc
@@ -0,0 +1,239 @@
+// Copyright (C) 2011-2015,2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using namespace isc::dns::rdata::generic;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_NAPTR_Test : public RdataTest {
+};
+
+// 10 100 "S" "SIP+D2U" "" _sip._udp.example.com.
+static uint8_t naptr_rdata[] = {0x00,0x0a,0x00,0x64,0x01,0x53,0x07,0x53,0x49,
+ 0x50,0x2b,0x44,0x32,0x55,0x00,0x04,0x5f,0x73,0x69,0x70,0x04,0x5f,0x75,0x64,
+ 0x70,0x07,0x65,0x78,0x61,0x6d,0x70,0x6c,0x65,0x03,0x63,0x6f,0x6d,0x00};
+
+static const char *naptr_str =
+ "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str2 =
+ "10 100 S SIP+D2U \"\" _sip._udp.example.com.";
+
+static const char *naptr_str_small1 =
+ "9 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_small2 =
+ "10 90 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_small3 =
+ "10 100 \"R\" \"SIP+D2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_small4 =
+ "10 100 \"S\" \"SIP+C2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_small5 =
+ "10 100 \"S\" \"SIP+D2U\" \"\" _rip._udp.example.com.";
+
+static const char *naptr_str_large1 =
+ "11 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_large2 =
+ "10 110 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_large3 =
+ "10 100 \"T\" \"SIP+D2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_large4 =
+ "10 100 \"S\" \"SIP+E2U\" \"\" _sip._udp.example.com.";
+static const char *naptr_str_large5 =
+ "10 100 \"S\" \"SIP+D2U\" \"\" _tip._udp.example.com.";
+
+TEST_F(Rdata_NAPTR_Test, createFromText) {
+ NAPTR naptr(naptr_str);
+ EXPECT_EQ(10, naptr.getOrder());
+ EXPECT_EQ(100, naptr.getPreference());
+ EXPECT_EQ(string("S"), naptr.getFlags());
+ EXPECT_EQ(string("SIP+D2U"), naptr.getServices());
+ EXPECT_EQ(string(""), naptr.getRegexp());
+ EXPECT_EQ(Name("_sip._udp.example.com."), naptr.getReplacement());
+
+ // Test <char-string> that separated by space
+ NAPTR naptr2(naptr_str2);
+ EXPECT_EQ(string("S"), naptr2.getFlags());
+ EXPECT_EQ(string("SIP+D2U"), naptr2.getServices());
+}
+
+TEST_F(Rdata_NAPTR_Test, badText) {
+ // Order number cannot exceed 65535
+ EXPECT_THROW(const NAPTR naptr("65536 10 S SIP \"\" _sip._udp.example.com."),
+ InvalidRdataText);
+ // Preference number cannot exceed 65535
+ EXPECT_THROW(const NAPTR naptr("100 65536 S SIP \"\" _sip._udp.example.com."),
+ InvalidRdataText);
+ // No regexp given
+ EXPECT_THROW(const NAPTR naptr("100 10 S SIP _sip._udp.example.com."),
+ InvalidRdataText);
+ // The double quotes seperator must match
+ EXPECT_THROW(const NAPTR naptr("100 10 \"S SIP \"\" _sip._udp.example.com."),
+ InvalidRdataText);
+ // Order or preference cannot be missed
+ EXPECT_THROW(const NAPTR naptr("10 \"S\" SIP \"\" _sip._udp.example.com."),
+ InvalidRdataText);
+ // Unquoted fields must be separated by spaces
+ EXPECT_THROW(const NAPTR naptr("100 10S SIP \"\" _sip._udp.example.com."),
+ InvalidRdataText);
+ EXPECT_THROW(const NAPTR naptr("10010 \"S\" \"SIP\" \"\" _sip._udp.example.com."),
+ InvalidRdataText);
+ EXPECT_THROW(const NAPTR naptr("100 10 SSIP \"\" _sip._udp.example.com."),
+ InvalidRdataText);
+ // Field cannot be missing
+ EXPECT_THROW(const NAPTR naptr("100 10 \"S\""), InvalidRdataText);
+
+ // The <character-string> cannot exceed 255 characters
+ string naptr_str;
+ naptr_str += "100 10 ";
+ for (int i = 0; i < 257; ++i) {
+ naptr_str += 'A';
+ }
+ naptr_str += " SIP \"\" _sip._udp.example.com.";
+ EXPECT_THROW(const NAPTR naptr(naptr_str), CharStringTooLong);
+}
+
+TEST_F(Rdata_NAPTR_Test, createFromWire) {
+ InputBuffer input_buffer(naptr_rdata, sizeof(naptr_rdata));
+ NAPTR naptr(input_buffer, sizeof(naptr_rdata));
+ EXPECT_EQ(10, naptr.getOrder());
+ EXPECT_EQ(100, naptr.getPreference());
+ EXPECT_EQ(string("S"), naptr.getFlags());
+ EXPECT_EQ(string("SIP+D2U"), naptr.getServices());
+ EXPECT_EQ(string(""), naptr.getRegexp());
+ EXPECT_EQ(Name("_sip._udp.example.com."), naptr.getReplacement());
+}
+
+TEST_F(Rdata_NAPTR_Test, createFromWireTooLongDataLen) {
+ static uint8_t naptr_rdata_long[] = {
+ 0x00,0x0a,0x00,0x64,0x01,0x53,0x07,0x53,0x49,0x50,0x2b,0x44,0x32,0x55,
+ 0x00,0x04,0x5f,0x73,0x69,0x70,0x04,0x5f,0x75,0x64,0x70,0x07,0x65,0x78,
+ 0x61,0x6d,0x70,0x6c,0x65,0x03,0x63,0x6f,0x6d,0x00,0xff,0xff,0xff,0xff};
+ InputBuffer input_buffer(naptr_rdata_long, sizeof(naptr_rdata_long));
+ EXPECT_THROW(NAPTR naptr(input_buffer, sizeof(naptr_rdata_long)),
+ isc::dns::DNSMessageFORMERR);
+}
+
+TEST_F(Rdata_NAPTR_Test, createFromWireTooShortDataLen) {
+ // missing data (just set rdata_len too low)
+ for (size_t i = 0; i < sizeof(naptr_rdata); ++i) {
+ // Just use existing correct buffer but set rdata_len too low
+ InputBuffer input_buffer(naptr_rdata, sizeof(naptr_rdata));
+ EXPECT_THROW(NAPTR naptr(input_buffer, i),
+ isc::dns::DNSMessageFORMERR);
+ }
+}
+
+TEST_F(Rdata_NAPTR_Test, createFromLexer) {
+ const NAPTR rdata_naptr(naptr_str);
+
+ EXPECT_EQ(0, rdata_naptr.compare(
+ *test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(),
+ naptr_str)));
+
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(),
+ "65536 10 S SIP \"\" "
+ "_sip._udp.example.com."));
+}
+
+TEST_F(Rdata_NAPTR_Test, toWire) {
+ NAPTR naptr(naptr_str);
+
+ naptr.toWire(obuffer);
+ matchWireData(naptr_rdata, sizeof(naptr_rdata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_NAPTR_Test, toWireRenderer) {
+ NAPTR naptr(naptr_str);
+
+ naptr.toWire(renderer);
+ matchWireData(naptr_rdata, sizeof(naptr_rdata),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_NAPTR_Test, toText) {
+ NAPTR naptr(naptr_str);
+ EXPECT_EQ(naptr_str, naptr.toText());
+
+ // will add quotes even if they were not in the original input
+ EXPECT_EQ("10 100 \"S\" \"SIP+D2U\" \".*\" _sip._udp.example.com.",
+ NAPTR("10 100 S SIP+D2U .* _sip._udp.example.com.").toText());
+ // will not add additional quotes
+ EXPECT_EQ("10 100 \"S\" \"SIP+D2U\" \".*\" _sip._udp.example.com.",
+ NAPTR("10 100 \"S\" \"SIP+D2U\" \".*\" _sip._udp.example.com.")
+ .toText());
+}
+
+TEST_F(Rdata_NAPTR_Test, compare) {
+ NAPTR naptr(naptr_str);
+ NAPTR naptr_small1(naptr_str_small1);
+ NAPTR naptr_small2(naptr_str_small2);
+ NAPTR naptr_small3(naptr_str_small3);
+ NAPTR naptr_small4(naptr_str_small4);
+ NAPTR naptr_small5(naptr_str_small5);
+ NAPTR naptr_large1(naptr_str_large1);
+ NAPTR naptr_large2(naptr_str_large2);
+ NAPTR naptr_large3(naptr_str_large3);
+ NAPTR naptr_large4(naptr_str_large4);
+ NAPTR naptr_large5(naptr_str_large5);
+
+ EXPECT_EQ(0, naptr.compare(NAPTR(naptr_str)));
+ EXPECT_EQ(1, naptr.compare(naptr_small1));
+ EXPECT_EQ(1, naptr.compare(naptr_small2));
+ EXPECT_EQ(1, naptr.compare(naptr_small3));
+ EXPECT_EQ(1, naptr.compare(naptr_small4));
+ EXPECT_EQ(1, naptr.compare(naptr_small5));
+ EXPECT_EQ(-1, naptr.compare(naptr_large1));
+ EXPECT_EQ(-1, naptr.compare(naptr_large2));
+ EXPECT_EQ(-1, naptr.compare(naptr_large3));
+ EXPECT_EQ(-1, naptr.compare(naptr_large4));
+ EXPECT_EQ(-1, naptr.compare(naptr_large5));
+ EXPECT_EQ(-1, naptr_small1.compare(naptr));
+ EXPECT_EQ(-1, naptr_small2.compare(naptr));
+ EXPECT_EQ(-1, naptr_small3.compare(naptr));
+ EXPECT_EQ(-1, naptr_small4.compare(naptr));
+ EXPECT_EQ(-1, naptr_small5.compare(naptr));
+ EXPECT_EQ(1, naptr_large1.compare(naptr));
+ EXPECT_EQ(1, naptr_large2.compare(naptr));
+ EXPECT_EQ(1, naptr_large3.compare(naptr));
+ EXPECT_EQ(1, naptr_large4.compare(naptr));
+ EXPECT_EQ(1, naptr_large5.compare(naptr));
+}
+
+TEST_F(Rdata_NAPTR_Test, copy) {
+ NAPTR naptr(naptr_str);
+ NAPTR naptr2(naptr);
+ NAPTR naptr3 = naptr;
+
+ EXPECT_EQ(0, naptr.compare(naptr2));
+ EXPECT_EQ(0, naptr.compare(naptr3));
+
+ naptr3 = naptr;
+ EXPECT_EQ(0, naptr.compare(naptr3));
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_ns_unittest.cc b/src/lib/dns/tests/rdata_ns_unittest.cc
new file mode 100644
index 0000000..31bb508
--- /dev/null
+++ b/src/lib/dns/tests/rdata_ns_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_NS_Test : public RdataTest {
+public:
+ Rdata_NS_Test() :
+ rdata_ns("ns.example.com."),
+ rdata_ns2("ns2.example.com.")
+ {}
+
+ const generic::NS rdata_ns;
+ const generic::NS rdata_ns2;
+};
+
+const uint8_t wiredata_ns[] = {
+ 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00 };
+const uint8_t wiredata_ns2[] = {
+ // first name: ns.example.com.
+ 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00,
+ // second name: ns2.example.com. all labels except the first should be
+ // compressed.
+ 0x03, 0x6e, 0x73, 0x32, 0xc0, 0x03 };
+
+TEST_F(Rdata_NS_Test, createFromText) {
+ EXPECT_EQ(0, rdata_ns.compare(generic::NS("ns.example.com.")));
+ // explicitly add a trailing dot. should be the same RDATA.
+ EXPECT_EQ(0, rdata_ns.compare(generic::NS("ns.example.com.")));
+ // should be case sensitive.
+ EXPECT_EQ(0, rdata_ns.compare(generic::NS("NS.EXAMPLE.COM.")));
+ // RDATA of a class-independent type should be recognized for any
+ // "unknown" class.
+ EXPECT_EQ(0, rdata_ns.compare(*createRdata(RRType("NS"), RRClass(65000),
+ "ns.example.com.")));
+}
+
+TEST_F(Rdata_NS_Test, badText) {
+ // Extra input at end of line
+ EXPECT_THROW(generic::NS("ns.example.com. extra."), InvalidRdataText);
+}
+
+TEST_F(Rdata_NS_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_ns.compare(
+ *rdataFactoryFromFile(RRType("NS"), RRClass("IN"),
+ "rdata_ns_fromWire")));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType("NS"), RRClass("IN"),
+ "rdata_ns_fromWire", 18),
+ InvalidRdataLength);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType("NS"), RRClass("IN"),
+ "rdata_ns_fromWire", 36),
+ InvalidRdataLength);
+ // incomplete name. the error should be detected in the name constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType("NS"), RRClass("IN"),
+ "rdata_ns_fromWire", 71),
+ DNSMessageFORMERR);
+
+ EXPECT_EQ(0, generic::NS("ns2.example.com.").compare(
+ *rdataFactoryFromFile(RRType("NS"), RRClass("IN"),
+ "rdata_ns_fromWire", 55)));
+ EXPECT_THROW(*rdataFactoryFromFile(RRType("NS"), RRClass("IN"),
+ "rdata_ns_fromWire", 63),
+ InvalidRdataLength);
+}
+
+TEST_F(Rdata_NS_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_ns.compare(
+ *test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+ "ns.example.com.")));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ EXPECT_EQ(0, generic::NS("ns8.example.org.").compare(
+ *test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+ "ns8")));
+
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+ ""));
+
+ // Extra input at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+ "ns.example.com. extra."));
+}
+
+TEST_F(Rdata_NS_Test, toWireBuffer) {
+ rdata_ns.toWire(obuffer);
+ matchWireData(wiredata_ns, sizeof(wiredata_ns),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_NS_Test, toWireRenderer) {
+ rdata_ns.toWire(renderer);
+ matchWireData(wiredata_ns, sizeof(wiredata_ns),
+ renderer.getData(), renderer.getLength());
+
+ rdata_ns2.toWire(renderer);
+ matchWireData(wiredata_ns2, sizeof(wiredata_ns2),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_NS_Test, toText) {
+ EXPECT_EQ("ns.example.com.", rdata_ns.toText());
+}
+
+TEST_F(Rdata_NS_Test, compare) {
+ generic::NS small("a.example.");
+ generic::NS large("example.");
+ EXPECT_TRUE(Name("a.example") > Name("example"));
+ EXPECT_GT(0, small.compare(large));
+}
+
+TEST_F(Rdata_NS_Test, getNSName) {
+ EXPECT_EQ(Name("ns.example.com."), rdata_ns.getNSName());
+}
+}
diff --git a/src/lib/dns/tests/rdata_nsec3_unittest.cc b/src/lib/dns/tests/rdata_nsec3_unittest.cc
new file mode 100644
index 0000000..c6d3a07
--- /dev/null
+++ b/src/lib/dns/tests/rdata_nsec3_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright (C) 2010-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+
+using isc::UnitTestUtil;
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+
+namespace {
+
+// Note: some tests can be shared with NSEC3PARAM. They are unified as
+// typed tests defined in nsec3param_like_unittest.
+class Rdata_NSEC3_Test : public RdataTest {
+protected:
+ Rdata_NSEC3_Test() :
+ nsec3_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+ "A NS SOA"),
+ nsec3_nosalt_txt("1 1 1 - H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"),
+ nsec3_notype_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6"),
+ rdata_nsec3(nsec3_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::NSEC3, isc::Exception, isc::Exception>(
+ rdata_str, rdata_nsec3, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::NSEC3, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_nsec3, true, true);
+ }
+
+ void checkFromText_BadValue(const string& rdata_str) {
+ checkFromText<generic::NSEC3, BadValue, BadValue>(
+ rdata_str, rdata_nsec3, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::NSEC3, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_nsec3, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::NSEC3, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_nsec3, true, false);
+ }
+
+ const string nsec3_txt;
+ const string nsec3_nosalt_txt;
+ const string nsec3_notype_txt;
+ const generic::NSEC3 rdata_nsec3;
+};
+
+TEST_F(Rdata_NSEC3_Test, fromText) {
+ // Hash that has the possible max length
+ EXPECT_EQ(255, generic::NSEC3("1 1 1 D399EAAB " +
+ string((255 * 8) / 5, '0') +
+ " NS").getNext().size());
+
+ // Hash is too long. Max = 255 bytes, base32-hex converts each 5 bytes
+ // of the original to 8 characters, so 260 * 8 / 5 is the smallest length
+ // of the encoded string that exceeds the max and doesn't require padding.
+ checkFromText_InvalidText("1 1 1 D399EAAB " + string((260 * 8) / 5, '0') +
+ " A NS SOA");
+
+ // Type bitmap is empty. it's possible and allowed for NSEC3.
+ EXPECT_NO_THROW(const generic::NSEC3 rdata_notype_nsec3(nsec3_notype_txt));
+
+ // Empty salt is also okay.
+ EXPECT_NO_THROW(const generic::NSEC3 rdata_nosalt_nsec3(nsec3_nosalt_txt));
+
+ // Bad type mnemonics
+ checkFromText_InvalidText("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6"
+ " BIFF POW SPOON");
+
+ // Bad base32hex
+ checkFromText_BadValue("1 1 1 D399EAAB "
+ "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW A NS SOA");
+
+ // Hash algorithm out of range
+ checkFromText_InvalidText("256 1 1 D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA");
+
+ // Flags out of range
+ checkFromText_InvalidText("1 256 1 D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA");
+
+ // Iterations out of range
+ checkFromText_InvalidText("1 1 65536 D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA");
+
+ // Space is not allowed in salt or the next hash. This actually
+ // causes the Base32 decoder that parses the next hash that comes
+ // afterwards, to throw.
+ checkFromText_BadValue("1 1 1 D399 EAAB H9RSFB7FPF2L8"
+ "HG35CMPC765TDK23RP6 A NS SOA");
+
+ // Next hash must not contain padding (trailing '=' characters)
+ checkFromText_InvalidText("1 1 1 D399EAAB "
+ "AAECAwQFBgcICQoLDA0ODw== A NS SOA");
+
+ // String instead of number
+ checkFromText_LexerError("foo 1 1 D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA");
+ checkFromText_LexerError("1 foo 1 D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA");
+ checkFromText_LexerError("1 1 foo D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA");
+
+ // Trailing garbage. This should cause only the string constructor
+ // to fail, but the lexer constructor must be able to continue
+ // parsing from it.
+ checkFromText_BadString(
+ "1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA ;comment\n"
+ "1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA");
+
+ // Unmatched parenthesis should cause a lexer error
+ checkFromText_LexerError("1 1 1 D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A ) NS SOA");
+}
+
+TEST_F(Rdata_NSEC3_Test, createFromWire) {
+ // A valid NSEC3 RR with empty type bitmap.
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire15.wire"));
+
+ // Invalid bitmap cases are tested in Rdata_NSECBITMAP_Test.
+
+ // hash length is too large
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire12.wire"),
+ DNSMessageFORMERR);
+
+ // empty hash. invalid.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire14.wire"),
+ DNSMessageFORMERR);
+
+ // RDLEN is too short to hold the hash length field
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire17.wire"),
+ DNSMessageFORMERR);
+
+ // Short buffer cases. The data is valid NSEC3 RDATA, but the buffer
+ // is trimmed at the end. All cases should result in an exception from
+ // the buffer class.
+ vector<uint8_t> data;
+ UnitTestUtil::readWireData("rdata_nsec3_fromWire1", data);
+ const uint16_t rdlen = (data.at(0) << 8) + data.at(1);
+ for (int i = 0; i < rdlen; ++i) {
+ // intentionally construct a short buffer
+ InputBuffer b(&data[0] + 2, i);
+ EXPECT_THROW(createRdata(RRType::NSEC3(), RRClass::IN(), b, 39),
+ InvalidBufferPosition);
+ }
+}
+
+TEST_F(Rdata_NSEC3_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_nsec3.compare(
+ *test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+ nsec3_txt)));
+
+ // empty salt is also okay.
+ const generic::NSEC3 rdata_nosalt_nsec3(nsec3_nosalt_txt);
+ EXPECT_EQ(0, rdata_nosalt_nsec3.compare(
+ *test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+ nsec3_nosalt_txt)));
+}
+
+TEST_F(Rdata_NSEC3_Test, assign) {
+ generic::NSEC3 other_nsec3 = rdata_nsec3;
+ EXPECT_EQ(0, rdata_nsec3.compare(other_nsec3));
+}
+
+TEST_F(Rdata_NSEC3_Test, compare) {
+ // trivial case: self equivalence
+ EXPECT_EQ(0, generic::NSEC3(nsec3_txt).compare(generic::NSEC3(nsec3_txt)));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(generic::NSEC3(nsec3_txt).compare(*rdata_nomatch),
+ bad_cast);
+
+ // test RDATAs, sorted in the ascending order. We only check comparison
+ // on NSEC3-specific fields. Bitmap comparison is tested in the bitmap
+ // tests. Common cases for NSEC3 and NSECPARAM3 are in their shared tests.
+ vector<generic::NSEC3> compare_set;
+ compare_set.push_back(generic::NSEC3("1 1 1 FF99EA0000 D1K6GQ38"));
+ compare_set.push_back(generic::NSEC3("1 1 1 FF99EA0000 D1K6GQ0000000000"));
+ compare_set.push_back(generic::NSEC3("1 1 1 FF99EA0000 D1K6GQ00UUUUUUUU"));
+
+ vector<generic::NSEC3>::const_iterator it;
+ const vector<generic::NSEC3>::const_iterator it_end = compare_set.end();
+ for (it = compare_set.begin(); it != it_end - 1; ++it) {
+ SCOPED_TRACE("compare " + it->toText() + " to " + (it + 1)->toText());
+ EXPECT_GT(0, (*it).compare(*(it + 1)));
+ EXPECT_LT(0, (*(it + 1)).compare(*it));
+ }
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
new file mode 100644
index 0000000..914a6f4
--- /dev/null
+++ b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
@@ -0,0 +1,272 @@
+// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/exceptions.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <string>
+#include <vector>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using namespace isc::util;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+
+// Template for shared tests for NSEC3 and NSEC3PARAM
+template <typename RDATA_TYPE>
+class NSEC3PARAMLikeTest : public RdataTest {
+protected:
+ NSEC3PARAMLikeTest() :
+ salt_txt("1 1 1 D399EAAB" + getCommonText()),
+ nosalt_txt("1 1 1 -" + getCommonText()),
+ obuffer(0)
+ {}
+
+ RDATA_TYPE fromText(const string& rdata_text) {
+ return (RDATA_TYPE(rdata_text));
+ }
+
+ void compareCheck() const {
+ typename vector<RDATA_TYPE>::const_iterator it;
+ typename vector<RDATA_TYPE>::const_iterator const it_end =
+ compare_set.end();
+ for (it = compare_set.begin(); it != it_end - 1; ++it) {
+ SCOPED_TRACE("compare " + it->toText() + " to " +
+ (it + 1)->toText());
+ EXPECT_GT(0, (*it).compare(*(it + 1)));
+ EXPECT_LT(0, (*(it + 1)).compare(*it));
+ }
+ }
+
+ const string salt_txt; // RDATA text with salt
+ const string nosalt_txt; // RDATA text without salt
+ OutputBuffer obuffer; // used in toWire() tests
+ MessageRenderer renderer; // ditto
+ vector<RDATA_TYPE> compare_set; // used in compare() tests
+
+ // Convert generic Rdata to the corresponding derived Rdata class object.
+ // Defined here because it depends on the template parameter.
+ static const RDATA_TYPE& convert(const Rdata& rdata) {
+ return (dynamic_cast<const RDATA_TYPE&>(rdata));
+ }
+
+ // These depend on the specific RR type. We use specialized methods
+ // for them.
+ static RRType getType(); // return either RRType::NSEC3() or NSEC3PARAM()
+ static string getWireFilePrefix();
+ static string getCommonText(); // commonly used part of textual form
+};
+
+// Instantiate specific typed tests
+typedef ::testing::Types<generic::NSEC3, generic::NSEC3PARAM> TestRdataTypes;
+#ifdef TYPED_TEST_SUITE
+TYPED_TEST_SUITE(NSEC3PARAMLikeTest, TestRdataTypes);
+#else
+TYPED_TEST_CASE(NSEC3PARAMLikeTest, TestRdataTypes);
+#endif
+
+template <>
+RRType
+NSEC3PARAMLikeTest<generic::NSEC3>::getType() {
+ return (RRType::NSEC3());
+}
+
+template <>
+RRType
+NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getType() {
+ return (RRType::NSEC3PARAM());
+}
+
+template <>
+string
+NSEC3PARAMLikeTest<generic::NSEC3>::getWireFilePrefix() {
+ return ("rdata_nsec3_");
+}
+
+template <>
+string
+NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getWireFilePrefix() {
+ return ("rdata_nsec3param_");
+}
+
+template <>
+string
+NSEC3PARAMLikeTest<generic::NSEC3>::getCommonText() {
+ // next hash + RR type bitmap
+ return (" H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+ "NS SOA RRSIG DNSKEY NSEC3PARAM");
+}
+
+template <>
+string
+NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getCommonText() {
+ // there's no more text for NSEC3PARAM
+ return ("");
+}
+
+TYPED_TEST(NSEC3PARAMLikeTest, fromText) {
+ // Numeric parameters have possible maximum values. Unusual, but must
+ // be accepted.
+ EXPECT_NO_THROW(this->fromText("255 255 65535 D399EAAB" +
+ this->getCommonText()));
+
+ // 0-length salt
+ EXPECT_EQ(0, this->fromText(this->nosalt_txt).getSalt().size());
+
+ // salt that has the possible max length
+ EXPECT_EQ(255, this->fromText("1 1 1 " + string(255 * 2, '0') +
+ this->getCommonText()).getSalt().size());
+}
+
+TYPED_TEST(NSEC3PARAMLikeTest, badText) {
+ // Bad salt hex
+ EXPECT_THROW(this->fromText("1 1 1 SPORK0" + this->getCommonText()),
+ isc::BadValue);
+ EXPECT_THROW(this->fromText("1 1 1 ADDAFEE" + this->getCommonText()),
+ isc::BadValue);
+
+ // Space within salt
+ EXPECT_THROW(this->fromText("1 1 1 ADDAFE ADDAFEEE" +
+ this->getCommonText()),
+ InvalidRdataText);
+
+ // Similar to empty salt, but not really. This shouldn't cause confusion.
+ EXPECT_THROW(this->fromText("1 1 1 --" + this->getCommonText()),
+ isc::BadValue);
+
+ // Too large algorithm
+ EXPECT_THROW(this->fromText("1000000 1 1 ADDAFEEE" + this->getCommonText()),
+ InvalidRdataText);
+
+ // Too large flags
+ EXPECT_THROW(this->fromText("1 1000000 1 ADDAFEEE" + this->getCommonText()),
+ InvalidRdataText);
+
+ // Too large iterations
+ EXPECT_THROW(this->fromText("1 1 65536 ADDAFEEE" + this->getCommonText()),
+ InvalidRdataText);
+
+ // There should be a space between "1" and "D399EAAB" (salt)
+ EXPECT_THROW(this->fromText("1 1 1D399EAAB" + this->getCommonText()),
+ InvalidRdataText);
+
+ // Salt is too long (possible max + 1 bytes)
+ EXPECT_THROW(this->fromText("1 1 1 " + string(256 * 2, '0') +
+ this->getCommonText()),
+ InvalidRdataText);
+}
+
+TYPED_TEST(NSEC3PARAMLikeTest, toText) {
+ // normal case
+ EXPECT_EQ(this->salt_txt, this->fromText(this->salt_txt).toText());
+
+ // empty salt case
+ EXPECT_EQ(this->nosalt_txt, this->fromText(this->nosalt_txt).toText());
+}
+
+TYPED_TEST(NSEC3PARAMLikeTest, createFromWire) {
+ // Normal case
+ EXPECT_EQ(0, this->fromText(this->salt_txt).compare(
+ *this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire1").c_str())));
+
+ // Too short RDLENGTH: it doesn't even contain the first 5 octets.
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire2.wire").c_str()),
+ DNSMessageFORMERR);
+
+ // salt length is too large
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire11.wire").c_str()),
+ DNSMessageFORMERR);
+
+ // empty salt. not so usual, but valid.
+ ConstRdataPtr rdata =
+ this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire13.wire").c_str());
+ EXPECT_EQ(0, this->convert(*rdata).getSalt().size());
+}
+
+TYPED_TEST(NSEC3PARAMLikeTest, createFromLexer) {
+ EXPECT_EQ(0, this->fromText(this->salt_txt).compare(
+ *test::createRdataUsingLexer(this->getType(), RRClass::IN(),
+ this->salt_txt)));
+
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(this->getType(), RRClass::IN(),
+ "1000000 1 1 ADDAFEEE" +
+ this->getCommonText()));
+}
+
+template <typename OUTPUT_TYPE>
+void
+toWireCheck(RRType rrtype, OUTPUT_TYPE& output, const string& data_file) {
+ vector<uint8_t> data;
+ UnitTestUtil::readWireData(data_file.c_str(), data);
+ InputBuffer buffer(&data[0], data.size());
+ const uint16_t rdlen = buffer.readUint16();
+
+ output.clear();
+ output.writeUint16(rdlen);
+ createRdata(rrtype, RRClass::IN(), buffer, rdlen)->toWire(output);
+ matchWireData(&data[0], data.size(),
+ output.getData(), output.getLength());
+}
+
+TYPED_TEST(NSEC3PARAMLikeTest, toWire) {
+ // normal case
+ toWireCheck(this->getType(), this->renderer,
+ this->getWireFilePrefix() + "fromWire1");
+ toWireCheck(this->getType(), this->obuffer,
+ this->getWireFilePrefix() + "fromWire1");
+
+ // empty salt
+ toWireCheck(this->getType(), this->renderer,
+ this->getWireFilePrefix() + "fromWire13.wire");
+ toWireCheck(this->getType(), this->obuffer,
+ this->getWireFilePrefix() + "fromWire13.wire");
+}
+
+TYPED_TEST(NSEC3PARAMLikeTest, compare) {
+ // test RDATAs, sorted in the ascending order.
+ this->compare_set.push_back(this->fromText("0 0 0 D399EAAB" +
+ this->getCommonText()));
+ this->compare_set.push_back(this->fromText("1 0 0 D399EAAB" +
+ this->getCommonText()));
+ this->compare_set.push_back(this->fromText("1 1 0 D399EAAB" +
+ this->getCommonText()));
+ this->compare_set.push_back(this->fromText("1 1 1 -" +
+ this->getCommonText()));
+ this->compare_set.push_back(this->fromText("1 1 1 D399EAAB" +
+ this->getCommonText()));
+ this->compare_set.push_back(this->fromText("1 1 1 FF99EAAB" +
+ this->getCommonText()));
+ this->compare_set.push_back(this->fromText("1 1 1 FF99EA0000" +
+ this->getCommonText()));
+
+ this->compareCheck();
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_nsec3param_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_unittest.cc
new file mode 100644
index 0000000..9a677be
--- /dev/null
+++ b/src/lib/dns/tests/rdata_nsec3param_unittest.cc
@@ -0,0 +1,209 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_NSEC3PARAM_Test : public RdataTest {
+protected:
+ Rdata_NSEC3PARAM_Test() :
+ nsec3param_txt("1 1 1 D399EAAB"),
+ nsec3param_nosalt_txt("1 1 1 -"),
+ rdata_nsec3param(nsec3param_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::NSEC3PARAM, isc::Exception, isc::Exception>(
+ rdata_str, rdata_nsec3param, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::NSEC3PARAM, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_nsec3param, true, true);
+ }
+
+ void checkFromText_BadValue(const string& rdata_str) {
+ checkFromText<generic::NSEC3PARAM, BadValue, BadValue>(
+ rdata_str, rdata_nsec3param, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::NSEC3PARAM, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_nsec3param, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str,
+ const generic::NSEC3PARAM& rdata)
+ {
+ checkFromText
+ <generic::NSEC3PARAM, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata, true, false);
+ }
+
+ const string nsec3param_txt;
+ const string nsec3param_nosalt_txt;
+ const generic::NSEC3PARAM rdata_nsec3param;
+};
+
+TEST_F(Rdata_NSEC3PARAM_Test, fromText) {
+ // Empty salt is okay.
+ EXPECT_EQ(0, generic::NSEC3PARAM(nsec3param_nosalt_txt).getSalt().size());
+
+ // Salt is missing.
+ checkFromText_LexerError("1 1 1");
+
+ // Salt has whitespace within. This only fails in the string
+ // constructor, as the lexer constructor stops reading at the end of
+ // its RDATA.
+ const generic::NSEC3PARAM rdata_nsec3param2("1 1 1 D399");
+ checkFromText_BadString("1 1 1 D399 EAAB", rdata_nsec3param2);
+
+ // Hash algorithm out of range.
+ checkFromText_InvalidText("256 1 1 D399EAAB");
+
+ // Flags out of range.
+ checkFromText_InvalidText("1 256 1 D399EAAB");
+
+ // Iterations out of range.
+ checkFromText_InvalidText("1 1 65536 D399EAAB");
+
+ // Bad hex sequence
+ checkFromText_BadValue("1 1 256 D399EAABZOO");
+
+ // String instead of number
+ checkFromText_LexerError("foo 1 256 D399EAAB");
+ checkFromText_LexerError("1 foo 256 D399EAAB");
+ checkFromText_LexerError("1 1 foo D399EAAB");
+
+ // Trailing garbage. This should cause only the string constructor
+ // to fail, but the lexer constructor must be able to continue
+ // parsing from it.
+ checkFromText_BadString("1 1 1 D399EAAB ; comment\n"
+ "1 1 1 D399EAAB", rdata_nsec3param);
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, toText) {
+ EXPECT_EQ(nsec3param_txt, rdata_nsec3param.toText());
+
+ // Garbage space at the end should be ok. RFC5155 only forbids
+ // whitespace within the salt field, but any whitespace afterwards
+ // should be fine.
+ EXPECT_NO_THROW(generic::NSEC3PARAM("1 1 1 D399EAAB "));
+
+ // Hash algorithm in range.
+ EXPECT_NO_THROW(generic::NSEC3PARAM("255 1 1 D399EAAB"));
+
+ // Flags in range.
+ EXPECT_NO_THROW(generic::NSEC3PARAM("1 255 1 D399EAAB"));
+
+ // Iterations in range.
+ EXPECT_NO_THROW(generic::NSEC3PARAM("1 1 65535 D399EAAB"));
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_nsec3param.compare(
+ *rdataFactoryFromFile(RRType::NSEC3PARAM(), RRClass::IN(),
+ "rdata_nsec3param_fromWire1")));
+
+ // Short buffer cases. The data is valid NSEC3PARAM RDATA, but the buffer
+ // is trimmed at the end. All cases should result in an exception from
+ // the buffer class.
+ vector<uint8_t> data;
+ UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data);
+ const uint16_t rdlen = (data.at(0) << 8) + data.at(1);
+ for (int i = 0; i < rdlen; ++i) {
+ // intentionally construct a short buffer
+ InputBuffer b(&data[0] + 2, i);
+ EXPECT_THROW(createRdata(RRType::NSEC3PARAM(), RRClass::IN(), b, 9),
+ InvalidBufferPosition);
+ }
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_nsec3param.compare(
+ *test::createRdataUsingLexer(RRType::NSEC3PARAM(), RRClass::IN(),
+ nsec3param_txt)));
+
+ // empty salt is also okay.
+ const generic::NSEC3PARAM rdata_nosalt_nsec3param(nsec3param_nosalt_txt);
+ EXPECT_EQ(0, rdata_nosalt_nsec3param.compare(
+ *test::createRdataUsingLexer(RRType::NSEC3PARAM(), RRClass::IN(),
+ nsec3param_nosalt_txt)));
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer) {
+ renderer.skip(2);
+ rdata_nsec3param.toWire(renderer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) {
+ rdata_nsec3param.toWire(obuffer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data);
+ matchWireData(&data[2], data.size() - 2,
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, getHashAlg) {
+ EXPECT_EQ(1, rdata_nsec3param.getHashalg());
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, getFlags) {
+ EXPECT_EQ(1, rdata_nsec3param.getFlags());
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, assign) {
+ generic::NSEC3PARAM other_nsec3param("1 1 1 -");
+ other_nsec3param = rdata_nsec3param;
+ EXPECT_EQ(0, rdata_nsec3param.compare(other_nsec3param));
+}
+
+TEST_F(Rdata_NSEC3PARAM_Test, compare) {
+ // trivial case: self equivalence
+ EXPECT_EQ(0, generic::NSEC3PARAM(nsec3param_txt).
+ compare(generic::NSEC3PARAM(nsec3param_txt)));
+ EXPECT_EQ(0, generic::NSEC3PARAM("1 1 1 -").
+ compare(generic::NSEC3PARAM("1 1 1 -")));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(generic::NSEC3PARAM(nsec3param_txt).compare(*rdata_nomatch),
+ bad_cast);
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_nsec_unittest.cc b/src/lib/dns/tests/rdata_nsec_unittest.cc
new file mode 100644
index 0000000..570a2ab
--- /dev/null
+++ b/src/lib/dns/tests/rdata_nsec_unittest.cc
@@ -0,0 +1,138 @@
+// Copyright (C) 2010-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_NSEC_Test : public RdataTest {
+ // there's nothing to specialize
+};
+
+const char* const nsec_txt = "www2.isc.org. CNAME RRSIG NSEC";
+
+TEST_F(Rdata_NSEC_Test, toText_NSEC) {
+ const generic::NSEC rdata_nsec(nsec_txt);
+ EXPECT_EQ(nsec_txt, rdata_nsec.toText());
+}
+
+TEST_F(Rdata_NSEC_Test, badText_NSEC) {
+ EXPECT_THROW(generic::NSEC rdata_nsec("www.isc.org. BIFF POW SPOON"),
+ InvalidRdataText);
+ EXPECT_THROW(generic::NSEC rdata_nsec("www.isc.org."),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_NSEC_Test, createFromWire_NSEC) {
+ const generic::NSEC rdata_nsec(nsec_txt);
+ EXPECT_EQ(0, rdata_nsec.compare(
+ *rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire1")));
+
+ // Too short RDLENGTH
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire2"),
+ DNSMessageFORMERR);
+
+ // Invalid bitmap cases are tested in Rdata_NSECBITMAP_Test.
+}
+
+TEST_F(Rdata_NSEC_Test, createFromLexer_NSEC) {
+ const generic::NSEC rdata_nsec(nsec_txt);
+ EXPECT_EQ(0, rdata_nsec.compare(
+ *test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(),
+ nsec_txt)));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ EXPECT_EQ(0, generic::NSEC("www2.example.org. CNAME RRSIG NSEC").compare(
+ *test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(),
+ "www2 CNAME RRSIG NSEC")));
+
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(),
+ "www.isc.org."));
+}
+
+TEST_F(Rdata_NSEC_Test, toWireRenderer_NSEC) {
+ renderer.skip(2);
+ const generic::NSEC rdata_nsec(nsec_txt);
+ rdata_nsec.toWire(renderer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_nsec_fromWire1", data);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
+}
+
+TEST_F(Rdata_NSEC_Test, toWireBuffer_NSEC) {
+ const generic::NSEC rdata_nsec(nsec_txt);
+ rdata_nsec.toWire(obuffer);
+}
+
+TEST_F(Rdata_NSEC_Test, assign) {
+ generic::NSEC rdata_nsec(nsec_txt);
+ generic::NSEC rdata_nsec2 = rdata_nsec;
+ EXPECT_EQ(0, rdata_nsec.compare(rdata_nsec2));
+}
+
+TEST_F(Rdata_NSEC_Test, getNextName) {
+ // The implementation is quite trivial, so we simply check it's actually
+ // defined and does work as intended in a simple case.
+ EXPECT_EQ(Name("www2.isc.org"), generic::NSEC((nsec_txt)).getNextName());
+}
+
+TEST_F(Rdata_NSEC_Test, compare) {
+ // trivial case: self equivalence
+ EXPECT_EQ(0, generic::NSEC("example. A").
+ compare(generic::NSEC("example. A")));
+ EXPECT_EQ(0, generic::NSEC("EXAMPLE. A"). // should be case insensitive
+ compare(generic::NSEC("example. A")));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(generic::NSEC(nsec_txt).compare(*rdata_nomatch),
+ bad_cast);
+
+ // test RDATAs, sorted in the ascending order. We only compare the
+ // next name here. Bitmap comparison is tested in the bitmap tests.
+ // Note that names are compared as wire-format data, not based on the
+ // domain name comparison.
+ vector<generic::NSEC> compare_set;
+ compare_set.push_back(generic::NSEC("a.example. A"));
+ compare_set.push_back(generic::NSEC("example. A"));
+ vector<generic::NSEC>::const_iterator it;
+ const vector<generic::NSEC>::const_iterator it_end = compare_set.end();
+ for (it = compare_set.begin(); it != it_end - 1; ++it) {
+ SCOPED_TRACE("compare " + it->toText() + " to " + (it + 1)->toText());
+ EXPECT_GT(0, (*it).compare(*(it + 1)));
+ EXPECT_LT(0, (*(it + 1)).compare(*it));
+ }
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc
new file mode 100644
index 0000000..f18e9df
--- /dev/null
+++ b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc
@@ -0,0 +1,269 @@
+// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/tests/unittest_util.h>
+
+#include <dns/exceptions.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <string>
+#include <vector>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using namespace isc::util;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+using boost::lexical_cast;
+
+namespace {
+
+// Template for shared tests for NSEC and NSEC3 bitmaps
+template <typename RDATA_TYPE>
+class NSECLikeBitmapTest : public RdataTest {
+protected:
+ RDATA_TYPE fromText(const string& rdata_text) {
+ return (RDATA_TYPE(rdata_text));
+ }
+
+ vector<RDATA_TYPE> compare_set; // used in compare() tests
+
+ void compareCheck() const {
+ typename vector<RDATA_TYPE>::const_iterator it;
+ typename vector<RDATA_TYPE>::const_iterator const it_end =
+ compare_set.end();
+ for (it = compare_set.begin(); it != it_end - 1; ++it) {
+ SCOPED_TRACE("compare " + it->toText() + " to " +
+ (it + 1)->toText());
+ EXPECT_GT(0, (*it).compare(*(it + 1)));
+ EXPECT_LT(0, (*(it + 1)).compare(*it));
+ }
+ }
+
+ // These depend on the specific RR type. We use specialized methods
+ // for them.
+ static RRType getType(); // return either RRType::NSEC() or NSEC3()
+ static string getWireFilePrefix();
+ static string getCommonText(); // commonly used part of textual form
+};
+
+// Instantiate specific typed tests
+typedef ::testing::Types<generic::NSEC, generic::NSEC3> TestRdataTypes;
+#ifdef TYPED_TEST_SUITE
+TYPED_TEST_SUITE(NSECLikeBitmapTest, TestRdataTypes);
+#else
+TYPED_TEST_CASE(NSECLikeBitmapTest, TestRdataTypes);
+#endif
+
+// NSEC and NSEC3 bitmaps have some subtle differences, in which case we
+// need to test them separately. Using these typedef type names with TEST_F
+// will do the trick.
+typedef NSECLikeBitmapTest<generic::NSEC3> NSEC3BitmapTest;
+typedef NSECLikeBitmapTest<generic::NSEC> NSECBitmapTest;
+
+template <>
+string
+NSECLikeBitmapTest<generic::NSEC>::getWireFilePrefix() {
+ return ("rdata_nsec_");
+}
+
+template <>
+RRType
+NSECLikeBitmapTest<generic::NSEC>::getType() {
+ return (RRType::NSEC());
+}
+
+template <>
+string
+NSECLikeBitmapTest<generic::NSEC3>::getWireFilePrefix() {
+ return ("rdata_nsec3_");
+}
+
+template <>
+RRType
+NSECLikeBitmapTest<generic::NSEC3>::getType() {
+ return (RRType::NSEC3());
+}
+
+template <>
+string
+NSECLikeBitmapTest<generic::NSEC>::getCommonText() {
+ return ("next. ");
+}
+
+template <>
+string
+NSECLikeBitmapTest<generic::NSEC3>::getCommonText() {
+ return ("1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR ");
+}
+
+// Tests against various types of bogus NSEC/NSEC3 type bitmaps.
+// The syntax and semantics are common for both RR types, and our
+// implementation of that part is shared, so in theory it should be sufficient
+// to test for only one RR type. But we check for both just in case.
+TYPED_TEST(NSECLikeBitmapTest, createFromWire) {
+ // A malformed NSEC bitmap length field that could cause overflow.
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire4.wire").c_str()),
+ DNSMessageFORMERR);
+
+ // The bitmap field is incomplete (only the first byte is included)
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire5.wire").c_str()),
+ DNSMessageFORMERR);
+
+ // Bitmap length is 0, which is invalid.
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire6.wire").c_str()),
+ DNSMessageFORMERR);
+
+ // Too large bitmap length with a short buffer.
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire3").c_str()),
+ DNSMessageFORMERR);
+
+ // A boundary case: longest possible bitmaps (32 maps). This should be
+ // accepted.
+ EXPECT_NO_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire7.wire").c_str()));
+
+ // Another boundary condition: 33 bitmaps, which should be rejected.
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire8.wire").c_str()),
+ DNSMessageFORMERR);
+
+ // Disordered bitmap window blocks.
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire9.wire").c_str()),
+ DNSMessageFORMERR);
+
+ // Bitmap ending with all-zero bytes. Not necessarily harmful except
+ // the additional overhead of parsing, but invalid according to the
+ // spec anyway.
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire10.wire").c_str()),
+ DNSMessageFORMERR);
+}
+
+// This tests the result of toText() with various kinds of NSEC/NSEC3 bitmaps.
+// It also tests the "from text" constructor as a result.
+TYPED_TEST(NSECLikeBitmapTest, toText) {
+ // A simple case (some commonly seen RR types in NSEC(3) bitmaps)
+ string rdata_text = this->getCommonText() + "NS SOA RRSIG DNSKEY";
+ EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
+
+ // Similar to above, but involves more than one bitmap window blocks.
+ rdata_text = this->getCommonText() + "NS DLV";
+ EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
+
+ // Make sure all possible bits in a one-octet bitmap field are handled
+ // correctly.
+ // We use the range around 1024 (reasonably higher number) so it's
+ // unlikely that they have predefined mnemonic and can be safely converted
+ // to TYPEnnnn by toText().
+ for (unsigned int i = 1024; i < 1032; ++i) {
+ rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i);
+ EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
+ }
+
+ // Make sure all possible 32 octets in a longest possible block are
+ // handled correctly.
+ for (unsigned int i = 1024; i < 1024 + 256; i += 8) {
+ rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i);
+ EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
+ }
+
+ // Check for the highest window block.
+ rdata_text = this->getCommonText() + "TYPE65535";
+ EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
+}
+
+TYPED_TEST(NSECLikeBitmapTest, compare) {
+ // Bit map: [win=0][len=1] 00000010
+ this->compare_set.push_back(this->fromText(this->getCommonText() + "SOA"));
+ // Bit map: [win=0][len=1] 00000010, [win=4][len=1] 10000000
+ this->compare_set.push_back(this->fromText(this->getCommonText() +
+ "SOA TYPE1024"));
+ // Bit map: [win=0][len=1] 00100000
+ this->compare_set.push_back(this->fromText(this->getCommonText() + "NS"));
+ // Bit map: [win=0][len=1] 00100010
+ this->compare_set.push_back(this->fromText(this->getCommonText() +
+ "NS SOA"));
+ // Bit map: [win=0][len=2] 00100000, 00000001
+ this->compare_set.push_back(this->fromText(this->getCommonText() +
+ "NS MX"));
+ // Bit map: [win=4][len=1] 10000000
+ this->compare_set.push_back(this->fromText(this->getCommonText() +
+ "TYPE1024"));
+
+ this->compareCheck();
+}
+
+// NSEC bitmaps must not be empty
+TEST_F(NSECBitmapTest, emptyMap) {
+ EXPECT_THROW(this->fromText("next.example.").toText(), InvalidRdataText);
+
+ EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
+ (this->getWireFilePrefix() +
+ "fromWire16.wire").c_str()),
+ DNSMessageFORMERR);
+}
+
+// NSEC3 bitmaps can be empty
+TEST_F(NSEC3BitmapTest, emptyMap) {
+ // Read wire data wit an empty NSEC3 bitmap. This should succeed.
+ vector<uint8_t> data;
+ UnitTestUtil::readWireData((this->getWireFilePrefix() +
+ "fromWire16.wire").c_str(), data);
+ InputBuffer buffer(&data[0], data.size());
+ const uint16_t rdlen = buffer.readUint16();
+ const generic::NSEC3 empty_nsec3 =
+ dynamic_cast<const generic::NSEC3&>(*createRdata(
+ RRType::NSEC3(), RRClass::IN(),
+ buffer, rdlen));
+
+ // Check the toText() result.
+ EXPECT_EQ("1 0 1 7373737373 D1K6GQ38D1K6GQ38D1K6GQ38D1K6GQ38",
+ empty_nsec3.toText());
+
+ // Check the toWire() result.
+ OutputBuffer obuffer(0);
+ obuffer.writeUint16(rdlen);
+ empty_nsec3.toWire(obuffer);
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
+
+ // Same for MessageRenderer.
+ obuffer.clear();
+ MessageRenderer renderer;
+ renderer.writeUint16(rdlen);
+ empty_nsec3.toWire(renderer);
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc
new file mode 100644
index 0000000..a235183
--- /dev/null
+++ b/src/lib/dns/tests/rdata_opt_unittest.cc
@@ -0,0 +1,198 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_OPT_Test : public RdataTest {
+ // there's nothing to specialize
+};
+
+const uint8_t rdata_opt_wiredata[] = {
+ // Option code
+ 0x00, 0x2a,
+ // Option length
+ 0x00, 0x03,
+ // Option data
+ 0x00, 0x01, 0x02
+};
+
+TEST_F(Rdata_OPT_Test, createFromText) {
+ // OPT RR cannot be created from text.
+ EXPECT_THROW(generic::OPT("this does not matter"), InvalidRdataText);
+}
+
+TEST_F(Rdata_OPT_Test, createFromWire) {
+ // Valid cases: in the simple implementation with no supported options,
+ // we can only check these don't throw.
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass("CLASS4096"),
+ "rdata_opt_fromWire1"));
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::CH(),
+ "rdata_opt_fromWire1", 2));
+
+ // Short RDLEN. This throws InvalidRdataLength even if subsequent
+ // pseudo RRs cause RDLEN size to be exhausted.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire2"),
+ InvalidRdataLength);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire3"),
+ InvalidRdataLength);
+ // Option lengths can add up and overflow RDLEN. Unlikely when
+ // parsed from wire data, but we'll check for it anyway.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire4"),
+ InvalidRdataText);
+
+ // short buffer case.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire1", 11),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_OPT_Test, createFromLexer) {
+ // OPT RR cannot be created from text. Exceptions cause NULL to be
+ // returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::OPT(), RRClass::IN(),
+ "this does not matter"));
+}
+
+TEST_F(Rdata_OPT_Test, toWireBuffer) {
+ const generic::OPT rdata_opt =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ obuffer.clear();
+ rdata_opt.toWire(obuffer);
+
+ matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_OPT_Test, toWireRenderer) {
+ const generic::OPT rdata_opt =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ renderer.clear();
+ rdata_opt.toWire(renderer);
+
+ matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_OPT_Test, toText) {
+ // empty OPT
+ const generic::OPT rdata_opt;
+
+ EXPECT_THROW(rdata_opt.toText(),
+ isc::InvalidOperation);
+}
+
+TEST_F(Rdata_OPT_Test, compare) {
+ // empty OPT
+ const generic::OPT rdata_opt;
+
+ EXPECT_THROW(rdata_opt.compare(
+ *rdataFactoryFromFile(RRType::OPT(), RRClass::CH(),
+ "rdata_opt_fromWire1", 2)),
+ isc::InvalidOperation);
+
+ // comparison attempt between incompatible RR types also results in
+ // isc::InvalidOperation.
+ EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch),
+ isc::InvalidOperation);
+}
+
+TEST_F(Rdata_OPT_Test, appendPseudoRR) {
+ generic::OPT rdata_opt;
+
+ // Append empty option data
+ rdata_opt.appendPseudoRR(0x0042, NULL, 0);
+
+ // Append simple option data
+ const uint8_t option_data[] = {'H', 'e', 'l', 'l', 'o'};
+ rdata_opt.appendPseudoRR(0x0043, option_data, sizeof(option_data));
+
+ // Duplicate option codes are okay.
+ rdata_opt.appendPseudoRR(0x0042, option_data, sizeof(option_data));
+
+ // When option length may overflow RDLEN, append should throw.
+ const std::vector<uint8_t> buffer((1 << 16) - 1);
+ EXPECT_THROW(rdata_opt.appendPseudoRR(0x0044, &buffer[0], buffer.size()),
+ isc::InvalidParameter);
+
+ const uint8_t rdata_opt_wiredata2[] = {
+ // OPTION #1
+ // ` Option code
+ 0x00, 0x42,
+ // ` Option length
+ 0x00, 0x00,
+
+ // OPTION #2
+ // ` Option code
+ 0x00, 0x43,
+ // ` Option length
+ 0x00, 0x05,
+ // ` Option data
+ 'H', 'e', 'l', 'l', 'o',
+
+ // OPTION #3
+ // ` Option code
+ 0x00, 0x42,
+ // ` Option length
+ 0x00, 0x05,
+ // ` Option data
+ 'H', 'e', 'l', 'l', 'o'
+ };
+
+ obuffer.clear();
+ rdata_opt.toWire(obuffer);
+
+ matchWireData(rdata_opt_wiredata2, sizeof(rdata_opt_wiredata2),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_OPT_Test, getPseudoRRs) {
+ const generic::OPT rdf =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ const std::vector<generic::OPT::PseudoRR>& rrs = rdf.getPseudoRRs();
+ ASSERT_FALSE(rrs.empty());
+ EXPECT_EQ(1, rrs.size());
+ EXPECT_EQ(0x2a, rrs.at(0).getCode());
+ EXPECT_EQ(3, rrs.at(0).getLength());
+
+ const uint8_t expected_data[] = {0x00, 0x01, 0x02};
+ const uint8_t* actual_data = rrs.at(0).getData();
+ EXPECT_EQ(0, std::memcmp(expected_data, actual_data,
+ sizeof(expected_data)));
+}
+}
diff --git a/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc b/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc
new file mode 100644
index 0000000..d639541
--- /dev/null
+++ b/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc
@@ -0,0 +1,56 @@
+// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/rdata_pimpl_holder.h>
+
+#include <gtest/gtest.h>
+
+using namespace isc::dns::rdata;
+
+namespace {
+
+TEST(RdataPimplHolderTest, all) {
+ // Let's check with an integer
+ int* i1 = new int(42);
+ RdataPimplHolder<int> holder1(i1);
+ // The same pointer must be returned.
+ EXPECT_EQ(i1, holder1.get());
+ // Obviously the value should match too.
+ EXPECT_EQ(42, *holder1.get());
+ // We don't explicitly delete i or holder1, so it should not leak
+ // anything when the test is done (checked by Valgrind).
+
+ // The following cases are similar:
+
+ // Test no-argument reset()
+ int* i2 = new int(43);
+ RdataPimplHolder<int> holder2(i2);
+ holder2.reset();
+ EXPECT_EQ(NULL, holder2.get());
+
+ // Test reset() with argument
+ int* i3 = new int(44);
+ int* i4 = new int(45);
+ RdataPimplHolder<int> holder3(i3);
+ EXPECT_EQ(i3, holder3.get());
+ holder3.reset(i4);
+ EXPECT_EQ(i4, holder3.get());
+ EXPECT_EQ(45, *holder3.get());
+
+ // Test release()
+ RdataPimplHolder<int> holder4(new int(46));
+ EXPECT_NE(static_cast<void*>(NULL), holder4.get());
+ EXPECT_EQ(46, *holder4.get());
+ int* i5 = holder4.release();
+ EXPECT_EQ(NULL, holder4.get());
+ EXPECT_NE(static_cast<void*>(NULL), i5);
+ EXPECT_EQ(46, *i5);
+ delete i5;
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_ptr_unittest.cc b/src/lib/dns/tests/rdata_ptr_unittest.cc
new file mode 100644
index 0000000..5ed3bce
--- /dev/null
+++ b/src/lib/dns/tests/rdata_ptr_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+//
+// This test currently simply copies the NS RDATA tests.
+//
+
+namespace {
+class Rdata_PTR_Test : public RdataTest {
+public:
+ Rdata_PTR_Test() :
+ rdata_ptr("ns.example.com."),
+ rdata_ptr2("ns2.example.com.")
+ {}
+
+ const generic::PTR rdata_ptr;
+ const generic::PTR rdata_ptr2;
+};
+
+const uint8_t wiredata_ptr[] = {
+ 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00 };
+const uint8_t wiredata_ptr2[] = {
+ // first name: ns.example.com.
+ 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+ 0x63, 0x6f, 0x6d, 0x00,
+ // second name: ns2.example.com. all labels except the first should be
+ // compressed.
+ 0x03, 0x6e, 0x73, 0x32, 0xc0, 0x03 };
+
+TEST_F(Rdata_PTR_Test, createFromText) {
+ EXPECT_EQ(0, rdata_ptr.compare(generic::PTR("ns.example.com.")));
+ // explicitly add a trailing dot. should be the same RDATA.
+ EXPECT_EQ(0, rdata_ptr.compare(generic::PTR("ns.example.com.")));
+ // should be case sensitive.
+ EXPECT_EQ(0, rdata_ptr.compare(generic::PTR("NS.EXAMPLE.COM.")));
+ // RDATA of a class-independent type should be recognized for any
+ // "unknown" class.
+ EXPECT_EQ(0, rdata_ptr.compare(*createRdata(RRType("PTR"), RRClass(65000),
+ "ns.example.com.")));
+}
+
+TEST_F(Rdata_PTR_Test, badText) {
+ // Extra text at end of line
+ EXPECT_THROW(generic::PTR("foo.example.com. extra."), InvalidRdataText);
+}
+
+TEST_F(Rdata_PTR_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_ptr.compare(
+ *rdataFactoryFromFile(RRType("PTR"), RRClass("IN"),
+ "rdata_ns_fromWire")));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType("PTR"), RRClass("IN"),
+ "rdata_ns_fromWire", 18),
+ InvalidRdataLength);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType("PTR"), RRClass("IN"),
+ "rdata_ns_fromWire", 36),
+ InvalidRdataLength);
+ // incomplete name. the error should be detected in the name constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType("PTR"), RRClass("IN"),
+ "rdata_ns_fromWire", 71),
+ DNSMessageFORMERR);
+
+ EXPECT_EQ(0, generic::PTR("ns2.example.com.").compare(
+ *rdataFactoryFromFile(RRType("PTR"), RRClass("IN"),
+ "rdata_ns_fromWire", 55)));
+ EXPECT_THROW(*rdataFactoryFromFile(RRType("PTR"), RRClass("IN"),
+ "rdata_ns_fromWire", 63),
+ InvalidRdataLength);
+}
+
+TEST_F(Rdata_PTR_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_ptr.compare(
+ *test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(),
+ "ns.example.com.")));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ EXPECT_EQ(0, generic::PTR("foo0.example.org.").compare(
+ *test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(),
+ "foo0")));
+
+ // Extra text at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(),
+ "foo.example.com. extra."));
+}
+
+TEST_F(Rdata_PTR_Test, toWireBuffer) {
+ rdata_ptr.toWire(obuffer);
+ matchWireData(wiredata_ptr, sizeof(wiredata_ptr),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_PTR_Test, toWireRenderer) {
+ rdata_ptr.toWire(renderer);
+ matchWireData(wiredata_ptr, sizeof(wiredata_ptr),
+ renderer.getData(), renderer.getLength());
+
+ rdata_ptr2.toWire(renderer);
+ matchWireData(wiredata_ptr2, sizeof(wiredata_ptr2),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_PTR_Test, toText) {
+ EXPECT_EQ("ns.example.com.", rdata_ptr.toText());
+}
+
+TEST_F(Rdata_PTR_Test, compare) {
+ generic::PTR small("a.example.");
+ generic::PTR large("example.");
+ EXPECT_TRUE(Name("a.example") > Name("example"));
+ EXPECT_GT(0, small.compare(large));
+}
+
+TEST_F(Rdata_PTR_Test, getPTRName) {
+ EXPECT_EQ(Name("ns.example.com"), rdata_ptr.getPTRName());
+}
+}
diff --git a/src/lib/dns/tests/rdata_rp_unittest.cc b/src/lib/dns/tests/rdata_rp_unittest.cc
new file mode 100644
index 0000000..e752f13
--- /dev/null
+++ b/src/lib/dns/tests/rdata_rp_unittest.cc
@@ -0,0 +1,200 @@
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/rdataclass.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_RP_Test : public RdataTest {
+protected:
+ Rdata_RP_Test() :
+ mailbox_name("root.example.com."),
+ text_name("rp-text.example.com."),
+ // this also serves as a test for "from text" constructor in a normal
+ // case.
+ rdata_rp("root.example.com. rp-text.example.com."),
+ obuffer(0)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::RP, isc::Exception, isc::Exception>(
+ rdata_str, rdata_rp, false, false);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::RP, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_rp, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText<generic::RP, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_rp, true, false);
+ }
+
+ void checkFromText_EmptyLabel(const string& rdata_str) {
+ checkFromText<generic::RP, EmptyLabel, EmptyLabel>(
+ rdata_str, rdata_rp, true, true);
+ }
+
+ void checkFromText_MissingOrigin(const string& rdata_str) {
+ checkFromText
+ <generic::RP, MissingNameOrigin, MissingNameOrigin>(
+ rdata_str, rdata_rp, true, true);
+ }
+
+ void checkFromText_Origin(const string& rdata_str, const Name* origin) {
+ checkFromText<generic::RP, MissingNameOrigin, isc::Exception>(
+ rdata_str, rdata_rp, true, false, origin);
+ }
+
+ const Name mailbox_name, text_name;
+ const generic::RP rdata_rp; // commonly used test RDATA
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+ vector<uint8_t> expected_wire;
+};
+
+TEST_F(Rdata_RP_Test, createFromText) {
+ EXPECT_EQ(mailbox_name, rdata_rp.getMailbox());
+ EXPECT_EQ(text_name, rdata_rp.getText());
+
+ checkFromText_None("root.example.com. rp-text.example.com.");
+
+ // origin defined for lexer constructor, but not string constructor
+ const Name origin("example.com");
+ checkFromText_Origin("root rp-text", &origin);
+
+ // lexer constructor accepts extra text, but string constructor doesn't
+ checkFromText_BadString("root.example.com. rp-text.example.com. "
+ "extra.example.com.");
+}
+
+TEST_F(Rdata_RP_Test, badText) {
+ // invalid names
+ checkFromText_EmptyLabel("root..example.com. rp-text.example.com.");
+ checkFromText_EmptyLabel("root.example.com. rp-text..example.com.");
+
+ // missing field
+ checkFromText_LexerError("root.example.com.");
+
+ // missing origin
+ checkFromText_MissingOrigin("root.example.com rp-text.example.com.");
+ checkFromText_MissingOrigin("root.example.com. rp-text.example.com");
+}
+
+TEST_F(Rdata_RP_Test, createFromWire) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+ "rdata_rp_fromWire1.wire"));
+ EXPECT_EQ(mailbox_name, dynamic_cast<generic::RP&>(*rdata).getMailbox());
+ EXPECT_EQ(text_name, dynamic_cast<generic::RP&>(*rdata).getText());
+
+ // a similar test with names being compressed
+ rdata = rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+ "rdata_rp_fromWire2.wire", 30);
+ EXPECT_EQ(mailbox_name, dynamic_cast<generic::RP&>(*rdata).getMailbox());
+ EXPECT_EQ(Name("rp-text.example.net"),
+ dynamic_cast<generic::RP&>(*rdata).getText());
+}
+
+TEST_F(Rdata_RP_Test, badFromWire) {
+ // RDLEN is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+ "rdata_rp_fromWire3.wire"),
+ InvalidRdataLength);
+
+ // RDLEN is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+ "rdata_rp_fromWire4.wire"),
+ InvalidRdataLength);
+
+ // bogus mailbox name
+ EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+ "rdata_rp_fromWire5.wire"),
+ DNSMessageFORMERR);
+
+ // bogus text name
+ EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(),
+ "rdata_rp_fromWire6.wire"),
+ DNSMessageFORMERR);
+}
+
+TEST_F(Rdata_RP_Test, createFromParams) {
+ EXPECT_EQ(mailbox_name, generic::RP(mailbox_name, text_name).getMailbox());
+ EXPECT_EQ(text_name, generic::RP(mailbox_name, text_name).getText());
+}
+
+TEST_F(Rdata_RP_Test, toWireBuffer) {
+ // construct expected data
+ UnitTestUtil::readWireData("rdata_rp_toWire1.wire", expected_wire);
+
+ // construct actual data
+ rdata_rp.toWire(obuffer);
+
+ // then compare them
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_RP_Test, toWireRenderer) {
+ // similar to toWireBuffer, but names in RDATA could be compressed due to
+ // preceding names. Actually they must not be compressed according to
+ // RFC3597, and this test checks that.
+
+ UnitTestUtil::readWireData("rdata_rp_toWire2.wire", expected_wire);
+
+ renderer.writeName(Name("a.example.com"));
+ renderer.writeName(Name("b.example.net"));
+ generic::RP(mailbox_name, Name("rp-text.example.net")).toWire(renderer);
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_RP_Test, toText) {
+ // there's not much to test for this method. Only checking a simple case.
+ EXPECT_EQ("root.example.com. rp-text.example.com.", rdata_rp.toText());
+}
+
+TEST_F(Rdata_RP_Test, compare) {
+ // check reflexivity
+ EXPECT_EQ(0, rdata_rp.compare(rdata_rp));
+
+ // names must be compared in case-insensitive manner
+ EXPECT_EQ(0, rdata_rp.compare(generic::RP("ROOT.example.com. "
+ "rp-text.EXAMPLE.com.")));
+
+ // another RP whose mailbox name is larger than that of rdata_rp.
+ const generic::RP large1_rp("zzzz.example.com. rp-text.example.com.");
+ EXPECT_GT(0, rdata_rp.compare(large1_rp));
+ EXPECT_LT(0, large1_rp.compare(rdata_rp));
+
+ // yet another RP whose text name is larger than that of rdata_rp.
+ const generic::RP large2_rp("root.example.com. zzzzzzz.example.com.");
+ EXPECT_GT(0, rdata_rp.compare(large2_rp));
+ EXPECT_LT(0, large2_rp.compare(rdata_rp));
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_rp.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_rrsig_unittest.cc b/src/lib/dns/tests/rdata_rrsig_unittest.cc
new file mode 100644
index 0000000..b198d15
--- /dev/null
+++ b/src/lib/dns/tests/rdata_rrsig_unittest.cc
@@ -0,0 +1,369 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/time_utilities.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+#include <dns/tests/rdata_unittest.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+
+const uint8_t wiredata_rrsig[] = {
+ // type covered = A
+ 0x00, 0x01,
+ // algorithm = 5
+ 0x05,
+ // labels = 4
+ 0x04,
+ // original TTL = 43200 (0x0000a8c0)
+ 0x00, 0x00, 0xa8, 0xc0,
+ // signature expiration = 1266961577 (0x4b844ca9)
+ 0x4b, 0x84, 0x4c, 0xa9,
+ // signature inception = 1266875177 (0x4b82fb29)
+ 0x4b, 0x82, 0xfb, 0x29,
+ // key tag = 8496 (0x2130)
+ 0x21, 0x30,
+ // signer's name (isc.org.)
+ // 3 i s c 3 o r g 0
+ 0x03, 0x69, 0x73, 0x63, 0x03, 0x6f, 0x72, 0x67, 0x00,
+ // signature data follows
+ 0x7a, 0xfc, 0x61, 0x94, 0x6c,
+ 0x75, 0xde, 0x6a, 0x4a, 0x2d, 0x59, 0x0a, 0xb2,
+ 0x3a, 0x46, 0xcf, 0x27, 0x12, 0xe6, 0xdc, 0x2d,
+ 0x22, 0x8c, 0x4e, 0x9a, 0x53, 0x75, 0xe3, 0x0f,
+ 0x6d, 0xe4, 0x08, 0x33, 0x18, 0x19, 0xb3, 0x76,
+ 0x21, 0x9d, 0x2c, 0x8a, 0xc5, 0x69, 0xba, 0xab,
+ 0xef, 0x66, 0x9f, 0xda, 0xb5, 0x2a, 0xf9, 0x40,
+ 0xc1, 0x28, 0xc5, 0x97, 0xba, 0x3c, 0x19, 0x4d,
+ 0x95, 0x13, 0xc2, 0xcd, 0xf6, 0xb1, 0x59, 0x5d,
+ 0x0c, 0xf9, 0x3f, 0x35, 0xbb, 0x9a, 0x70, 0x93,
+ 0x36, 0xe5, 0xf4, 0x17, 0x7e, 0xfe, 0x66, 0x3b,
+ 0x70, 0x1f, 0xed, 0x33, 0xa8, 0xa3, 0x0d, 0xc0,
+ 0x8c, 0xc6, 0x95, 0x1b, 0xd8, 0x9c, 0x8c, 0x25,
+ 0xb4, 0x57, 0x9e, 0x56, 0x71, 0x64, 0x14, 0x7f,
+ 0x8f, 0x6d, 0xfa, 0xc5, 0xca, 0x3f, 0x36, 0xe2,
+ 0xa4, 0xdf, 0x60, 0xfa, 0xcd, 0x59, 0x3e, 0x22,
+ 0x32, 0xa1, 0xf7
+};
+
+class Rdata_RRSIG_Test : public RdataTest {
+protected:
+ Rdata_RRSIG_Test() :
+ rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc="),
+ rdata_rrsig(rrsig_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::RRSIG, isc::Exception, isc::Exception>(
+ rdata_str, rdata_rrsig, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::RRSIG, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_rrsig, true, true);
+ }
+
+ void checkFromText_InvalidType(const string& rdata_str) {
+ checkFromText<generic::RRSIG, InvalidRRType, InvalidRRType>(
+ rdata_str, rdata_rrsig, true, true);
+ }
+
+ void checkFromText_InvalidTime(const string& rdata_str) {
+ checkFromText<generic::RRSIG, InvalidTime, InvalidTime>(
+ rdata_str, rdata_rrsig, true, true);
+ }
+
+ void checkFromText_BadValue(const string& rdata_str) {
+ checkFromText<generic::RRSIG, BadValue, BadValue>(
+ rdata_str, rdata_rrsig, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::RRSIG, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_rrsig, true, true);
+ }
+
+ void checkFromText_MissingOrigin(const string& rdata_str) {
+ checkFromText
+ <generic::RRSIG, MissingNameOrigin, MissingNameOrigin>(
+ rdata_str, rdata_rrsig, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::RRSIG, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_rrsig, true, false);
+ }
+
+ const string rrsig_txt;
+ const generic::RRSIG rdata_rrsig;
+};
+
+TEST_F(Rdata_RRSIG_Test, fromText) {
+ EXPECT_EQ(rrsig_txt, rdata_rrsig.toText());
+ EXPECT_EQ(isc::dns::RRType::A(), rdata_rrsig.typeCovered());
+
+ // Missing signature is OK
+ EXPECT_NO_THROW(const generic::RRSIG sig(
+ "A 5 4 43200 20100223214617 20100222214617 8496 isc.org."));
+
+ // Space in signature data is OK
+ checkFromText_None(
+ "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz "
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/ "
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU "
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+
+ // Multi-line signature data is OK, if enclosed in parentheses
+ checkFromText_None(
+ "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+ "( evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz\n"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/\n"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU\n"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc= )");
+
+ // Trailing garbage. This should cause only the string constructor
+ // to fail, but the lexer constructor must be able to continue
+ // parsing from it.
+ checkFromText_BadString(
+ "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc= ; comment\n"
+ "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_missingFields) {
+ checkFromText_LexerError("A");
+ checkFromText_LexerError("A 5");
+ checkFromText_LexerError("A 5 4");
+ checkFromText_LexerError("A 5 4 43200");
+ checkFromText_LexerError("A 5 4 43200 20100223214617");
+ checkFromText_LexerError("A 5 4 43200 20100223214617 20100222214617");
+ checkFromText_LexerError("A 5 4 43200 20100223214617 20100222214617 "
+ "8496");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_coveredType) {
+ checkFromText_InvalidType("SPORK");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_algorithm) {
+ checkFromText_InvalidText(
+ "A 555 4 43200 "
+ "20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+ checkFromText_LexerError(
+ "A FIVE 4 43200 "
+ "20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_labels) {
+ checkFromText_InvalidText(
+ "A 5 4444 43200 "
+ "20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+ checkFromText_LexerError(
+ "A 5 FOUR 43200 "
+ "20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_ttl) {
+ checkFromText_LexerError(
+ "A 5 4 999999999999 "
+ "20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+ checkFromText_LexerError(
+ "A 5 4 TTL "
+ "20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+
+ // alternate form of TTL is not okay
+ checkFromText_LexerError(
+ "A 5 4 12H 20100223214617 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz "
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/ "
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU "
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_expiration) {
+ checkFromText_InvalidTime(
+ "A 5 4 43200 "
+ "201002232 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+ checkFromText_InvalidTime(
+ "A 5 4 43200 "
+ "EXPIRATION 20100222214617 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_inception) {
+ checkFromText_InvalidTime(
+ "A 5 4 43200 "
+ "20100223214617 20100227 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+ checkFromText_InvalidTime(
+ "A 5 4 43200 "
+ "20100223214617 INCEPTION 8496 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_keytag) {
+ checkFromText_InvalidText(
+ "A 5 4 43200 "
+ "20100223214617 20100222214617 999999 isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+ checkFromText_LexerError(
+ "A 5 4 43200 "
+ "20100223214617 20100222214617 TAG isc.org. "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_signer) {
+ checkFromText_MissingOrigin(
+ "A 5 4 43200 "
+ "20100223214617 20100222214617 8496 isc.org "
+ "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, badText_signature) {
+ checkFromText_BadValue(
+ "A 5 4 43200 "
+ "20100223214617 20100222214617 8496 isc.org. "
+ "EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!=");
+
+ // no space between the tag and signer
+ checkFromText_LexerError(
+ "A 5 4 43200 20100223214617 20100222214617 "
+ "8496isc.org. ofc=");
+
+ // unterminated multi-line base64
+ checkFromText_LexerError(
+ "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+ "( evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz\n"
+ "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/\n"
+ "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU\n"
+ "f49t+sXKPzbipN9g+s1ZPiIyofc=");
+}
+
+TEST_F(Rdata_RRSIG_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_rrsig.compare(
+ *test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(),
+ rrsig_txt)));
+
+ // Exceptions cause NULL to be returned.
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(),
+ "INVALIDINPUT"));
+}
+
+TEST_F(Rdata_RRSIG_Test, toWireRenderer) {
+ rdata_rrsig.toWire(renderer);
+
+ matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_RRSIG_Test, toWireBuffer) {
+ rdata_rrsig.toWire(obuffer);
+
+ matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_RRSIG_Test, createFromWire) {
+ const string rrsig_txt2(
+ "A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
+ "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX"
+ "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5"
+ "m36Mo2/Gdxjj8lJ/IjPVkdpKyBpcnYND8KEIma5MyNCNeyO1UkfPQZGHNSQ=");
+ EXPECT_EQ(rrsig_txt2,
+ rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
+ "rdata_rrsig_fromWire1")->toText());
+ const generic::RRSIG rdata_rrsig2(rrsig_txt2);
+ EXPECT_EQ(0, rdata_rrsig2.compare(
+ *rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
+ "rdata_rrsig_fromWire1")));
+
+ // RDLEN is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType::RRSIG(), RRClass::IN(),
+ "rdata_rrsig_fromWire2.wire"),
+ InvalidRdataLength);
+}
+}
diff --git a/src/lib/dns/tests/rdata_soa_unittest.cc b/src/lib/dns/tests/rdata_soa_unittest.cc
new file mode 100644
index 0000000..21f4dc4
--- /dev/null
+++ b/src/lib/dns/tests/rdata_soa_unittest.cc
@@ -0,0 +1,249 @@
+// Copyright (C) 2010-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_SOA_Test : public RdataTest {
+protected:
+ Rdata_SOA_Test() :
+ rdata_soa(Name("ns.example.com"),
+ Name("root.example.com"),
+ 2010012601, 3600, 300, 3600000, 1200)
+ {}
+
+ template <typename ExForString, typename ExForLexer>
+ void checkFromTextSOA(const string& soa_txt, const Name* origin = NULL,
+ bool throw_str_version = true,
+ bool throw_lexer_version = true)
+ {
+ checkFromText<generic::SOA, ExForString, ExForLexer>(
+ soa_txt, rdata_soa, throw_str_version, throw_lexer_version,
+ origin);
+ }
+
+ const generic::SOA rdata_soa;
+};
+
+TEST_F(Rdata_SOA_Test, createFromText) {
+ // Below we specify isc::Exception as a dummy value for the exception type
+ // in case it's not expected to throw an exception; the type isn't used
+ // in the check code.
+
+ // A simple case.
+ checkFromTextSOA<isc::Exception, isc::Exception>(
+ "ns.example.com. root.example.com. 2010012601 3600 300 3600000 1200",
+ NULL, false, false);
+
+ // Beginning and trailing space are ignored.
+ checkFromTextSOA<isc::Exception, isc::Exception>(
+ " ns.example.com. root.example.com. "
+ "2010012601 3600 300 3600000 1200 ", NULL, false, false);
+
+ // using extended TTL-like form for some parameters.
+ checkFromTextSOA<isc::Exception, isc::Exception>(
+ "ns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M",
+ NULL, false, false);
+
+ // multi-line.
+ checkFromTextSOA<isc::Exception, isc::Exception>(
+ "ns.example.com. (root.example.com.\n"
+ "2010012601 1H 5M 1000H) 20M", NULL, false, false);
+
+ // relative names for MNAME and RNAME with a separate origin (lexer
+ // version only)
+ const Name origin("example.com");
+ checkFromTextSOA<MissingNameOrigin, isc::Exception>(
+ "ns root 2010012601 1H 5M 1000H 20M", &origin, true, false);
+
+ // with the '@' notation with a separate origin (lexer version only;
+ // string version would throw)
+ const Name full_mname("ns.example.com");
+ checkFromTextSOA<MissingNameOrigin, isc::Exception>(
+ "@ root.example.com. 2010012601 1H 5M 1000H 20M", &full_mname, true,
+ false);
+
+ // bad MNAME/RNAMEs
+ checkFromTextSOA<EmptyLabel, EmptyLabel>(
+ "bad..example. . 2010012601 1H 5M 1000H 20M");
+ checkFromTextSOA<EmptyLabel, EmptyLabel>(
+ ". bad..example. 2010012601 1H 5M 1000H 20M");
+
+ // Names shouldn't be quoted.
+ checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>(
+ "\".\" . 0 0 0 0 0");
+ checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>(
+ ". \".\" 0 0 0 0 0");
+
+ // Missing MAME or RNAME: for the string version, the serial would be
+ // tried as RNAME and result in "not absolute". For the lexer version,
+ // it reaches the end-of-line, missing min TTL.
+ checkFromTextSOA<MissingNameOrigin, MasterLexer::LexerError>(
+ ". 2010012601 0 0 0 0", &Name::ROOT_NAME());
+
+ // bad serial. the string version converts lexer error to
+ // InvalidRdataText.
+ checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>(
+ ". . bad 0 0 0 0");
+
+ // bad serial; exceeding the uint32_t range (4294967296 = 2^32)
+ checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>(
+ ". . 4294967296 0 0 0 0");
+
+ // Bad format for other numeric parameters. These will be tried as a TTL,
+ // and result in an exception there.
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 bad 0 0 0");
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 4294967296 0 0 0");
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 0 bad 0 0");
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 0 4294967296 0 0");
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 0 0 bad 0");
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 0 0 4294967296 0");
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 0 0 0 bad");
+ checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>(
+ ". . 2010012601 0 0 0 4294967296");
+
+ // No space between RNAME and serial. This case is the same as missing
+ // M/RNAME.
+ checkFromTextSOA<MissingNameOrigin, MasterLexer::LexerError>(
+ ". example.0 0 0 0 0", &Name::ROOT_NAME());
+
+ // Extra parameter. string version immediately detects the error.
+ // lexer version defers the check to the upper layer (we pass origin
+ // to skip the check with the string version).
+ checkFromTextSOA<InvalidRdataText, isc::Exception>(
+ "ns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M "
+ "extra", &origin, true, false);
+
+ // Likewise. Redundant newline is also considered an error. The lexer
+ // version accepts trailing newline, but not the beginning one (where
+ // the lexer expects a string excluding newline and EOF).
+ checkFromTextSOA<InvalidRdataText, isc::Exception>(
+ "ns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M\n",
+ NULL, true, false);
+ checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>(
+ "\nns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M",
+ NULL, true, true);
+}
+
+TEST_F(Rdata_SOA_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_soa.compare(
+ *rdataFactoryFromFile(RRType("SOA"), RRClass("IN"),
+ "rdata_soa_fromWire")));
+ // TBD: more tests
+}
+
+TEST_F(Rdata_SOA_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_soa.compare(
+ *test::createRdataUsingLexer(RRType::SOA(), RRClass::IN(),
+ "ns.example.com. root.example.com. "
+ "2010012601 3600 300 3600000 1200")));
+}
+
+TEST_F(Rdata_SOA_Test, toWireRenderer) {
+ renderer.skip(2);
+ rdata_soa.toWire(renderer);
+
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_soa_fromWire", data);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
+}
+
+TEST_F(Rdata_SOA_Test, toWireBuffer) {
+ obuffer.skip(2);
+ rdata_soa.toWire(obuffer);
+ vector<unsigned char> data;
+ UnitTestUtil::readWireData("rdata_soa_toWireUncompressed.wire", data);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(obuffer.getData()) + 2,
+ obuffer.getLength() - 2);
+}
+
+TEST_F(Rdata_SOA_Test, toText) {
+ EXPECT_EQ("ns.example.com. root.example.com. "
+ "2010012601 3600 300 3600000 1200", rdata_soa.toText());
+}
+
+TEST_F(Rdata_SOA_Test, getSerial) {
+ EXPECT_EQ(2010012601, rdata_soa.getSerial().getValue());
+}
+
+TEST_F(Rdata_SOA_Test, getMinimum) {
+ EXPECT_EQ(1200, rdata_soa.getMinimum());
+
+ // Also check with a very large number (with the MSB being 1).
+ EXPECT_EQ(2154848336u, generic::SOA(Name("ns.example.com"),
+ Name("root.example.com"),
+ 0, 0, 0, 0, 0x80706050).getMinimum());
+}
+
+void
+compareCheck(const generic::SOA& small, const generic::SOA& large) {
+ EXPECT_GT(0, small.compare(large));
+ EXPECT_LT(0, large.compare(small));
+}
+
+TEST_F(Rdata_SOA_Test, compare) {
+ // Check simple equivalence
+ EXPECT_EQ(0, rdata_soa.compare(generic::SOA(
+ "ns.example.com. root.example.com. "
+ "2010012601 3600 300 3600000 1200")));
+ // Check name comparison is case insensitive
+ EXPECT_EQ(0, rdata_soa.compare(generic::SOA(
+ "NS.example.com. root.EXAMPLE.com. "
+ "2010012601 3600 300 3600000 1200")));
+
+ // Check names are compared in the RDATA comparison semantics (different
+ // from DNSSEC ordering for owner names)
+ compareCheck(generic::SOA("a.example. . 0 0 0 0 0"),
+ generic::SOA("example. . 0 0 0 0 0"));
+ compareCheck(generic::SOA(". a.example. 0 0 0 0 0"),
+ generic::SOA(". example. 0 0 0 0 0"));
+
+ // Compare other numeric fields: 1076895760 = 0x40302010,
+ // 270544960 = 0x10203040. These are chosen to make sure that machine
+ // endianness doesn't confuse the comparison results.
+ compareCheck(generic::SOA(". . 270544960 0 0 0 0"),
+ generic::SOA(". . 1076895760 0 0 0 0"));
+ compareCheck(generic::SOA(". . 0 270544960 0 0 0"),
+ generic::SOA(". . 0 1076895760 0 0 0"));
+ compareCheck(generic::SOA(". . 0 0 270544960 0 0"),
+ generic::SOA(". . 0 0 1076895760 0 0"));
+ compareCheck(generic::SOA(". . 0 0 0 270544960 0"),
+ generic::SOA(". . 0 0 0 1076895760 0"));
+ compareCheck(generic::SOA(". . 0 0 0 0 270544960"),
+ generic::SOA(". . 0 0 0 0 1076895760"));
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_srv_unittest.cc b/src/lib/dns/tests/rdata_srv_unittest.cc
new file mode 100644
index 0000000..a3296f2
--- /dev/null
+++ b/src/lib/dns/tests/rdata_srv_unittest.cc
@@ -0,0 +1,205 @@
+// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_SRV_Test : public RdataTest {
+public:
+ Rdata_SRV_Test() :
+ srv_txt("1 5 1500 a.example.com."),
+ srv_txt2("1 5 1400 example.com."),
+ too_long_label("012345678901234567890123456789"
+ "0123456789012345678901234567890123."),
+ rdata_srv(srv_txt),
+ rdata_srv2(srv_txt2)
+ {}
+
+ const string srv_txt;
+ const string srv_txt2;
+ const string too_long_label;
+ const in::SRV rdata_srv;
+ const in::SRV rdata_srv2;
+};
+
+// 1 5 1500 a.example.com.
+const uint8_t wiredata_srv[] = {
+ 0x00, 0x01, 0x00, 0x05, 0x05, 0xdc, 0x01, 0x61, 0x07, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00};
+// 1 5 1400 example.com.
+const uint8_t wiredata_srv2[] = {
+ 0x00, 0x01, 0x00, 0x05, 0x05, 0x78, 0x07, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00};
+
+TEST_F(Rdata_SRV_Test, createFromText) {
+ EXPECT_EQ(1, rdata_srv.getPriority());
+ EXPECT_EQ(5, rdata_srv.getWeight());
+ EXPECT_EQ(1500, rdata_srv.getPort());
+ EXPECT_EQ(Name("a.example.com."), rdata_srv.getTarget());
+}
+
+TEST_F(Rdata_SRV_Test, badText) {
+ // priority is too large (2814...6 is 2^48)
+ EXPECT_THROW(in::SRV("281474976710656 5 1500 a.example.com."),
+ InvalidRdataText);
+ // weight is too large
+ EXPECT_THROW(in::SRV("1 281474976710656 1500 a.example.com."),
+ InvalidRdataText);
+ // port is too large
+ EXPECT_THROW(in::SRV("1 5 281474976710656 a.example.com."),
+ InvalidRdataText);
+ // incomplete text
+ EXPECT_THROW(in::SRV("1 5 a.example.com."),
+ InvalidRdataText);
+ EXPECT_THROW(in::SRV("1 5 1500a.example.com."),
+ InvalidRdataText);
+ // bad name
+ EXPECT_THROW(in::SRV("1 5 1500 a.example.com." + too_long_label),
+ TooLongLabel);
+ // Extra text at end of line
+ EXPECT_THROW(in::SRV("1 5 1500 a.example.com. extra."), InvalidRdataText);
+}
+
+TEST_F(Rdata_SRV_Test, assignment) {
+ in::SRV copy((string(srv_txt2)));
+ copy = rdata_srv;
+ EXPECT_EQ(0, copy.compare(rdata_srv));
+
+ // Check if the copied data is valid even after the original is deleted
+ in::SRV* copy2 = new in::SRV(rdata_srv);
+ in::SRV copy3((string(srv_txt2)));
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_srv));
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(0, copy.compare(rdata_srv));
+}
+
+TEST_F(Rdata_SRV_Test, createFromWire) {
+ EXPECT_EQ(0, rdata_srv.compare(
+ *rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
+ "rdata_srv_fromWire")));
+ // RDLENGTH is too short
+ EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
+ "rdata_srv_fromWire", 23),
+ InvalidRdataLength);
+ // RDLENGTH is too long
+ EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
+ "rdata_srv_fromWire", 46),
+ InvalidRdataLength);
+ // incomplete name. the error should be detected in the name constructor
+ EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
+ "rdata_cname_fromWire", 69),
+ DNSMessageFORMERR);
+ // parse compressed target name
+ EXPECT_EQ(0, rdata_srv.compare(
+ *rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
+ "rdata_srv_fromWire", 89)));
+}
+
+TEST_F(Rdata_SRV_Test, createFromLexer) {
+ EXPECT_EQ(0, rdata_srv.compare(
+ *test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+ "1 5 1500 a.example.com.")));
+
+ // test::createRdataUsingLexer() constructs relative to
+ // "example.org." origin.
+ EXPECT_EQ(0, in::SRV("1 5 1500 server16.example.org.").compare(
+ *test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+ "1 5 1500 server16")));
+
+ // Exceptions cause NULL to be returned.
+
+ // Bad priority
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+ "65536 5 1500 "
+ "a.example.com."));
+ // Bad weight
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+ "1 65536 1500 "
+ "a.example.com."));
+ // Bad port
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+ "1 5 281474976710656 "
+ "a.example.com."));
+ // Extra text at end of line
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+ "1 5 1500 a.example.com. extra."));
+}
+
+TEST_F(Rdata_SRV_Test, toWireBuffer) {
+ rdata_srv.toWire(obuffer);
+ matchWireData(wiredata_srv, sizeof(wiredata_srv),
+ obuffer.getData(), obuffer.getLength());
+
+ obuffer.clear();
+ rdata_srv2.toWire(obuffer);
+ matchWireData(wiredata_srv2, sizeof(wiredata_srv2),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_SRV_Test, toWireRenderer) {
+ rdata_srv.toWire(renderer);
+ matchWireData(wiredata_srv, sizeof(wiredata_srv),
+ renderer.getData(), renderer.getLength());
+
+ renderer.clear();
+ rdata_srv2.toWire(renderer);
+ matchWireData(wiredata_srv2, sizeof(wiredata_srv2),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_SRV_Test, toText) {
+ EXPECT_EQ(srv_txt, rdata_srv.toText());
+ EXPECT_EQ(srv_txt2, rdata_srv2.toText());
+}
+
+TEST_F(Rdata_SRV_Test, compare) {
+ // test RDATAs, sorted in the ascending order.
+ vector<in::SRV> compare_set;
+ compare_set.push_back(in::SRV("1 5 1500 a.example.com."));
+ compare_set.push_back(in::SRV("2 5 1500 a.example.com."));
+ compare_set.push_back(in::SRV("2 6 1500 a.example.com."));
+ compare_set.push_back(in::SRV("2 6 1600 a.example.com."));
+ compare_set.push_back(in::SRV("2 6 1600 example.com."));
+
+ EXPECT_EQ(0, compare_set[0].compare(
+ in::SRV("1 5 1500 a.example.com.")));
+
+ vector<in::SRV>::const_iterator it;
+ vector<in::SRV>::const_iterator it_end = compare_set.end();
+ for (it = compare_set.begin(); it != it_end - 1; ++it) {
+ EXPECT_GT(0, (*it).compare(*(it + 1)));
+ EXPECT_LT(0, (*(it + 1)).compare(*it));
+ }
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_srv.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc
new file mode 100644
index 0000000..2bf88f3
--- /dev/null
+++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc
@@ -0,0 +1,311 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_SSHFP_Test : public RdataTest {
+protected:
+ Rdata_SSHFP_Test() :
+ sshfp_txt("2 1 123456789abcdef67890123456789abcdef67890"),
+ rdata_sshfp(sshfp_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::SSHFP, isc::Exception, isc::Exception>(
+ rdata_str, rdata_sshfp, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::SSHFP, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_sshfp, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::SSHFP, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_sshfp, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::SSHFP, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_sshfp, true, false);
+ }
+
+ const string sshfp_txt;
+ const generic::SSHFP rdata_sshfp;
+};
+
+const uint8_t rdata_sshfp_wiredata[] = {
+ // algorithm
+ 0x02,
+ // fingerprint type
+ 0x01,
+ // fingerprint
+ 0x12, 0x34, 0x56, 0x78,
+ 0x9a, 0xbc, 0xde, 0xf6,
+ 0x78, 0x90, 0x12, 0x34,
+ 0x56, 0x78, 0x9a, 0xbc,
+ 0xde, 0xf6, 0x78, 0x90
+};
+
+TEST_F(Rdata_SSHFP_Test, createFromText) {
+ // Basic test
+ checkFromText_None(sshfp_txt);
+
+ // With different spacing
+ checkFromText_None("2 1 123456789abcdef67890123456789abcdef67890");
+
+ // Combination of lowercase and uppercase
+ checkFromText_None("2 1 123456789ABCDEF67890123456789abcdef67890");
+
+ // spacing in the fingerprint field
+ checkFromText_None("2 1 123456789abcdef67890 123456789abcdef67890");
+
+ // multi-line fingerprint field
+ checkFromText_None("2 1 ( 123456789abcdef67890\n 123456789abcdef67890 )");
+
+ // string constructor throws if there's extra text,
+ // but lexer constructor doesn't
+ checkFromText_BadString(sshfp_txt + "\n" + sshfp_txt);
+}
+
+TEST_F(Rdata_SSHFP_Test, algorithmTypes) {
+ // Some of these may not be RFC conformant, but we relax the check
+ // in our code to work with algorithm and fingerprint types that may
+ // show up in the future.
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 1 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("2 1 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("3 1 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("128 1 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("255 1 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 1 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 2 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 3 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 128 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 255 12ab"));
+
+ // 0 is reserved, but we allow that too
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("0 1 12ab"));
+ EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 0 12ab"));
+
+ // > 255 would be broken
+ EXPECT_THROW(const generic::SSHFP rdata_sshfp("256 1 12ab"),
+ InvalidRdataText);
+ EXPECT_THROW(const generic::SSHFP rdata_sshfp("2 256 12ab"),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_SSHFP_Test, badText) {
+ checkFromText_LexerError("1");
+ checkFromText_LexerError("ONE 2 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("1 TWO 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText("1 2 BUCKLEMYSHOE");
+ checkFromText_InvalidText(sshfp_txt + " extra text");
+
+ // yes, these are redundant to the last test cases in algorithmTypes
+ checkFromText_InvalidText(
+ "2345 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText(
+ "2 1234 123456789abcdef67890123456789abcdef67890");
+
+ // negative values are trapped in the lexer rather than the constructor
+ checkFromText_LexerError("-2 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("2 -1 123456789abcdef67890123456789abcdef67890");
+}
+
+TEST_F(Rdata_SSHFP_Test, copyAndAssign) {
+ // Copy construct
+ generic::SSHFP rdata_sshfp2(rdata_sshfp);
+ EXPECT_EQ(0, rdata_sshfp.compare(rdata_sshfp2));
+
+ // Assignment, mainly to confirm it doesn't cause disruption.
+ rdata_sshfp2 = rdata_sshfp;
+ EXPECT_EQ(0, rdata_sshfp.compare(rdata_sshfp2));
+}
+
+TEST_F(Rdata_SSHFP_Test, createFromWire) {
+ // Basic test
+ EXPECT_EQ(0, rdata_sshfp.compare(
+ *rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire")));
+ // Combination of lowercase and uppercase
+ EXPECT_EQ(0, rdata_sshfp.compare(
+ *rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire2")));
+ // algorithm=1, fingerprint=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire3.wire"));
+
+ // algorithm=255, fingerprint=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire4.wire"));
+
+ // algorithm=0, fingerprint=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire5.wire"));
+
+ // algorithm=5, fingerprint=0
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire6.wire"));
+
+ // algorithm=255, fingerprint=255
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire7.wire"));
+
+ // short fingerprint data
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire8.wire"));
+
+ // fingerprint is shorter than rdata len
+ EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire9"),
+ InvalidBufferPosition);
+
+ // fingerprint is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire10"),
+ InvalidBufferPosition);
+
+ // all rdata is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire11"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_SSHFP_Test, createFromParams) {
+ const generic::SSHFP rdata_sshfp2(
+ 2, 1, "123456789abcdef67890123456789abcdef67890");
+ EXPECT_EQ(0, rdata_sshfp2.compare(rdata_sshfp));
+}
+
+TEST_F(Rdata_SSHFP_Test, toText) {
+ EXPECT_TRUE(boost::iequals(sshfp_txt, rdata_sshfp.toText()));
+
+ const string sshfp_txt2("2 1");
+ const generic::SSHFP rdata_sshfp2(sshfp_txt2);
+ EXPECT_TRUE(boost::iequals(sshfp_txt2, rdata_sshfp2.toText()));
+
+ const generic::SSHFP rdata_sshfp3("2 1 ");
+ EXPECT_TRUE(boost::iequals(sshfp_txt2, rdata_sshfp3.toText()));
+}
+
+TEST_F(Rdata_SSHFP_Test, toWire) {
+ this->obuffer.clear();
+ rdata_sshfp.toWire(this->obuffer);
+
+ EXPECT_EQ(sizeof (rdata_sshfp_wiredata),
+ this->obuffer.getLength());
+
+ matchWireData(rdata_sshfp_wiredata, sizeof(rdata_sshfp_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_SSHFP_Test, compare) {
+ const generic::SSHFP rdata_sshfp2("2 1");
+ EXPECT_EQ(-1, rdata_sshfp2.compare(rdata_sshfp));
+ EXPECT_EQ(1, rdata_sshfp.compare(rdata_sshfp2));
+}
+
+TEST_F(Rdata_SSHFP_Test, getAlgorithmNumber) {
+ EXPECT_EQ(2, rdata_sshfp.getAlgorithmNumber());
+}
+
+TEST_F(Rdata_SSHFP_Test, getFingerprintType) {
+ EXPECT_EQ(1, rdata_sshfp.getFingerprintType());
+}
+
+TEST_F(Rdata_SSHFP_Test, getFingerprint) {
+ const std::vector<uint8_t>& fingerprint =
+ rdata_sshfp.getFingerprint();
+
+ EXPECT_EQ(rdata_sshfp.getFingerprintLength(),
+ fingerprint.size());
+ for (size_t i = 0; i < fingerprint.size(); ++i) {
+ EXPECT_EQ(rdata_sshfp_wiredata[i + 2],
+ fingerprint.at(i));
+ }
+}
+
+TEST_F(Rdata_SSHFP_Test, getFingerprintLength) {
+ EXPECT_EQ(20, rdata_sshfp.getFingerprintLength());
+}
+
+TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) {
+ const uint8_t rdf_wiredata[] = {
+ // algorithm
+ 0x04,
+ // fingerprint type
+ 0x09
+ };
+
+ const generic::SSHFP rdf =
+ dynamic_cast<const generic::SSHFP&>
+ (*rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+ "rdata_sshfp_fromWire12"));
+
+ EXPECT_EQ(4, rdf.getAlgorithmNumber());
+ EXPECT_EQ(9, rdf.getFingerprintType());
+ EXPECT_EQ(0, rdf.getFingerprintLength());
+
+ this->obuffer.clear();
+ rdf.toWire(this->obuffer);
+
+ EXPECT_EQ(2, this->obuffer.getLength());
+
+ matchWireData(rdf_wiredata, sizeof(rdf_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromString) {
+ const generic::SSHFP rdata_sshfp2("5 6");
+ const uint8_t rdata_sshfp2_wiredata[] = {
+ // algorithm
+ 0x05,
+ // fingerprint type
+ 0x06
+ };
+
+ EXPECT_EQ(5, rdata_sshfp2.getAlgorithmNumber());
+ EXPECT_EQ(6, rdata_sshfp2.getFingerprintType());
+ EXPECT_EQ(0, rdata_sshfp2.getFingerprintLength());
+
+ this->obuffer.clear();
+ rdata_sshfp2.toWire(this->obuffer);
+
+ EXPECT_EQ(2, this->obuffer.getLength());
+
+ matchWireData(rdata_sshfp2_wiredata, sizeof(rdata_sshfp2_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+}
diff --git a/src/lib/dns/tests/rdata_tkey_unittest.cc b/src/lib/dns/tests/rdata_tkey_unittest.cc
new file mode 100644
index 0000000..8592a27
--- /dev/null
+++ b/src/lib/dns/tests/rdata_tkey_unittest.cc
@@ -0,0 +1,450 @@
+// Copyright (C) 2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/time_utilities.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/tsigerror.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+
+class Rdata_TKEY_Test : public RdataTest {
+protected:
+ Rdata_TKEY_Test() :
+ // no Key or Other Data
+ valid_text1("gss-tsig. 20210501120000 20210501130000 GSS-API NOERROR 0 0"),
+ // Key but no Other Data
+ valid_text2("GSS-TSIG. 20210501120000 20210501130000 GSS-API BADSIG "
+ "12 FAKEFAKEFAKEFAKE 0"),
+ // Key and Other Data
+ valid_text3("gss.tsig. 20210501120000 20210501130000 GSS-API BADSIG "
+ "12 FAKEFAKEFAKEFAKE 6 FAKEFAKE"),
+ // Key and Other Data (with Error that doesn't expect Other Data)
+ valid_text4("gss.tsig. 20210501120000 20210501130000 3 BADSIG 12 "
+ "FAKEFAKEFAKEFAKE 6 FAKEFAKE"),
+ // numeric error code
+ valid_text5("GSS-TSIG. 20210501120000 20210501130000 GSS-API 2845 12 "
+ "FAKEFAKEFAKEFAKE 0"),
+ // GSS-API mode
+ valid_text6("gss-tsig. 20210501120000 20210501130000 GSS-API 0 12 "
+ "FAKEFAKEFAKEFAKE 0"),
+ rdata_tkey(valid_text1)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::TKEY, isc::Exception, isc::Exception>(
+ rdata_str, rdata_tkey, false, false);
+ }
+
+ void checkFromText_InvalidTime(const string& rdata_str) {
+ checkFromText<generic::TKEY, InvalidTime, InvalidTime>(
+ rdata_str, rdata_tkey, true, true);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::TKEY, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_tkey, true, true);
+ }
+
+ void checkFromText_BadValue(const string& rdata_str) {
+ checkFromText<generic::TKEY, BadValue, BadValue>(
+ rdata_str, rdata_tkey, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::TKEY, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_tkey, true, true);
+ }
+
+ void checkFromText_TooLongLabel(const string& rdata_str) {
+ checkFromText<generic::TKEY, TooLongLabel, TooLongLabel>(
+ rdata_str, rdata_tkey, true, true);
+ }
+
+ void checkFromText_EmptyLabel(const string& rdata_str) {
+ checkFromText<generic::TKEY, EmptyLabel, EmptyLabel>(
+ rdata_str, rdata_tkey, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::TKEY, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_tkey, true, false);
+ }
+
+ template <typename Output>
+ void toWireCommonChecks(Output& output) const;
+
+ const string valid_text1;
+ const string valid_text2;
+ const string valid_text3;
+ const string valid_text4;
+ const string valid_text5;
+ const string valid_text6;
+ vector<uint8_t> expect_data;
+ const generic::TKEY rdata_tkey; // commonly used test RDATA
+};
+
+TEST_F(Rdata_TKEY_Test, fromText) {
+ // normal case. it also tests getter methods.
+ EXPECT_EQ(Name("gss-tsig"), rdata_tkey.getAlgorithm());
+ EXPECT_EQ(1619870400, rdata_tkey.getInception());
+ EXPECT_EQ("20210501120000", rdata_tkey.getInceptionDate());
+ EXPECT_EQ(1619874000, rdata_tkey.getExpire());
+ EXPECT_EQ("20210501130000", rdata_tkey.getExpireDate());
+ EXPECT_EQ(3, rdata_tkey.getMode());
+ EXPECT_EQ(0, rdata_tkey.getError());
+ EXPECT_EQ(0, rdata_tkey.getKeyLen());
+ EXPECT_EQ(static_cast<void*>(0), rdata_tkey.getKey());
+ EXPECT_EQ(0, rdata_tkey.getOtherLen());
+ EXPECT_EQ(static_cast<void*>(0), rdata_tkey.getOtherData());
+
+ generic::TKEY tkey2(valid_text2);
+ EXPECT_EQ(12, tkey2.getKeyLen());
+ EXPECT_EQ(TSIGError::BAD_SIG_CODE, tkey2.getError());
+
+ generic::TKEY tkey3(valid_text3);
+ EXPECT_EQ(6, tkey3.getOtherLen());
+
+ // The other data is unusual, but we don't reject it.
+ EXPECT_NO_THROW(generic::TKEY tkey4(valid_text4));
+
+ // numeric representation of TKEY error
+ generic::TKEY tkey5(valid_text5);
+ EXPECT_EQ(2845, tkey5.getError());
+
+ // symbolic representation of TKEY mode
+ generic::TKEY tkey6(valid_text6);
+ EXPECT_EQ(generic::TKEY::GSS_API_MODE, tkey6.getMode());
+
+ // not fully qualified algorithm name
+ generic::TKEY tkey1("gss-tsig 20210501120000 20210501130000 3 0 0 0");
+ EXPECT_EQ(0, tkey1.compare(rdata_tkey));
+
+ // multi-line rdata
+ checkFromText_None("gss-tsig. ( 20210501120000 20210501130000 GSS-API \n"
+ "NOERROR 0 0 )");
+};
+
+TEST_F(Rdata_TKEY_Test, badText) {
+ // too many fields
+ checkFromText_BadString(valid_text1 + " 0 0");
+ // not enough fields
+ checkFromText_LexerError("foo 20210501120000 20210501130000 0 BADKEY");
+ // bad domain name
+ checkFromText_TooLongLabel(
+ "0123456789012345678901234567890123456789012345678901234567890123"
+ " 20210501120000 20210501130000 0 0 0 0");
+ checkFromText_EmptyLabel("foo..bar 20210501120000 20210501130000 0 0 0 0");
+ // invalid inception (no digit)
+ checkFromText_InvalidTime("foo TIME 20210501130000 0 0 0 0");
+ // invalid inception (bad format)
+ checkFromText_InvalidTime("foo 0 20210501130000 0 0 0 0");
+ // invalid expire (no digit)
+ checkFromText_InvalidTime("foo 20210501120000 TIME 0 0 0 0");
+ // invalid expire (bad format)
+ checkFromText_InvalidTime("foo 20210501120000 0 0 0 0 0");
+ // Unknown mode
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 TEST 0 0 0");
+ // Numeric mode is is too large
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 65536 0 0 0");
+ // Numeric mode is negative
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 -1 0 0 0 0");
+ // Unknown error code
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 0 TEST 0 0");
+ // Numeric error code is too large
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 0 65536 0 0");
+ // Numeric error code is negative
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 0 -1 0 0");
+ // Key len is too large
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 65536 0");
+ // invalid Key len (negative)
+ checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 -1 0");
+ // invalid Key len (not a number)
+ checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 MACSIZE 0");
+ // Key len and Key mismatch
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 9 FAKE 0");
+ // Key is bad base64
+ checkFromText_BadValue("foo 20210501120000 20210501130000 0 0 3 FAK= 0");
+ // Other len is too large
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 0 65536 FAKE");
+ // Other len is negative
+ checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 0 -1 FAKE");
+ // invalid Other len
+ checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 0 LEN FAKE");
+ // Other len and data mismatch
+ checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 0 9 FAKE");
+}
+
+void
+fromWireCommonChecks(const generic::TKEY& tkey) {
+ EXPECT_EQ(Name("gss-tsig"), tkey.getAlgorithm());
+ EXPECT_EQ(1619870400, tkey.getInception());
+ EXPECT_EQ("20210501120000", tkey.getInceptionDate());
+ EXPECT_EQ(1619874000, tkey.getExpire());
+ EXPECT_EQ("20210501130000", tkey.getExpireDate());
+ EXPECT_EQ(3, tkey.getMode());
+ EXPECT_EQ(0, tkey.getError());
+
+ vector<uint8_t> expect_key(32, 'x');
+ matchWireData(&expect_key[0], expect_key.size(),
+ tkey.getKey(), tkey.getKeyLen());
+
+ EXPECT_EQ(0, tkey.getOtherLen());
+ EXPECT_EQ(static_cast<const void*>(0), tkey.getOtherData());
+}
+
+TEST_F(Rdata_TKEY_Test, createFromWire) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire1.wire"));
+ fromWireCommonChecks(dynamic_cast<generic::TKEY&>(*rdata));
+}
+
+TEST_F(Rdata_TKEY_Test, createFromWireWithOtherData) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire2.wire"));
+ const generic::TKEY& tkey(dynamic_cast<generic::TKEY&>(*rdata));
+
+ vector<uint8_t> expect_key(32, 'x');
+ matchWireData(&expect_key[0], expect_key.size(),
+ tkey.getKey(), tkey.getKeyLen());
+
+ vector<uint8_t> expect_data = { 'a', 'b', 'c', 'd', '0', '1', '2', '3' };
+ matchWireData(&expect_data[0], expect_data.size(),
+ tkey.getOtherData(), tkey.getOtherLen());
+}
+
+TEST_F(Rdata_TKEY_Test, createFromWireWithoutKey) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire3.wire"));
+ const generic::TKEY& tkey(dynamic_cast<generic::TKEY&>(*rdata));
+ EXPECT_EQ(0, tkey.getKeyLen());
+ EXPECT_EQ(static_cast<const void*>(0), tkey.getKey());
+
+ vector<uint8_t> expect_data = { 'a', 'b', 'c', 'd', '0', '1', '2', '3' };
+ matchWireData(&expect_data[0], expect_data.size(),
+ tkey.getOtherData(), tkey.getOtherLen());
+}
+
+TEST_F(Rdata_TKEY_Test, createFromWireWithCompression) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire4.wire",
+ // we need to skip the dummy name:
+ Name("gss-tsig").getLength()));
+ fromWireCommonChecks(dynamic_cast<generic::TKEY&>(*rdata));
+}
+
+TEST_F(Rdata_TKEY_Test, badFromWire) {
+ // RDLENGTH is too short:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire5.wire"),
+ InvalidRdataLength);
+ // RDLENGTH is too long:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire6.wire"),
+ InvalidRdataLength);
+ // Algorithm name is broken:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire7.wire"),
+ DNSMessageFORMERR);
+ // Key length is bogus:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire8.wire"),
+ InvalidBufferPosition);
+ // Other-data length is bogus:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(),
+ "rdata_tkey_fromWire9.wire"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_TKEY_Test, copyConstruct) {
+ const generic::TKEY copy(rdata_tkey);
+ EXPECT_EQ(0, copy.compare(rdata_tkey));
+
+ // Check the copied data is valid even after the original is deleted
+ generic::TKEY* copy2 = new generic::TKEY(rdata_tkey);
+ generic::TKEY copy3(*copy2);
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_tkey));
+}
+
+TEST_F(Rdata_TKEY_Test, createFromParams) {
+ EXPECT_EQ(0, rdata_tkey.compare(generic::TKEY(Name("gss-tsig"),
+ 1619870400,
+ 1619874000,
+ 3, 0, 0, 0, 0, 0)));
+
+ const uint8_t fake_data[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84,
+ 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 };
+ EXPECT_EQ(0, generic::TKEY(valid_text2).compare(
+ generic::TKEY(Name("GSS-TSIG"), 1619870400, 1619874000,
+ 3, 16, 12, fake_data, 0, 0)));
+
+ const uint8_t fake_data2[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 };
+ EXPECT_EQ(0, generic::TKEY(valid_text3).compare(
+ generic::TKEY(Name("gss.tsig"), 1619870400, 1619874000,
+ 3, 16, 12, fake_data, 6, fake_data2)));
+
+ EXPECT_THROW(generic::TKEY(Name("gss-tsig"), 0, 0, 0, 0, 0, fake_data, 0, 0),
+ isc::InvalidParameter);
+ EXPECT_THROW(generic::TKEY(Name("gss-tsig"), 0, 0, 0, 0, 12, 0, 0, 0),
+ isc::InvalidParameter);
+ EXPECT_THROW(generic::TKEY(Name("gss-tsig"), 0, 0, 0, 0, 0, 0, 0, fake_data),
+ isc::InvalidParameter);
+ EXPECT_THROW(generic::TKEY(Name("fake_data"), 0, 0, 0, 0, 0, 0, 6, 0),
+ isc::InvalidParameter);
+}
+
+TEST_F(Rdata_TKEY_Test, assignment) {
+ generic::TKEY copy(valid_text2);
+ copy = rdata_tkey;
+ EXPECT_EQ(0, copy.compare(rdata_tkey));
+
+ // Check if the copied data is valid even after the original is deleted
+ generic::TKEY* copy2 = new generic::TKEY(rdata_tkey);
+ generic::TKEY copy3(valid_text2);
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_tkey));
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(0, copy.compare(rdata_tkey));
+}
+
+template <typename Output>
+void
+Rdata_TKEY_Test::toWireCommonChecks(Output& output) const {
+ vector<uint8_t> expect_data;
+
+ output.clear();
+ expect_data.clear();
+ rdata_tkey.toWire(output);
+ // read the expected wire format data and trim the RDLEN part.
+ UnitTestUtil::readWireData("rdata_tkey_toWire1.wire", expect_data);
+ expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
+
+ expect_data.clear();
+ output.clear();
+ generic::TKEY(valid_text2).toWire(output);
+ UnitTestUtil::readWireData("rdata_tkey_toWire2.wire", expect_data);
+ expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
+
+ expect_data.clear();
+ output.clear();
+ generic::TKEY(valid_text3).toWire(output);
+ UnitTestUtil::readWireData("rdata_tkey_toWire3.wire", expect_data);
+ expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
+}
+
+TEST_F(Rdata_TKEY_Test, toWireBuffer) {
+ toWireCommonChecks<OutputBuffer>(obuffer);
+}
+
+TEST_F(Rdata_TKEY_Test, toWireRenderer) {
+ toWireCommonChecks<MessageRenderer>(renderer);
+
+ // check algorithm name won't compressed when it would otherwise.
+ expect_data.clear();
+ renderer.clear();
+ renderer.writeName(Name("gss-tsig"));
+ renderer.writeUint16(26); // RDLEN
+ rdata_tkey.toWire(renderer);
+ UnitTestUtil::readWireData("rdata_tkey_toWire4.wire", expect_data);
+ matchWireData(&expect_data[0], expect_data.size(),
+ renderer.getData(), renderer.getLength());
+
+ // check algorithm can be used as a compression target.
+ expect_data.clear();
+ renderer.clear();
+ renderer.writeUint16(26);
+ rdata_tkey.toWire(renderer);
+ renderer.writeName(Name("gss-tsig"));
+ UnitTestUtil::readWireData("rdata_tkey_toWire5.wire", expect_data);
+ matchWireData(&expect_data[0], expect_data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_TKEY_Test, toText) {
+ EXPECT_EQ(valid_text1, rdata_tkey.toText());
+ EXPECT_EQ(valid_text2, generic::TKEY(valid_text2).toText());
+ EXPECT_EQ(valid_text3, generic::TKEY(valid_text3).toText());
+ EXPECT_EQ(valid_text5, generic::TKEY(valid_text5).toText());
+}
+
+TEST_F(Rdata_TKEY_Test, compare) {
+ // test RDATAs, sorted in the ascending order.
+ // "AAAA" encoded in BASE64 corresponds to 0x000000, so it should be the
+ // smallest data of the same length.
+ vector<generic::TKEY> compare_set;
+ compare_set.push_back(generic::TKEY("a.example 20210501120000 "
+ "20210501130000 3 0 0 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120000 "
+ "20210501130000 3 0 0 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130000 3 0 0 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130001 3 0 0 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130001 4 0 0 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130001 4 1 0 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130001 4 1 3 AAAA 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130001 4 1 3 FAKE 0"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130001 4 1 3 FAKE 3 AAAA"));
+ compare_set.push_back(generic::TKEY("example 20210501120001 "
+ "20210501130001 4 1 3 FAKE 3 FAKE"));
+
+ EXPECT_EQ(0,
+ compare_set[0].compare(generic::TKEY("A.EXAMPLE 20210501120000 "
+ "20210501130000 3 0 0 0")));
+
+ vector<generic::TKEY>::const_iterator it;
+ vector<generic::TKEY>::const_iterator it_end = compare_set.end();
+ for (it = compare_set.begin(); it != it_end - 1; ++it) {
+ EXPECT_GT(0, (*it).compare(*(it + 1)));
+ EXPECT_LT(0, (*(it + 1)).compare(*it));
+ }
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_tkey.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_tlsa_unittest.cc b/src/lib/dns/tests/rdata_tlsa_unittest.cc
new file mode 100644
index 0000000..92970cb
--- /dev/null
+++ b/src/lib/dns/tests/rdata_tlsa_unittest.cc
@@ -0,0 +1,276 @@
+// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_TLSA_Test : public RdataTest {
+protected:
+ Rdata_TLSA_Test() :
+ tlsa_txt("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971"),
+ rdata_tlsa(tlsa_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::TLSA, isc::Exception, isc::Exception>(
+ rdata_str, rdata_tlsa, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::TLSA, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_tlsa, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::TLSA, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_tlsa, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::TLSA, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_tlsa, true, false);
+ }
+
+ const string tlsa_txt;
+ const generic::TLSA rdata_tlsa;
+};
+
+const uint8_t rdata_tlsa_wiredata[] = {
+ // certificate usage
+ 0x00,
+ // selector
+ 0x00,
+ // matching type
+ 0x01,
+ // certificate association data
+ 0xd2, 0xab, 0xde, 0x24, 0x0d, 0x7c, 0xd3, 0xee,
+ 0x6b, 0x4b, 0x28, 0xc5, 0x4d, 0xf0, 0x34, 0xb9,
+ 0x79, 0x83, 0xa1, 0xd1, 0x6e, 0x8a, 0x41, 0x0e,
+ 0x45, 0x61, 0xcb, 0x10, 0x66, 0x18, 0xe9, 0x71
+};
+
+TEST_F(Rdata_TLSA_Test, createFromText) {
+ // Basic test
+ checkFromText_None(tlsa_txt);
+
+ // With different spacing
+ checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+
+ // Combination of lowercase and uppercase
+ checkFromText_None("0 0 1 D2ABDE240D7CD3EE6B4B28C54DF034B9"
+ "7983a1d16e8a410e4561cb106618e971");
+
+ // spacing in the certificate association data field
+ checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ " 7983a1d16e8a410e4561cb106618e971");
+
+ // multi-line certificate association data field
+ checkFromText_None("0 0 1 ( d2abde240d7cd3ee6b4b28c54df034b9\n"
+ " 7983a1d16e8a410e4561cb106618e971 )");
+
+ // string constructor throws if there's extra text,
+ // but lexer constructor doesn't
+ checkFromText_BadString(tlsa_txt + "\n" + tlsa_txt);
+}
+
+TEST_F(Rdata_TLSA_Test, fields) {
+ // Some of these may not be RFC conformant, but we relax the check
+ // in our code to work with other field values that may show up in
+ // the future.
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("1 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("2 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("3 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("128 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("255 0 1 12ab"));
+
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 1 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 2 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 3 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 128 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 255 1 12ab"));
+
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 2 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 3 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 128 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 255 12ab"));
+
+ // > 255 would be broken
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("256 0 1 12ab"),
+ InvalidRdataText);
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("0 256 1 12ab"),
+ InvalidRdataText);
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("0 0 256 12ab"),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_TLSA_Test, badText) {
+ checkFromText_LexerError("1");
+ checkFromText_LexerError("ONE 2 3 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("1 TWO 3 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("1 2 THREE 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText("1 2 3 BAABAABLACKSHEEP");
+ checkFromText_InvalidText(tlsa_txt + " extra text");
+
+ // yes, these are redundant to the last test cases in the .fields
+ // test
+ checkFromText_InvalidText(
+ "2345 1 2 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText(
+ "3 1234 4 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText(
+ "5 6 1234 123456789abcdef67890123456789abcdef67890");
+
+ // negative values are trapped in the lexer rather than the
+ // constructor
+ checkFromText_LexerError("-2 0 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("0 -2 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("0 0 -2 123456789abcdef67890123456789abcdef67890");
+}
+
+TEST_F(Rdata_TLSA_Test, copyAndAssign) {
+ // Copy construct
+ generic::TLSA rdata_tlsa2(rdata_tlsa);
+ EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2));
+
+ // Assignment, mainly to confirm it doesn't cause disruption.
+ rdata_tlsa2 = rdata_tlsa;
+ EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2));
+}
+
+TEST_F(Rdata_TLSA_Test, createFromWire) {
+ // Basic test
+ EXPECT_EQ(0, rdata_tlsa.compare(
+ *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire")));
+ // Combination of lowercase and uppercase
+ EXPECT_EQ(0, rdata_tlsa.compare(
+ *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire2")));
+ // certificate_usage=0, selector=0, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire3.wire"));
+
+ // certificate_usage=255, selector=0, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire4.wire"));
+
+ // certificate_usage=0, selector=255, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire5.wire"));
+
+ // certificate_usage=0, selector=0, matching_type=255
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire6.wire"));
+
+ // certificate_usage=3, selector=1, matching_type=2
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire7.wire"));
+
+ // short certificate association data
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire8.wire"));
+
+ // certificate association data is shorter than rdata len
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire9"),
+ InvalidBufferPosition);
+
+ // certificate association data is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire10"),
+ InvalidBufferPosition);
+
+ // certificate association data is empty
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire12"),
+ InvalidRdataLength);
+
+ // all RDATA is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire11"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_TLSA_Test, createFromParams) {
+ const generic::TLSA rdata_tlsa2(
+ 0, 0, 1, "d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+ EXPECT_EQ(0, rdata_tlsa2.compare(rdata_tlsa));
+
+ // empty certificate association data should throw
+ EXPECT_THROW(const generic::TLSA rdata_tlsa2(0, 0, 1, ""),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_TLSA_Test, toText) {
+ EXPECT_TRUE(boost::iequals(tlsa_txt, rdata_tlsa.toText()));
+}
+
+TEST_F(Rdata_TLSA_Test, toWire) {
+ this->obuffer.clear();
+ rdata_tlsa.toWire(this->obuffer);
+
+ EXPECT_EQ(sizeof (rdata_tlsa_wiredata),
+ this->obuffer.getLength());
+
+ matchWireData(rdata_tlsa_wiredata, sizeof(rdata_tlsa_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_TLSA_Test, compare) {
+ const generic::TLSA rdata_tlsa2("0 0 0 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+ EXPECT_EQ(-1, rdata_tlsa2.compare(rdata_tlsa));
+ EXPECT_EQ(1, rdata_tlsa.compare(rdata_tlsa2));
+}
+
+TEST_F(Rdata_TLSA_Test, getCertificateUsage) {
+ EXPECT_EQ(0, rdata_tlsa.getCertificateUsage());
+}
+
+TEST_F(Rdata_TLSA_Test, getSelector) {
+ EXPECT_EQ(0, rdata_tlsa.getSelector());
+}
+
+TEST_F(Rdata_TLSA_Test, getMatchingType) {
+ EXPECT_EQ(1, rdata_tlsa.getMatchingType());
+}
+
+TEST_F(Rdata_TLSA_Test, getDataLength) {
+ EXPECT_EQ(32, rdata_tlsa.getDataLength());
+}
+}
diff --git a/src/lib/dns/tests/rdata_tsig_unittest.cc b/src/lib/dns/tests/rdata_tsig_unittest.cc
new file mode 100644
index 0000000..9d3bd89
--- /dev/null
+++ b/src/lib/dns/tests/rdata_tsig_unittest.cc
@@ -0,0 +1,423 @@
+// Copyright (C) 2010-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/tsigerror.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using namespace isc::dns::rdata::any;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+
+class Rdata_TSIG_Test : public RdataTest {
+protected:
+ Rdata_TSIG_Test() :
+ // no MAC or Other Data
+ valid_text1("hmac-md5.sig-alg.reg.int. 1286779327 300 "
+ "0 16020 BADKEY 0"),
+ // MAC but no Other Data
+ valid_text2("hmac-sha256. 1286779327 300 12 "
+ "FAKEFAKEFAKEFAKE 16020 BADSIG 0"),
+ // MAC and Other Data
+ valid_text3("hmac-sha1. 1286779327 300 12 "
+ "FAKEFAKEFAKEFAKE 16020 BADTIME 6 FAKEFAKE"),
+ // MAC and Other Data (with Error that doesn't expect Other Data)
+ valid_text4("hmac-sha1. 1286779327 300 12 "
+ "FAKEFAKEFAKEFAKE 16020 BADSIG 6 FAKEFAKE"),
+ // numeric error code
+ valid_text5("hmac-sha256. 1286779327 300 12 "
+ "FAKEFAKEFAKEFAKE 16020 2845 0"),
+ rdata_tsig(valid_text1)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<TSIG, isc::Exception, isc::Exception>(
+ rdata_str, rdata_tsig, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<TSIG, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_tsig, true, true);
+ }
+
+ void checkFromText_BadValue(const string& rdata_str) {
+ checkFromText<TSIG, BadValue, BadValue>(
+ rdata_str, rdata_tsig, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <TSIG, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_tsig, true, true);
+ }
+
+ void checkFromText_TooLongLabel(const string& rdata_str) {
+ checkFromText<TSIG, TooLongLabel, TooLongLabel>(
+ rdata_str, rdata_tsig, true, true);
+ }
+
+ void checkFromText_EmptyLabel(const string& rdata_str) {
+ checkFromText<TSIG, EmptyLabel, EmptyLabel>(
+ rdata_str, rdata_tsig, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <TSIG, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_tsig, true, false);
+ }
+
+ template <typename Output>
+ void toWireCommonChecks(Output& output) const;
+
+ const string valid_text1;
+ const string valid_text2;
+ const string valid_text3;
+ const string valid_text4;
+ const string valid_text5;
+ vector<uint8_t> expect_data;
+ const TSIG rdata_tsig; // commonly used test RDATA
+};
+
+TEST_F(Rdata_TSIG_Test, fromText) {
+ // normal case. it also tests getter methods.
+ EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), rdata_tsig.getAlgorithm());
+ EXPECT_EQ(1286779327, rdata_tsig.getTimeSigned());
+ EXPECT_EQ(300, rdata_tsig.getFudge());
+ EXPECT_EQ(0, rdata_tsig.getMACSize());
+ EXPECT_EQ(static_cast<void*>(NULL), rdata_tsig.getMAC());
+ EXPECT_EQ(16020, rdata_tsig.getOriginalID());
+ EXPECT_EQ(TSIGError::BAD_KEY_CODE, rdata_tsig.getError());
+ EXPECT_EQ(0, rdata_tsig.getOtherLen());
+ EXPECT_EQ(static_cast<void*>(NULL), rdata_tsig.getOtherData());
+
+ TSIG tsig2(valid_text2);
+ EXPECT_EQ(12, tsig2.getMACSize());
+ EXPECT_EQ(TSIGError::BAD_SIG_CODE, tsig2.getError());
+
+ TSIG tsig3(valid_text3);
+ EXPECT_EQ(6, tsig3.getOtherLen());
+
+ // The other data is unusual, but we don't reject it.
+ EXPECT_NO_THROW(TSIG tsig4(valid_text4));
+
+ // numeric representation of TSIG error
+ TSIG tsig5(valid_text5);
+ EXPECT_EQ(2845, tsig5.getError());
+
+ // not fully qualified algorithm name
+ TSIG tsig1("hmac-md5.sig-alg.reg.int 1286779327 300 0 16020 BADKEY 0");
+ EXPECT_EQ(0, tsig1.compare(rdata_tsig));
+
+ // multi-line rdata
+ checkFromText_None("hmac-md5.sig-alg.reg.int. ( 1286779327 300 \n"
+ "0 16020 BADKEY 0 )");
+
+ // short-form HMAC-MD5 name
+ const TSIG tsig6("hmac-md5. 1286779327 300 0 16020 BADKEY 0");
+ EXPECT_EQ(0, tsig6.compare(rdata_tsig));
+};
+
+TEST_F(Rdata_TSIG_Test, badText) {
+ // too many fields
+ checkFromText_BadString(valid_text1 + " 0 0");
+ // not enough fields
+ checkFromText_LexerError("foo 0 0 0 0 BADKEY");
+ // bad domain name
+ checkFromText_TooLongLabel(
+ "0123456789012345678901234567890123456789012345678901234567890123"
+ " 0 0 0 0 BADKEY 0");
+ checkFromText_EmptyLabel("foo..bar 0 0 0 0 BADKEY");
+ // time is too large (2814...6 is 2^48)
+ checkFromText_InvalidText("foo 281474976710656 0 0 0 BADKEY 0");
+ // invalid time (negative)
+ checkFromText_InvalidText("foo -1 0 0 0 BADKEY 0");
+ // invalid time (not a number)
+ checkFromText_InvalidText("foo TIME 0 0 0 BADKEY 0");
+ // fudge is too large
+ checkFromText_InvalidText("foo 0 65536 0 0 BADKEY 0");
+ // invalid fudge (negative)
+ checkFromText_LexerError("foo 0 -1 0 0 BADKEY 0");
+ // invalid fudge (not a number)
+ checkFromText_LexerError("foo 0 FUDGE 0 0 BADKEY 0");
+ // MAC size is too large
+ checkFromText_InvalidText("foo 0 0 65536 0 BADKEY 0");
+ // invalid MAC size (negative)
+ checkFromText_LexerError("foo 0 0 -1 0 BADKEY 0");
+ // invalid MAC size (not a number)
+ checkFromText_LexerError("foo 0 0 MACSIZE 0 BADKEY 0");
+ // MAC size and MAC mismatch
+ checkFromText_InvalidText("foo 0 0 9 FAKE 0 BADKEY 0");
+ // MAC is bad base64
+ checkFromText_BadValue("foo 0 0 3 FAK= 0 BADKEY 0");
+ // Unknown error code
+ checkFromText_InvalidText("foo 0 0 0 0 TEST 0");
+ // Numeric error code is too large
+ checkFromText_InvalidText("foo 0 0 0 0 65536 0");
+ // Numeric error code is negative
+ checkFromText_InvalidText("foo 0 0 0 0 -1 0");
+ // Other len is too large
+ checkFromText_InvalidText("foo 0 0 0 0 NOERROR 65536 FAKE");
+ // Other len is negative
+ checkFromText_LexerError("foo 0 0 0 0 NOERROR -1 FAKE");
+ // invalid Other len
+ checkFromText_LexerError("foo 0 0 0 0 NOERROR LEN FAKE");
+ // Other len and data mismatch
+ checkFromText_InvalidText("foo 0 0 0 0 NOERROR 9 FAKE");
+}
+
+void
+fromWireCommonChecks(const TSIG& tsig) {
+ EXPECT_EQ(Name("hmac-sha256"), tsig.getAlgorithm());
+ EXPECT_EQ(1286978795, tsig.getTimeSigned());
+ EXPECT_EQ(300, tsig.getFudge());
+
+ vector<uint8_t> expect_mac(32, 'x');
+ matchWireData(&expect_mac[0], expect_mac.size(),
+ tsig.getMAC(), tsig.getMACSize());
+
+ EXPECT_EQ(2845, tsig.getOriginalID());
+
+ EXPECT_EQ(0, tsig.getOtherLen());
+ EXPECT_EQ(static_cast<const void*>(NULL), tsig.getOtherData());
+}
+
+TEST_F(Rdata_TSIG_Test, createFromWire) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire1.wire"));
+ fromWireCommonChecks(dynamic_cast<TSIG&>(*rdata));
+}
+
+TEST_F(Rdata_TSIG_Test, createFromWireWithOtherData) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire2.wire"));
+ const TSIG& tsig(dynamic_cast<TSIG&>(*rdata));
+
+ EXPECT_EQ(18, tsig.getError());
+ const uint64_t otherdata = 1286978795 + 300 + 1; // time-signed + fudge + 1
+ expect_data.resize(6);
+ expect_data[0] = (otherdata >> 40);
+ expect_data[1] = ((otherdata >> 32) & 0xff);
+ expect_data[2] = ((otherdata >> 24) & 0xff);
+ expect_data[3] = ((otherdata >> 16) & 0xff);
+ expect_data[4] = ((otherdata >> 8) & 0xff);
+ expect_data[5] = (otherdata & 0xff);
+ matchWireData(&expect_data[0], expect_data.size(),
+ tsig.getOtherData(), tsig.getOtherLen());
+}
+
+TEST_F(Rdata_TSIG_Test, createFromWireWithoutMAC) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire3.wire"));
+ const TSIG& tsig(dynamic_cast<TSIG&>(*rdata));
+ EXPECT_EQ(16, tsig.getError());
+ EXPECT_EQ(0, tsig.getMACSize());
+ EXPECT_EQ(static_cast<const void*>(NULL), tsig.getMAC());
+}
+
+TEST_F(Rdata_TSIG_Test, createFromWireWithCompression) {
+ RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire4.wire",
+ // we need to skip the dummy name:
+ Name("hmac-sha256").getLength()));
+ fromWireCommonChecks(dynamic_cast<TSIG&>(*rdata));
+}
+
+TEST_F(Rdata_TSIG_Test, badFromWire) {
+ // RDLENGTH is too short:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire5.wire"),
+ InvalidRdataLength);
+ // RDLENGTH is too long:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire6.wire"),
+ InvalidRdataLength);
+ // Algorithm name is broken:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire7.wire"),
+ DNSMessageFORMERR);
+ // MAC size is bogus:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire8.wire"),
+ InvalidBufferPosition);
+ // Other-data length is bogus:
+ EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(),
+ "rdata_tsig_fromWire9.wire"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_TSIG_Test, copyConstruct) {
+ const TSIG copy(rdata_tsig);
+ EXPECT_EQ(0, copy.compare(rdata_tsig));
+
+ // Check the copied data is valid even after the original is deleted
+ TSIG* copy2 = new TSIG(rdata_tsig);
+ TSIG copy3(*copy2);
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_tsig));
+}
+
+TEST_F(Rdata_TSIG_Test, createFromParams) {
+ EXPECT_EQ(0, rdata_tsig.compare(TSIG(Name("hmac-md5.sig-alg.reg.int"),
+ 1286779327, 300, 0, NULL, 16020, 17, 0, NULL)));
+
+ const uint8_t fake_data[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84,
+ 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 };
+ EXPECT_EQ(0, TSIG(valid_text2).compare(TSIG(Name("hmac-sha256"), 1286779327, 300, 12,
+ fake_data, 16020, 16, 0, NULL)));
+
+ const uint8_t fake_data2[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 };
+ EXPECT_EQ(0, TSIG(valid_text3).compare(TSIG(Name("hmac-sha1"), 1286779327, 300, 12,
+ fake_data, 16020, 18, 6, fake_data2)));
+
+ EXPECT_THROW(TSIG(Name("hmac-sha256"), 1ULL << 48, 300, 12, fake_data, 16020, 18, 6, fake_data2),
+ isc::OutOfRange);
+ EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 0, fake_data, 16020, 18, 0, NULL),
+ isc::InvalidParameter);
+ EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 12, NULL, 16020, 18, 0, NULL),
+ isc::InvalidParameter);
+ EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 0, NULL, 16020, 18, 0, fake_data),
+ isc::InvalidParameter);
+ EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 0, NULL, 16020, 18, 6, NULL),
+ isc::InvalidParameter);
+}
+
+TEST_F(Rdata_TSIG_Test, assignment) {
+ TSIG copy(valid_text2);
+ copy = rdata_tsig;
+ EXPECT_EQ(0, copy.compare(rdata_tsig));
+
+ // Check if the copied data is valid even after the original is deleted
+ TSIG* copy2 = new TSIG(rdata_tsig);
+ TSIG copy3(valid_text2);
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_tsig));
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(0, copy.compare(rdata_tsig));
+}
+
+template <typename Output>
+void
+Rdata_TSIG_Test::toWireCommonChecks(Output& output) const {
+ vector<uint8_t> expect_data;
+
+ output.clear();
+ expect_data.clear();
+ rdata_tsig.toWire(output);
+ // read the expected wire format data and trim the RDLEN part.
+ UnitTestUtil::readWireData("rdata_tsig_toWire1.wire", expect_data);
+ expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
+
+ expect_data.clear();
+ output.clear();
+ TSIG(valid_text2).toWire(output);
+ UnitTestUtil::readWireData("rdata_tsig_toWire2.wire", expect_data);
+ expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
+
+ expect_data.clear();
+ output.clear();
+ TSIG(valid_text3).toWire(output);
+ UnitTestUtil::readWireData("rdata_tsig_toWire3.wire", expect_data);
+ expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
+}
+
+TEST_F(Rdata_TSIG_Test, toWireBuffer) {
+ toWireCommonChecks<OutputBuffer>(obuffer);
+}
+
+TEST_F(Rdata_TSIG_Test, toWireRenderer) {
+ toWireCommonChecks<MessageRenderer>(renderer);
+
+ // check algorithm name won't compressed when it would otherwise.
+ expect_data.clear();
+ renderer.clear();
+ renderer.writeName(Name("hmac-md5.sig-alg.reg.int"));
+ renderer.writeUint16(42); // RDLEN
+ rdata_tsig.toWire(renderer);
+ UnitTestUtil::readWireData("rdata_tsig_toWire4.wire", expect_data);
+ matchWireData(&expect_data[0], expect_data.size(),
+ renderer.getData(), renderer.getLength());
+
+ // check algorithm can be used as a compression target.
+ expect_data.clear();
+ renderer.clear();
+ renderer.writeUint16(42);
+ rdata_tsig.toWire(renderer);
+ renderer.writeName(Name("hmac-md5.sig-alg.reg.int"));
+ UnitTestUtil::readWireData("rdata_tsig_toWire5.wire", expect_data);
+ matchWireData(&expect_data[0], expect_data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_TSIG_Test, toText) {
+ EXPECT_EQ(valid_text1, rdata_tsig.toText());
+ EXPECT_EQ(valid_text2, TSIG(valid_text2).toText());
+ EXPECT_EQ(valid_text3, TSIG(valid_text3).toText());
+ EXPECT_EQ(valid_text5, TSIG(valid_text5).toText());
+}
+
+TEST_F(Rdata_TSIG_Test, compare) {
+ // test RDATAs, sorted in the ascending order.
+ // "AAAA" encoded in BASE64 corresponds to 0x000000, so it should be the
+ // smallest data of the same length.
+ vector<TSIG> compare_set;
+ compare_set.push_back(TSIG("a.example 0 300 0 16020 0 0"));
+ compare_set.push_back(TSIG("example 0 300 0 16020 0 0"));
+ compare_set.push_back(TSIG("example 1 300 0 16020 0 0"));
+ compare_set.push_back(TSIG("example 1 600 0 16020 0 0"));
+ compare_set.push_back(TSIG("example 1 600 3 AAAA 16020 0 0"));
+ compare_set.push_back(TSIG("example 1 600 3 FAKE 16020 0 0"));
+ compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 0 0"));
+ compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 1 0"));
+ compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 1 3 AAAA"));
+ compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 1 3 FAKE"));
+
+ EXPECT_EQ(0, compare_set[0].compare(TSIG("A.EXAMPLE 0 300 0 16020 0 0")));
+
+ vector<TSIG>::const_iterator it;
+ vector<TSIG>::const_iterator it_end = compare_set.end();
+ for (it = compare_set.begin(); it != it_end - 1; ++it) {
+ EXPECT_GT(0, (*it).compare(*(it + 1)));
+ EXPECT_LT(0, (*(it + 1)).compare(*it));
+ }
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(rdata_tsig.compare(*RdataTest::rdata_nomatch), bad_cast);
+}
+}
diff --git a/src/lib/dns/tests/rdata_txt_like_unittest.cc b/src/lib/dns/tests/rdata_txt_like_unittest.cc
new file mode 100644
index 0000000..e2828c2
--- /dev/null
+++ b/src/lib/dns/tests/rdata_txt_like_unittest.cc
@@ -0,0 +1,397 @@
+// Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// This is the common code for TXT and SPF tests.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/exceptions.h>
+#include <dns/rdataclass.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+
+#include <util/unittests/wiredata.h>
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+
+template<class T>
+class RRTYPE : public RRType {
+public:
+ RRTYPE();
+};
+
+template<> RRTYPE<generic::TXT>::RRTYPE() : RRType(RRType::TXT()) {}
+template<> RRTYPE<generic::SPF>::RRTYPE() : RRType(RRType::SPF()) {}
+
+const uint8_t wiredata_txt_like[] = {
+ sizeof("Test-String") - 1,
+ 'T', 'e', 's', 't', '-', 'S', 't', 'r', 'i', 'n', 'g'
+};
+
+const uint8_t wiredata_nulltxt[] = { 0 };
+
+template<class TXT_LIKE>
+class Rdata_TXT_LIKE_Test : public RdataTest {
+protected:
+ Rdata_TXT_LIKE_Test() :
+ wiredata_longesttxt(256, 'a'),
+ rdata_txt_like("Test-String"),
+ rdata_txt_like_empty("\"\""),
+ rdata_txt_like_quoted("\"Test-String\"")
+ {
+ wiredata_longesttxt[0] = 255; // adjust length
+ }
+
+protected:
+ vector<uint8_t> wiredata_longesttxt;
+ const TXT_LIKE rdata_txt_like;
+ const TXT_LIKE rdata_txt_like_empty;
+ const TXT_LIKE rdata_txt_like_quoted;
+};
+
+// The list of types we want to test.
+typedef testing::Types<generic::TXT, generic::SPF> Implementations;
+
+#ifdef TYPED_TEST_SUITE
+TYPED_TEST_SUITE(Rdata_TXT_LIKE_Test, Implementations);
+#else
+TYPED_TEST_CASE(Rdata_TXT_LIKE_Test, Implementations);
+#endif
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, createFromText) {
+ // Below we check the behavior for the "from text" constructors, both
+ // from std::string and with MasterLexer. The underlying implementation
+ // is the same, so both should work exactly same, but we confirm both
+ // cases.
+
+ const std::string multi_line = "(\n \"Test-String\" )";
+ const std::string escaped_txt = "Test\\045Strin\\g";
+
+ // test input for the lexer version
+ std::stringstream ss;
+ ss << "Test-String\n";
+ ss << "\"Test-String\"\n"; // explicitly surrounded by '"'s
+ ss << multi_line << "\n"; // multi-line text with ()
+ ss << escaped_txt << "\n"; // using the two types of escape with '\'
+ ss << "\"\"\n"; // empty string (note: still valid char-str)
+ ss << string(255, 'a') << "\n"; // Longest possible character-string.
+ ss << string(256, 'a') << "\n"; // char-string too long
+ ss << "\"Test-String\\\"\n"; // unbalanced quote
+ ss << "\"Test-String\\\"\"\n";
+ this->lexer.pushSource(ss);
+
+ // commonly used Rdata to compare below, created from wire
+ ConstRdataPtr const rdata =
+ this->rdataFactoryFromFile(RRTYPE<TypeParam>(),
+ RRClass("IN"), "rdata_txt_fromWire1");
+
+ // normal case is covered in toWireBuffer. First check the std::string
+ // case, then with MasterLexer. For the latter, we need to read and skip
+ // '\n'. These apply to most of the other cases below.
+ EXPECT_EQ(0, this->rdata_txt_like.compare(*rdata));
+ EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS,
+ this->loader_cb).compare(*rdata));
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+
+ // surrounding double-quotes shouldn't change the result.
+ EXPECT_EQ(0, this->rdata_txt_like_quoted.compare(*rdata));
+ EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS,
+ this->loader_cb).compare(*rdata));
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+
+ // multi-line input with ()
+ EXPECT_EQ(0, TypeParam(multi_line).compare(*rdata));
+ EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS,
+ this->loader_cb).compare(*rdata));
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+
+ // for the same data using escape
+ EXPECT_EQ(0, TypeParam(escaped_txt).compare(*rdata));
+ EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS,
+ this->loader_cb).compare(*rdata));
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+
+ // Null character-string.
+ this->obuffer.clear();
+ TypeParam(string("\"\"")).toWire(this->obuffer);
+ matchWireData(wiredata_nulltxt, sizeof(wiredata_nulltxt),
+ this->obuffer.getData(), this->obuffer.getLength());
+
+ this->obuffer.clear();
+ TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, this->loader_cb).
+ toWire(this->obuffer);
+ matchWireData(wiredata_nulltxt, sizeof(wiredata_nulltxt),
+ this->obuffer.getData(), this->obuffer.getLength());
+
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+
+ // Longest possible character-string.
+ this->obuffer.clear();
+ TypeParam(string(255, 'a')).toWire(this->obuffer);
+ matchWireData(&this->wiredata_longesttxt[0],
+ this->wiredata_longesttxt.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
+
+ this->obuffer.clear();
+ TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, this->loader_cb).
+ toWire(this->obuffer);
+ matchWireData(&this->wiredata_longesttxt[0],
+ this->wiredata_longesttxt.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
+
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+
+ // Too long text for a valid character-string.
+ EXPECT_THROW(TypeParam(string(256, 'a')), CharStringTooLong);
+ EXPECT_THROW(TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS,
+ this->loader_cb), CharStringTooLong);
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+
+ // The escape character makes the double quote a part of character-string,
+ // so this is invalid input and should be rejected.
+ EXPECT_THROW(TypeParam("\"Test-String\\\""), InvalidRdataText);
+ EXPECT_THROW(TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS,
+ this->loader_cb), MasterLexer::LexerError);
+ EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, createMultiStringsFromText) {
+ // Tests for "from text" variants construction with various forms of
+ // multi character-strings.
+
+ std::vector<std::string > texts;
+ texts.push_back("\"Test-String\" \"Test-String\""); // most common form
+ texts.push_back("\"Test-String\"\"Test-String\""); // no space between'em
+ texts.push_back("\"Test-String\" Test-String"); // no '"' for one
+ texts.push_back("\"Test-String\"Test-String"); // and no space either
+ texts.push_back("Test-String \"Test-String\""); // no '"' for the other
+ texts.push_back("Test-String\"Test-String\""); // and no space either
+
+ std::stringstream ss;
+ for (std::vector<std::string >::const_iterator it = texts.begin();
+ it != texts.end(); ++it) {
+ ss << *it << "\n";
+ }
+ this->lexer.pushSource(ss);
+
+ // The corresponding Rdata built from wire to compare in the checks below.
+ ConstRdataPtr const rdata =
+ this->rdataFactoryFromFile(RRTYPE<TypeParam>(),
+ RRClass("IN"), "rdata_txt_fromWire3.wire");
+
+ // Confirm we can construct the Rdata from the test text, both from
+ // std::string and with lexer, and that matches the from-wire data.
+ for (std::vector<std::string >::const_iterator it = texts.begin();
+ it != texts.end(); ++it) {
+ SCOPED_TRACE(*it);
+ EXPECT_EQ(0, TypeParam(*it).compare(*rdata));
+
+ EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS,
+ this->loader_cb).compare(*rdata));
+ EXPECT_EQ(MasterToken::END_OF_LINE,
+ this->lexer.getNextToken().getType());
+ }
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, createFromTextExtra) {
+ // This is for the std::string version only: the input must end with EOF;
+ // an extra new-line will result in an exception.
+ EXPECT_THROW(TypeParam("\"Test-String\"\n"), InvalidRdataText);
+ // Same if there's a space before '\n'
+ EXPECT_THROW(TypeParam("\"Test-String\" \n"), InvalidRdataText);
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, fromTextEmpty) {
+ // If the input text doesn't contain any character-string, it should be
+ // rejected
+ EXPECT_THROW(TypeParam(""), InvalidRdataText);
+ EXPECT_THROW(TypeParam(" "), InvalidRdataText); // even with a space
+ EXPECT_THROW(TypeParam("(\n)"), InvalidRdataText); // or multi-line with ()
+}
+
+void
+makeLargest(vector<uint8_t>& data) {
+ uint8_t ch = 0;
+
+ // create 255 sets of character-strings, each of which has the longest
+ // length (255bytes string + 1-byte length field)
+ for (int i = 0; i < 255; ++i, ++ch) {
+ data.push_back(255);
+ data.insert(data.end(), 255, ch);
+ }
+ // the last character-string should be 255 bytes (including the one-byte
+ // length field) in length so that the total length should be in the range
+ // of 16-bit integers.
+ data.push_back(254);
+ data.insert(data.end(), 254, ch);
+
+ assert(data.size() == 65535);
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, createFromWire) {
+ EXPECT_EQ(0, this->rdata_txt_like.compare(
+ *this->rdataFactoryFromFile(RRTYPE<TypeParam>(),
+ RRClass("IN"),
+ "rdata_txt_fromWire1")));
+
+ // Empty character string
+ EXPECT_EQ(0, this->rdata_txt_like_empty.compare(
+ *this->rdataFactoryFromFile(RRTYPE<TypeParam>(),
+ RRClass("IN"),
+ "rdata_txt_fromWire2.wire")));
+
+ // Multiple character strings
+ this->obuffer.clear();
+ this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
+ "rdata_txt_fromWire3.wire")->toWire(this->obuffer);
+ // the result should be 'wiredata_txt' repeated twice
+ vector<uint8_t> expected_data(wiredata_txt_like, wiredata_txt_like +
+ sizeof(wiredata_txt_like));
+ expected_data.insert(expected_data.end(), wiredata_txt_like,
+ wiredata_txt_like + sizeof(wiredata_txt_like));
+ matchWireData(&expected_data[0], expected_data.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
+
+ // Largest length of data. There's nothing special, but should be
+ // constructed safely, and the content should be identical to the original
+ // data.
+ vector<uint8_t> largest_txt_like_data;
+ makeLargest(largest_txt_like_data);
+ InputBuffer ibuffer(&largest_txt_like_data[0],
+ largest_txt_like_data.size());
+ TypeParam largest_txt_like(ibuffer, largest_txt_like_data.size());
+ this->obuffer.clear();
+ largest_txt_like.toWire(this->obuffer);
+ matchWireData(&largest_txt_like_data[0], largest_txt_like_data.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
+
+ // rdlen parameter is out of range. This is a rare event because we'd
+ // normally call the constructor via a polymorphic wrapper, where the
+ // length is validated. But this should be checked explicitly.
+ InputBuffer ibuffer2(&largest_txt_like_data[0],
+ largest_txt_like_data.size());
+ EXPECT_THROW(TypeParam(ibuffer2, 65536), InvalidRdataLength);
+
+ // RDATA is empty, which is invalid for TXT_LIKE.
+ EXPECT_THROW(this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
+ "rdata_txt_fromWire4.wire"),
+ DNSMessageFORMERR);
+
+ // character-string length is too large, which could cause overrun.
+ EXPECT_THROW(this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
+ "rdata_txt_fromWire5.wire"),
+ DNSMessageFORMERR);
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, createFromLexer) {
+ EXPECT_EQ(0, this->rdata_txt_like.compare(
+ *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
+ "Test-String")));
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, toWireBuffer) {
+ this->rdata_txt_like.toWire(this->obuffer);
+ matchWireData(wiredata_txt_like, sizeof(wiredata_txt_like),
+ this->obuffer.getData(), this->obuffer.getLength());
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, toWireRenderer) {
+ this->rdata_txt_like.toWire(this->renderer);
+ matchWireData(wiredata_txt_like, sizeof(wiredata_txt_like),
+ this->renderer.getData(), this->renderer.getLength());
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, toText) {
+ EXPECT_EQ("\"Test-String\"", this->rdata_txt_like.toText());
+ EXPECT_EQ("\"\"", this->rdata_txt_like_empty.toText());
+ EXPECT_EQ("\"Test-String\"", this->rdata_txt_like_quoted.toText());
+
+ // Check escape behavior
+ const TypeParam double_quotes("Test-String\"Test-String\"");
+ EXPECT_EQ("\"Test-String\" \"Test-String\"", double_quotes.toText());
+ const TypeParam semicolon("Test-String\\;Test-String");
+ EXPECT_EQ("\"Test-String\\;Test-String\"", semicolon.toText());
+ const TypeParam backslash("Test-String\\\\Test-String");
+ EXPECT_EQ("\"Test-String\\\\Test-String\"", backslash.toText());
+ const TypeParam before_x20("Test-String\\031Test-String");
+ EXPECT_EQ("\"Test-String\\031Test-String\"", before_x20.toText());
+ const TypeParam from_x20_to_x7e("\"Test-String ~ Test-String\"");
+ EXPECT_EQ("\"Test-String ~ Test-String\"", from_x20_to_x7e.toText());
+ const TypeParam from_x20_to_x7e_2("Test-String\\032\\126\\032Test-String");
+ EXPECT_EQ("\"Test-String ~ Test-String\"", from_x20_to_x7e_2.toText());
+ const TypeParam after_x7e("Test-String\\127Test-String");
+ EXPECT_EQ("\"Test-String\\127Test-String\"", after_x7e.toText());
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, assignment) {
+ TypeParam rdata1("assignment1");
+ TypeParam rdata2("assignment2");
+ rdata1 = rdata2;
+ EXPECT_EQ(0, rdata2.compare(rdata1));
+
+ // Check if the copied data is valid even after the original is deleted
+ TypeParam* rdata3 = new TypeParam(rdata1);
+ TypeParam rdata4("assignment3");
+ rdata4 = *rdata3;
+ delete rdata3;
+ EXPECT_EQ(0, rdata4.compare(rdata1));
+
+ // Self assignment
+ rdata2 = *&rdata2;
+ EXPECT_EQ(0, rdata2.compare(rdata1));
+}
+
+TYPED_TEST(Rdata_TXT_LIKE_Test, compare) {
+ string const txt1("aaaaaaaa");
+ string const txt2("aaaaaaaaaa");
+ string const txt3("bbbbbbbb");
+ string const txt4(129, 'a');
+ string const txt5(128, 'b');
+
+ EXPECT_EQ(TypeParam(txt1).compare(TypeParam(txt1)), 0);
+
+ EXPECT_LT(TypeParam("\"\"").compare(TypeParam(txt1)), 0);
+ EXPECT_GT(TypeParam(txt1).compare(TypeParam("\"\"")), 0);
+
+ EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt2)), 0);
+ EXPECT_GT(TypeParam(txt2).compare(TypeParam(txt1)), 0);
+
+ EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt3)), 0);
+ EXPECT_GT(TypeParam(txt3).compare(TypeParam(txt1)), 0);
+
+ // we're comparing the data raw, starting at the length octet, so a shorter
+ // string sorts before a longer one no matter the lexicopraphical order
+ EXPECT_LT(TypeParam(txt3).compare(TypeParam(txt2)), 0);
+ EXPECT_GT(TypeParam(txt2).compare(TypeParam(txt3)), 0);
+
+ // to make sure the length octet compares unsigned
+ EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt4)), 0);
+ EXPECT_GT(TypeParam(txt4).compare(TypeParam(txt1)), 0);
+
+ EXPECT_LT(TypeParam(txt5).compare(TypeParam(txt4)), 0);
+ EXPECT_GT(TypeParam(txt4).compare(TypeParam(txt5)), 0);
+
+ // comparison attempt between incompatible RR types should be rejected
+ EXPECT_THROW(TypeParam(txt1).compare(*this->rdata_nomatch),
+ bad_cast);
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc
new file mode 100644
index 0000000..afc16a1
--- /dev/null
+++ b/src/lib/dns/tests/rdata_unittest.cc
@@ -0,0 +1,467 @@
+// Copyright (C) 2010-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <functional>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include <sstream>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+
+#include <util/unittests/wiredata.h>
+
+#include <boost/lexical_cast.hpp>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+namespace ph = std::placeholders;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+RdataTest::RdataTest() :
+ obuffer(0), rdata_nomatch(createRdata(RRType(0), RRClass(1), "\\# 0")),
+ loader_cb(MasterLoaderCallbacks::getNullCallbacks())
+{}
+
+RdataPtr
+RdataTest::rdataFactoryFromFile(const RRType& rrtype, const RRClass& rrclass,
+ const char* datafile, size_t position)
+{
+ std::vector<unsigned char> data;
+ UnitTestUtil::readWireData(datafile, data);
+
+ InputBuffer buffer(&data[0], data.size());
+ buffer.setPosition(position);
+
+ uint16_t rdlen = buffer.readUint16();
+ return (createRdata(rrtype, rrclass, buffer, rdlen));
+}
+
+namespace test {
+
+RdataPtr
+createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
+ const std::string& str)
+{
+ std::stringstream ss(str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ MasterLoaderCallbacks callbacks =
+ MasterLoaderCallbacks::getNullCallbacks();
+ const Name origin("example.org.");
+
+ return (createRdata(rrtype, rrclass, lexer, &origin,
+ MasterLoader::MANY_ERRORS, callbacks));
+}
+
+} // end of namespace isc::dns::rdata::test
+
+// A mock class to check parameters passed via loader callbacks. Its callback
+// records the passed parameters, allowing the test to check them later via
+// the check() method.
+class CreateRdataCallback {
+public:
+ enum CallbackType { NONE, ERROR, WARN };
+ CreateRdataCallback() : type_(NONE), line_(0) {}
+ void callback(CallbackType type, const string& source, size_t line,
+ const string& reason_txt) {
+ type_ = type;
+ source_ = source;
+ line_ = line;
+ reason_txt_ = reason_txt;
+ }
+
+ void clear() {
+ type_ = NONE;
+ source_.clear();
+ line_ = 0;
+ reason_txt_.clear();
+ }
+
+ // Return if callback is called since the previous call to clear().
+ bool isCalled() const { return (type_ != NONE); }
+
+ void check(const string& expected_srcname, size_t expected_line,
+ CallbackType expected_type, const string& expected_reason)
+ const
+ {
+ EXPECT_EQ(expected_srcname, source_);
+ EXPECT_EQ(expected_line, line_);
+ EXPECT_EQ(expected_type, type_);
+ EXPECT_EQ(expected_reason, reason_txt_);
+ }
+
+private:
+ CallbackType type_;
+ string source_;
+ size_t line_;
+ string reason_txt_;
+};
+
+// Test class/type-independent behavior of createRdata().
+TEST_F(RdataTest, createRdataWithLexer) {
+ const in::AAAA aaaa_rdata("2001:db8::1");
+
+ stringstream ss;
+ const string src_name = "stream-" + boost::lexical_cast<string>(&ss);
+ ss << aaaa_rdata.toText() << "\n"; // valid case
+ ss << aaaa_rdata.toText() << "; comment, should be ignored\n";
+ ss << aaaa_rdata.toText() << " extra-token\n"; // extra token
+ ss << aaaa_rdata.toText() << " extra token\n"; // 2 extra tokens
+ ss << ")\n"; // causing lexer error in parsing the RDATA text
+ ss << "192.0.2.1\n"; // semantics error: IPv4 address is given for AAAA
+ ss << aaaa_rdata.toText(); // valid, but end with EOF, not EOL
+ lexer.pushSource(ss);
+
+ CreateRdataCallback callback;
+ MasterLoaderCallbacks callbacks(
+ std::bind(&CreateRdataCallback::callback, &callback,
+ CreateRdataCallback::ERROR, ph::_1, ph::_2, ph::_3),
+ std::bind(&CreateRdataCallback::callback, &callback,
+ CreateRdataCallback::WARN, ph::_1, ph::_2, ph::_3));
+
+ size_t line = 0;
+
+ // Valid case.
+ ++line;
+ ConstRdataPtr rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer,
+ NULL, MasterLoader::MANY_ERRORS,
+ callbacks);
+ EXPECT_EQ(0, aaaa_rdata.compare(*rdata));
+ EXPECT_FALSE(callback.isCalled());
+
+ // Similar to the previous case, but RDATA is followed by a comment.
+ // It should cause any confusion.
+ ++line;
+ callback.clear();
+ rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
+ MasterLoader::MANY_ERRORS, callbacks);
+ EXPECT_EQ(0, aaaa_rdata.compare(*rdata));
+ EXPECT_FALSE(callback.isCalled());
+
+ // Broken RDATA text: extra token. createRdata() returns NULL, error
+ // callback is called.
+ ++line;
+ callback.clear();
+ EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
+ MasterLoader::MANY_ERRORS, callbacks));
+ callback.check(src_name, line, CreateRdataCallback::ERROR,
+ "createRdata from text failed near 'extra-token': "
+ "extra input text");
+
+ // Similar to the previous case, but only the first extra token triggers
+ // callback.
+ ++line;
+ callback.clear();
+ EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
+ MasterLoader::MANY_ERRORS, callbacks));
+ callback.check(src_name, line, CreateRdataCallback::ERROR,
+ "createRdata from text failed near 'extra': "
+ "extra input text");
+
+ // Lexer error will happen, corresponding error callback will be triggered.
+ ++line;
+ callback.clear();
+ EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
+ MasterLoader::MANY_ERRORS, callbacks));
+ callback.check(src_name, line, CreateRdataCallback::ERROR,
+ "createRdata from text failed: unbalanced parentheses");
+
+ // Semantics level error will happen, corresponding error callback will be
+ // triggered.
+ ++line;
+ callback.clear();
+ EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
+ MasterLoader::MANY_ERRORS, callbacks));
+ callback.check(src_name, line, CreateRdataCallback::ERROR,
+ "createRdata from text failed: Bad IN/AAAA RDATA text: "
+ "'192.0.2.1'");
+
+ // Input is valid and parse will succeed, but with a warning that the
+ // file is not ended with a newline.
+ ++line;
+ callback.clear();
+ rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
+ MasterLoader::MANY_ERRORS, callbacks);
+ EXPECT_EQ(0, aaaa_rdata.compare(*rdata));
+ callback.check(src_name, line, CreateRdataCallback::WARN,
+ "file does not end with newline");
+}
+
+TEST_F(RdataTest, getLength) {
+ const in::AAAA aaaa_rdata("2001:db8::1");
+ EXPECT_EQ(16, aaaa_rdata.getLength());
+
+ const generic::TXT txt_rdata("Hello World");
+ EXPECT_EQ(12, txt_rdata.getLength());
+}
+
+}
+}
+}
+
+namespace {
+
+// Wire-format data correspond to rdata_unknown. Note that it doesn't
+// include RDLENGTH.
+const uint8_t wiredata_unknown[] = { 0xa1, 0xb2, 0xc3, 0x0d };
+
+class Rdata_Unknown_Test : public RdataTest {
+public:
+ Rdata_Unknown_Test() :
+ // "Unknown" RR Type used for the test cases below. If/when we
+ // use this type number as a "well-known" (probably
+ // experimental) type, we'll need to renumber it.
+ unknown_rrtype(RRType(65000)),
+ rdata_unknowntxt("\\# 4 a1b2c30d"),
+ rdata_unknown(rdata_unknowntxt)
+ {}
+protected:
+ static string getLongestRdataTxt();
+ static void getLongestRdataWire(vector<uint8_t>& v);
+
+ const RRType unknown_rrtype;
+ const std::string rdata_unknowntxt;
+ const generic::Generic rdata_unknown;
+};
+
+string
+Rdata_Unknown_Test::getLongestRdataTxt() {
+ ostringstream oss;
+
+ oss << "\\# " << MAX_RDLENGTH << " ";
+ oss.fill('0');
+ oss << right << hex;
+ for (int i = 0; i < MAX_RDLENGTH; i++) {
+ oss << setw(2) << (i & 0xff);
+ }
+
+ return (oss.str());
+}
+
+void
+Rdata_Unknown_Test::getLongestRdataWire(vector<uint8_t>& v) {
+ unsigned char ch = 0;
+ for (int i = 0; i < MAX_RDLENGTH; ++i, ++ch) {
+ v.push_back(ch);
+ }
+}
+
+TEST_F(Rdata_Unknown_Test, createFromText) {
+ // valid construction. This also tests a normal case of "FromWire".
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1b2c30d").compare(
+ *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
+ "rdata_unknown_fromWire")));
+ // upper case hexadecimal digits should also be okay.
+ EXPECT_EQ(0, generic::Generic("\\# 4 A1B2C30D").compare(
+ *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
+ "rdata_unknown_fromWire")));
+ // 0-length RDATA should be accepted
+ EXPECT_EQ(0, generic::Generic("\\# 0").compare(
+ *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
+ "rdata_unknown_fromWire", 6)));
+ // hex encoding can be space-separated
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2c30d").compare(rdata_unknown));
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1b2 c30d").compare(rdata_unknown));
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2 c3 0d").compare(rdata_unknown));
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1\tb2c3 0d").compare(rdata_unknown));
+
+ // Max-length RDATA
+ vector<uint8_t> v;
+ getLongestRdataWire(v);
+ InputBuffer ibuffer(&v[0], v.size());
+ EXPECT_EQ(0, generic::Generic(getLongestRdataTxt()).compare(
+ generic::Generic(ibuffer, v.size())));
+
+ // the length field must match the encoding data length.
+ EXPECT_THROW(generic::Generic("\\# 4 1080c0ff00"), InvalidRdataLength);
+ EXPECT_THROW(generic::Generic("\\# 5 1080c0ff"), InvalidRdataLength);
+ // RDATA encoding part must consist of an even number of hex digits.
+ EXPECT_THROW(generic::Generic("\\# 1 1"), InvalidRdataText);
+ EXPECT_THROW(generic::Generic("\\# 1 ax"), InvalidRdataText);
+ // the length should be 16-bit unsigned integer
+ EXPECT_THROW(generic::Generic("\\# 65536 a1b2c30d"), InvalidRdataLength);
+ EXPECT_THROW(generic::Generic("\\# -1 a1b2c30d"), InvalidRdataLength);
+ EXPECT_THROW(generic::Generic("\\# 1.1 a1"), InvalidRdataLength);
+ EXPECT_THROW(generic::Generic("\\# 0a 00010203040506070809"),
+ InvalidRdataLength);
+ // should reject if the special token is missing.
+ EXPECT_THROW(generic::Generic("4 a1b2c30d"), InvalidRdataText);
+ // the special token, the RDLENGTH and the data must be space separated.
+ EXPECT_THROW(generic::Generic("\\#0"), InvalidRdataText);
+ EXPECT_THROW(generic::Generic("\\# 1ff"), InvalidRdataLength);
+}
+
+TEST_F(Rdata_Unknown_Test, createFromWire) {
+ // normal case (including 0-length data) is covered in createFromText.
+
+ // buffer too short. the error should be detected in buffer read
+ EXPECT_THROW(rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
+ "rdata_unknown_fromWire", 8),
+ InvalidBufferPosition);
+
+ // too large data
+ vector<uint8_t> v;
+ getLongestRdataWire(v);
+ v.push_back(0); // making it too long
+ InputBuffer ibuffer(&v[0], v.size());
+ EXPECT_THROW(generic::Generic(ibuffer, v.size()), InvalidRdataLength);
+}
+
+// The following 3 sets of tests check the behavior of createRdata() variants
+// with the "unknown" RRtype. The result should be RRclass independent.
+TEST_F(Rdata_Unknown_Test, createRdataFromString) {
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass::IN(),
+ rdata_unknowntxt)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass::CH(),
+ rdata_unknowntxt)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("CLASS65000"),
+ rdata_unknowntxt)));
+}
+
+TEST_F(Rdata_Unknown_Test, createRdataFromWire) {
+ InputBuffer ibuffer(wiredata_unknown, sizeof(wiredata_unknown));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass::IN(),
+ ibuffer, sizeof(wiredata_unknown))));
+
+ InputBuffer ibuffer2(wiredata_unknown, sizeof(wiredata_unknown));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass::CH(),
+ ibuffer2, sizeof(wiredata_unknown))));
+
+ InputBuffer ibuffer3(wiredata_unknown, sizeof(wiredata_unknown));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass(65000),
+ ibuffer3, sizeof(wiredata_unknown))));
+}
+
+TEST_F(Rdata_Unknown_Test, createRdataByCopy) {
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass::IN(), rdata_unknown)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass::CH(), rdata_unknown)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass(65000),
+ rdata_unknown)));
+}
+
+TEST_F(Rdata_Unknown_Test, copyConstruct) {
+ generic::Generic copy(rdata_unknown);
+ EXPECT_EQ(0, copy.compare(rdata_unknown));
+
+ // Check the copied data is valid even after the original is deleted
+ generic::Generic* copy2 = new generic::Generic(rdata_unknown);
+ generic::Generic copy3(*copy2);
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_unknown));
+}
+
+TEST_F(Rdata_Unknown_Test, assignment) {
+ generic::Generic copy("\\# 1 10");
+ copy = rdata_unknown;
+ EXPECT_EQ(0, copy.compare(rdata_unknown));
+
+ // Check if the copied data is valid even after the original is deleted
+ generic::Generic* copy2 = new generic::Generic(rdata_unknown);
+ generic::Generic copy3("\\# 1 10");
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_unknown));
+
+ // Self assignment
+ copy = *&copy;
+ EXPECT_EQ(0, copy.compare(rdata_unknown));
+}
+
+TEST_F(Rdata_Unknown_Test, toText) {
+ EXPECT_EQ(rdata_unknowntxt, rdata_unknown.toText());
+ EXPECT_EQ(getLongestRdataTxt(),
+ generic::Generic(getLongestRdataTxt()).toText());
+}
+
+TEST_F(Rdata_Unknown_Test, toWireBuffer) {
+ rdata_unknown.toWire(obuffer);
+ matchWireData(wiredata_unknown, sizeof(wiredata_unknown),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_Unknown_Test, toWireRenderer) {
+ rdata_unknown.toWire(renderer);
+ matchWireData(wiredata_unknown, sizeof(wiredata_unknown),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(Rdata_Unknown_Test, compare) {
+ // comparison as left-justified unsigned octet sequences:
+ // cppcheck-suppress uselessCallsCompare
+ EXPECT_EQ(0, rdata_unknown.compare(rdata_unknown));
+
+ generic::Generic rdata_unknown_small("\\# 4 00b2c3ff");
+ EXPECT_GT(0, rdata_unknown_small.compare(rdata_unknown));
+ EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_small));
+
+ generic::Generic rdata_unknown_large("\\# 4 ffb2c300");
+ EXPECT_LT(0, rdata_unknown_large.compare(rdata_unknown));
+ EXPECT_GT(0, rdata_unknown.compare(rdata_unknown_large));
+
+ // the absence of an octet sorts before a zero octet.
+ generic::Generic rdata_unknown_short("\\# 3 a1b2c3");
+ EXPECT_GT(0, rdata_unknown_short.compare(rdata_unknown));
+ EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_short));
+}
+
+TEST_F(Rdata_Unknown_Test, LeftShiftOperator) {
+ ostringstream oss;
+ oss << rdata_unknown;
+ EXPECT_EQ(rdata_unknown.toText(), oss.str());
+}
+
+//
+// Tests for global utility functions
+//
+TEST_F(RdataTest, compareNames) {
+ Name small("a.example");
+ Name large("example");
+
+ // Check the case where the order is different from the owner name
+ // comparison:
+ EXPECT_TRUE(small > large);
+ EXPECT_EQ(-1, compareNames(small, large));
+ EXPECT_EQ(1, compareNames(large, small));
+
+ // Check case insensitive comparison:
+ Name small_upper("A.EXAMPLE");
+ EXPECT_EQ(0, compareNames(small, small_upper));
+
+ // the absence of an octet sorts before a zero octet.
+ Name large2("a.example2");
+ EXPECT_EQ(-1, compareNames(small, large2));
+ EXPECT_EQ(1, compareNames(large2, small));
+}
+}
diff --git a/src/lib/dns/tests/rdata_unittest.h b/src/lib/dns/tests/rdata_unittest.h
new file mode 100644
index 0000000..0c9178e
--- /dev/null
+++ b/src/lib/dns/tests/rdata_unittest.h
@@ -0,0 +1,92 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef RDATA_UNITTEST_H
+#define RDATA_UNITTEST_H 1
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/rdata.h>
+#include <dns/master_lexer.h>
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <sstream>
+
+namespace isc {
+namespace dns {
+namespace rdata {
+class RdataTest : public ::testing::Test {
+protected:
+ RdataTest();
+ static RdataPtr rdataFactoryFromFile(const RRType& rrtype,
+ const RRClass& rrclass,
+ const char* datafile,
+ size_t position = 0);
+
+ // Common check to see the result of Rdata construction of given type
+ // (template parameter RdataType) either from std::string or with
+ // MasterLexer object. If it's expected to succeed the result should be
+ // identical to the commonly used test data (rdata_expected); otherwise it
+ // should result in the exception specified as the template parameter:
+ // ExForString for the string version, and ExForLexer for the lexer
+ // version. throw_str_version and throw_lexer_version are set to true
+ // iff the string/lexer version is expected to throw, respectively.
+ // Parameter origin can be set to non NULL for the origin parameter of
+ // the lexer version of Rdata constructor.
+ template <typename RdataType, typename ExForString, typename ExForLexer>
+ void checkFromText(const std::string& rdata_txt,
+ const RdataType& rdata_expected,
+ bool throw_str_version = true,
+ bool throw_lexer_version = true,
+ const Name* origin = NULL)
+ {
+ SCOPED_TRACE(rdata_txt);
+
+ if (throw_str_version) {
+ EXPECT_THROW(RdataType rdata(rdata_txt), ExForString);
+ } else {
+ EXPECT_EQ(0, RdataType(rdata_txt).compare(rdata_expected));
+ }
+
+ std::stringstream ss(rdata_txt);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+ if (throw_lexer_version) {
+ EXPECT_THROW(RdataType rdata(lexer, origin, MasterLoader::DEFAULT,
+ loader_cb), ExForLexer);
+ } else {
+ EXPECT_EQ(0, RdataType(lexer, origin, MasterLoader::DEFAULT,
+ loader_cb).compare(rdata_expected));
+ }
+ }
+
+ isc::util::OutputBuffer obuffer;
+ MessageRenderer renderer;
+ /// This is an RDATA object of some "unknown" RR type so that it can be
+ /// used to test the compare() method against a well-known RR type.
+ RdataPtr rdata_nomatch;
+ MasterLexer lexer;
+ MasterLoaderCallbacks loader_cb;
+};
+
+namespace test {
+RdataPtr
+createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
+ const std::string& str);
+}
+
+}
+}
+}
+#endif // RDATA_UNITTEST_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/tests/rdatafields_unittest.cc b/src/lib/dns/tests/rdatafields_unittest.cc
new file mode 100644
index 0000000..0531439
--- /dev/null
+++ b/src/lib/dns/tests/rdatafields_unittest.cc
@@ -0,0 +1,366 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <vector>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatafields.h>
+#include <dns/tests/unittest_util.h>
+
+#include <util/unittests/wiredata.h>
+
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::OutputBuffer;
+using isc::util::InputBuffer;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class RdataFieldsTest : public ::testing::Test {
+protected:
+ RdataFieldsTest() : obuffer(0), ns_name("example.com"),
+ other_name("www.example.com")
+ {}
+ void constructCommonTests(const RdataFields& fields,
+ const uint8_t* const expected_data,
+ const size_t expected_data_len);
+ void constructCommonTestsNS(const RdataFields& fields);
+ void constructCommonTestsTXT(const RdataFields& fields);
+ void constructCommonTestsRRSIG(const RdataFields& fields);
+ void constructCommonTestsOPT(const RdataFields& fields);
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+ const Name ns_name;
+ const Name other_name;
+ vector<unsigned char> expected_wire;
+ vector<unsigned char> fields_wire;
+};
+
+const uint8_t in_a_data[] = { 192, 0, 2, 1 };
+// binary representation of example.com.
+const uint8_t ns_data[] = { 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+ 0x03, 0x63, 0x6f, 0x6d, 0x00 };
+
+//
+// IN/A RDATA: fixed length, single data field
+//
+void
+RdataFieldsTest::constructCommonTests(const RdataFields& fields,
+ const uint8_t* const expected_data,
+ const size_t expected_data_len)
+{
+ matchWireData(expected_data, expected_data_len,
+ fields.getData(), fields.getDataLength());
+
+ EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
+ EXPECT_EQ(1, fields.getFieldCount());
+ EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
+ EXPECT_EQ(4, fields.getFieldSpec(0).len);
+
+ fields.toWire(obuffer);
+ matchWireData(expected_data, expected_data_len,
+ obuffer.getData(), obuffer.getLength());
+
+ fields.toWire(renderer);
+ matchWireData(expected_data, expected_data_len,
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(RdataFieldsTest, constructFromRdata) {
+ const RdataFields fields(in::A("192.0.2.1"));
+ constructCommonTests(fields, in_a_data, sizeof(in_a_data));
+}
+
+TEST_F(RdataFieldsTest, constructFromParams) {
+ const RdataFields::FieldSpec spec(RdataFields::DATA, 4);
+ const RdataFields fields(&spec, sizeof(spec), in_a_data,
+ sizeof(in_a_data));
+ constructCommonTests(fields, in_a_data, sizeof(in_a_data));
+}
+
+//
+// NS RDATA: containing a compressible name.
+//
+void
+RdataFieldsTest::constructCommonTestsNS(const RdataFields& fields) {
+ EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
+ EXPECT_EQ(1, fields.getFieldCount());
+ EXPECT_EQ(RdataFields::COMPRESSIBLE_NAME, fields.getFieldSpec(0).type);
+ EXPECT_EQ(ns_name.getLength(), fields.getFieldSpec(0).len);
+
+ expected_wire.clear();
+ UnitTestUtil::readWireData("rdatafields1.wire", expected_wire);
+ other_name.toWire(obuffer);
+ fields.toWire(obuffer);
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
+
+ expected_wire.clear();
+ UnitTestUtil::readWireData("rdatafields2.wire", expected_wire);
+ other_name.toWire(renderer);
+ fields.toWire(renderer);
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(RdataFieldsTest, constructFromRdataNS) {
+ const RdataFields fields_ns((generic::NS(ns_name)));
+ constructCommonTestsNS(fields_ns);
+}
+
+TEST_F(RdataFieldsTest, constructFromParamsNS) {
+ const RdataFields::FieldSpec spec(RdataFields::COMPRESSIBLE_NAME,
+ sizeof(ns_data));
+ const RdataFields fields_ns(&spec, sizeof(spec), ns_data, sizeof(ns_data));
+ constructCommonTestsNS(fields_ns);
+}
+
+//
+// TXT RDATA: multiple fields, lengths vary
+//
+void
+RdataFieldsTest::constructCommonTestsTXT(const RdataFields& fields) {
+ // Since all fields are plain data, they are handled as a single data
+ // field.
+ EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
+ EXPECT_EQ(1, fields.getFieldCount());
+ EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
+ EXPECT_EQ(expected_wire.size(), fields.getFieldSpec(0).len);
+
+ fields.toWire(obuffer);
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
+
+ fields.toWire(renderer);
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(RdataFieldsTest, constructFromRdataTXT) {
+ UnitTestUtil::readWireData("rdatafields3.wire", expected_wire);
+ InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
+ const uint16_t rdlen = ibuffer.readUint16();
+ const RdataFields fields(generic::TXT(ibuffer, rdlen));
+
+ // drop the RDLEN part
+ expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
+
+ constructCommonTestsTXT(fields);
+}
+
+TEST_F(RdataFieldsTest, constructFromParamsTXT) {
+ UnitTestUtil::readWireData("rdatafields3.wire", expected_wire);
+ expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
+ const RdataFields::FieldSpec spec(RdataFields::DATA, expected_wire.size());
+ const RdataFields fields(&spec, sizeof(spec), &expected_wire[0],
+ expected_wire.size());
+ constructCommonTestsTXT(fields);
+}
+
+//
+// RRSIG: multiple fields, with an incompressible name
+//
+void
+RdataFieldsTest::constructCommonTestsRRSIG(const RdataFields& fields) {
+ // In terms of RdataFields RRSIG RDATA consists of 3 fields:
+ // - 18-byte data field (from the "type covered" field to "key tag" field)
+ // - an incompressible name field (for the signer's name field).
+ // this is a variable length field. In this test it's a 13-byte field.
+ // - a variable-length data field for the signature. In this tests
+ // it's a 15-byte field.
+ EXPECT_EQ(3 * sizeof(RdataFields::FieldSpec),
+ fields.getFieldSpecDataSize());
+ EXPECT_EQ(3, fields.getFieldCount());
+ EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
+ EXPECT_EQ(18, fields.getFieldSpec(0).len);
+ EXPECT_EQ(RdataFields::INCOMPRESSIBLE_NAME, fields.getFieldSpec(1).type);
+ EXPECT_EQ(13, fields.getFieldSpec(1).len);
+ EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(2).type);
+ EXPECT_EQ(15, fields.getFieldSpec(2).len);
+
+ expected_wire.clear();
+ UnitTestUtil::readWireData("rdatafields5.wire", expected_wire);
+ Name("com").toWire(obuffer);
+ obuffer.writeUint16(fields.getDataLength());
+ fields.toWire(obuffer);
+ other_name.toWire(obuffer);
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
+
+ expected_wire.clear();
+ UnitTestUtil::readWireData("rdatafields6.wire", expected_wire);
+ Name("com").toWire(renderer);
+ renderer.writeUint16(fields.getDataLength());
+ fields.toWire(renderer); // the signer field won't be compressed
+ other_name.toWire(renderer); // but will be used as a compression target
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(RdataFieldsTest, constructFromRdataRRSIG) {
+ UnitTestUtil::readWireData("rdatafields4.wire", expected_wire);
+ InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
+ const uint16_t rdlen = ibuffer.readUint16();
+ const RdataFields fields(generic::RRSIG(ibuffer, rdlen));
+
+ // drop the RDLEN part
+ expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
+
+ constructCommonTestsRRSIG(fields);
+}
+
+TEST_F(RdataFieldsTest, constructFromParamsRRSIG) {
+ UnitTestUtil::readWireData("rdatafields4.wire", fields_wire);
+ fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2);
+
+ const RdataFields::FieldSpec specs[] = {
+ RdataFields::FieldSpec(RdataFields::DATA, 18),
+ RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13),
+ RdataFields::FieldSpec(RdataFields::DATA, 15)
+ };
+ const RdataFields fields(specs, sizeof(specs), &fields_wire[0],
+ fields_wire.size());
+ constructCommonTestsRRSIG(fields);
+}
+
+TEST_F(RdataFieldsTest, convertRdatatoParams) {
+ // Confirm we can restore the original data from the serialized data.
+ // We use RRSIG as a relatively complicated field structure.
+ UnitTestUtil::readWireData("rdatafields4.wire", expected_wire);
+ InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
+ const uint16_t rdlen = ibuffer.readUint16();
+ const RdataFields fields(generic::RRSIG(ibuffer, rdlen));
+
+ expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
+
+ // Copy the data in separate storage
+ vector<uint8_t> spec_store(fields.getFieldSpecDataSize());
+ void* cp_spec = &spec_store[0];
+ memcpy(cp_spec, fields.getFieldSpecData(), spec_store.size());
+ vector<uint8_t> data_store(fields.getDataLength());
+ memcpy(&data_store[0], fields.getData(), fields.getDataLength());
+
+ // Restore the data in the form of RdataFields
+ const RdataFields fields_byparams(cp_spec, fields.getFieldSpecDataSize(),
+ &data_store[0], fields.getDataLength());
+
+ // Check it's valid
+ constructCommonTestsRRSIG(fields_byparams);
+}
+
+//
+// OPT: an empty RDATA
+//
+void
+RdataFieldsTest::constructCommonTestsOPT(const RdataFields& fields) {
+ EXPECT_EQ(0, fields.getFieldSpecDataSize());
+ EXPECT_EQ(0, fields.getFieldCount());
+ EXPECT_EQ(0, fields.getDataLength());
+ EXPECT_EQ((const uint8_t*) NULL, fields.getData());
+ fields.toWire(obuffer);
+ EXPECT_EQ(0, obuffer.getLength());
+ fields.toWire(renderer);
+ EXPECT_EQ(0, renderer.getLength());
+}
+
+TEST_F(RdataFieldsTest, constructFromRdataOPT) {
+ InputBuffer ibuffer(NULL, 0);
+ const RdataFields fields(generic::OPT(ibuffer, 0));
+ constructCommonTestsOPT(fields);
+}
+
+TEST_F(RdataFieldsTest, constructFromParamsOPT) {
+ const RdataFields fields(NULL, 0, NULL, 0);
+ constructCommonTestsOPT(fields);
+}
+
+// Invalid input to the "from parameter" constructor: sum of the field lengths
+// is not equal to the data length.
+TEST_F(RdataFieldsTest, invalidFieldLength) {
+ UnitTestUtil::readWireData("rdatafields4.wire", fields_wire);
+ fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2);
+
+ const RdataFields::FieldSpec specs[] = {
+ RdataFields::FieldSpec(RdataFields::DATA, 18),
+ RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13),
+ RdataFields::FieldSpec(RdataFields::DATA, 14)
+ };
+ // sum of field len < data len
+ EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0], fields_wire.size()),
+ isc::InvalidParameter);
+ // sum of field len > data len
+ EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0],
+ fields_wire.size() - 2),
+ isc::InvalidParameter);
+}
+
+// Invalid input to the "from parameter" constructor: NULL vs length mismatch
+TEST_F(RdataFieldsTest, mismatchFieldLengthAndData) {
+ const unsigned char dummy_data = 0;
+ const RdataFields::FieldSpec dummy_spec(RdataFields::DATA, 1);
+
+ EXPECT_THROW(RdataFields(NULL, 1, &dummy_data, 1), isc::InvalidParameter);
+ EXPECT_THROW(RdataFields(&dummy_spec, 0, NULL, 0), isc::InvalidParameter);
+ EXPECT_THROW(RdataFields(&dummy_spec, 1, NULL, 1), isc::InvalidParameter);
+ EXPECT_THROW(RdataFields(NULL, 0, &dummy_data, 0), isc::InvalidParameter);
+}
+
+// Bogus input to getFieldSpec()
+TEST_F(RdataFieldsTest, getFieldSpecWithBadFieldId) {
+ const RdataFields fields_in_a(in::A("192.0.2.1"));
+ EXPECT_THROW(fields_in_a.getFieldSpec(1), isc::OutOfRange);
+}
+
+// Tests for unexpected methods in RdataFieldComposerTest. Confirm
+// a call to these methods triggers an exception. Expected methods are
+// tested via other tests above.
+class DummyRdata : public Rdata {
+public:
+ enum Mode { CLEAR, SKIP, TRIM };
+ explicit DummyRdata(Mode mode) : mode_(mode) {}
+ DummyRdata(const DummyRdata& source) : Rdata(), mode_(source.mode_) {}
+ virtual ~DummyRdata() {}
+ virtual void toWire(AbstractMessageRenderer& renderer) const {
+ // call the unexpected method corresponding to the test mode.
+ // method parameters don't matter.
+ switch (mode_) {
+ case CLEAR:
+ renderer.clear();
+ break;
+ case SKIP:
+ renderer.skip(2);
+ break;
+ case TRIM:
+ renderer.trim(2);
+ break;
+ }
+ }
+
+ // These are defined only to make the compiler happy. We don't use them
+ // for the test.
+ virtual string toText() const { return (""); }
+ virtual void toWire(OutputBuffer&) const {}
+ virtual int compare(const Rdata&) const { return (0); }
+private:
+ const int mode_;
+};
+
+TEST(RdataFieldComposerTest, unusedMethods) {
+ EXPECT_THROW(RdataFields(DummyRdata(DummyRdata::CLEAR)), isc::Unexpected);
+}
+}
diff --git a/src/lib/dns/tests/rrclass_unittest.cc b/src/lib/dns/tests/rrclass_unittest.cc
new file mode 100644
index 0000000..ae85f01
--- /dev/null
+++ b/src/lib/dns/tests/rrclass_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright (C) 2010-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <gtest/gtest.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rrclass.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/scoped_ptr.hpp>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using boost::scoped_ptr;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class RRClassTest : public ::testing::Test {
+protected:
+ RRClassTest() : obuffer(0) {}
+
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+
+ static RRClass rrclassFactoryFromWire(const char* datafile);
+ static const RRClass rrclass_1, rrclass_0x80, rrclass_0x800,
+ rrclass_0x8000, rrclass_max;
+ static const uint8_t wiredata[];
+};
+
+const RRClass RRClassTest::rrclass_1(1);
+const RRClass RRClassTest::rrclass_0x80(0x80);
+const RRClass RRClassTest::rrclass_0x800(0x800);
+const RRClass RRClassTest::rrclass_0x8000(0x8000);
+const RRClass RRClassTest::rrclass_max(0xffff);
+// This is wire-format data for the above sample RRClass rendered in the
+// appearing order.
+const uint8_t RRClassTest::wiredata[] = { 0x00, 0x01, 0x00, 0x80, 0x08,
+ 0x00, 0x80, 0x00, 0xff, 0xff };
+
+RRClass
+RRClassTest::rrclassFactoryFromWire(const char* datafile) {
+ std::vector<unsigned char> data;
+ UnitTestUtil::readWireData(datafile, data);
+
+ InputBuffer buffer(&data[0], data.size());
+
+ return (RRClass(buffer));
+}
+
+TEST_F(RRClassTest, fromTextConstructor) {
+ EXPECT_EQ("IN", RRClass("IN").toText());
+ EXPECT_EQ("CH", RRClass("CH").toText());
+
+ EXPECT_EQ("CLASS65535", RRClass("CLASS65535").toText());
+
+ // some uncommon cases: see the corresponding RRType tests.
+ EXPECT_EQ(53, RRClass("CLASS00053").getCode());
+ EXPECT_THROW(RRClass("CLASS000053"), InvalidRRClass);
+
+ // bogus CLASSnnn representations: should trigger an exception
+ EXPECT_THROW(RRClass("CLASS"), InvalidRRClass);
+ EXPECT_THROW(RRClass("CLASS-1"), InvalidRRClass);
+ EXPECT_THROW(RRClass("CLASSxxx"), InvalidRRClass);
+ EXPECT_THROW(RRClass("CLASS65536"), InvalidRRClass);
+ EXPECT_THROW(RRClass("CLASS6500x"), InvalidRRClass);
+ EXPECT_THROW(RRClass("CLASS65000 "), InvalidRRClass);
+}
+
+TEST_F(RRClassTest, fromWire) {
+ EXPECT_EQ(0x1234,
+ rrclassFactoryFromWire("rrcode16_fromWire1").getCode());
+ EXPECT_THROW(rrclassFactoryFromWire("rrcode16_fromWire2"),
+ IncompleteRRClass);
+}
+
+TEST_F(RRClassTest, caseConstruct) {
+ EXPECT_EQ("IN", RRClass("in").toText());
+ EXPECT_EQ("CH", RRClass("ch").toText());
+ EXPECT_EQ("CLASS65535", RRClass("class65535").toText());
+}
+
+TEST_F(RRClassTest, toText) {
+ EXPECT_EQ("IN", RRClass(1).toText());
+ EXPECT_EQ("CLASS65000", RRClass(65000).toText());
+}
+
+TEST_F(RRClassTest, createFromText) {
+ scoped_ptr<RRClass> chclass(RRClass::createFromText("CH"));
+ EXPECT_TRUE(chclass);
+ EXPECT_EQ("CH", chclass->toText());
+
+ scoped_ptr<RRClass> zzclass(RRClass::createFromText("ZZ"));
+ EXPECT_FALSE(zzclass);
+}
+
+TEST_F(RRClassTest, toWireBuffer) {
+ rrclass_1.toWire(obuffer);
+ rrclass_0x80.toWire(obuffer);
+ rrclass_0x800.toWire(obuffer);
+ rrclass_0x8000.toWire(obuffer);
+ rrclass_max.toWire(obuffer);
+
+ matchWireData(wiredata, sizeof (wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(RRClassTest, toWireRenderer) {
+ rrclass_1.toWire(renderer);
+ rrclass_0x80.toWire(renderer);
+ rrclass_0x800.toWire(renderer);
+ rrclass_0x8000.toWire(renderer);
+ rrclass_max.toWire(renderer);
+
+ matchWireData(wiredata, sizeof (wiredata),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(RRClassTest, wellKnownClass) {
+ EXPECT_EQ(1, RRClass::IN().getCode());
+ EXPECT_EQ("IN", RRClass::IN().toText());
+}
+
+TEST_F(RRClassTest, compare) {
+ EXPECT_TRUE(RRClass(1) == RRClass("IN"));
+ EXPECT_TRUE(RRClass(1).equals(RRClass("IN")));
+ EXPECT_TRUE(RRClass(0).nequals(RRClass("IN")));
+
+ EXPECT_TRUE(RRClass("IN") < RRClass("CH"));
+ EXPECT_TRUE(RRClass(100) < RRClass(65535));
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(RRClassTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << RRClass::IN();
+ EXPECT_EQ(RRClass::IN().toText(), oss.str());
+}
+
+// Below, we'll check definitions for all well-known RR classes; whether they
+// are defined and have the correct parameter values. Test data are generated
+// from the list available at:
+// http://www.iana.org/assignments/dns-parameters/dns-parameters.xml
+struct ClassParam {
+ const char* const txt; // "IN", "CH", etc
+ const uint16_t code; // 1, 3,
+ const RRClass& (*obj)(); // RRClass::IN(), etc
+} known_classes[] = {
+ {"IN", 1, RRClass::IN}, {"CH", 3, RRClass::CH}, {"HS", 4, RRClass::HS},
+ {"NONE", 254, RRClass::NONE}, {"ANY", 255, RRClass::ANY},
+ {NULL, 0, NULL}
+};
+
+TEST(RRClassConstTest, wellKnowns) {
+ for (int i = 0; known_classes[i].txt; ++i) {
+ SCOPED_TRACE("Checking well known RRClass: " +
+ string(known_classes[i].txt));
+ EXPECT_EQ(known_classes[i].code,
+ RRClass(known_classes[i].txt).getCode());
+ EXPECT_EQ(known_classes[i].code,
+ (*known_classes[i].obj)().getCode());
+ }
+}
+}
diff --git a/src/lib/dns/tests/rrcollator_unittest.cc b/src/lib/dns/tests/rrcollator_unittest.cc
new file mode 100644
index 0000000..4247911
--- /dev/null
+++ b/src/lib/dns/tests/rrcollator_unittest.cc
@@ -0,0 +1,208 @@
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/name.h>
+#include <dns/master_loader.h>
+#include <dns/master_loader_callbacks.h>
+#include <dns/rrclass.h>
+#include <dns/rrcollator.h>
+#include <dns/rdata.h>
+#include <dns/rrset.h>
+#include <dns/rrttl.h>
+
+#include <gtest/gtest.h>
+
+#include <functional>
+#include <sstream>
+#include <vector>
+
+using std::vector;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+namespace ph = std::placeholders;
+
+namespace {
+
+typedef RRCollator::AddRRsetCallback AddRRsetCallback;
+
+void
+addRRset(const RRsetPtr& rrset, vector<ConstRRsetPtr>* to_append,
+ const bool* do_throw) {
+ if (*do_throw) {
+ isc_throw(isc::Unexpected, "faked failure");
+ }
+ to_append->push_back(rrset);
+}
+
+class RRCollatorTest : public ::testing::Test {
+protected:
+ RRCollatorTest() :
+ origin_("example.com"), rrclass_(RRClass::IN()), rrttl_(3600),
+ throw_from_callback_(false),
+ collator_(std::bind(addRRset, ph::_1, &rrsets_, &throw_from_callback_)),
+ rr_callback_(collator_.getCallback()),
+ a_rdata1_(createRdata(RRType::A(), rrclass_, "192.0.2.1")),
+ a_rdata2_(createRdata(RRType::A(), rrclass_, "192.0.2.2")),
+ txt_rdata_(createRdata(RRType::TXT(), rrclass_, "test")),
+ sig_rdata1_(createRdata(RRType::RRSIG(), rrclass_,
+ "A 5 3 3600 20000101000000 20000201000000 "
+ "12345 example.com. FAKE")),
+ sig_rdata2_(createRdata(RRType::RRSIG(), rrclass_,
+ "NS 5 3 3600 20000101000000 20000201000000 "
+ "12345 example.com. FAKE"))
+ {}
+
+ void checkRRset(const Name& expected_name, const RRClass& expected_class,
+ const RRType& expected_type, const RRTTL& expected_ttl,
+ const vector<ConstRdataPtr>& expected_rdatas) {
+ SCOPED_TRACE(expected_name.toText(true) + "/" +
+ expected_class.toText() + "/" + expected_type.toText());
+
+ // This test always clears rrsets_ to confirm RRsets are added
+ // one-by-one
+ ASSERT_EQ(1, rrsets_.size());
+
+ ConstRRsetPtr actual = rrsets_[0];
+ EXPECT_EQ(expected_name, actual->getName());
+ EXPECT_EQ(expected_class, actual->getClass());
+ EXPECT_EQ(expected_type, actual->getType());
+ EXPECT_EQ(expected_ttl, actual->getTTL());
+ ASSERT_EQ(expected_rdatas.size(), actual->getRdataCount());
+ vector<ConstRdataPtr>::const_iterator it = expected_rdatas.begin();
+ for (RdataIteratorPtr rit = actual->getRdataIterator();
+ !rit->isLast();
+ rit->next()) {
+ EXPECT_EQ(0, rit->getCurrent().compare(**it));
+ ++it;
+ }
+
+ rrsets_.clear();
+ }
+
+ const Name origin_;
+ const RRClass rrclass_;
+ const RRTTL rrttl_;
+ vector<ConstRRsetPtr> rrsets_;
+ bool throw_from_callback_;
+ RRCollator collator_;
+ AddRRCallback rr_callback_;
+ const RdataPtr a_rdata1_, a_rdata2_, txt_rdata_, sig_rdata1_, sig_rdata2_;
+ vector<ConstRdataPtr> rdatas_; // placeholder for expected data
+};
+
+TEST_F(RRCollatorTest, basicCases) {
+ // Add two RRs belonging to the same RRset. These will be buffered.
+ rr_callback_(origin_, rrclass_, RRType::A(), rrttl_, a_rdata1_);
+ EXPECT_TRUE(rrsets_.empty()); // not yet given as an RRset
+ rr_callback_(origin_, rrclass_, RRType::A(), rrttl_, a_rdata2_);
+ EXPECT_TRUE(rrsets_.empty()); // still not given
+
+ // Add another type of RR. This completes the construction of the A RRset,
+ // which will be given via the callback.
+ rr_callback_(origin_, rrclass_, RRType::TXT(), rrttl_, txt_rdata_);
+ rdatas_.push_back(a_rdata1_);
+ rdatas_.push_back(a_rdata2_);
+ checkRRset(origin_, rrclass_, RRType::A(), rrttl_, rdatas_);
+
+ // Add the same type of RR but of different name. This should make another
+ // callback for the previous TXT RR.
+ rr_callback_(Name("txt.example.com"), rrclass_, RRType::TXT(), rrttl_,
+ txt_rdata_);
+ rdatas_.clear();
+ rdatas_.push_back(txt_rdata_);
+ checkRRset(origin_, rrclass_, RRType::TXT(), rrttl_, rdatas_);
+
+ // Add the same type and name of RR but of different class (rare case
+ // in practice)
+ rr_callback_(Name("txt.example.com"), RRClass::CH(), RRType::TXT(), rrttl_,
+ txt_rdata_);
+ rdatas_.clear();
+ rdatas_.push_back(txt_rdata_);
+ checkRRset(Name("txt.example.com"), rrclass_, RRType::TXT(), rrttl_,
+ rdatas_);
+
+ // Tell the collator we are done, then we'll see the last RR as an RRset.
+ collator_.flush();
+ checkRRset(Name("txt.example.com"), RRClass::CH(), RRType::TXT(), rrttl_,
+ rdatas_);
+
+ // Redundant flush() will be no-op.
+ collator_.flush();
+ EXPECT_TRUE(rrsets_.empty());
+}
+
+TEST_F(RRCollatorTest, minTTLFirst) {
+ // RRs of the same RRset but has different TTLs. The first RR has
+ // the smaller TTL, which should be used for the TTL of the RRset.
+ rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(10), a_rdata1_);
+ rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(20), a_rdata2_);
+ rdatas_.push_back(a_rdata1_);
+ rdatas_.push_back(a_rdata2_);
+ collator_.flush();
+ checkRRset(origin_, rrclass_, RRType::A(), RRTTL(10), rdatas_);
+}
+
+TEST_F(RRCollatorTest, maxTTLFirst) {
+ // RRs of the same RRset but has different TTLs. The second RR has
+ // the smaller TTL, which should be used for the TTL of the RRset.
+ rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(20), a_rdata1_);
+ rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(10), a_rdata2_);
+ rdatas_.push_back(a_rdata1_);
+ rdatas_.push_back(a_rdata2_);
+ collator_.flush();
+ checkRRset(origin_, rrclass_, RRType::A(), RRTTL(10), rdatas_);
+}
+
+TEST_F(RRCollatorTest, addRRSIGs) {
+ // RRSIG is special; they are also distinguished by their covered types.
+ rr_callback_(origin_, rrclass_, RRType::RRSIG(), rrttl_, sig_rdata1_);
+ rr_callback_(origin_, rrclass_, RRType::RRSIG(), rrttl_, sig_rdata2_);
+
+ rdatas_.push_back(sig_rdata1_);
+ checkRRset(origin_, rrclass_, RRType::RRSIG(), rrttl_, rdatas_);
+}
+
+TEST_F(RRCollatorTest, emptyFlush) {
+ collator_.flush();
+ EXPECT_TRUE(rrsets_.empty());
+}
+
+TEST_F(RRCollatorTest, throwFromCallback) {
+ // Adding an A RR
+ rr_callback_(origin_, rrclass_, RRType::A(), rrttl_, a_rdata1_);
+
+ // Adding a TXT RR, which would trigger RRset callback, but in this test
+ // it throws. The added TXT RR will be effectively lost.
+ throw_from_callback_ = true;
+ EXPECT_THROW(rr_callback_(origin_, rrclass_, RRType::TXT(), rrttl_,
+ txt_rdata_), isc::Unexpected);
+
+ // We'll only see the A RR.
+ throw_from_callback_ = false;
+ collator_.flush();
+ rdatas_.push_back(a_rdata1_);
+ checkRRset(origin_, rrclass_, RRType::A(), rrttl_, rdatas_);
+}
+
+TEST_F(RRCollatorTest, withMasterLoader) {
+ // Test a simple case with MasterLoader. There shouldn't be anything
+ // special, but that's the mainly intended usage of the collator, so we
+ // check it explicitly.
+ std::istringstream ss("example.com. 3600 IN A 192.0.2.1\n");
+ MasterLoader loader(ss, origin_, rrclass_,
+ MasterLoaderCallbacks::getNullCallbacks(),
+ collator_.getCallback());
+ loader.load();
+ collator_.flush();
+ rdatas_.push_back(a_rdata1_);
+ checkRRset(origin_, rrclass_, RRType::A(), rrttl_, rdatas_);
+}
+
+}
diff --git a/src/lib/dns/tests/rrparamregistry_unittest.cc b/src/lib/dns/tests/rrparamregistry_unittest.cc
new file mode 100644
index 0000000..90574d0
--- /dev/null
+++ b/src/lib/dns/tests/rrparamregistry_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright (C) 2010-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+#include <sstream>
+
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/rrclass.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrparamregistry.h>
+#include <dns/rrtype.h>
+#include <dns/master_loader.h>
+
+#include <boost/scoped_ptr.hpp>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+
+namespace {
+class RRParamRegistryTest : public ::testing::Test {
+protected:
+ RRParamRegistryTest()
+ {
+ ostringstream oss1;
+ oss1 << test_class_code;
+ // cppcheck-suppress useInitializationList
+ test_class_unknown_str = "CLASS" + oss1.str();
+
+ ostringstream oss2;
+ oss2 << test_type_code;
+ test_type_unknown_str = "TYPE" + oss2.str();
+ }
+ ~RRParamRegistryTest()
+ {
+ // cleanup any non well-known parameters that possibly remain
+ // as a side effect.
+ RRParamRegistry::getRegistry().removeType(test_type_code);
+ RRParamRegistry::getRegistry().removeClass(test_class_code);
+ RRParamRegistry::getRegistry().removeRdataFactory(
+ RRType(test_type_code), RRClass(test_class_code));
+ RRParamRegistry::getRegistry().removeRdataFactory(
+ RRType(test_type_code));
+ }
+
+ string test_class_unknown_str;
+ string test_type_unknown_str;
+
+ // we assume class/type numbers are officially unassigned. If not we'll
+ // need to update the test cases.
+ static const uint16_t test_class_code = 65533;
+ static const uint16_t test_type_code = 65534;
+ static const string test_class_str;
+ static const string test_type_str;
+};
+
+const string RRParamRegistryTest::test_class_str("TESTCLASS");
+const string RRParamRegistryTest::test_type_str("TESTTYPE");
+
+TEST_F(RRParamRegistryTest, addRemove) {
+ RRParamRegistry::getRegistry().addType(test_type_str, test_type_code);
+ RRParamRegistry::getRegistry().addClass(test_class_str, test_class_code);
+ EXPECT_EQ(65533, RRClass("TESTCLASS").getCode());
+ EXPECT_EQ(65534, RRType("TESTTYPE").getCode());
+
+ // the first removal attempt should succeed
+ EXPECT_TRUE(RRParamRegistry::getRegistry().removeType(test_type_code));
+ // then toText() should treat it as an "unknown"
+ EXPECT_EQ(test_type_unknown_str, RRType(test_type_code).toText());
+ // attempt of removing non-existent mapping should result in 'false'
+ EXPECT_FALSE(RRParamRegistry::getRegistry().removeType(test_type_code));
+
+ // same set of tests for RR class.
+ EXPECT_TRUE(RRParamRegistry::getRegistry().removeClass(test_class_code));
+ EXPECT_EQ(test_class_unknown_str, RRClass(test_class_code).toText());
+ EXPECT_FALSE(RRParamRegistry::getRegistry().removeClass(test_class_code));
+}
+
+TEST_F(RRParamRegistryTest, addError) {
+ // An attempt to override a pre-registered class should fail with an
+ // exception, and the pre-registered one should remain in the registry.
+ EXPECT_THROW(RRParamRegistry::getRegistry().addClass(test_class_str, 1),
+ RRClassExists);
+ EXPECT_EQ("IN", RRClass(1).toText());
+
+ // Same for RRType
+ EXPECT_THROW(RRParamRegistry::getRegistry().addType(test_type_str, 1),
+ RRTypeExists);
+ EXPECT_EQ("A", RRType(1).toText());
+}
+
+class TestRdataFactory : public AbstractRdataFactory {
+public:
+ virtual RdataPtr create(const string& rdata_str) const
+ { return (RdataPtr(new in::A(rdata_str))); }
+ virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const
+ { return (RdataPtr(new in::A(buffer, rdata_len))); }
+ virtual RdataPtr create(const Rdata& source) const
+ { return (RdataPtr(new in::A(dynamic_cast<const in::A&>(source)))); }
+ virtual RdataPtr create(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options options,
+ MasterLoaderCallbacks& callbacks) const
+ { return (RdataPtr(new in::A(lexer, origin, options, callbacks))); }
+};
+
+TEST_F(RRParamRegistryTest, addRemoveFactory) {
+ // By default, the test type/code pair should be considered "unknown",
+ // so the following should trigger an exception.
+ EXPECT_THROW(createRdata(RRType(test_type_code), RRClass(test_class_code),
+ "192.0.2.1"),
+ InvalidRdataText);
+ // Add factories so that we can treat this pair just like in::A.
+ RRParamRegistry::getRegistry().add(test_type_str, test_type_code,
+ test_class_str, test_class_code,
+ RdataFactoryPtr(new TestRdataFactory));
+ // Now it should be accepted, and should be identical to the same data of
+ // in::A.
+ EXPECT_EQ(0, in::A("192.0.2.1").compare(
+ *createRdata(RRType(test_type_code), RRClass(test_class_code),
+ "192.0.2.1")));
+ // It should still fail with other classes as we specified the factories
+ // as class-specific.
+ EXPECT_THROW(createRdata(RRType(test_type_code), RRClass("IN"),
+ "192.0.2.1"),
+ InvalidRdataText);
+ // Add the factories also as a class independent RRtype
+ RRParamRegistry::getRegistry().add(test_type_str, test_type_code,
+ RdataFactoryPtr(new TestRdataFactory));
+ // Now it should be okay for other classes than the test class.
+ EXPECT_EQ(0, in::A("192.0.2.1").compare(
+ *createRdata(RRType(test_type_code), RRClass("IN"),
+ "192.0.2.1")));
+
+ // Remove the added factories: first attempt should succeed; the second
+ // should return false as there's no match
+ EXPECT_TRUE(RRParamRegistry::getRegistry().removeRdataFactory(
+ RRType(test_type_code), RRClass(test_class_code)));
+ EXPECT_FALSE(RRParamRegistry::getRegistry().removeRdataFactory(
+ RRType(test_type_code), RRClass(test_class_code)));
+ EXPECT_TRUE(RRParamRegistry::getRegistry().removeRdataFactory(
+ RRType(test_type_code)));
+ EXPECT_FALSE(RRParamRegistry::getRegistry().removeRdataFactory(
+ RRType(test_type_code)));
+}
+
+RdataPtr
+createRdataHelper(const std::string& str) {
+ boost::scoped_ptr<AbstractRdataFactory> rdf(new TestRdataFactory);
+
+ std::stringstream ss(str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ MasterLoaderCallbacks callbacks(MasterLoaderCallbacks::getNullCallbacks());
+ const Name origin("example.org.");
+
+ return (rdf->create(lexer, &origin,
+ MasterLoader::MANY_ERRORS,
+ callbacks));
+}
+
+TEST_F(RRParamRegistryTest, createFromLexer) {
+ // This test basically checks that the string version of
+ // AbstractRdataFactory::create() is called by the MasterLexer
+ // variant of create().
+ EXPECT_EQ(0, in::A("192.168.0.1").compare(
+ *createRdataHelper("192.168.0.1")));
+
+ // This should parse only up to the end of line. Everything that
+ // comes afterwards is not parsed.
+ EXPECT_EQ(0, in::A("192.168.0.42").compare(
+ *createRdataHelper("192.168.0.42\na b c d e f")));
+}
+
+}
diff --git a/src/lib/dns/tests/rrset_collection_unittest.cc b/src/lib/dns/tests/rrset_collection_unittest.cc
new file mode 100644
index 0000000..be16ab5
--- /dev/null
+++ b/src/lib/dns/tests/rrset_collection_unittest.cc
@@ -0,0 +1,240 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/rrset_collection.h>
+#include <dns/rrttl.h>
+#include <dns/rdataclass.h>
+
+#include <gtest/gtest.h>
+
+#include <list>
+#include <fstream>
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using namespace std;
+
+namespace {
+
+class RRsetCollectionTest : public ::testing::Test {
+public:
+ RRsetCollectionTest() :
+ rrclass("IN"),
+ origin("example.org"),
+ collection(TEST_DATA_SRCDIR "/example.org", origin, rrclass)
+ {}
+
+ const RRClass rrclass;
+ const Name origin;
+ RRsetCollection collection;
+};
+
+TEST_F(RRsetCollectionTest, istreamConstructor) {
+ std::ifstream fs(TEST_DATA_SRCDIR "/example.org");
+ RRsetCollection collection2(fs, origin, rrclass);
+
+ RRsetCollectionBase::Iterator iter = collection.begin();
+ RRsetCollectionBase::Iterator iter2 = collection2.begin();
+ while (iter != collection.end()) {
+ ASSERT_TRUE(iter2 != collection2.end());
+ EXPECT_EQ((*iter).toText(), (*iter2).toText());
+ ++iter;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter2 == collection2.end());
+}
+
+template <typename T, typename TP>
+void doFind(T& collection, const RRClass& rrclass) {
+ // Test the find() that returns ConstRRsetPtr
+ TP rrset = collection.find(Name("www.example.org"), rrclass, RRType::A());
+ EXPECT_TRUE(rrset);
+ EXPECT_EQ(RRType::A(), rrset->getType());
+ EXPECT_EQ(RRTTL(3600), rrset->getTTL());
+ EXPECT_EQ(RRClass("IN"), rrset->getClass());
+ EXPECT_EQ(Name("www.example.org"), rrset->getName());
+
+ // foo.example.org doesn't exist
+ rrset = collection.find(Name("foo.example.org"), rrclass, RRType::A());
+ EXPECT_FALSE(rrset);
+
+ // www.example.org exists, but not with MX
+ rrset = collection.find(Name("www.example.org"), rrclass, RRType::MX());
+ EXPECT_FALSE(rrset);
+
+ // www.example.org exists, with AAAA
+ rrset = collection.find(Name("www.example.org"), rrclass, RRType::AAAA());
+ EXPECT_TRUE(rrset);
+
+ // www.example.org with AAAA does not exist in RRClass::CH()
+ rrset = collection.find(Name("www.example.org"), RRClass::CH(),
+ RRType::AAAA());
+ EXPECT_FALSE(rrset);
+}
+
+TEST_F(RRsetCollectionTest, findConst) {
+ // Test the find() that returns ConstRRsetPtr
+ const RRsetCollection& ccln = collection;
+ doFind<const RRsetCollection, ConstRRsetPtr>(ccln, rrclass);
+}
+
+TEST_F(RRsetCollectionTest, find) {
+ // Test the find() that returns RRsetPtr
+ doFind<RRsetCollection, RRsetPtr>(collection, rrclass);
+}
+
+void
+doAddAndRemove(RRsetCollection& collection, const RRClass& rrclass) {
+ // foo.example.org/A doesn't exist
+ RRsetPtr rrset_found = collection.find(Name("foo.example.org"), rrclass,
+ RRType::A());
+ EXPECT_FALSE(rrset_found);
+
+ // Add foo.example.org/A
+ RRsetPtr rrset(new BasicRRset(Name("foo.example.org"), rrclass, RRType::A(),
+ RRTTL(7200)));
+ rrset->addRdata(in::A("192.0.2.1"));
+ collection.addRRset(rrset);
+
+ // foo.example.org/A should now exist
+ rrset_found = collection.find(Name("foo.example.org"), rrclass,
+ RRType::A());
+ EXPECT_TRUE(rrset_found);
+ EXPECT_EQ(RRType::A(), rrset_found->getType());
+ EXPECT_EQ(RRTTL(7200), rrset_found->getTTL());
+ EXPECT_EQ(RRClass("IN"), rrset_found->getClass());
+ EXPECT_EQ(Name("foo.example.org"), rrset_found->getName());
+
+ // The collection must not be empty.
+ EXPECT_TRUE(collection.end() != collection.begin());
+
+ // Adding a duplicate RRset must throw.
+ EXPECT_THROW({
+ collection.addRRset(rrset);
+ }, isc::InvalidParameter);
+
+ // Remove foo.example.org/A, which should pass
+ EXPECT_TRUE(collection.removeRRset(Name("foo.example.org"),
+ rrclass, RRType::A()));
+ // foo.example.org/A should not exist now
+ rrset_found = collection.find(Name("foo.example.org"), rrclass,
+ RRType::A());
+ EXPECT_FALSE(rrset_found);
+
+ // Removing foo.example.org/A should fail now
+ EXPECT_FALSE(collection.removeRRset(Name("foo.example.org"),
+ rrclass, RRType::A()));
+}
+
+TEST_F(RRsetCollectionTest, addAndRemove) {
+ doAddAndRemove(collection, rrclass);
+}
+
+TEST_F(RRsetCollectionTest, empty) {
+ RRsetCollection cln;
+
+ // Here, cln is empty.
+ EXPECT_TRUE(cln.end() == cln.begin());
+
+ doAddAndRemove(cln, rrclass);
+
+ // cln should be empty again here, after the add and remove
+ // operations.
+ EXPECT_TRUE(cln.end() == cln.begin());
+}
+
+TEST_F(RRsetCollectionTest, iteratorTest) {
+ // The collection must not be empty.
+ EXPECT_TRUE(collection.end() != collection.begin());
+
+ // Here, we just count the records and do some basic tests on them.
+ size_t count = 0;
+ for (RRsetCollection::Iterator it = collection.begin();
+ it != collection.end(); ++it) {
+ ++count;
+ const AbstractRRset& rrset = *it;
+ EXPECT_EQ(rrclass, rrset.getClass());
+ EXPECT_EQ(RRTTL(3600), rrset.getTTL());
+ }
+
+ // example.org master file has SOA, NS, A, AAAA
+ EXPECT_EQ(4, count);
+}
+
+// This is a dummy class which is used in iteratorCompareDifferent test
+// to compare iterators from different RRsetCollectionBase
+// implementations.
+class MyRRsetCollection : public RRsetCollectionBase {
+public:
+ MyRRsetCollection()
+ {}
+
+ virtual isc::dns::ConstRRsetPtr find(const isc::dns::Name&,
+ const isc::dns::RRClass&,
+ const isc::dns::RRType&) const {
+ return (ConstRRsetPtr());
+ }
+
+ typedef std::list<isc::dns::RRset> MyCollection;
+
+protected:
+ class MyIter : public RRsetCollectionBase::Iter {
+ public:
+ MyIter(MyCollection::iterator& iter) :
+ iter_(iter)
+ {}
+
+ virtual const isc::dns::AbstractRRset& getValue() {
+ return (*iter_);
+ }
+
+ virtual IterPtr getNext() {
+ MyCollection::iterator it = iter_;
+ ++it;
+ return (RRsetCollectionBase::IterPtr(new MyIter(it)));
+ }
+
+ virtual bool equals(Iter& other) {
+ const MyIter* other_real = dynamic_cast<MyIter*>(&other);
+ if (other_real == NULL) {
+ return (false);
+ }
+ return (iter_ == other_real->iter_);
+ }
+
+ private:
+ MyCollection::iterator iter_;
+ };
+
+ virtual RRsetCollectionBase::IterPtr getBeginning() {
+ MyCollection::iterator it = dummy_list_.begin();
+ return (RRsetCollectionBase::IterPtr(new MyIter(it)));
+ }
+
+ virtual RRsetCollectionBase::IterPtr getEnd() {
+ MyCollection::iterator it = dummy_list_.end();
+ return (RRsetCollectionBase::IterPtr(new MyIter(it)));
+ }
+
+private:
+ MyCollection dummy_list_;
+};
+
+TEST_F(RRsetCollectionTest, iteratorCompareDifferent) {
+ // Create objects of two different RRsetCollectionBase
+ // implementations.
+ RRsetCollection cln1;
+ MyRRsetCollection cln2;
+
+ // Comparing two iterators from different RRsetCollectionBase
+ // implementations must not throw.
+ EXPECT_TRUE(cln2.begin() != cln1.begin());
+ EXPECT_TRUE(cln1.end() != cln2.end());
+}
+
+} // namespace
diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc
new file mode 100644
index 0000000..0425812
--- /dev/null
+++ b/src/lib/dns/tests/rrset_unittest.cc
@@ -0,0 +1,442 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rrset.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+#include <gtest/gtest.h>
+
+#include <stdexcept>
+#include <sstream>
+
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class RRsetTest : public ::testing::Test {
+protected:
+ RRsetTest() : buffer(0),
+ test_name("test.example.com"),
+ test_domain("example.com"),
+ test_nsname("ns.example.com"),
+ rrset_a(test_name, RRClass::IN(), RRType::A(), RRTTL(3600)),
+ rrset_a_empty(test_name, RRClass::IN(), RRType::A(),
+ RRTTL(3600)),
+ rrset_any_a_empty(test_name, RRClass::ANY(), RRType::A(),
+ RRTTL(3600)),
+ rrset_none_a_empty(test_name, RRClass::NONE(), RRType::A(),
+ RRTTL(3600)),
+ rrset_ns(test_domain, RRClass::IN(), RRType::NS(),
+ RRTTL(86400)),
+ rrset_ch_txt(test_domain, RRClass::CH(), RRType::TXT(),
+ RRTTL(0))
+ {
+ rrset_a.addRdata(in::A("192.0.2.1"));
+ rrset_a.addRdata(in::A("192.0.2.2"));
+ }
+
+ OutputBuffer buffer;
+ MessageRenderer renderer;
+ Name test_name;
+ Name test_domain;
+ Name test_nsname;
+ RRset rrset_a;
+ RRset rrset_a_empty;
+ RRset rrset_any_a_empty;
+ RRset rrset_none_a_empty;
+ RRset rrset_ns;
+ RRset rrset_ch_txt;
+ std::vector<unsigned char> wiredata;
+
+ // max number of Rdata objects added to a test RRset object.
+ // this is an arbitrary chosen limit, but should be sufficiently large
+ // in practice and reasonable even as an extreme test case.
+ static const int MAX_RDATA_COUNT = 100;
+};
+
+TEST_F(RRsetTest, getRdataCount) {
+ for (int i = 0; i < MAX_RDATA_COUNT; ++i) {
+ EXPECT_EQ(i, rrset_a_empty.getRdataCount());
+ rrset_a_empty.addRdata(in::A("192.0.2.1"));
+ }
+}
+
+TEST_F(RRsetTest, getName) {
+ EXPECT_EQ(test_name, rrset_a.getName());
+ EXPECT_EQ(test_domain, rrset_ns.getName());
+}
+
+TEST_F(RRsetTest, getClass) {
+ EXPECT_EQ(RRClass("IN"), rrset_a.getClass());
+ EXPECT_EQ(RRClass("CH"), rrset_ch_txt.getClass());
+}
+
+TEST_F(RRsetTest, getType) {
+ EXPECT_EQ(RRType("A"), rrset_a.getType());
+ EXPECT_EQ(RRType("NS"), rrset_ns.getType());
+ EXPECT_EQ(RRType("TXT"), rrset_ch_txt.getType());
+}
+
+TEST_F(RRsetTest, getTTL) {
+ EXPECT_EQ(RRTTL(3600), rrset_a.getTTL());
+ EXPECT_EQ(RRTTL(86400), rrset_ns.getTTL());
+ EXPECT_EQ(RRTTL(0), rrset_ch_txt.getTTL());
+}
+
+TEST_F(RRsetTest, setTTL) {
+ rrset_a.setTTL(RRTTL(86400));
+ EXPECT_EQ(RRTTL(86400), rrset_a.getTTL());
+ rrset_a.setTTL(RRTTL(0));
+ EXPECT_EQ(RRTTL(0), rrset_a.getTTL());
+}
+
+TEST_F(RRsetTest, isSameKind) {
+ RRset rrset_w(test_name, RRClass::IN(), RRType::A(), RRTTL(3600));
+ RRset rrset_x(test_name, RRClass::IN(), RRType::A(), RRTTL(3600));
+ RRset rrset_y(test_name, RRClass::IN(), RRType::NS(), RRTTL(3600));
+ RRset rrset_z(test_name, RRClass::CH(), RRType::A(), RRTTL(3600));
+ RRset rrset_p(test_nsname, RRClass::IN(), RRType::A(), RRTTL(3600));
+
+ EXPECT_TRUE(rrset_w.isSameKind(rrset_w));
+ EXPECT_TRUE(rrset_w.isSameKind(rrset_x));
+ EXPECT_FALSE(rrset_w.isSameKind(rrset_y));
+ EXPECT_FALSE(rrset_w.isSameKind(rrset_z));
+ EXPECT_FALSE(rrset_w.isSameKind(rrset_p));
+}
+
+void
+addRdataTestCommon(const RRset& rrset) {
+ ASSERT_EQ(2, rrset.getRdataCount());
+
+ RdataIteratorPtr it = rrset.getRdataIterator(); // cursor is set to the 1st
+ EXPECT_FALSE(it->isLast());
+ EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.1")));
+ it->next();
+ EXPECT_FALSE(it->isLast());
+ EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.2")));
+ it->next();
+ EXPECT_TRUE(it->isLast());
+}
+
+TEST_F(RRsetTest, addRdata) {
+ addRdataTestCommon(rrset_a);
+
+ // Reference version of addRdata() doesn't allow to add a different
+ // type of Rdata.
+ EXPECT_THROW(rrset_a.addRdata(generic::NS(test_nsname)), std::bad_cast);
+}
+
+TEST_F(RRsetTest, addRdataPtr) {
+ rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
+ rrset_a_empty.getClass(),
+ "192.0.2.1"));
+ rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
+ rrset_a_empty.getClass(),
+ "192.0.2.2"));
+ addRdataTestCommon(rrset_a_empty);
+}
+
+TEST_F(RRsetTest, addRdataPtrMismatched) {
+ // Pointer version of addRdata() doesn't type check and does allow to
+ //add a different type of Rdata as a result.
+
+ // Type mismatch
+ rrset_a_empty.addRdata(createRdata(RRType::NS(), RRClass::IN(),
+ "ns.example.com."));
+ EXPECT_EQ(1, rrset_a_empty.getRdataCount());
+
+ // Class mismatch
+ rrset_ch_txt.addRdata(createRdata(RRType::TXT(), RRClass::IN(),
+ "Test String"));
+ EXPECT_EQ(1, rrset_ch_txt.getRdataCount());
+}
+
+TEST_F(RRsetTest, addRdataString) {
+ rrset_a_empty.addRdata("192.0.2.1");
+ rrset_a_empty.addRdata("192.0.2.2");
+
+ addRdataTestCommon(rrset_a_empty);
+
+ // String version of addRdata() will throw for bad RDATA for
+ // RRType::A().
+ EXPECT_THROW(rrset_a_empty.addRdata("ns.example.com."), InvalidRdataText);
+ addRdataTestCommon(rrset_a_empty);
+}
+
+TEST_F(RRsetTest, iterator) {
+ // Iterator for an empty RRset.
+ RdataIteratorPtr it = rrset_a_empty.getRdataIterator();
+ EXPECT_TRUE(it->isLast());
+
+ // Normal case (already tested, but do it again just in case)
+ rrset_a_empty.addRdata(in::A("192.0.2.1"));
+ rrset_a_empty.addRdata(in::A("192.0.2.2"));
+ addRdataTestCommon(rrset_a_empty);
+
+ // Rewind test: should be repeat the iteration by calling first().
+ for (int i = 0; i < 2; ++i) {
+ it = rrset_a_empty.getRdataIterator();
+ it->first();
+ EXPECT_FALSE(it->isLast());
+ it->next();
+ EXPECT_FALSE(it->isLast());
+ it->next();
+ EXPECT_TRUE(it->isLast());
+ }
+}
+
+TEST_F(RRsetTest, toText) {
+ EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
+ "test.example.com. 3600 IN A 192.0.2.2\n",
+ rrset_a.toText());
+
+ // toText() cannot be performed for an empty RRset
+ EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
+
+ // Unless it is type ANY or NONE
+ EXPECT_EQ("test.example.com. 3600 ANY A\n",
+ rrset_any_a_empty.toText());
+ EXPECT_EQ("test.example.com. 3600 NONE A\n",
+ rrset_none_a_empty.toText());
+}
+
+TEST_F(RRsetTest, getLength) {
+ // Empty RRset should throw
+ EXPECT_THROW(rrset_a_empty.getLength(), EmptyRRset);
+
+ // Unless it is type ANY or NONE:
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 4 octets
+ // RDLENGTH field = 2 octets
+ // Total = 18 + 2 + 2 + 4 + 2 = 28 octets
+ EXPECT_EQ(28, rrset_any_a_empty.getLength());
+ EXPECT_EQ(28, rrset_none_a_empty.getLength());
+
+ // RRset with single RDATA
+ // 28 (above) + 4 octets (A RDATA) = 32 octets
+ rrset_a_empty.addRdata(in::A("192.0.2.1"));
+ EXPECT_EQ(32, rrset_a_empty.getLength());
+
+ // 2 A RRs
+ rrset_a_empty.addRdata(in::A("192.0.2.2"));
+ EXPECT_EQ(32 + 32, rrset_a_empty.getLength());
+}
+
+TEST_F(RRsetTest, toWireBuffer) {
+ rrset_a.toWire(buffer);
+
+ UnitTestUtil::readWireData("rrset_toWire1", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ buffer.getData(), buffer.getLength());
+
+ // toWire() cannot be performed for an empty RRset except when
+ // class=ANY or class=NONE.
+ buffer.clear();
+ EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
+
+ // When class=ANY or class=NONE, toWire() can also be performed for
+ // an empty RRset.
+ buffer.clear();
+ rrset_any_a_empty.toWire(buffer);
+ wiredata.clear();
+ UnitTestUtil::readWireData("rrset_toWire3", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ buffer.getData(), buffer.getLength());
+
+ buffer.clear();
+ rrset_none_a_empty.toWire(buffer);
+ wiredata.clear();
+ UnitTestUtil::readWireData("rrset_toWire4", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ buffer.getData(), buffer.getLength());
+}
+
+TEST_F(RRsetTest, toWireRenderer) {
+ rrset_ns.addRdata(generic::NS(test_nsname));
+
+ rrset_a.toWire(renderer);
+ rrset_ns.toWire(renderer);
+
+ UnitTestUtil::readWireData("rrset_toWire2", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+
+ // toWire() cannot be performed for an empty RRset except when
+ // class=ANY or class=NONE.
+ renderer.clear();
+ EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
+
+ // When class=ANY or class=NONE, toWire() can also be performed for
+ // an empty RRset.
+ renderer.clear();
+ rrset_any_a_empty.toWire(renderer);
+ wiredata.clear();
+ UnitTestUtil::readWireData("rrset_toWire3", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+
+ renderer.clear();
+ rrset_none_a_empty.toWire(renderer);
+ wiredata.clear();
+ UnitTestUtil::readWireData("rrset_toWire4", wiredata);
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(RRsetTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << rrset_a;
+ EXPECT_EQ(rrset_a.toText(), oss.str());
+}
+
+class RRsetRRSIGTest : public ::testing::Test {
+protected:
+ RRsetRRSIGTest() : test_name("test.example.com")
+ {
+ rrset_a = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::A(), RRTTL(3600)));
+ rrset_a->addRdata(in::A("192.0.2.1"));
+ rrset_a->addRdata(in::A("192.0.2.2"));
+
+ rrset_aaaa = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::AAAA(), RRTTL(3600)));
+ rrset_aaaa->addRdata(in::AAAA("2001:db8::1234"));
+
+ rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ rrset_rrsig->addRdata(generic::RRSIG("AAAA 5 3 7200 20100322084538 "
+ "20100220084538 1 example.com. "
+ "FAKEFAKEFAKEFAKE"));
+ rrset_aaaa->addRRsig(rrset_rrsig);
+ }
+
+ const Name test_name;
+ RRsetPtr rrset_a; // A RRset with two RDATAs
+ RRsetPtr rrset_aaaa; // AAAA RRset with one RDATA with RRSIG
+ RRsetPtr rrset_rrsig; // RRSIG for the AAAA RRset
+};
+
+TEST_F(RRsetRRSIGTest, getRRsig) {
+ RRsetPtr sp = rrset_a->getRRsig();
+ EXPECT_EQ(static_cast<void*>(NULL), sp.get());
+
+ sp = rrset_aaaa->getRRsig();
+ EXPECT_NE(static_cast<void*>(NULL), sp.get());
+}
+
+TEST_F(RRsetRRSIGTest, addRRsig) {
+ RRsetPtr sp = rrset_a->getRRsig();
+ EXPECT_EQ(static_cast<void*>(NULL), sp.get());
+
+ rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ // one signature algorithm (5 = RSA/SHA-1)
+ rrset_rrsig->addRdata(generic::RRSIG("A 5 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ // another signature algorithm (3 = DSA/SHA-1)
+ rrset_rrsig->addRdata(generic::RRSIG("A 3 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ rrset_a->addRRsig(rrset_rrsig);
+
+ sp = rrset_a->getRRsig();
+ EXPECT_NE(static_cast<void*>(NULL), sp.get());
+ EXPECT_EQ(2, sp->getRdataCount());
+
+ // add to existing RRSIG
+ rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ // another signature algorithm (4 = ECC)
+ rrset_rrsig->addRdata(generic::RRSIG("A 4 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ rrset_a->addRRsig(rrset_rrsig);
+ EXPECT_EQ(3, sp->getRdataCount());
+}
+
+TEST_F(RRsetRRSIGTest, getRRsigDataCount) {
+ EXPECT_EQ(1, rrset_aaaa->getRRsigDataCount());
+ EXPECT_EQ(0, rrset_a->getRRsigDataCount());
+
+ rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ // one signature algorithm (5 = RSA/SHA-1)
+ rrset_rrsig->addRdata(generic::RRSIG("A 5 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ // another signature algorithm (3 = DSA/SHA-1)
+ rrset_rrsig->addRdata(generic::RRSIG("A 3 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ rrset_a->addRRsig(rrset_rrsig);
+ EXPECT_EQ(2, rrset_a->getRRsigDataCount());
+
+ rrset_a->removeRRsig();
+ EXPECT_EQ(0, rrset_a->getRRsigDataCount());
+}
+
+TEST_F(RRsetRRSIGTest, toText) {
+ // toText() should also return the associated RRSIG.
+ EXPECT_EQ("test.example.com. 3600 IN AAAA 2001:db8::1234\n"
+ "test.example.com. 3600 IN RRSIG AAAA 5 3 7200 "
+ "20100322084538 20100220084538 1 example.com. FAKEFAKEFAKEFAKE\n",
+ rrset_aaaa->toText());
+}
+
+TEST_F(RRsetRRSIGTest, getLength) {
+ // A RR
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 4 octets
+ // RDLENGTH field = 2 octets
+ // A RDATA = 4 octets
+ // Total = 18 + 2 + 2 + 4 + 2 + 4 = 32 octets
+
+ // 2 A RRs
+ EXPECT_EQ(32 + 32, rrset_a->getLength());
+
+ // RRSIG
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 4 octets
+ // RDLENGTH field = 2 octets
+ // RRSIG RDATA = 40 octets
+ // Total = 18 + 2 + 2 + 4 + 2 + 40 = 68 octets
+ RRsetPtr my_rrsig(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ my_rrsig->addRdata(generic::RRSIG("A 4 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ EXPECT_EQ(68, my_rrsig->getLength());
+
+ // RRset with attached RRSIG
+ rrset_a->addRRsig(my_rrsig);
+
+ EXPECT_EQ(32 + 32 + 68, rrset_a->getLength());
+}
+}
diff --git a/src/lib/dns/tests/rrttl_unittest.cc b/src/lib/dns/tests/rrttl_unittest.cc
new file mode 100644
index 0000000..3cada14
--- /dev/null
+++ b/src/lib/dns/tests/rrttl_unittest.cc
@@ -0,0 +1,279 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <gtest/gtest.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rrttl.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/scoped_ptr.hpp>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using boost::scoped_ptr;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class RRTTLTest : public ::testing::Test {
+protected:
+ RRTTLTest() : obuffer(0) {}
+
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+
+ static RRTTL rrttlFactoryFromWire(const char* datafile);
+ static const RRTTL ttl_0, ttl_1h, ttl_1d, ttl_32bit, ttl_max;
+ static const RRTTL ttl_small, ttl_large;
+ static const uint8_t wiredata[20];
+};
+
+const RRTTL RRTTLTest::ttl_0(0);
+const RRTTL RRTTLTest::ttl_1h(3600);
+const RRTTL RRTTLTest::ttl_1d(86400);
+const RRTTL RRTTLTest::ttl_32bit(0x12345678);
+const RRTTL RRTTLTest::ttl_max(0xffffffff);
+
+const RRTTL RRTTLTest::ttl_small(1);
+const RRTTL RRTTLTest::ttl_large(0x80000001);
+// This is wire-format data for the above sample RRTTLs rendered in the
+// appearing order.
+const uint8_t RRTTLTest::wiredata[20] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x10,
+ 0x00, 0x01, 0x51, 0x80,
+ 0x12, 0x34, 0x56, 0x78,
+ 0xff, 0xff, 0xff, 0xff };
+
+RRTTL
+RRTTLTest::rrttlFactoryFromWire(const char* datafile) {
+ std::vector<unsigned char> data;
+ UnitTestUtil::readWireData(datafile, data);
+
+ InputBuffer buffer(&data[0], data.size());
+
+ return (RRTTL(buffer));
+}
+
+TEST_F(RRTTLTest, getValue) {
+ EXPECT_EQ(0, ttl_0.getValue());
+ EXPECT_EQ(3600, ttl_1h.getValue());
+ EXPECT_EQ(86400, ttl_1d.getValue());
+ EXPECT_EQ(0x12345678, ttl_32bit.getValue());
+ EXPECT_EQ(0xffffffff, ttl_max.getValue());
+}
+
+TEST_F(RRTTLTest, copyConstruct) {
+ const RRTTL ttl1(3600);
+ const RRTTL ttl2(ttl1);
+ EXPECT_EQ(ttl1.getValue(), ttl2.getValue());
+}
+
+TEST_F(RRTTLTest, fromText) {
+ // Border cases
+ EXPECT_EQ(0, RRTTL("0").getValue());
+ EXPECT_EQ(4294967295U, RRTTL("4294967295").getValue());
+
+ // Invalid cases
+ EXPECT_THROW(RRTTL("0xdeadbeef"), InvalidRRTTL); // must be decimal
+ EXPECT_THROW(RRTTL("-1"), InvalidRRTTL); // must be positive
+ EXPECT_THROW(RRTTL("1.1"), InvalidRRTTL); // must be integer
+ EXPECT_THROW(RRTTL("4294967296"), InvalidRRTTL); // must be 32-bit
+}
+
+TEST_F(RRTTLTest, createFromText) {
+ // It returns an actual RRTTL iff the given text is recognized as a
+ // valid RR TTL.
+ scoped_ptr<RRTTL> good_ttl(RRTTL::createFromText("3600"));
+ EXPECT_TRUE(good_ttl);
+ EXPECT_EQ(RRTTL(3600), *good_ttl);
+
+ scoped_ptr<RRTTL> bad_ttl(RRTTL::createFromText("bad"));
+ EXPECT_FALSE(bad_ttl);
+}
+
+void
+checkUnit(unsigned multiply, char suffix) {
+ SCOPED_TRACE(string("Unit check with suffix ") + suffix);
+ const uint32_t value = 10 * multiply;
+ const string num = "10";
+ // Check both lower and upper version of the suffix
+ EXPECT_EQ(value,
+ RRTTL(num + static_cast<char>(tolower(suffix))).getValue());
+ EXPECT_EQ(value,
+ RRTTL(num + static_cast<char>(toupper(suffix))).getValue());
+}
+
+// Check parsing the unit form (1D, etc)
+TEST_F(RRTTLTest, fromTextUnit) {
+ // Check each of the units separately
+ checkUnit(1, 'S');
+ checkUnit(60, 'M');
+ checkUnit(60 * 60, 'H');
+ checkUnit(24 * 60 * 60, 'D');
+ checkUnit(7 * 24 * 60 * 60, 'W');
+
+ // Some border cases (with units)
+ EXPECT_EQ(4294967295U, RRTTL("4294967295S").getValue());
+ EXPECT_EQ(0, RRTTL("0W0D0H0M0S").getValue());
+ EXPECT_EQ(4294967295U, RRTTL("1193046H1695S").getValue());
+ // Leading zeroes are accepted
+ EXPECT_EQ(4294967295U, RRTTL("0000000000000004294967295S").getValue());
+
+ // Now some compound ones. We allow any order (it would be much work to
+ // check the order anyway).
+ EXPECT_EQ(60 * 60 + 3, RRTTL("1H3S").getValue());
+
+ // Awkward, but allowed case - the same unit used twice.
+ EXPECT_EQ(20 * 3600, RRTTL("12H8H").getValue());
+
+ // Negative number in part of the expression, but the total is positive.
+ // Rejected.
+ EXPECT_THROW(RRTTL("-1S1H"), InvalidRRTTL);
+
+ // Some things out of range in the ttl, but it wraps to number in range
+ // in int64_t. Should still not get fooled and reject it.
+
+ // First part out of range
+ EXPECT_THROW(RRTTL("9223372036854775807S9223372036854775807S2S"),
+ InvalidRRTTL);
+ // Second part out of range, but it immediately wraps (2S+2^64-2S)
+ EXPECT_THROW(RRTTL("2S18446744073709551614S"), InvalidRRTTL);
+ // The whole thing wraps right away (2^64S)
+ EXPECT_THROW(RRTTL("18446744073709551616S"), InvalidRRTTL);
+ // Second part out of range, and will become negative with the unit,
+ EXPECT_THROW(RRTTL("256S307445734561825856M"), InvalidRRTTL);
+
+ // Missing before unit.
+ EXPECT_THROW(RRTTL("W5H"), InvalidRRTTL);
+ EXPECT_THROW(RRTTL("5hW"), InvalidRRTTL);
+
+ // Empty string is not allowed
+ EXPECT_THROW(RRTTL(""), InvalidRRTTL);
+ // Missing the last unit is not allowed
+ EXPECT_THROW(RRTTL("3D5"), InvalidRRTTL);
+
+ // There are some wrong units
+ EXPECT_THROW(RRTTL("13X"), InvalidRRTTL);
+ EXPECT_THROW(RRTTL("3D5F"), InvalidRRTTL);
+}
+
+TEST_F(RRTTLTest, fromWire) {
+ EXPECT_EQ(0x12345678,
+ rrttlFactoryFromWire("rrcode32_fromWire1").getValue());
+ EXPECT_THROW(rrttlFactoryFromWire("rrcode32_fromWire2"),
+ IncompleteRRTTL);
+}
+
+TEST_F(RRTTLTest, toText) {
+ EXPECT_EQ("0", ttl_0.toText());
+ EXPECT_EQ("3600", ttl_1h.toText());
+ EXPECT_EQ("86400", ttl_1d.toText());
+ EXPECT_EQ("305419896", ttl_32bit.toText());
+ EXPECT_EQ("4294967295", ttl_max.toText());
+}
+
+TEST_F(RRTTLTest, toWireBuffer) {
+ ttl_0.toWire(obuffer);
+ ttl_1h.toWire(obuffer);
+ ttl_1d.toWire(obuffer);
+ ttl_32bit.toWire(obuffer);
+ ttl_max.toWire(obuffer);
+
+ matchWireData(wiredata, sizeof(wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(RRTTLTest, toWireRenderer) {
+ ttl_0.toWire(renderer);
+ ttl_1h.toWire(renderer);
+ ttl_1d.toWire(renderer);
+ ttl_32bit.toWire(renderer);
+ ttl_max.toWire(renderer);
+
+ matchWireData(wiredata, sizeof(wiredata),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(RRTTLTest, equal) {
+ EXPECT_TRUE(RRTTL("3600") == ttl_1h);
+ EXPECT_TRUE(RRTTL("86400").equals(ttl_1d));
+
+ EXPECT_TRUE(ttl_1d != ttl_1h);
+ EXPECT_TRUE(ttl_1d.nequals(ttl_max));
+}
+
+//
+// The following set of tests confirm the result of <=, <, >=, >
+// The test logic is simple, and all tests are just straightforward variations
+// of the first one.
+//
+TEST_F(RRTTLTest, leq) {
+ // small <= large is true
+ EXPECT_TRUE(ttl_small.leq(ttl_large));
+ EXPECT_TRUE(ttl_small <= ttl_large);
+
+ // small <= small is true
+ EXPECT_TRUE(ttl_small.leq(ttl_small));
+ EXPECT_LE(ttl_small, ttl_small);
+
+ // large <= small is false
+ EXPECT_FALSE(ttl_large.leq(ttl_small));
+ EXPECT_FALSE(ttl_large <= ttl_small);
+}
+
+TEST_F(RRTTLTest, geq) {
+ EXPECT_TRUE(ttl_large.geq(ttl_small));
+ EXPECT_TRUE(ttl_large >= ttl_small);
+
+ EXPECT_TRUE(ttl_large.geq(ttl_large));
+ EXPECT_GE(ttl_large, ttl_large);
+
+ EXPECT_FALSE(ttl_small.geq(ttl_large));
+ EXPECT_FALSE(ttl_small >= ttl_large);
+}
+
+TEST_F(RRTTLTest, lthan) {
+ EXPECT_TRUE(ttl_small.lthan(ttl_large));
+ EXPECT_TRUE(ttl_small < ttl_large);
+
+ EXPECT_FALSE(ttl_small.lthan(ttl_small));
+ // cppcheck-suppress duplicateExpression
+ EXPECT_FALSE(ttl_small < ttl_small);
+
+ EXPECT_FALSE(ttl_large.lthan(ttl_small));
+ EXPECT_FALSE(ttl_large < ttl_small);
+}
+
+TEST_F(RRTTLTest, gthan) {
+ EXPECT_TRUE(ttl_large.gthan(ttl_small));
+ EXPECT_TRUE(ttl_large > ttl_small);
+
+ EXPECT_FALSE(ttl_large.gthan(ttl_large));
+ // cppcheck-suppress duplicateExpression
+ EXPECT_FALSE(ttl_large > ttl_large);
+
+ EXPECT_FALSE(ttl_small.gthan(ttl_large));
+ EXPECT_FALSE(ttl_small > ttl_large);
+}
+
+TEST_F(RRTTLTest, maxTTL) {
+ EXPECT_EQ((1u << 31) - 1, RRTTL::MAX_TTL().getValue());
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(RRTTLTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << ttl_1h;
+ EXPECT_EQ(ttl_1h.toText(), oss.str());
+}
+}
diff --git a/src/lib/dns/tests/rrtype_unittest.cc b/src/lib/dns/tests/rrtype_unittest.cc
new file mode 100644
index 0000000..a2f8ba5
--- /dev/null
+++ b/src/lib/dns/tests/rrtype_unittest.cc
@@ -0,0 +1,195 @@
+// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <gtest/gtest.h>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rrtype.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class RRTypeTest : public ::testing::Test {
+protected:
+ RRTypeTest() : obuffer(0) {}
+
+ OutputBuffer obuffer;
+ MessageRenderer renderer;
+
+ static RRType rrtypeFactoryFromWire(const char* datafile);
+ static const RRType rrtype_1, rrtype_0x80, rrtype_0x800, rrtype_0x8000,
+ rrtype_max;
+ static const uint8_t wiredata[];
+};
+
+const RRType RRTypeTest::rrtype_1(1);
+const RRType RRTypeTest::rrtype_0x80(0x80);
+const RRType RRTypeTest::rrtype_0x800(0x800);
+const RRType RRTypeTest::rrtype_0x8000(0x8000);
+const RRType RRTypeTest::rrtype_max(0xffff);
+// This is wire-format data for the above sample RRTypes rendered in the
+// appearing order.
+const uint8_t RRTypeTest::wiredata[] = { 0x00, 0x01, 0x00, 0x80, 0x08,
+ 0x00, 0x80, 0x00, 0xff, 0xff };
+
+RRType
+RRTypeTest::rrtypeFactoryFromWire(const char* datafile) {
+ std::vector<unsigned char> data;
+ UnitTestUtil::readWireData(datafile, data);
+
+ InputBuffer buffer(&data[0], data.size());
+
+ return (RRType(buffer));
+}
+
+TEST_F(RRTypeTest, fromText) {
+ EXPECT_EQ("A", RRType("A").toText());
+ EXPECT_EQ("NS", RRType("NS").toText());
+
+ EXPECT_EQ("TYPE65535", RRType("TYPE65535").toText());
+
+ // something unusual, but existing implementations accept this form,
+ // so do we.
+ EXPECT_EQ(53, RRType("TYPE00053").getCode());
+ // again, unusual, and the majority of other implementations reject it.
+ // In any case, there should be no reasonable reason to accept such a
+ // ridiculously long input.
+ EXPECT_THROW(RRType("TYPE000053"), InvalidRRType);
+
+ // bogus TYPEnnn representations: should trigger an exception
+ EXPECT_THROW(RRType("TYPE"), InvalidRRType);
+ EXPECT_THROW(RRType("TYPE-1"), InvalidRRType);
+ EXPECT_THROW(RRType("TYPExxx"), InvalidRRType);
+ EXPECT_THROW(RRType("TYPE65536"), InvalidRRType);
+ EXPECT_THROW(RRType("TYPE6500x"), InvalidRRType);
+ EXPECT_THROW(RRType("TYPE65000 "), InvalidRRType);
+}
+
+TEST_F(RRTypeTest, fromWire) {
+ EXPECT_EQ(0x1234,
+ rrtypeFactoryFromWire("rrcode16_fromWire1").getCode());
+ EXPECT_THROW(rrtypeFactoryFromWire("rrcode16_fromWire2"), IncompleteRRType);
+}
+
+// from string, lower case
+TEST_F(RRTypeTest, caseConstruct) {
+ EXPECT_EQ("A", RRType("a").toText());
+ EXPECT_EQ("NS", RRType("ns").toText());
+ EXPECT_EQ("TYPE65535", RRType("type65535").toText());
+}
+
+TEST_F(RRTypeTest, toText) {
+ EXPECT_EQ("A", RRType(1).toText());
+ EXPECT_EQ("TYPE65000", RRType(65000).toText());
+}
+
+TEST_F(RRTypeTest, toWireBuffer) {
+ rrtype_1.toWire(obuffer);
+ rrtype_0x80.toWire(obuffer);
+ rrtype_0x800.toWire(obuffer);
+ rrtype_0x8000.toWire(obuffer);
+ rrtype_max.toWire(obuffer);
+
+ matchWireData(wiredata, sizeof(wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(RRTypeTest, toWireRenderer) {
+ rrtype_1.toWire(renderer);
+ rrtype_0x80.toWire(renderer);
+ rrtype_0x800.toWire(renderer);
+ rrtype_0x8000.toWire(renderer);
+ rrtype_max.toWire(renderer);
+
+ matchWireData(wiredata, sizeof(wiredata),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(RRTypeTest, wellKnownTypes) {
+ EXPECT_EQ(1, RRType::A().getCode());
+ EXPECT_EQ("A", RRType::A().toText());
+}
+
+TEST_F(RRTypeTest, compare) {
+ EXPECT_TRUE(RRType(1) == RRType("A"));
+ EXPECT_TRUE(RRType(1).equals(RRType("A")));
+ EXPECT_TRUE(RRType(0) != RRType("A"));
+ EXPECT_TRUE(RRType(0).nequals(RRType("A")));
+
+ EXPECT_TRUE(RRType("A") < RRType("NS"));
+ EXPECT_TRUE(RRType(100) < RRType(65535));
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(RRTypeTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << RRType::A();
+ EXPECT_EQ(RRType::A().toText(), oss.str());
+}
+
+// Below, we'll check definitions for all well-known RR types; whether they
+// are defined and have the correct parameter values. Test data are generated
+// from the list available at:
+// http://www.iana.org/assignments/dns-parameters/dns-parameters.xml
+struct TypeParam {
+ const char* const txt; // "A", "AAAA", "NS", etc
+ const uint16_t code; // 1, 28, 2, etc
+ const RRType& (*obj)(); // RRType::A(), etc
+} known_types[] = {
+ {"A", 1, RRType::A}, {"NS", 2, RRType::NS}, {"MD", 3, RRType::MD},
+ {"MF", 4, RRType::MF}, {"CNAME", 5, RRType::CNAME},
+ {"SOA", 6, RRType::SOA}, {"MB", 7, RRType::MB}, {"MG", 8, RRType::MG},
+ {"MR", 9, RRType::MR}, {"NULL", 10, RRType::Null},
+ {"WKS", 11, RRType::WKS}, {"PTR", 12, RRType::PTR},
+ {"HINFO", 13, RRType::HINFO}, {"MINFO", 14, RRType::MINFO},
+ {"MX", 15, RRType::MX}, {"TXT", 16, RRType::TXT}, {"RP", 17, RRType::RP},
+ {"AFSDB", 18, RRType::AFSDB}, {"X25", 19, RRType::X25},
+ {"ISDN", 20, RRType::ISDN}, {"RT", 21, RRType::RT},
+ {"NSAP", 22, RRType::NSAP}, {"NSAP-PTR", 23, RRType::NSAP_PTR},
+ {"SIG", 24, RRType::SIG}, {"KEY", 25, RRType::KEY},
+ {"PX", 26, RRType::PX}, {"GPOS", 27, RRType::GPOS},
+ {"AAAA", 28, RRType::AAAA}, {"LOC", 29, RRType::LOC},
+ {"NXT", 30, RRType::NXT}, {"SRV", 33, RRType::SRV},
+ {"NAPTR", 35, RRType::NAPTR}, {"KX", 36, RRType::KX},
+ {"CERT", 37, RRType::CERT}, {"A6", 38, RRType::A6},
+ {"DNAME", 39, RRType::DNAME}, {"OPT", 41, RRType::OPT},
+ {"APL", 42, RRType::APL}, {"DS", 43, RRType::DS},
+ {"SSHFP", 44, RRType::SSHFP}, {"IPSECKEY", 45, RRType::IPSECKEY},
+ {"RRSIG", 46, RRType::RRSIG}, {"NSEC", 47, RRType::NSEC},
+ {"DNSKEY", 48, RRType::DNSKEY}, {"DHCID", 49, RRType::DHCID},
+ {"NSEC3", 50, RRType::NSEC3}, {"NSEC3PARAM", 51, RRType::NSEC3PARAM},
+ {"TLSA", 52, RRType::TLSA}, {"HIP", 55, RRType::HIP},
+ {"SPF", 99, RRType::SPF}, {"UNSPEC", 103, RRType::UNSPEC},
+ {"NID", 104, RRType::NID}, {"L32", 105, RRType::L32},
+ {"L64", 106, RRType::L64}, {"LP", 107, RRType::LP},
+ {"TKEY", 249, RRType::TKEY}, {"TSIG", 250, RRType::TSIG},
+ {"IXFR", 251, RRType::IXFR}, {"AXFR", 252, RRType::AXFR},
+ {"MAILB", 253, RRType::MAILB}, {"MAILA", 254, RRType::MAILA},
+ {"ANY", 255, RRType::ANY}, {"URI", 256, RRType::URI},
+ {"CAA", 257, RRType::CAA}, {"DLV", 32769, RRType::DLV},
+ {NULL, 0, NULL}
+};
+
+TEST(RRTypeConstTest, wellKnowns) {
+ for (int i = 0; known_types[i].txt; ++i) {
+ SCOPED_TRACE("Checking well known RRType: " +
+ string(known_types[i].txt));
+ EXPECT_EQ(known_types[i].code, RRType(known_types[i].txt).getCode());
+ EXPECT_EQ(known_types[i].code,
+ (*known_types[i].obj)().getCode());
+ }
+}
+}
diff --git a/src/lib/dns/tests/run_unittests.cc b/src/lib/dns/tests/run_unittests.cc
new file mode 100644
index 0000000..de396fa
--- /dev/null
+++ b/src/lib/dns/tests/run_unittests.cc
@@ -0,0 +1,24 @@
+// Copyright (C) 2009-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <gtest/gtest.h>
+#include <util/unittests/run_all.h>
+
+#include <util/unittests/testdata.h>
+#include <dns/tests/unittest_util.h>
+
+int
+main(int argc, char* argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ isc::UnitTestUtil::addDataPath(TEST_DATA_SRCDIR);
+ isc::util::unittests::addTestDataPath(TEST_DATA_SRCDIR);
+ isc::UnitTestUtil::addDataPath(TEST_DATA_BUILDDIR);
+ isc::util::unittests::addTestDataPath(TEST_DATA_BUILDDIR);
+
+ return (isc::util::unittests::run_all());
+}
diff --git a/src/lib/dns/tests/serial_unittest.cc b/src/lib/dns/tests/serial_unittest.cc
new file mode 100644
index 0000000..305b0b0
--- /dev/null
+++ b/src/lib/dns/tests/serial_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/serial.h>
+
+using namespace isc::dns;
+
+class SerialTest : public ::testing::Test {
+public:
+ SerialTest() : one(1), one_2(1), two(2),
+ date_zero(1980120100), date_one(1980120101),
+ min(0), max(4294967295u),
+ number_low(12345),
+ number_medium(2000000000),
+ number_high(4000000000u)
+ {}
+ Serial one, one_2, two, date_zero, date_one, min, max, number_low, number_medium, number_high;
+};
+
+//
+// Basic tests
+//
+
+TEST_F(SerialTest, get_value) {
+ EXPECT_EQ(1, one.getValue());
+ EXPECT_NE(2, one.getValue());
+ EXPECT_EQ(2, two.getValue());
+ EXPECT_EQ(1980120100, date_zero.getValue());
+ EXPECT_EQ(1980120101, date_one.getValue());
+ EXPECT_EQ(0, min.getValue());
+ EXPECT_EQ(4294967295u, max.getValue());
+ EXPECT_EQ(12345, number_low.getValue());
+ EXPECT_EQ(2000000000, number_medium.getValue());
+ EXPECT_EQ(4000000000u, number_high.getValue());
+}
+
+TEST_F(SerialTest, equals) {
+ EXPECT_EQ(one, one);
+ EXPECT_EQ(one, one_2);
+ EXPECT_NE(one, two);
+ EXPECT_NE(two, one);
+ EXPECT_EQ(Serial(12345), number_low);
+ EXPECT_NE(Serial(12346), number_low);
+}
+
+TEST_F(SerialTest, comparison) {
+ // These should be true/false even without serial arithmetic
+ EXPECT_LE(one, one);
+ EXPECT_LE(one, one_2);
+ EXPECT_LT(one, two);
+ EXPECT_LE(one, two);
+ EXPECT_GE(two, two);
+ EXPECT_GT(two, one);
+ EXPECT_GE(two, one);
+ EXPECT_LT(one, number_low);
+ EXPECT_LT(number_low, number_medium);
+ EXPECT_LT(number_medium, number_high);
+
+ // now let's try some that 'wrap', as it were
+ EXPECT_GT(min, max);
+ EXPECT_LT(max, min);
+ EXPECT_LT(number_high, number_low);
+}
+
+//
+// RFC 1982 Section 3.1
+//
+TEST_F(SerialTest, addition) {
+ EXPECT_EQ(two, one + one);
+ EXPECT_EQ(two, one + one_2);
+ EXPECT_EQ(max, max + min);
+ EXPECT_EQ(min, max + one);
+ EXPECT_EQ(one, max + two);
+ EXPECT_EQ(one, max + one + one);
+
+ EXPECT_EQ(one + 100, max + 102);
+ EXPECT_EQ(min + 2147483645, max + 2147483646);
+ EXPECT_EQ(min + 2147483646, max + MAX_SERIAL_INCREMENT);
+}
+
+//
+// RFC 1982 Section 3.2 has been checked by the basic tests above
+//
+
+//
+// RFC 1982 Section 4.1
+//
+
+// Helper function for addition_always_larger test, add some numbers
+// and check that the result is always larger than the original
+void do_addition_larger_test(const Serial& number) {
+ EXPECT_GE(number + 0, number);
+ EXPECT_EQ(number + 0, number);
+ EXPECT_GT(number + 1, number);
+ EXPECT_GT(number + 2, number);
+ EXPECT_GT(number + 100, number);
+ EXPECT_GT(number + 1111111, number);
+ EXPECT_GT(number + 2147483646, number);
+ EXPECT_GT(number + MAX_SERIAL_INCREMENT, number);
+ // Try MAX_SERIAL_INCREMENT as a hardcoded number as well
+ EXPECT_GT(number + 2147483647, number);
+}
+
+TEST_F(SerialTest, addition_always_larger) {
+ do_addition_larger_test(one);
+ do_addition_larger_test(two);
+ do_addition_larger_test(date_zero);
+ do_addition_larger_test(date_one);
+ do_addition_larger_test(min);
+ do_addition_larger_test(max);
+ do_addition_larger_test(number_low);
+ do_addition_larger_test(number_medium);
+ do_addition_larger_test(number_high);
+}
+
+//
+// RFC 1982 Section 4.2
+//
+
+// Helper function to do the second addition
+void
+do_two_additions_test_second(const Serial &original,
+ const Serial &number)
+{
+ EXPECT_NE(original, number);
+ EXPECT_NE(original, number + 0);
+ EXPECT_NE(original, number + 1);
+ EXPECT_NE(original, number + 2);
+ EXPECT_NE(original, number + 100);
+ EXPECT_NE(original, number + 1111111);
+ EXPECT_NE(original, number + 2147483646);
+ EXPECT_NE(original, number + MAX_SERIAL_INCREMENT);
+ EXPECT_NE(original, number + 2147483647);
+}
+
+void do_two_additions_test_first(const Serial &number) {
+ do_two_additions_test_second(number, number + 1);
+ do_two_additions_test_second(number, number + 2);
+ do_two_additions_test_second(number, number + 100);
+ do_two_additions_test_second(number, number + 1111111);
+ do_two_additions_test_second(number, number + 2147483646);
+ do_two_additions_test_second(number, number + MAX_SERIAL_INCREMENT);
+ do_two_additions_test_second(number, number + 2147483647);
+}
+
+TEST_F(SerialTest, two_additions_never_equal) {
+ do_two_additions_test_first(one);
+ do_two_additions_test_first(two);
+ do_two_additions_test_first(date_zero);
+ do_two_additions_test_first(date_one);
+ do_two_additions_test_first(min);
+ do_two_additions_test_first(max);
+ do_two_additions_test_first(number_low);
+ do_two_additions_test_first(number_medium);
+ do_two_additions_test_first(number_high);
+}
+
+//
+// RFC 1982 Section 4.3 and 4.4 have nothing to test
+//
+
+//
+// Tests from RFC 1982 examples
+//
+TEST(SerialTextRFCExamples, rfc_example_tests) {
+}
diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am
new file mode 100644
index 0000000..e5c8081
--- /dev/null
+++ b/src/lib/dns/tests/testdata/Makefile.am
@@ -0,0 +1,219 @@
+CLEANFILES =
+
+# NOTE: keep this in sync with real file listing
+# so is included in tarball
+EXTRA_DIST = edns_toWire1.spec edns_toWire2.spec
+EXTRA_DIST += edns_toWire3.spec edns_toWire4.spec
+EXTRA_DIST += masterload.txt
+EXTRA_DIST += message_fromWire1 message_fromWire2
+EXTRA_DIST += message_fromWire3 message_fromWire4
+EXTRA_DIST += message_fromWire5 message_fromWire6
+EXTRA_DIST += message_fromWire7 message_fromWire8
+EXTRA_DIST += message_fromWire9 message_fromWire10.spec
+EXTRA_DIST += message_fromWire11.spec message_fromWire12.spec
+EXTRA_DIST += message_fromWire13.spec message_fromWire14.spec
+EXTRA_DIST += message_fromWire15.spec message_fromWire16.spec
+EXTRA_DIST += message_fromWire17.spec message_fromWire18.spec
+EXTRA_DIST += message_fromWire19.spec message_fromWire20.spec
+EXTRA_DIST += message_fromWire21.spec message_fromWire22.spec
+EXTRA_DIST += message_toWire1 message_toWire2.spec message_toWire3.spec
+EXTRA_DIST += message_toWire4.spec message_toWire5.spec
+EXTRA_DIST += message_toWire6 message_toWire7
+EXTRA_DIST += message_toText1.txt message_toText1.spec
+EXTRA_DIST += message_toText2.txt message_toText2.spec
+EXTRA_DIST += message_toText3.txt message_toText3.spec
+EXTRA_DIST += name_fromWire1 name_fromWire2 name_fromWire3_1 name_fromWire3_2
+EXTRA_DIST += name_fromWire4 name_fromWire6 name_fromWire7 name_fromWire8
+EXTRA_DIST += name_fromWire9 name_fromWire10 name_fromWire11 name_fromWire12
+EXTRA_DIST += name_fromWire13 name_fromWire14
+EXTRA_DIST += name_toWire1 name_toWire2 name_toWire3 name_toWire4
+EXTRA_DIST += name_toWire5.spec name_toWire6.spec
+EXTRA_DIST += name_toWire7 name_toWire8 name_toWire9
+EXTRA_DIST += question_fromWire question_toWire1 question_toWire2
+EXTRA_DIST += rdatafields1.spec rdatafields2.spec rdatafields3.spec
+EXTRA_DIST += rdatafields4.spec rdatafields5.spec rdatafields6.spec
+EXTRA_DIST += rdata_cname_fromWire rdata_dname_fromWire
+EXTRA_DIST += rdata_dnskey_fromWire.spec rdata_dnskey_empty_keydata_fromWire.spec
+EXTRA_DIST += rdata_dhcid_fromWire rdata_dhcid_toWire
+EXTRA_DIST += rdata_ds_fromWire rdata_in_a_fromWire rdata_in_aaaa_fromWire
+EXTRA_DIST += rdata_mx_fromWire rdata_mx_toWire1 rdata_mx_toWire2
+EXTRA_DIST += rdata_ns_fromWire
+EXTRA_DIST += rdata_nsec_fromWire1 rdata_nsec_fromWire2 rdata_nsec_fromWire3
+EXTRA_DIST += rdata_nsec_fromWire4.spec rdata_nsec_fromWire5.spec
+EXTRA_DIST += rdata_nsec_fromWire6.spec rdata_nsec_fromWire7.spec
+EXTRA_DIST += rdata_nsec_fromWire8.spec rdata_nsec_fromWire9.spec
+EXTRA_DIST += rdata_nsec_fromWire10.spec
+EXTRA_DIST += rdata_nsec_fromWire16.spec
+EXTRA_DIST += rdata_nsec3param_fromWire1
+EXTRA_DIST += rdata_nsec3param_fromWire2.spec
+EXTRA_DIST += rdata_nsec3param_fromWire11.spec
+EXTRA_DIST += rdata_nsec3param_fromWire13.spec
+EXTRA_DIST += rdata_nsec3_fromWire1 rdata_nsec3_fromWire1.spec
+EXTRA_DIST += rdata_nsec3_fromWire2.spec rdata_nsec3_fromWire3
+EXTRA_DIST += rdata_nsec3_fromWire4.spec rdata_nsec3_fromWire5.spec
+EXTRA_DIST += rdata_nsec3_fromWire6.spec rdata_nsec3_fromWire7.spec
+EXTRA_DIST += rdata_nsec3_fromWire8.spec rdata_nsec3_fromWire9.spec
+EXTRA_DIST += rdata_nsec3_fromWire10.spec rdata_nsec3_fromWire11.spec
+EXTRA_DIST += rdata_nsec3_fromWire12.spec rdata_nsec3_fromWire13.spec
+EXTRA_DIST += rdata_nsec3_fromWire14.spec rdata_nsec3_fromWire15.spec
+EXTRA_DIST += rdata_nsec3_fromWire16.spec rdata_nsec3_fromWire17.spec
+EXTRA_DIST += rdata_opt_fromWire1 rdata_opt_fromWire2
+EXTRA_DIST += rdata_opt_fromWire3 rdata_opt_fromWire4
+EXTRA_DIST += rdata_rrsig_fromWire1
+EXTRA_DIST += rdata_rrsig_fromWire2.spec
+EXTRA_DIST += rdata_rp_fromWire1.spec rdata_rp_fromWire2.spec
+EXTRA_DIST += rdata_rp_fromWire3.spec rdata_rp_fromWire4.spec
+EXTRA_DIST += rdata_rp_fromWire5.spec rdata_rp_fromWire6.spec
+EXTRA_DIST += rdata_rp_toWire1.spec rdata_rp_toWire2.spec
+EXTRA_DIST += rdata_sshfp_fromWire rdata_sshfp_fromWire2
+EXTRA_DIST += rdata_sshfp_fromWire1.spec rdata_sshfp_fromWire2.spec
+EXTRA_DIST += rdata_sshfp_fromWire3.spec rdata_sshfp_fromWire4.spec
+EXTRA_DIST += rdata_sshfp_fromWire5.spec rdata_sshfp_fromWire6.spec
+EXTRA_DIST += rdata_sshfp_fromWire7.spec rdata_sshfp_fromWire8.spec
+EXTRA_DIST += rdata_sshfp_fromWire9 rdata_sshfp_fromWire10
+EXTRA_DIST += rdata_sshfp_fromWire11 rdata_sshfp_fromWire12
+EXTRA_DIST += rdata_afsdb_fromWire1.spec rdata_afsdb_fromWire2.spec
+EXTRA_DIST += rdata_afsdb_fromWire3.spec rdata_afsdb_fromWire4.spec
+EXTRA_DIST += rdata_afsdb_fromWire5.spec
+EXTRA_DIST += rdata_afsdb_toWire1.spec rdata_afsdb_toWire2.spec
+EXTRA_DIST += rdata_soa_fromWire rdata_soa_toWireUncompressed.spec
+EXTRA_DIST += rdata_srv_fromWire
+EXTRA_DIST += rdata_minfo_fromWire1.spec rdata_minfo_fromWire2.spec
+EXTRA_DIST += rdata_minfo_fromWire3.spec rdata_minfo_fromWire4.spec
+EXTRA_DIST += rdata_minfo_fromWire5.spec rdata_minfo_fromWire6.spec
+EXTRA_DIST += rdata_minfo_toWire1.spec rdata_minfo_toWire2.spec
+EXTRA_DIST += rdata_minfo_toWireUncompressed1.spec
+EXTRA_DIST += rdata_minfo_toWireUncompressed2.spec
+EXTRA_DIST += rdata_txt_fromWire1 rdata_txt_fromWire2.spec
+EXTRA_DIST += rdata_txt_fromWire3.spec rdata_txt_fromWire4.spec
+EXTRA_DIST += rdata_txt_fromWire5.spec rdata_unknown_fromWire
+EXTRA_DIST += rrcode16_fromWire1 rrcode16_fromWire2
+EXTRA_DIST += rrcode32_fromWire1 rrcode32_fromWire2
+EXTRA_DIST += rrset_toWire1 rrset_toWire2
+EXTRA_DIST += rrset_toWire3 rrset_toWire4
+EXTRA_DIST += rdata_tkey_fromWire1.spec rdata_tkey_fromWire2.spec
+EXTRA_DIST += rdata_tkey_fromWire3.spec rdata_tkey_fromWire4.spec
+EXTRA_DIST += rdata_tkey_fromWire5.spec rdata_tkey_fromWire6.spec
+EXTRA_DIST += rdata_tkey_fromWire7.spec rdata_tkey_fromWire8.spec
+EXTRA_DIST += rdata_tkey_fromWire9.spec
+EXTRA_DIST += rdata_tkey_toWire1.spec rdata_tkey_toWire2.spec
+EXTRA_DIST += rdata_tkey_toWire3.spec rdata_tkey_toWire4.spec
+EXTRA_DIST += rdata_tkey_toWire5.spec
+EXTRA_DIST += rdata_tlsa_fromWire rdata_tlsa_fromWire2
+EXTRA_DIST += rdata_tlsa_fromWire3.spec rdata_tlsa_fromWire4.spec
+EXTRA_DIST += rdata_tlsa_fromWire5.spec rdata_tlsa_fromWire6.spec
+EXTRA_DIST += rdata_tlsa_fromWire7.spec rdata_tlsa_fromWire8.spec
+EXTRA_DIST += rdata_tlsa_fromWire9 rdata_tlsa_fromWire10
+EXTRA_DIST += rdata_tlsa_fromWire11 rdata_tlsa_fromWire12
+EXTRA_DIST += rdata_tsig_fromWire1.spec rdata_tsig_fromWire2.spec
+EXTRA_DIST += rdata_tsig_fromWire3.spec rdata_tsig_fromWire4.spec
+EXTRA_DIST += rdata_tsig_fromWire5.spec rdata_tsig_fromWire6.spec
+EXTRA_DIST += rdata_tsig_fromWire7.spec rdata_tsig_fromWire8.spec
+EXTRA_DIST += rdata_tsig_fromWire9.spec
+EXTRA_DIST += rdata_tsig_toWire1.spec rdata_tsig_toWire2.spec
+EXTRA_DIST += rdata_tsig_toWire3.spec rdata_tsig_toWire4.spec
+EXTRA_DIST += rdata_tsig_toWire5.spec
+EXTRA_DIST += rdata_caa_fromWire1.spec rdata_caa_fromWire2.spec
+EXTRA_DIST += rdata_caa_fromWire3.spec rdata_caa_fromWire4.spec
+EXTRA_DIST += rdata_caa_fromWire5 rdata_caa_fromWire6
+EXTRA_DIST += tsigrecord_toWire1.spec tsigrecord_toWire2.spec
+EXTRA_DIST += tsig_verify1.spec tsig_verify2.spec tsig_verify3.spec
+EXTRA_DIST += tsig_verify4.spec tsig_verify5.spec tsig_verify6.spec
+EXTRA_DIST += tsig_verify7.spec tsig_verify8.spec tsig_verify9.spec
+EXTRA_DIST += tsig_verify10.spec tsig_verify11.spec
+EXTRA_DIST += example.org
+EXTRA_DIST += broken.zone
+EXTRA_DIST += origincheck.txt
+EXTRA_DIST += omitcheck.txt
+
+# Generated .wire files
+EXTRA_DIST += edns_toWire1.wire edns_toWire2.wire
+EXTRA_DIST += edns_toWire3.wire edns_toWire4.wire
+EXTRA_DIST += message_fromWire10.wire
+EXTRA_DIST += message_fromWire11.wire message_fromWire12.wire
+EXTRA_DIST += message_fromWire13.wire message_fromWire14.wire
+EXTRA_DIST += message_fromWire15.wire message_fromWire16.wire
+EXTRA_DIST += message_fromWire17.wire message_fromWire18.wire
+EXTRA_DIST += message_fromWire19.wire message_fromWire20.wire
+EXTRA_DIST += message_fromWire21.wire message_fromWire22.wire
+EXTRA_DIST += message_toWire1 message_toWire2.wire message_toWire3.wire
+EXTRA_DIST += message_toWire4.wire message_toWire5.wire
+EXTRA_DIST += message_toText1.txt message_toText1.wire
+EXTRA_DIST += message_toText2.txt message_toText2.wire
+EXTRA_DIST += message_toText3.txt message_toText3.wire
+EXTRA_DIST += name_toWire5.wire name_toWire6.wire
+EXTRA_DIST += rdatafields1.wire rdatafields2.wire rdatafields3.wire
+EXTRA_DIST += rdatafields4.wire rdatafields5.wire rdatafields6.wire
+EXTRA_DIST += rdata_dnskey_fromWire.wire rdata_dnskey_empty_keydata_fromWire.wire
+EXTRA_DIST += rdata_nsec_fromWire4.wire rdata_nsec_fromWire5.wire
+EXTRA_DIST += rdata_nsec_fromWire6.wire rdata_nsec_fromWire7.wire
+EXTRA_DIST += rdata_nsec_fromWire8.wire rdata_nsec_fromWire9.wire
+EXTRA_DIST += rdata_nsec_fromWire10.wire
+EXTRA_DIST += rdata_nsec_fromWire16.wire
+EXTRA_DIST += rdata_nsec3param_fromWire2.wire
+EXTRA_DIST += rdata_nsec3param_fromWire11.wire
+EXTRA_DIST += rdata_nsec3param_fromWire13.wire
+EXTRA_DIST += rdata_nsec3_fromWire2.wire rdata_nsec3_fromWire3
+EXTRA_DIST += rdata_nsec3_fromWire4.wire rdata_nsec3_fromWire5.wire
+EXTRA_DIST += rdata_nsec3_fromWire6.wire rdata_nsec3_fromWire7.wire
+EXTRA_DIST += rdata_nsec3_fromWire8.wire rdata_nsec3_fromWire9.wire
+EXTRA_DIST += rdata_nsec3_fromWire10.wire rdata_nsec3_fromWire11.wire
+EXTRA_DIST += rdata_nsec3_fromWire12.wire rdata_nsec3_fromWire13.wire
+EXTRA_DIST += rdata_nsec3_fromWire14.wire rdata_nsec3_fromWire15.wire
+EXTRA_DIST += rdata_nsec3_fromWire16.wire rdata_nsec3_fromWire17.wire
+EXTRA_DIST += rdata_rrsig_fromWire2.wire
+EXTRA_DIST += rdata_rp_fromWire1.wire rdata_rp_fromWire2.wire
+EXTRA_DIST += rdata_rp_fromWire3.wire rdata_rp_fromWire4.wire
+EXTRA_DIST += rdata_rp_fromWire5.wire rdata_rp_fromWire6.wire
+EXTRA_DIST += rdata_rp_toWire1.wire rdata_rp_toWire2.wire
+EXTRA_DIST += rdata_sshfp_fromWire1.wire rdata_sshfp_fromWire2.wire
+EXTRA_DIST += rdata_sshfp_fromWire3.wire rdata_sshfp_fromWire4.wire
+EXTRA_DIST += rdata_sshfp_fromWire5.wire rdata_sshfp_fromWire6.wire
+EXTRA_DIST += rdata_sshfp_fromWire7.wire rdata_sshfp_fromWire8.wire
+EXTRA_DIST += rdata_afsdb_fromWire1.wire rdata_afsdb_fromWire2.wire
+EXTRA_DIST += rdata_afsdb_fromWire3.wire rdata_afsdb_fromWire4.wire
+EXTRA_DIST += rdata_afsdb_fromWire5.wire
+EXTRA_DIST += rdata_afsdb_toWire1.wire rdata_afsdb_toWire2.wire
+EXTRA_DIST += rdata_soa_fromWire rdata_soa_toWireUncompressed.wire
+EXTRA_DIST += rdata_minfo_fromWire1.wire rdata_minfo_fromWire2.wire
+EXTRA_DIST += rdata_minfo_fromWire3.wire rdata_minfo_fromWire4.wire
+EXTRA_DIST += rdata_minfo_fromWire5.wire rdata_minfo_fromWire6.wire
+EXTRA_DIST += rdata_minfo_toWire1.wire rdata_minfo_toWire2.wire
+EXTRA_DIST += rdata_minfo_toWireUncompressed1.wire
+EXTRA_DIST += rdata_minfo_toWireUncompressed2.wire
+EXTRA_DIST += rdata_txt_fromWire1 rdata_txt_fromWire2.wire
+EXTRA_DIST += rdata_txt_fromWire3.wire rdata_txt_fromWire4.wire
+EXTRA_DIST += rdata_txt_fromWire5.wire rdata_unknown_fromWire
+EXTRA_DIST += rdata_tlsa_fromWire3.wire rdata_tlsa_fromWire4.wire
+EXTRA_DIST += rdata_tlsa_fromWire5.wire rdata_tlsa_fromWire6.wire
+EXTRA_DIST += rdata_tlsa_fromWire7.wire rdata_tlsa_fromWire8.wire
+EXTRA_DIST += rdata_tsig_fromWire1.wire rdata_tsig_fromWire2.wire
+EXTRA_DIST += rdata_tsig_fromWire3.wire rdata_tsig_fromWire4.wire
+EXTRA_DIST += rdata_tsig_fromWire5.wire rdata_tsig_fromWire6.wire
+EXTRA_DIST += rdata_tsig_fromWire7.wire rdata_tsig_fromWire8.wire
+EXTRA_DIST += rdata_tsig_fromWire9.wire
+EXTRA_DIST += rdata_tsig_toWire1.wire rdata_tsig_toWire2.wire
+EXTRA_DIST += rdata_tsig_toWire3.wire rdata_tsig_toWire4.wire
+EXTRA_DIST += rdata_tsig_toWire5.wire
+EXTRA_DIST += rdata_caa_fromWire1.wire rdata_caa_fromWire2.wire
+EXTRA_DIST += rdata_caa_fromWire3.wire rdata_caa_fromWire4.wire
+EXTRA_DIST += rdata_tkey_fromWire1.wire rdata_tkey_fromWire2.wire
+EXTRA_DIST += rdata_tkey_fromWire3.wire rdata_tkey_fromWire4.wire
+EXTRA_DIST += rdata_tkey_fromWire5.wire rdata_tkey_fromWire6.wire
+EXTRA_DIST += rdata_tkey_fromWire7.wire rdata_tkey_fromWire8.wire
+EXTRA_DIST += rdata_tkey_fromWire9.wire
+EXTRA_DIST += rdata_tkey_toWire1.wire rdata_tkey_toWire2.wire
+EXTRA_DIST += rdata_tkey_toWire3.wire rdata_tkey_toWire4.wire
+EXTRA_DIST += rdata_tkey_toWire5.wire
+EXTRA_DIST += tsigrecord_toWire1.wire tsigrecord_toWire2.wire
+EXTRA_DIST += tsig_verify1.wire tsig_verify2.wire tsig_verify3.wire
+EXTRA_DIST += tsig_verify4.wire tsig_verify5.wire tsig_verify6.wire
+EXTRA_DIST += tsig_verify7.wire tsig_verify8.wire tsig_verify9.wire
+EXTRA_DIST += tsig_verify10.wire tsig_verify11.wire
+
+# We no longer use gen_wiredata.py during build process, so the
+# dependency is no longer needed. However, we'll keep this dependency
+# commented till the gen_wiredata.py script is removed.
+
+#.spec.wire:
+# $(PYTHON) $(top_builddir)/src/lib/util/python/gen_wiredata.py -o $@ $<
diff --git a/src/lib/dns/tests/testdata/Makefile.in b/src/lib/dns/tests/testdata/Makefile.in
new file mode 100644
index 0000000..0a311f3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/Makefile.in
@@ -0,0 +1,740 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/lib/dns/tests/testdata
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \
+ $(top_srcdir)/m4macros/ax_cpp11.m4 \
+ $(top_srcdir)/m4macros/ax_cpp20.m4 \
+ $(top_srcdir)/m4macros/ax_crypto.m4 \
+ $(top_srcdir)/m4macros/ax_find_library.m4 \
+ $(top_srcdir)/m4macros/ax_gssapi.m4 \
+ $(top_srcdir)/m4macros/ax_gtest.m4 \
+ $(top_srcdir)/m4macros/ax_isc_rpath.m4 \
+ $(top_srcdir)/m4macros/ax_netconf.m4 \
+ $(top_srcdir)/m4macros/libtool.m4 \
+ $(top_srcdir)/m4macros/ltoptions.m4 \
+ $(top_srcdir)/m4macros/ltsugar.m4 \
+ $(top_srcdir)/m4macros/ltversion.m4 \
+ $(top_srcdir)/m4macros/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ASCIIDOC = @ASCIIDOC@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_INCLUDES = @BOOST_INCLUDES@
+BOOST_LIBS = @BOOST_LIBS@
+BOTAN_TOOL = @BOTAN_TOOL@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTRIB_DIR = @CONTRIB_DIR@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CRYPTO_CFLAGS = @CRYPTO_CFLAGS@
+CRYPTO_INCLUDES = @CRYPTO_INCLUDES@
+CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@
+CRYPTO_LIBS = @CRYPTO_LIBS@
+CRYPTO_PACKAGE = @CRYPTO_PACKAGE@
+CRYPTO_RPATH = @CRYPTO_RPATH@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@
+DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@
+DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@
+DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@
+DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@
+DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@
+DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@
+DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@
+DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@
+DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@
+DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@
+DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@
+DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@
+DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@
+DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_INCLUDES = @GTEST_INCLUDES@
+GTEST_LDADD = @GTEST_LDADD@
+GTEST_LDFLAGS = @GTEST_LDFLAGS@
+GTEST_SOURCE = @GTEST_SOURCE@
+HAVE_NETCONF = @HAVE_NETCONF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KEA_CXXFLAGS = @KEA_CXXFLAGS@
+KEA_SRCID = @KEA_SRCID@
+KRB5_CONFIG = @KRB5_CONFIG@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@
+LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@
+LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@
+LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@
+LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@
+LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@
+LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@
+LIBYANG_LIBS = @LIBYANG_LIBS@
+LIBYANG_PREFIX = @LIBYANG_PREFIX@
+LIBYANG_VERSION = @LIBYANG_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@
+LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
+PERL = @PERL@
+PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PKGPYTHONDIR = @PKGPYTHONDIR@
+PKG_CONFIG = @PKG_CONFIG@
+PLANTUML = @PLANTUML@
+PREMIUM_DIR = @PREMIUM_DIR@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SEP = @SEP@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINXBUILD = @SPHINXBUILD@
+SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@
+SR_PLUGINS_PATH = @SR_PLUGINS_PATH@
+SR_REPO_PATH = @SR_REPO_PATH@
+STRIP = @STRIP@
+SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@
+SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@
+SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@
+SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@
+SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@
+SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@
+SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@
+SYSREPO_LIBS = @SYSREPO_LIBS@
+SYSREPO_PREFIX = @SYSREPO_PREFIX@
+SYSREPO_VERSION = @SYSREPO_VERSION@
+USE_LCOV = @USE_LCOV@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@
+YACC = @YACC@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES =
+
+# NOTE: keep this in sync with real file listing
+# so is included in tarball
+
+# Generated .wire files
+EXTRA_DIST = edns_toWire1.spec edns_toWire2.spec edns_toWire3.spec \
+ edns_toWire4.spec masterload.txt message_fromWire1 \
+ message_fromWire2 message_fromWire3 message_fromWire4 \
+ message_fromWire5 message_fromWire6 message_fromWire7 \
+ message_fromWire8 message_fromWire9 message_fromWire10.spec \
+ message_fromWire11.spec message_fromWire12.spec \
+ message_fromWire13.spec message_fromWire14.spec \
+ message_fromWire15.spec message_fromWire16.spec \
+ message_fromWire17.spec message_fromWire18.spec \
+ message_fromWire19.spec message_fromWire20.spec \
+ message_fromWire21.spec message_fromWire22.spec \
+ message_toWire1 message_toWire2.spec message_toWire3.spec \
+ message_toWire4.spec message_toWire5.spec message_toWire6 \
+ message_toWire7 message_toText1.txt message_toText1.spec \
+ message_toText2.txt message_toText2.spec message_toText3.txt \
+ message_toText3.spec name_fromWire1 name_fromWire2 \
+ name_fromWire3_1 name_fromWire3_2 name_fromWire4 \
+ name_fromWire6 name_fromWire7 name_fromWire8 name_fromWire9 \
+ name_fromWire10 name_fromWire11 name_fromWire12 \
+ name_fromWire13 name_fromWire14 name_toWire1 name_toWire2 \
+ name_toWire3 name_toWire4 name_toWire5.spec name_toWire6.spec \
+ name_toWire7 name_toWire8 name_toWire9 question_fromWire \
+ question_toWire1 question_toWire2 rdatafields1.spec \
+ rdatafields2.spec rdatafields3.spec rdatafields4.spec \
+ rdatafields5.spec rdatafields6.spec rdata_cname_fromWire \
+ rdata_dname_fromWire rdata_dnskey_fromWire.spec \
+ rdata_dnskey_empty_keydata_fromWire.spec rdata_dhcid_fromWire \
+ rdata_dhcid_toWire rdata_ds_fromWire rdata_in_a_fromWire \
+ rdata_in_aaaa_fromWire rdata_mx_fromWire rdata_mx_toWire1 \
+ rdata_mx_toWire2 rdata_ns_fromWire rdata_nsec_fromWire1 \
+ rdata_nsec_fromWire2 rdata_nsec_fromWire3 \
+ rdata_nsec_fromWire4.spec rdata_nsec_fromWire5.spec \
+ rdata_nsec_fromWire6.spec rdata_nsec_fromWire7.spec \
+ rdata_nsec_fromWire8.spec rdata_nsec_fromWire9.spec \
+ rdata_nsec_fromWire10.spec rdata_nsec_fromWire16.spec \
+ rdata_nsec3param_fromWire1 rdata_nsec3param_fromWire2.spec \
+ rdata_nsec3param_fromWire11.spec \
+ rdata_nsec3param_fromWire13.spec rdata_nsec3_fromWire1 \
+ rdata_nsec3_fromWire1.spec rdata_nsec3_fromWire2.spec \
+ rdata_nsec3_fromWire3 rdata_nsec3_fromWire4.spec \
+ rdata_nsec3_fromWire5.spec rdata_nsec3_fromWire6.spec \
+ rdata_nsec3_fromWire7.spec rdata_nsec3_fromWire8.spec \
+ rdata_nsec3_fromWire9.spec rdata_nsec3_fromWire10.spec \
+ rdata_nsec3_fromWire11.spec rdata_nsec3_fromWire12.spec \
+ rdata_nsec3_fromWire13.spec rdata_nsec3_fromWire14.spec \
+ rdata_nsec3_fromWire15.spec rdata_nsec3_fromWire16.spec \
+ rdata_nsec3_fromWire17.spec rdata_opt_fromWire1 \
+ rdata_opt_fromWire2 rdata_opt_fromWire3 rdata_opt_fromWire4 \
+ rdata_rrsig_fromWire1 rdata_rrsig_fromWire2.spec \
+ rdata_rp_fromWire1.spec rdata_rp_fromWire2.spec \
+ rdata_rp_fromWire3.spec rdata_rp_fromWire4.spec \
+ rdata_rp_fromWire5.spec rdata_rp_fromWire6.spec \
+ rdata_rp_toWire1.spec rdata_rp_toWire2.spec \
+ rdata_sshfp_fromWire rdata_sshfp_fromWire2 \
+ rdata_sshfp_fromWire1.spec rdata_sshfp_fromWire2.spec \
+ rdata_sshfp_fromWire3.spec rdata_sshfp_fromWire4.spec \
+ rdata_sshfp_fromWire5.spec rdata_sshfp_fromWire6.spec \
+ rdata_sshfp_fromWire7.spec rdata_sshfp_fromWire8.spec \
+ rdata_sshfp_fromWire9 rdata_sshfp_fromWire10 \
+ rdata_sshfp_fromWire11 rdata_sshfp_fromWire12 \
+ rdata_afsdb_fromWire1.spec rdata_afsdb_fromWire2.spec \
+ rdata_afsdb_fromWire3.spec rdata_afsdb_fromWire4.spec \
+ rdata_afsdb_fromWire5.spec rdata_afsdb_toWire1.spec \
+ rdata_afsdb_toWire2.spec rdata_soa_fromWire \
+ rdata_soa_toWireUncompressed.spec rdata_srv_fromWire \
+ rdata_minfo_fromWire1.spec rdata_minfo_fromWire2.spec \
+ rdata_minfo_fromWire3.spec rdata_minfo_fromWire4.spec \
+ rdata_minfo_fromWire5.spec rdata_minfo_fromWire6.spec \
+ rdata_minfo_toWire1.spec rdata_minfo_toWire2.spec \
+ rdata_minfo_toWireUncompressed1.spec \
+ rdata_minfo_toWireUncompressed2.spec rdata_txt_fromWire1 \
+ rdata_txt_fromWire2.spec rdata_txt_fromWire3.spec \
+ rdata_txt_fromWire4.spec rdata_txt_fromWire5.spec \
+ rdata_unknown_fromWire rrcode16_fromWire1 rrcode16_fromWire2 \
+ rrcode32_fromWire1 rrcode32_fromWire2 rrset_toWire1 \
+ rrset_toWire2 rrset_toWire3 rrset_toWire4 \
+ rdata_tkey_fromWire1.spec rdata_tkey_fromWire2.spec \
+ rdata_tkey_fromWire3.spec rdata_tkey_fromWire4.spec \
+ rdata_tkey_fromWire5.spec rdata_tkey_fromWire6.spec \
+ rdata_tkey_fromWire7.spec rdata_tkey_fromWire8.spec \
+ rdata_tkey_fromWire9.spec rdata_tkey_toWire1.spec \
+ rdata_tkey_toWire2.spec rdata_tkey_toWire3.spec \
+ rdata_tkey_toWire4.spec rdata_tkey_toWire5.spec \
+ rdata_tlsa_fromWire rdata_tlsa_fromWire2 \
+ rdata_tlsa_fromWire3.spec rdata_tlsa_fromWire4.spec \
+ rdata_tlsa_fromWire5.spec rdata_tlsa_fromWire6.spec \
+ rdata_tlsa_fromWire7.spec rdata_tlsa_fromWire8.spec \
+ rdata_tlsa_fromWire9 rdata_tlsa_fromWire10 \
+ rdata_tlsa_fromWire11 rdata_tlsa_fromWire12 \
+ rdata_tsig_fromWire1.spec rdata_tsig_fromWire2.spec \
+ rdata_tsig_fromWire3.spec rdata_tsig_fromWire4.spec \
+ rdata_tsig_fromWire5.spec rdata_tsig_fromWire6.spec \
+ rdata_tsig_fromWire7.spec rdata_tsig_fromWire8.spec \
+ rdata_tsig_fromWire9.spec rdata_tsig_toWire1.spec \
+ rdata_tsig_toWire2.spec rdata_tsig_toWire3.spec \
+ rdata_tsig_toWire4.spec rdata_tsig_toWire5.spec \
+ rdata_caa_fromWire1.spec rdata_caa_fromWire2.spec \
+ rdata_caa_fromWire3.spec rdata_caa_fromWire4.spec \
+ rdata_caa_fromWire5 rdata_caa_fromWire6 \
+ tsigrecord_toWire1.spec tsigrecord_toWire2.spec \
+ tsig_verify1.spec tsig_verify2.spec tsig_verify3.spec \
+ tsig_verify4.spec tsig_verify5.spec tsig_verify6.spec \
+ tsig_verify7.spec tsig_verify8.spec tsig_verify9.spec \
+ tsig_verify10.spec tsig_verify11.spec example.org broken.zone \
+ origincheck.txt omitcheck.txt edns_toWire1.wire \
+ edns_toWire2.wire edns_toWire3.wire edns_toWire4.wire \
+ message_fromWire10.wire message_fromWire11.wire \
+ message_fromWire12.wire message_fromWire13.wire \
+ message_fromWire14.wire message_fromWire15.wire \
+ message_fromWire16.wire message_fromWire17.wire \
+ message_fromWire18.wire message_fromWire19.wire \
+ message_fromWire20.wire message_fromWire21.wire \
+ message_fromWire22.wire message_toWire1 message_toWire2.wire \
+ message_toWire3.wire message_toWire4.wire message_toWire5.wire \
+ message_toText1.txt message_toText1.wire message_toText2.txt \
+ message_toText2.wire message_toText3.txt message_toText3.wire \
+ name_toWire5.wire name_toWire6.wire rdatafields1.wire \
+ rdatafields2.wire rdatafields3.wire rdatafields4.wire \
+ rdatafields5.wire rdatafields6.wire rdata_dnskey_fromWire.wire \
+ rdata_dnskey_empty_keydata_fromWire.wire \
+ rdata_nsec_fromWire4.wire rdata_nsec_fromWire5.wire \
+ rdata_nsec_fromWire6.wire rdata_nsec_fromWire7.wire \
+ rdata_nsec_fromWire8.wire rdata_nsec_fromWire9.wire \
+ rdata_nsec_fromWire10.wire rdata_nsec_fromWire16.wire \
+ rdata_nsec3param_fromWire2.wire \
+ rdata_nsec3param_fromWire11.wire \
+ rdata_nsec3param_fromWire13.wire rdata_nsec3_fromWire2.wire \
+ rdata_nsec3_fromWire3 rdata_nsec3_fromWire4.wire \
+ rdata_nsec3_fromWire5.wire rdata_nsec3_fromWire6.wire \
+ rdata_nsec3_fromWire7.wire rdata_nsec3_fromWire8.wire \
+ rdata_nsec3_fromWire9.wire rdata_nsec3_fromWire10.wire \
+ rdata_nsec3_fromWire11.wire rdata_nsec3_fromWire12.wire \
+ rdata_nsec3_fromWire13.wire rdata_nsec3_fromWire14.wire \
+ rdata_nsec3_fromWire15.wire rdata_nsec3_fromWire16.wire \
+ rdata_nsec3_fromWire17.wire rdata_rrsig_fromWire2.wire \
+ rdata_rp_fromWire1.wire rdata_rp_fromWire2.wire \
+ rdata_rp_fromWire3.wire rdata_rp_fromWire4.wire \
+ rdata_rp_fromWire5.wire rdata_rp_fromWire6.wire \
+ rdata_rp_toWire1.wire rdata_rp_toWire2.wire \
+ rdata_sshfp_fromWire1.wire rdata_sshfp_fromWire2.wire \
+ rdata_sshfp_fromWire3.wire rdata_sshfp_fromWire4.wire \
+ rdata_sshfp_fromWire5.wire rdata_sshfp_fromWire6.wire \
+ rdata_sshfp_fromWire7.wire rdata_sshfp_fromWire8.wire \
+ rdata_afsdb_fromWire1.wire rdata_afsdb_fromWire2.wire \
+ rdata_afsdb_fromWire3.wire rdata_afsdb_fromWire4.wire \
+ rdata_afsdb_fromWire5.wire rdata_afsdb_toWire1.wire \
+ rdata_afsdb_toWire2.wire rdata_soa_fromWire \
+ rdata_soa_toWireUncompressed.wire rdata_minfo_fromWire1.wire \
+ rdata_minfo_fromWire2.wire rdata_minfo_fromWire3.wire \
+ rdata_minfo_fromWire4.wire rdata_minfo_fromWire5.wire \
+ rdata_minfo_fromWire6.wire rdata_minfo_toWire1.wire \
+ rdata_minfo_toWire2.wire rdata_minfo_toWireUncompressed1.wire \
+ rdata_minfo_toWireUncompressed2.wire rdata_txt_fromWire1 \
+ rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire \
+ rdata_txt_fromWire4.wire rdata_txt_fromWire5.wire \
+ rdata_unknown_fromWire rdata_tlsa_fromWire3.wire \
+ rdata_tlsa_fromWire4.wire rdata_tlsa_fromWire5.wire \
+ rdata_tlsa_fromWire6.wire rdata_tlsa_fromWire7.wire \
+ rdata_tlsa_fromWire8.wire rdata_tsig_fromWire1.wire \
+ rdata_tsig_fromWire2.wire rdata_tsig_fromWire3.wire \
+ rdata_tsig_fromWire4.wire rdata_tsig_fromWire5.wire \
+ rdata_tsig_fromWire6.wire rdata_tsig_fromWire7.wire \
+ rdata_tsig_fromWire8.wire rdata_tsig_fromWire9.wire \
+ rdata_tsig_toWire1.wire rdata_tsig_toWire2.wire \
+ rdata_tsig_toWire3.wire rdata_tsig_toWire4.wire \
+ rdata_tsig_toWire5.wire rdata_caa_fromWire1.wire \
+ rdata_caa_fromWire2.wire rdata_caa_fromWire3.wire \
+ rdata_caa_fromWire4.wire rdata_tkey_fromWire1.wire \
+ rdata_tkey_fromWire2.wire rdata_tkey_fromWire3.wire \
+ rdata_tkey_fromWire4.wire rdata_tkey_fromWire5.wire \
+ rdata_tkey_fromWire6.wire rdata_tkey_fromWire7.wire \
+ rdata_tkey_fromWire8.wire rdata_tkey_fromWire9.wire \
+ rdata_tkey_toWire1.wire rdata_tkey_toWire2.wire \
+ rdata_tkey_toWire3.wire rdata_tkey_toWire4.wire \
+ rdata_tkey_toWire5.wire tsigrecord_toWire1.wire \
+ tsigrecord_toWire2.wire tsig_verify1.wire tsig_verify2.wire \
+ tsig_verify3.wire tsig_verify4.wire tsig_verify5.wire \
+ tsig_verify6.wire tsig_verify7.wire tsig_verify8.wire \
+ tsig_verify9.wire tsig_verify10.wire tsig_verify11.wire
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/dns/tests/testdata/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/lib/dns/tests/testdata/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# We no longer use gen_wiredata.py during build process, so the
+# dependency is no longer needed. However, we'll keep this dependency
+# commented till the gen_wiredata.py script is removed.
+
+#.spec.wire:
+# $(PYTHON) $(top_builddir)/src/lib/util/python/gen_wiredata.py -o $@ $<
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/lib/dns/tests/testdata/broken.zone b/src/lib/dns/tests/testdata/broken.zone
new file mode 100644
index 0000000..70f4540
--- /dev/null
+++ b/src/lib/dns/tests/testdata/broken.zone
@@ -0,0 +1,3 @@
+; This should fail due to broken TTL
+; The file should _NOT_ end with EOLN
+broken. 3600X IN A 192.0.2.2 More data \ No newline at end of file
diff --git a/src/lib/dns/tests/testdata/edns_toWire1.spec b/src/lib/dns/tests/testdata/edns_toWire1.spec
new file mode 100644
index 0000000..483aefa
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire1.spec
@@ -0,0 +1,5 @@
+#
+# A simplest form of EDNS: all default parameters
+#
+[edns]
+
diff --git a/src/lib/dns/tests/testdata/edns_toWire1.wire b/src/lib/dns/tests/testdata/edns_toWire1.wire
new file mode 100644
index 0000000..2884e29
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire1.wire
@@ -0,0 +1,9 @@
+###
+### This data file was auto-generated from edns_toWire1.spec
+###
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=0 Version=0 DO=0
+00 0029 1000 0000 0000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/edns_toWire2.spec b/src/lib/dns/tests/testdata/edns_toWire2.spec
new file mode 100644
index 0000000..7fe1ffd
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire2.spec
@@ -0,0 +1,5 @@
+#
+# Same as edns_toWire1 but setting the DO bit
+#
+[edns]
+do: 1
diff --git a/src/lib/dns/tests/testdata/edns_toWire2.wire b/src/lib/dns/tests/testdata/edns_toWire2.wire
new file mode 100644
index 0000000..cb09000
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire2.wire
@@ -0,0 +1,9 @@
+###
+### This data file was auto-generated from edns_toWire2.spec
+###
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=0 Version=0 DO=1
+00 0029 1000 0000 8000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/edns_toWire3.spec b/src/lib/dns/tests/testdata/edns_toWire3.spec
new file mode 100644
index 0000000..0332097
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire3.spec
@@ -0,0 +1,7 @@
+#
+# Same as edns_toWire1 but setting the DO bit, and extended Rcode being non 0
+# (for BADVER)
+#
+[edns]
+do: 1
+extrcode: 0x1
diff --git a/src/lib/dns/tests/testdata/edns_toWire3.wire b/src/lib/dns/tests/testdata/edns_toWire3.wire
new file mode 100644
index 0000000..b8d0775
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire3.wire
@@ -0,0 +1,9 @@
+###
+### This data file was auto-generated from edns_toWire3.spec
+###
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=1 Version=0 DO=1
+00 0029 1000 0100 8000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/edns_toWire4.spec b/src/lib/dns/tests/testdata/edns_toWire4.spec
new file mode 100644
index 0000000..ea1f5e3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire4.spec
@@ -0,0 +1,7 @@
+#
+# Same as edns_toWire1 but setting the DO bit, and using an unusual
+# UDP payload size
+#
+[edns]
+do: 1
+udpsize = 511
diff --git a/src/lib/dns/tests/testdata/edns_toWire4.wire b/src/lib/dns/tests/testdata/edns_toWire4.wire
new file mode 100644
index 0000000..73bf757
--- /dev/null
+++ b/src/lib/dns/tests/testdata/edns_toWire4.wire
@@ -0,0 +1,9 @@
+###
+### This data file was auto-generated from edns_toWire4.spec
+###
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=511 ExtRcode=0 Version=0 DO=1
+00 0029 01ff 0000 8000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/example.org b/src/lib/dns/tests/testdata/example.org
new file mode 100644
index 0000000..2708ef4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/example.org
@@ -0,0 +1,17 @@
+example.org. 3600 IN SOA ( ; The SOA, split across lines for testing
+ ns1.example.org.
+ admin.example.org.
+ 1234
+ 3600
+ 1800
+ 2419200
+ 7200
+ )
+; Check it accepts quoted name too
+"\101xample.org." 3600 IN NS ns1.example.org.
+
+
+; Some empty lines here. They are to make sure the loader can skip them.
+www 3600 IN A 192.0.2.1 ; Test a relative name as well.
+ 3600 IN AAAA 2001:db8::1 ; And initial whitespace handling
+ ; Here be just some space, no RRs
diff --git a/src/lib/dns/tests/testdata/masterload.txt b/src/lib/dns/tests/testdata/masterload.txt
new file mode 100644
index 0000000..0d2f942
--- /dev/null
+++ b/src/lib/dns/tests/testdata/masterload.txt
@@ -0,0 +1,5 @@
+;; a simple (incomplete) zone file
+
+example.com. 3600 IN TXT "test data"
+www.example.com. 60 IN A 192.0.2.1
+www.example.com. 60 IN A 192.0.2.2
diff --git a/src/lib/dns/tests/testdata/message_fromWire1 b/src/lib/dns/tests/testdata/message_fromWire1
new file mode 100644
index 0000000..5b76e3f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire1
@@ -0,0 +1,22 @@
+#
+# A simple DNS response message
+# ID = 0x1035
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=2, other COUNTS=0
+# Question: test.example.com. IN A
+# Answer:
+# test.example.com. 3600 IN A 192.0.2.1
+# test.example.com. 7200 IN A 192.0.2.2
+#
+1035 8500
+0001 0002 0000 0000
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# same name, fully compressed
+c0 0c
+# TTL=3600, A, IN, RDLENGTH=4, RDATA
+0001 0001 00000e10 0004 c0 00 02 01
+# mostly same, with the slight difference in RDATA and TTL
+c0 0c
+0001 0001 00001c20 0004 c0 00 02 02
diff --git a/src/lib/dns/tests/testdata/message_fromWire10.spec b/src/lib/dns/tests/testdata/message_fromWire10.spec
new file mode 100644
index 0000000..d3fb014
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire10.spec
@@ -0,0 +1,13 @@
+#
+# A simple DNS response message with an EDNS0 indicating a BADVERS error
+#
+
+[header]
+qr: response
+rd: 1
+arcount: 1
+[question]
+# use default
+[edns]
+do: 1
+extrcode: 1
diff --git a/src/lib/dns/tests/testdata/message_fromWire10.wire b/src/lib/dns/tests/testdata/message_fromWire10.wire
new file mode 100644
index 0000000..fa76b92
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire10.wire
@@ -0,0 +1,19 @@
+###
+### This data file was auto-generated from message_fromWire10.spec
+###
+
+# Header Section
+# ID=4149 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) RD
+1035 8100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=example.com. QTYPE=A(1) QCLASS=IN(1)
+076578616d706c6503636f6d00 0001 0001
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=1 Version=0 DO=1
+00 0029 1000 0100 8000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire11.spec b/src/lib/dns/tests/testdata/message_fromWire11.spec
new file mode 100644
index 0000000..5f31746
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire11.spec
@@ -0,0 +1,15 @@
+#
+# A simple DNS response message with an EDNS0 indicating the maximum error code
+# (0xfff)
+#
+
+[header]
+qr: response
+rd: 1
+rcode: 0xf
+arcount: 1
+[question]
+# use default
+[edns]
+do: 1
+extrcode: 0xff
diff --git a/src/lib/dns/tests/testdata/message_fromWire11.wire b/src/lib/dns/tests/testdata/message_fromWire11.wire
new file mode 100644
index 0000000..f20132c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire11.wire
@@ -0,0 +1,19 @@
+###
+### This data file was auto-generated from message_fromWire11.spec
+###
+
+# Header Section
+# ID=4149 QR=Response Opcode=QUERY(0) Rcode=15 RD
+1035 810f
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=example.com. QTYPE=A(1) QCLASS=IN(1)
+076578616d706c6503636f6d00 0001 0001
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=255 Version=0 DO=1
+00 0029 1000 ff00 8000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire12.spec b/src/lib/dns/tests/testdata/message_fromWire12.spec
new file mode 100644
index 0000000..4eadeed
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire12.spec
@@ -0,0 +1,21 @@
+#
+# A simple DNS response message with TSIG signed, but the owner name of TSIG
+# is compressed
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: ptr=12
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_fromWire12.wire b/src/lib/dns/tests/testdata/message_fromWire12.wire
new file mode 100644
index 0000000..9ceb356
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire12.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from message_fromWire12.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=ptr=12 Class=ANY(255) TTL=0, RDLEN=58)
+c00c 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire13.spec b/src/lib/dns/tests/testdata/message_fromWire13.spec
new file mode 100644
index 0000000..e81ec4c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire13.spec
@@ -0,0 +1,20 @@
+#
+# Invalid TSIG: containing 2 TSIG RRs.
+#
+
+[custom]
+sections: header:question:tsig:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 2
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_fromWire13.wire b/src/lib/dns/tests/testdata/message_fromWire13.wire
new file mode 100644
index 0000000..05b064a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire13.wire
@@ -0,0 +1,35 @@
+###
+### This data file was auto-generated from message_fromWire13.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=2
+0001 0000 0000 0002
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire14.spec b/src/lib/dns/tests/testdata/message_fromWire14.spec
new file mode 100644
index 0000000..bf68a93
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire14.spec
@@ -0,0 +1,21 @@
+#
+# Invalid TSIG: not in the additional section.
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+# TSIG goes to the answer section
+ancount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_fromWire14.wire b/src/lib/dns/tests/testdata/message_fromWire14.wire
new file mode 100644
index 0000000..17d0e21
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire14.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from message_fromWire14.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=1, NSCNT=0, ARCNT=0
+0001 0001 0000 0000
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire15.spec b/src/lib/dns/tests/testdata/message_fromWire15.spec
new file mode 100644
index 0000000..25d810f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire15.spec
@@ -0,0 +1,22 @@
+#
+# Invalid TSIG: not at the end of the message
+#
+
+[custom]
+sections: header:question:tsig:edns
+[header]
+id: 0x2d65
+rd: 1
+arcount: 2
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
+[edns]
+# (all default)
diff --git a/src/lib/dns/tests/testdata/message_fromWire15.wire b/src/lib/dns/tests/testdata/message_fromWire15.wire
new file mode 100644
index 0000000..e3f36d0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire15.wire
@@ -0,0 +1,30 @@
+###
+### This data file was auto-generated from message_fromWire15.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=2
+0001 0000 0000 0002
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=0 Version=0 DO=0
+00 0029 1000 0000 0000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire16.spec b/src/lib/dns/tests/testdata/message_fromWire16.spec
new file mode 100644
index 0000000..be0abc3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire16.spec
@@ -0,0 +1,21 @@
+#
+# Invalid TSIG: not in the additional section.
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_class: IN
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_fromWire16.wire b/src/lib/dns/tests/testdata/message_fromWire16.wire
new file mode 100644
index 0000000..04a791a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire16.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from message_fromWire16.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=IN(1) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 0001 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire17.spec b/src/lib/dns/tests/testdata/message_fromWire17.spec
new file mode 100644
index 0000000..366cf05
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire17.spec
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with TSIG signed
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x22c2
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+rrtype: TXT
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4e179212
+mac_size: 16
+mac: 0x8214b04634e32323d651ac60b08e6388
+original_id: 0x22c2
diff --git a/src/lib/dns/tests/testdata/message_fromWire17.wire b/src/lib/dns/tests/testdata/message_fromWire17.wire
new file mode 100644
index 0000000..e607c52
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire17.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from message_fromWire17.spec
+###
+
+# Header Section
+# ID=8898 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+22c2 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=TXT(16) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0010 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1310167570 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004e179212 012c
+# MAC Size=16 MAC=(see hex)
+0010 8214b04634e32323d651ac60b08e6388
+# Original-ID=8898 Error=0
+22c2 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire18.spec b/src/lib/dns/tests/testdata/message_fromWire18.spec
new file mode 100644
index 0000000..0b2592a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire18.spec
@@ -0,0 +1,23 @@
+#
+# Another simple DNS query message with TSIG signed. Only ID and time signed
+# (and MAC as a result) are different.
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0xd6e2
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+rrtype: TXT
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4e17b38d
+mac_size: 16
+mac: 0x903b5b194a799b03a37718820c2404f2
+original_id: 0xd6e2
diff --git a/src/lib/dns/tests/testdata/message_fromWire18.wire b/src/lib/dns/tests/testdata/message_fromWire18.wire
new file mode 100644
index 0000000..82bdf6b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire18.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from message_fromWire18.spec
+###
+
+# Header Section
+# ID=55010 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+d6e2 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=TXT(16) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0010 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1310176141 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004e17b38d 012c
+# MAC Size=16 MAC=(see hex)
+0010 903b5b194a799b03a37718820c2404f2
+# Original-ID=55010 Error=0
+d6e2 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire19.spec b/src/lib/dns/tests/testdata/message_fromWire19.spec
new file mode 100644
index 0000000..8212dbf
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire19.spec
@@ -0,0 +1,20 @@
+#
+# A non realistic DNS response message containing mixed types of RRs in the
+# answer section in a mixed order.
+#
+
+[custom]
+sections: header:question:a/1:aaaa:a/2
+[header]
+qr: 1
+ancount: 3
+[question]
+name: www.example.com
+rrtype: A
+[a/1]
+as_rr: True
+[aaaa]
+as_rr: True
+[a/2]
+as_rr: True
+address: 192.0.2.2
diff --git a/src/lib/dns/tests/testdata/message_fromWire19.wire b/src/lib/dns/tests/testdata/message_fromWire19.wire
new file mode 100644
index 0000000..d154244
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire19.wire
@@ -0,0 +1,28 @@
+###
+### This data file was auto-generated from message_fromWire19.spec
+###
+
+# Header Section
+# ID=4149 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0)
+1035 8000
+# QDCNT=1, ANCNT=3, NSCNT=0, ARCNT=0
+0001 0003 0000 0000
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# A RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=4)
+076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.1
+c0000201
+
+# AAAA RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=16)
+076578616d706c6503636f6d00 001c 0001 00015180 0010
+# Address=2001:db8::1
+20010db8000000000000000000000001
+
+# A RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=4)
+076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.2
+c0000202
diff --git a/src/lib/dns/tests/testdata/message_fromWire2 b/src/lib/dns/tests/testdata/message_fromWire2
new file mode 100644
index 0000000..194cbf2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire2
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with a valid EDNS0 OPT RR
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+# Question: test.example.com. IN A
+1035 0100
+0001 0000 0000 0001
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire20.spec b/src/lib/dns/tests/testdata/message_fromWire20.spec
new file mode 100644
index 0000000..91986e4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire20.spec
@@ -0,0 +1,20 @@
+#
+# A non realistic DNS response message containing mixed types of RRs in the
+# authority section in a mixed order.
+#
+
+[custom]
+sections: header:question:a/1:aaaa:a/2
+[header]
+qr: 1
+nscount: 3
+[question]
+name: www.example.com
+rrtype: A
+[a/1]
+as_rr: True
+[aaaa]
+as_rr: True
+[a/2]
+as_rr: True
+address: 192.0.2.2
diff --git a/src/lib/dns/tests/testdata/message_fromWire20.wire b/src/lib/dns/tests/testdata/message_fromWire20.wire
new file mode 100644
index 0000000..887dd1e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire20.wire
@@ -0,0 +1,28 @@
+###
+### This data file was auto-generated from message_fromWire20.spec
+###
+
+# Header Section
+# ID=4149 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0)
+1035 8000
+# QDCNT=1, ANCNT=0, NSCNT=3, ARCNT=0
+0001 0000 0003 0000
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# A RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=4)
+076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.1
+c0000201
+
+# AAAA RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=16)
+076578616d706c6503636f6d00 001c 0001 00015180 0010
+# Address=2001:db8::1
+20010db8000000000000000000000001
+
+# A RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=4)
+076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.2
+c0000202
diff --git a/src/lib/dns/tests/testdata/message_fromWire21.spec b/src/lib/dns/tests/testdata/message_fromWire21.spec
new file mode 100644
index 0000000..cd6aac9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire21.spec
@@ -0,0 +1,20 @@
+#
+# A non realistic DNS response message containing mixed types of RRs in the
+# additional section in a mixed order.
+#
+
+[custom]
+sections: header:question:a/1:aaaa:a/2
+[header]
+qr: 1
+arcount: 3
+[question]
+name: www.example.com
+rrtype: A
+[a/1]
+as_rr: True
+[aaaa]
+as_rr: True
+[a/2]
+as_rr: True
+address: 192.0.2.2
diff --git a/src/lib/dns/tests/testdata/message_fromWire21.wire b/src/lib/dns/tests/testdata/message_fromWire21.wire
new file mode 100644
index 0000000..14cfcc0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire21.wire
@@ -0,0 +1,28 @@
+###
+### This data file was auto-generated from message_fromWire21.spec
+###
+
+# Header Section
+# ID=4149 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0)
+1035 8000
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=3
+0001 0000 0000 0003
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# A RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=4)
+076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.1
+c0000201
+
+# AAAA RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=16)
+076578616d706c6503636f6d00 001c 0001 00015180 0010
+# Address=2001:db8::1
+20010db8000000000000000000000001
+
+# A RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=4)
+076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.2
+c0000202
diff --git a/src/lib/dns/tests/testdata/message_fromWire22.spec b/src/lib/dns/tests/testdata/message_fromWire22.spec
new file mode 100644
index 0000000..a52523b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire22.spec
@@ -0,0 +1,14 @@
+#
+# A simple DNS message containing one SOA RR in the answer section. This is
+# intended to be trimmed to emulate a bogus message.
+#
+
+[custom]
+sections: header:question:soa
+[header]
+qr: 1
+ancount: 1
+[question]
+rrtype: SOA
+[soa]
+as_rr: True
diff --git a/src/lib/dns/tests/testdata/message_fromWire22.wire b/src/lib/dns/tests/testdata/message_fromWire22.wire
new file mode 100644
index 0000000..69c3254
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire22.wire
@@ -0,0 +1,20 @@
+###
+### This data file was auto-generated from message_fromWire22.spec
+###
+
+# Header Section
+# ID=4149 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0)
+1035 8000
+# QDCNT=1, ANCNT=1, NSCNT=0, ARCNT=0
+0001 0001 0000 0000
+
+# Question Section
+# QNAME=example.com. QTYPE=SOA(6) QCLASS=IN(1)
+076578616d706c6503636f6d00 0006 0001
+
+# SOA RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=54)
+076578616d706c6503636f6d00 0006 0001 00015180 0036
+# NNAME=ns.example.com RNAME=root.example.com
+026e73076578616d706c6503636f6d00 04726f6f74076578616d706c6503636f6d00
+# SERIAL(2010012601) REFRESH(3600) RETRY(300) EXPIRE(3600000) MINIMUM(1200)
+77ce5bb9 00000e10 0000012c 0036ee80 000004b0
diff --git a/src/lib/dns/tests/testdata/message_fromWire3 b/src/lib/dns/tests/testdata/message_fromWire3
new file mode 100644
index 0000000..9bd536a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire3
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with a valid EDNS0 OPT RR, DO bit off
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+# Question: test.example.com. IN A
+1035 0100
+0001 0000 0000 0001
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=0
+0000 0000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire4 b/src/lib/dns/tests/testdata/message_fromWire4
new file mode 100644
index 0000000..23eb7cf
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire4
@@ -0,0 +1,23 @@
+#
+# A simple DNS query message with a bogus EDNS0 OPT RR (included in the
+# answer section)
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=1, NSCOUNT=0, ARCOUNT=0
+# Question: test.example.com. IN A
+1035 0100
+0001 0001 0000 0000
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire5 b/src/lib/dns/tests/testdata/message_fromWire5
new file mode 100644
index 0000000..6f08d22
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire5
@@ -0,0 +1,33 @@
+#
+# A simple DNS query message with multiple EDNS0 OPT RRs (bogus)
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=2
+# Question: test.example.com. IN A
+1035 0100
+0001 0000 0000 0002
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR (1st)
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000
+# EDNS0 OPT RR (2nd)
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire6 b/src/lib/dns/tests/testdata/message_fromWire6
new file mode 100644
index 0000000..2783fd0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire6
@@ -0,0 +1,23 @@
+#
+# A simple DNS query message with EDNS0 OPT RRs of non root name (bogus)
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+1035 0100
+0001 0000 0000 0001
+# Question: test.example.com. IN A
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "example.com"
+#(7) e x a m p l e (3) c o m .
+ 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire7 b/src/lib/dns/tests/testdata/message_fromWire7
new file mode 100644
index 0000000..4d85314
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire7
@@ -0,0 +1,27 @@
+#
+# A simple DNS query message with EDNS0 OPT RRs of compressed owner name
+# pointing to root (is this bogus?)
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+#0 1 2 3
+1035 0100
+#4 5 6 7 8 9 10 1
+0001 0000 0000 0001
+# Question: test.example.com. IN A
+# 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "example.com"
+# pointer = 29 (end of question section)
+ c0 1d
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire8 b/src/lib/dns/tests/testdata/message_fromWire8
new file mode 100644
index 0000000..c950b5e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire8
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with a valid EDNS0 OPT RR (but unusual UDP size)
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+# Question: test.example.com. IN A
+1035 0100
+0001 0000 0000 0001
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 500
+01f4
+# TTL (extended RCODE and flags): RCODE=0, version=0, flags=DO
+0000 8000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_fromWire9 b/src/lib/dns/tests/testdata/message_fromWire9
new file mode 100644
index 0000000..f9ff950
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_fromWire9
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with an unsupported version of EDNS0
+# ID = 0x1035
+# QR=0 (query), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=0, NSCOUNT=0, ARCOUNT=1
+# Question: test.example.com. IN A
+1035 0100
+0001 0000 0000 0001
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# EDNS0 OPT RR
+# owner name: "."
+00
+# TYPE: OPT (41 = 0x29)
+00 29
+# CLASS (= UDP size): 4096
+1000
+# TTL (extended RCODE and flags): RCODE=0, version=1, flags=DO
+0001 8000
+# RDLEN = 0
+0000
diff --git a/src/lib/dns/tests/testdata/message_toText1.spec b/src/lib/dns/tests/testdata/message_toText1.spec
new file mode 100644
index 0000000..b31310e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText1.spec
@@ -0,0 +1,24 @@
+#
+# A standard DNS message (taken from an invocation of dig)
+#
+
+[custom]
+sections: header:question:a/1:ns:a/2
+[header]
+id: 29174
+qr: 1
+aa: 1
+ancount: 1
+nscount: 1
+arcount: 1
+[question]
+name: www.example.com
+[a/1]
+as_rr: True
+rr_name: www.example.com
+address: 192.0.2.80
+[ns]
+as_rr: True
+[a/2]
+as_rr: True
+rr_name: ns.example.com
diff --git a/src/lib/dns/tests/testdata/message_toText1.txt b/src/lib/dns/tests/testdata/message_toText1.txt
new file mode 100644
index 0000000..58c7239
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText1.txt
@@ -0,0 +1,14 @@
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29174
+;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
+
+;; QUESTION SECTION:
+;www.example.com. IN A
+
+;; ANSWER SECTION:
+www.example.com. 86400 IN A 192.0.2.80
+
+;; AUTHORITY SECTION:
+example.com. 86400 IN NS ns.example.com.
+
+;; ADDITIONAL SECTION:
+ns.example.com. 86400 IN A 192.0.2.1
diff --git a/src/lib/dns/tests/testdata/message_toText1.wire b/src/lib/dns/tests/testdata/message_toText1.wire
new file mode 100644
index 0000000..2a959bd
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText1.wire
@@ -0,0 +1,28 @@
+###
+### This data file was auto-generated from message_toText1.spec
+###
+
+# Header Section
+# ID=29174 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA
+71f6 8400
+# QDCNT=1, ANCNT=1, NSCNT=1, ARCNT=1
+0001 0001 0001 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# A RR (QNAME=www.example.com Class=IN(1) TTL=86400, RDLEN=4)
+03777777076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.80
+c0000250
+
+# NS RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=16)
+076578616d706c6503636f6d00 0002 0001 00015180 0010
+# NS name=ns.example.com
+026e73076578616d706c6503636f6d00
+
+# A RR (QNAME=ns.example.com Class=IN(1) TTL=86400, RDLEN=4)
+026e73076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.1
+c0000201
diff --git a/src/lib/dns/tests/testdata/message_toText2.spec b/src/lib/dns/tests/testdata/message_toText2.spec
new file mode 100644
index 0000000..978aab3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText2.spec
@@ -0,0 +1,14 @@
+#
+# A standard DNS message with EDNS (taken from an invocation of dig)
+#
+
+[custom]
+sections: header:question:edns
+[header]
+id: 45981
+qr: 1
+rcode: refused
+arcount: 1
+[question]
+[edns]
+do: 1
diff --git a/src/lib/dns/tests/testdata/message_toText2.txt b/src/lib/dns/tests/testdata/message_toText2.txt
new file mode 100644
index 0000000..42cc2c1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText2.txt
@@ -0,0 +1,8 @@
+;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 45981
+;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
+
+;; OPT PSEUDOSECTION:
+; EDNS: version: 0, flags: do; udp: 4096
+
+;; QUESTION SECTION:
+;example.com. IN A
diff --git a/src/lib/dns/tests/testdata/message_toText2.wire b/src/lib/dns/tests/testdata/message_toText2.wire
new file mode 100644
index 0000000..1047b63
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText2.wire
@@ -0,0 +1,19 @@
+###
+### This data file was auto-generated from message_toText2.spec
+###
+
+# Header Section
+# ID=45981 QR=Response Opcode=QUERY(0) Rcode=REFUSED(5)
+b39d 8005
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=example.com. QTYPE=A(1) QCLASS=IN(1)
+076578616d706c6503636f6d00 0001 0001
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=0 Version=0 DO=1
+00 0029 1000 0000 8000
+# RDLEN=0
+0000
diff --git a/src/lib/dns/tests/testdata/message_toText3.spec b/src/lib/dns/tests/testdata/message_toText3.spec
new file mode 100644
index 0000000..a74ea1b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText3.spec
@@ -0,0 +1,31 @@
+#
+# A standard DNS message with TSIG (taken from an invocation of dig)
+#
+
+[custom]
+sections: header:question:a/1:ns:a/2:tsig
+[header]
+id: 10140
+qr: 1
+aa: 1
+ancount: 1
+nscount: 1
+arcount: 2
+[question]
+name: www.example.com
+[a/1]
+as_rr: True
+rr_name: www.example.com
+address: 192.0.2.80
+[ns]
+as_rr: True
+[a/2]
+as_rr: True
+rr_name: ns.example.com
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 1304384318
+original_id: 10140
+mac: 0x5257c80396f2fa95b20c77ae9a652fb2
diff --git a/src/lib/dns/tests/testdata/message_toText3.txt b/src/lib/dns/tests/testdata/message_toText3.txt
new file mode 100644
index 0000000..359b9c5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText3.txt
@@ -0,0 +1,17 @@
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10140
+;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2
+
+;; QUESTION SECTION:
+;www.example.com. IN A
+
+;; ANSWER SECTION:
+www.example.com. 86400 IN A 192.0.2.80
+
+;; AUTHORITY SECTION:
+example.com. 86400 IN NS ns.example.com.
+
+;; ADDITIONAL SECTION:
+ns.example.com. 86400 IN A 192.0.2.1
+
+;; TSIG PSEUDOSECTION:
+www.example.com. 0 ANY TSIG hmac-md5.sig-alg.reg.int. 1304384318 300 16 UlfIA5by+pWyDHeummUvsg== 10140 NOERROR 0
diff --git a/src/lib/dns/tests/testdata/message_toText3.wire b/src/lib/dns/tests/testdata/message_toText3.wire
new file mode 100644
index 0000000..eb3632b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toText3.wire
@@ -0,0 +1,39 @@
+###
+### This data file was auto-generated from message_toText3.spec
+###
+
+# Header Section
+# ID=10140 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA
+279c 8400
+# QDCNT=1, ANCNT=1, NSCNT=1, ARCNT=2
+0001 0001 0001 0002
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# A RR (QNAME=www.example.com Class=IN(1) TTL=86400, RDLEN=4)
+03777777076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.80
+c0000250
+
+# NS RR (QNAME=example.com Class=IN(1) TTL=86400, RDLEN=16)
+076578616d706c6503636f6d00 0002 0001 00015180 0010
+# NS name=ns.example.com
+026e73076578616d706c6503636f6d00
+
+# A RR (QNAME=ns.example.com Class=IN(1) TTL=86400, RDLEN=4)
+026e73076578616d706c6503636f6d00 0001 0001 00015180 0004
+# Address=192.0.2.1
+c0000201
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1304384318 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004dbf533e 012c
+# MAC Size=16 MAC=(see hex)
+0010 5257c80396f2fa95b20c77ae9a652fb2
+# Original-ID=10140 Error=0
+279c 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_toWire1 b/src/lib/dns/tests/testdata/message_toWire1
new file mode 100644
index 0000000..daeb85a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire1
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message
+# ID = 0x1035
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=2, other COUNTS=0
+# Question: test.example.com. IN A
+# Answer:
+# test.example.com. 3600 IN A 192.0.2.1
+# test.example.com. 7200 IN A 192.0.2.2
+#
+1035 8500
+0001 0002 0000 0000
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# same name, fully compressed
+c0 0c
+# TTL=3600, A, IN, RDLENGTH=4, RDATA
+0001 0001 00000e10 0004 c0 00 02 01
+# mostly same, with the slight difference in RDATA
+c0 0c
+0001 0001 00000e10 0004 c0 00 02 02
diff --git a/src/lib/dns/tests/testdata/message_toWire2.spec b/src/lib/dns/tests/testdata/message_toWire2.spec
new file mode 100644
index 0000000..d256052
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire2.spec
@@ -0,0 +1,21 @@
+#
+# A simple DNS query message with TSIG signed
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/message_toWire2.wire b/src/lib/dns/tests/testdata/message_toWire2.wire
new file mode 100644
index 0000000..a495253
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire2.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from message_toWire2.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_toWire3.spec b/src/lib/dns/tests/testdata/message_toWire3.spec
new file mode 100644
index 0000000..c8e9453
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire3.spec
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with EDNS and TSIG
+#
+
+[custom]
+sections: header:question:edns:tsig
+[header]
+id: 0x06cd
+rd: 1
+arcount: 2
+[question]
+name: www.example.com
+[edns]
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4db60d1f
+mac_size: 16
+mac: 0x93444053881c83d7eb120e86f25b369e
+original_id: 0x06cd
diff --git a/src/lib/dns/tests/testdata/message_toWire3.wire b/src/lib/dns/tests/testdata/message_toWire3.wire
new file mode 100644
index 0000000..46808b9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire3.wire
@@ -0,0 +1,30 @@
+###
+### This data file was auto-generated from message_toWire3.spec
+###
+
+# Header Section
+# ID=1741 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+06cd 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=2
+0001 0000 0000 0002
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# EDNS OPT RR
+# NAME=. TYPE=OPT(41) UDPSize=4096 ExtRcode=0 Version=0 DO=0
+00 0029 1000 0000 0000
+# RDLEN=0
+0000
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1303776543 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004db60d1f 012c
+# MAC Size=16 MAC=(see hex)
+0010 93444053881c83d7eb120e86f25b369e
+# Original-ID=1741 Error=0
+06cd 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_toWire4.spec b/src/lib/dns/tests/testdata/message_toWire4.spec
new file mode 100644
index 0000000..aab7e10
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire4.spec
@@ -0,0 +1,27 @@
+#
+# Truncated DNS response with TSIG signed
+# This is expected to be a response to "fromWire17"
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x22c2
+rd: 1
+qr: 1
+aa: 1
+# It's "truncated":
+tc: 1
+arcount: 1
+[question]
+name: www.example.com
+rrtype: TXT
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4e179212
+mac_size: 16
+mac: 0x88adc3811d1d6bec7c684438906fc694
+original_id: 0x22c2
diff --git a/src/lib/dns/tests/testdata/message_toWire4.wire b/src/lib/dns/tests/testdata/message_toWire4.wire
new file mode 100644
index 0000000..d2cda30
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire4.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from message_toWire4.spec
+###
+
+# Header Section
+# ID=8898 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA TC RD
+22c2 8700
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=TXT(16) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0010 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1310167570 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004e179212 012c
+# MAC Size=16 MAC=(see hex)
+0010 88adc3811d1d6bec7c684438906fc694
+# Original-ID=8898 Error=0
+22c2 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_toWire5.spec b/src/lib/dns/tests/testdata/message_toWire5.spec
new file mode 100644
index 0000000..e316833
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire5.spec
@@ -0,0 +1,36 @@
+#
+# A longest possible (without EDNS) DNS response with TSIG, i.e. total
+# length should be 512 bytes.
+#
+
+[custom]
+sections: header:question:txt/1:txt/2:tsig
+[header]
+id: 0xd6e2
+rd: 1
+qr: 1
+aa: 1
+ancount: 2
+arcount: 1
+[question]
+name: www.example.com
+rrtype: TXT
+[txt/1]
+as_rr: True
+# QNAME is fully compressed
+rr_name: ptr=12
+string: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde
+[txt/2]
+as_rr: True
+# QNAME is fully compressed
+rr_name: ptr=12
+string: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4e17b38d
+mac_size: 16
+mac: 0xbe2ba477373d2496891e2fda240ee4ec
+original_id: 0xd6e2
diff --git a/src/lib/dns/tests/testdata/message_toWire5.wire b/src/lib/dns/tests/testdata/message_toWire5.wire
new file mode 100644
index 0000000..ef7ee6e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire5.wire
@@ -0,0 +1,34 @@
+###
+### This data file was auto-generated from message_toWire5.spec
+###
+
+# Header Section
+# ID=55010 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA RD
+d6e2 8500
+# QDCNT=1, ANCNT=2, NSCNT=0, ARCNT=1
+0001 0002 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=TXT(16) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0010 0001
+
+# TXT RR (QNAME=ptr=12 Class=IN(1) TTL=86400, RDLEN=256)
+c00c 0010 0001 00015180 0100
+# String Len=255, String="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde"
+ff 303132333435363738396162636465663031323334353637383961626364656630313233343536373839616263646566303132333435363738396162636465663031323334353637383961626364656630313233343536373839616263646566303132333435363738396162636465663031323334353637383961626364656630313233343536373839616263646566303132333435363738396162636465663031323334353637383961626364656630313233343536373839616263646566303132333435363738396162636465663031323334353637383961626364656630313233343536373839616263646566303132333435363738396162636465
+
+# TXT RR (QNAME=ptr=12 Class=IN(1) TTL=86400, RDLEN=114)
+c00c 0010 0001 00015180 0072
+# String Len=113, String="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0"
+71 3031323334353637383961626364656630313233343536373839616263646566303132333435363738396162636465663031323334353637383961626364656630313233343536373839616263646566303132333435363738396162636465663031323334353637383961626364656630
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1310176141 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004e17b38d 012c
+# MAC Size=16 MAC=(see hex)
+0010 be2ba477373d2496891e2fda240ee4ec
+# Original-ID=55010 Error=0
+d6e2 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/message_toWire6 b/src/lib/dns/tests/testdata/message_toWire6
new file mode 100644
index 0000000..996c99c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire6
@@ -0,0 +1,48 @@
+#
+# A simple DNS query message (with a signed response)
+# ID = 0x75c1
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=4, other COUNTS=0
+# Question: test.example.com. IN A
+# Answer:
+# test.example.com. 3600 IN A 192.0.2.1
+# test.example.com. 7200 IN A 192.0.2.2
+#
+75c1 8500
+0001 0004 0000 0000
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0001 0001
+# same name, fully compressed
+c0 0c
+# TTL=3600, A, IN, RDLENGTH=4, RDATA
+0001 0001 00000e10 0004 c0 00 02 01
+# mostly same, with the slight difference in RDATA
+c0 0c
+0001 0001 00000e10 0004 c0 00 02 02
+
+# signature 1
+
+# same name
+c0 0c
+# RRSIG, IN, TTL=3600, RDLENGTH=0x28 TYPE_COV=A ALGO=5 (RSA/SHA-1) LABELS=3 ORIG_TTL=3600
+002e 0001 00000e10 0028 0001 05 03 00000e10
+# SIG_EXPIRY=20000101000000 SIG_INCEP=20000201000000 KEY_ID=12345
+386d4380 38962200 3039
+#(7) e x a m p l e (3) c o m .
+ 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# FAKEFAKEFAKE
+14 02 84 14 02 84 14 02 84
+
+# signature 2
+
+# same name
+c0 0c
+# RRSIG, IN, TTL=3600, RDLENGTH=0x28 TYPE_COV=A ALGO=3 (DSA/SHA-1) LABELS=3 ORIG_TTL=3600
+002e 0001 00000e10 0028 0001 03 03 00000e10
+# SIG_EXPIRY=20000101000000 SIG_INCEP=20000201000000 KEY_ID=12345
+386d4380 38962200 3039
+#(7) e x a m p l e (3) c o m .
+ 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# FAKEFAKEFAKE
+14 02 84 14 02 84 14 02 84
diff --git a/src/lib/dns/tests/testdata/message_toWire7 b/src/lib/dns/tests/testdata/message_toWire7
new file mode 100644
index 0000000..ba22634
--- /dev/null
+++ b/src/lib/dns/tests/testdata/message_toWire7
@@ -0,0 +1,35 @@
+#
+# A simple DNS query message (with a signed response)
+# ID = 0x75c1
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=1, ADCOUNT=0
+# Question: test.example.com. IN TXT
+# Answer:
+# test.example.com. 3600 IN TXT aaaaa...
+#
+75c1 8700
+0001 0001 0000 0000
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0010 0001
+# same name, fully compressed
+c0 0c
+# TTL=3600, TXT, IN, RDLENGTH=256, RDATA
+0010 0001 00000e10 0100 ff
+# 'a' repeated 255 times
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
+61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
diff --git a/src/lib/dns/tests/testdata/name_fromWire1 b/src/lib/dns/tests/testdata/name_fromWire1
new file mode 100644
index 0000000..42fc61d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire1
@@ -0,0 +1,14 @@
+#
+# a global14 compression pointer
+#
+000a85800001000300000003
+# V i x c o m
+0356697803636f6d0000020001c00c00
+02000100000e10000b05697372763102
+7061c00cc00c0002000100000e100009
+066e732d657874c00cc00c0002000100
+000e10000e036e733104676e61630363
+6f6d00c0250001000100000e100004cc
+98b886c03c0001000100000e100004cc
+98b840c051000100010002a14a0004c6
+97f8f6
diff --git a/src/lib/dns/tests/testdata/name_fromWire10 b/src/lib/dns/tests/testdata/name_fromWire10
new file mode 100644
index 0000000..65be775
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire10
@@ -0,0 +1,12 @@
+#
+# Too large name; should trigger an exception.
+#
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 040102030400
diff --git a/src/lib/dns/tests/testdata/name_fromWire11 b/src/lib/dns/tests/testdata/name_fromWire11
new file mode 100644
index 0000000..32184f6
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire11
@@ -0,0 +1,12 @@
+#
+# A name with possible maximum number of labels; should be accepted safely.
+#
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 01000100010001000100 01000100010001000100
+01000100010001000100 0100010000
diff --git a/src/lib/dns/tests/testdata/name_fromWire12 b/src/lib/dns/tests/testdata/name_fromWire12
new file mode 100644
index 0000000..073adda
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire12
@@ -0,0 +1,13 @@
+#
+# Wire format including an invalid label length
+#
+#(1) a (7) e x a m p l e
+ 01 61 07 65 78 61 6d 70 6c 65
+# invalid label length: 64
+40
+# a "label" of 64 characters: shouldn't be parsed
+00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+00
diff --git a/src/lib/dns/tests/testdata/name_fromWire13 b/src/lib/dns/tests/testdata/name_fromWire13
new file mode 100644
index 0000000..447f54b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire13
@@ -0,0 +1,5 @@
+#
+# A name including all "printable" characters
+#
+
+3f2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f1f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e00
diff --git a/src/lib/dns/tests/testdata/name_fromWire14 b/src/lib/dns/tests/testdata/name_fromWire14
new file mode 100644
index 0000000..3123aec
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire14
@@ -0,0 +1,7 @@
+#
+# A name including all "non-printable" characters
+#
+
+3f000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f207f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c
+3f9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadb
+24dcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00
diff --git a/src/lib/dns/tests/testdata/name_fromWire2 b/src/lib/dns/tests/testdata/name_fromWire2
new file mode 100644
index 0000000..0758a68
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire2
@@ -0,0 +1,15 @@
+#
+# bogus label character (looks like a local compression pointer)
+#
+000a85800001000300000003
+#this is the bogus label character:
+83
+76697803636f6d0000020001c00c00
+02000100000e10000b05697372763102
+7061c00cc00c0002000100000e100009
+066e732d657874c00cc00c0002000100
+000e10000e036e733104676e61630363
+6f6d00c0250001000100000e100004cc
+98b886c03c0001000100000e100004cc
+98b840c051000100010002a14a0004c6
+97f8f6
diff --git a/src/lib/dns/tests/testdata/name_fromWire3_1 b/src/lib/dns/tests/testdata/name_fromWire3_1
new file mode 100644
index 0000000..e38efcc
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire3_1
@@ -0,0 +1,11 @@
+#
+# a bad compression pointer starting with the bits 1111 (too big pointer)
+#
+000a85800001000300000003
+03766978 03636f6d 00 0002 0001
+f00c 0002 0001 0000 0e10 000b 056973727631 027061 c00c
+c00c 0002 0001 0000 0e10 0009 066e732d657874 c00c
+c00c 0002 0001 0000 0e10 000e 036e7331 04676e6163 03636f6d 00
+c025 0001 0001 0000 0e10 0004 cc98b886
+c03c 0001 0001 0000 0e10 0004 cc98b840
+c051 0001 0001 0002 a14a 0004 c697f8f6
diff --git a/src/lib/dns/tests/testdata/name_fromWire3_2 b/src/lib/dns/tests/testdata/name_fromWire3_2
new file mode 100644
index 0000000..c377bb1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire3_2
@@ -0,0 +1,13 @@
+#
+# a bad compression pointer due to forward reference of 0x30 to
+# another compression pointer with a valid backreference
+#
+000a85800001000300000003
+03766978 03636f6d 00 0002 0001
+#'30' is the forward reference, 'c00c' at the end is the valid pointer:
+c030 0002 0001 0000 0e10 000b 056973727631 027061 c00c
+c00c 0002 0001 0000 0e10 0009 066e732d657874 c00c
+c00c 0002 0001 0000 0e10 000e 036e7331 04676e6163 03636f6d 00
+c025 0001 0001 0000 0e10 0004 cc98b886
+c03c 0001 0001 0000 0e10 0004 cc98b840
+c051 0001 0001 0002 a14a 0004 c697f8f6
diff --git a/src/lib/dns/tests/testdata/name_fromWire4 b/src/lib/dns/tests/testdata/name_fromWire4
new file mode 100644
index 0000000..dba6035
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire4
@@ -0,0 +1,45 @@
+#
+# invalid name length, pointer at offset 0x0226 points to
+# long name at offset 0x25
+#
+000a 8580 0001 0003 0000 0001
+03 766978 03 636f6d 00 0002 0001
+c00c 0002 0001 00000e10
+0101
+# long name starts here
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a 00
+# compression pointer start here and refers back to long name
+c023 0002 0001 00000e10 0009 066e732d657874 c00c
+c00c 0002 0001 00000e10 000e 036e733104676e616303636f6d00
+c025 0001 0001 00000e10 0004 cc98b886
diff --git a/src/lib/dns/tests/testdata/name_fromWire6 b/src/lib/dns/tests/testdata/name_fromWire6
new file mode 100644
index 0000000..fa1abe6
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire6
@@ -0,0 +1,14 @@
+#
+# a bad pointer
+#
+000a85800001000300000003
+# the bad pointer is f00c (offset = 300c) which is too large
+0376697803636f6d0000020001 f00c 00
+02000100000e10000b05697372763102
+7061c00cc00c0002000100000e100009
+066e732d657874c00cc00c0002000100
+000e10000e036e733104676e61630363
+6f6d00c0250001000100000e100004cc
+98b886c03c0001000100000e100004cc
+98b840c051000100010002a14a0004c6
+97f8f6
diff --git a/src/lib/dns/tests/testdata/name_fromWire7 b/src/lib/dns/tests/testdata/name_fromWire7
new file mode 100644
index 0000000..2dedd4a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire7
@@ -0,0 +1,6 @@
+#
+# input ends unexpectedly
+#
+000a85800001000300000003
+# parser will start at the ending 'c0', which is an incomplete sequence.
+0376697803636f6d0000020001 c0
diff --git a/src/lib/dns/tests/testdata/name_fromWire8 b/src/lib/dns/tests/testdata/name_fromWire8
new file mode 100644
index 0000000..575563d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire8
@@ -0,0 +1,27 @@
+#
+# many hops of compression. absolutely many, but should be decompressed.
+#
+000a85800001000300000013
+03 766978 03 636f6d 00 0002 0001
+c00c 0002 0001 00000e10 000b 056973727631027061 c00c
+c019 0002 0001 00000e10 0009 066e732d657874 c00c
+c030 0002 0001 00000e10 000e 036e7331 04676e6163 03636f6d 00
+c045 0001 0001 00000e10 0004 cc98b886
+c05f 0001 0001 00000e10 0004 cc98b840
+c06f 0001 0001 0002a14a 0004 c697f8f6
+c07f 0001 0001 0002a14a 0004 c697f8f6
+c08f 0001 0001 0002a14a 0004 c697f8f6
+c09f 0001 0001 0002a14a 0004 c697f8f6
+c0af 0001 0001 0002a14a 0004 c697f8f6
+c0bf 0001 0001 0002a14a 0004 c697f8f6
+c0cf 0001 0001 0002a14a 0004 c697f8f6
+c0df 0001 0001 0002a14a 0004 c697f8f6
+c0ef 0001 0001 0002a14a 0004 c697f8f6
+c0ff 0001 0001 0002a14a 0004 c697f8f6
+c10f 0001 0001 0002a14a 0004 c697f8f6
+c11f 0001 0001 0002a14a 0004 c697f8f6
+c12f 0001 0001 0002a14a 0004 c697f8f6
+c13f 0001 0001 0002a14a 0004 c697f8f6
+c14f 0001 0001 0002a14a 0004 c697f8f6
+c15f 0001 0001 0002a14a 0004 c697f8f6
+c16f 0001 0001 0002a14a 0004 c697f8f6
diff --git a/src/lib/dns/tests/testdata/name_fromWire9 b/src/lib/dns/tests/testdata/name_fromWire9
new file mode 100644
index 0000000..79b2978
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_fromWire9
@@ -0,0 +1,12 @@
+#
+# A possible longest name; should be accepted safely.
+#
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 09010203040506070809 09010203040506070809
+09010203040506070809 0301020300
diff --git a/src/lib/dns/tests/testdata/name_toWire1 b/src/lib/dns/tests/testdata/name_toWire1
new file mode 100644
index 0000000..c06ec4b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire1
@@ -0,0 +1,12 @@
+#
+# Rendering 3 names with compression. [x] means a compression pointer pointing
+# to offset 'x'.
+#
+#bytes:
+# 0 1 2 3 4 5 6 7 8 9 a b c d e
+#(1)a(7)e x a m p l e(3)c o m .
+ 0161076578616d706c6503636f6d00
+#(1)b [2]
+ 0162c002
+# a . e x a m p l e . o r g .
+ 0161076578616d706c65036f726700
diff --git a/src/lib/dns/tests/testdata/name_toWire2 b/src/lib/dns/tests/testdata/name_toWire2
new file mode 100644
index 0000000..2377121
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire2
@@ -0,0 +1,14 @@
+#
+# Rendering names in a large buffer. [x] means a compression pointer pointing
+# to offset 'x'.
+#
+#bytes:
+#3f 40
+#ff 00
+#(1) a (7) e x a m p l e (3) c o m .
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#[3fff] = a.example.com: can be compressed
+ ffff
+#(1) b(7) e x a m p l e (3) c o m .; cannot compress as the pointer
+# (0x4001) would exceed 0x4000
+ 01 62 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
diff --git a/src/lib/dns/tests/testdata/name_toWire3 b/src/lib/dns/tests/testdata/name_toWire3
new file mode 100644
index 0000000..08c1474
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire3
@@ -0,0 +1,14 @@
+#
+# Rendering names including one explicitly uncompressed.
+# [x] means a compression pointer pointing to offset 'x'.
+#
+# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (bytes)
+#(1) a (7) e x a m p l e (3) c o m .
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+
+#15 29 (bytes)
+#(1) b (7) e x a m p l e (3) c o m .; specified to be not compressed,
+# but can be pointed to from others
+ 01 62 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#[0f] referring to the second (uncompressed name)
+ c0 0f
diff --git a/src/lib/dns/tests/testdata/name_toWire4 b/src/lib/dns/tests/testdata/name_toWire4
new file mode 100644
index 0000000..740d718
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire4
@@ -0,0 +1,16 @@
+#
+# Rendering 3 names with compression, including one resulting in a chain of
+# pointers (the last one).
+# legend: [x] means a compression pointer pointing to offset 'x'.
+#bytes:
+#00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e
+#(1) a (7) e x a m p l e (3) c o m .
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+
+#0f 10 11 12
+#(1) b [2] (b.example.com.)
+ 01 62 c0 02
+
+#13 14
+# [0f]: (b.example.com.)
+ c0 0f
diff --git a/src/lib/dns/tests/testdata/name_toWire5.spec b/src/lib/dns/tests/testdata/name_toWire5.spec
new file mode 100644
index 0000000..87e140d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire5.spec
@@ -0,0 +1,19 @@
+#
+# A sequence of names that would be compressed case-sensitive manner.
+# First name: "a.example.com"
+# Second name: "b.eXample.com". Due to case-sensitive comparison only "com"
+# can be compressed.
+# Third name: "c.eXample.com". "eXample.com" part matches that of the second
+# name and can be compressed.
+#
+
+[custom]
+sections: name/1:name/2:name/3
+[name/1]
+name: a.example.com
+[name/2]
+name: b.eXample
+pointer: 10
+[name/3]
+name: c
+pointer: 17
diff --git a/src/lib/dns/tests/testdata/name_toWire5.wire b/src/lib/dns/tests/testdata/name_toWire5.wire
new file mode 100644
index 0000000..c6e62ed
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire5.wire
@@ -0,0 +1,12 @@
+###
+### This data file was auto-generated from name_toWire5.spec
+###
+
+# DNS Name: a.example.com
+0161076578616d706c6503636f6d00
+
+# DNS Name: b.eXample + compression pointer: 10
+0162076558616d706c65c00a
+
+# DNS Name: c + compression pointer: 17
+0163c011
diff --git a/src/lib/dns/tests/testdata/name_toWire6.spec b/src/lib/dns/tests/testdata/name_toWire6.spec
new file mode 100644
index 0000000..a536f5d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire6.spec
@@ -0,0 +1,19 @@
+#
+# A sequence of names that would be compressed both case-sensitive and
+# case-insensitive manner (unusual, but allowed).
+# First and second name: see name_toWire5.spec.
+# Third name: "c.b.EXAMPLE.com". This is rendered with case-insensitive
+# compression, so "b.EXAMPLE.com" part of the name matches that of the
+# second name.
+#
+
+[custom]
+sections: name/1:name/2:name/3
+[name/1]
+name: a.example.com
+[name/2]
+name: b.eXample
+pointer: 10
+[name/3]
+name: c
+pointer: 15
diff --git a/src/lib/dns/tests/testdata/name_toWire6.wire b/src/lib/dns/tests/testdata/name_toWire6.wire
new file mode 100644
index 0000000..dcaa39f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire6.wire
@@ -0,0 +1,12 @@
+###
+### This data file was auto-generated from name_toWire6.spec
+###
+
+# DNS Name: a.example.com
+0161076578616d706c6503636f6d00
+
+# DNS Name: b.eXample + compression pointer: 10
+0162076558616d706c65c00a
+
+# DNS Name: c + compression pointer: 15
+0163c00f
diff --git a/src/lib/dns/tests/testdata/name_toWire7 b/src/lib/dns/tests/testdata/name_toWire7
new file mode 100644
index 0000000..bff599f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire7
@@ -0,0 +1,10 @@
+#
+# Rendering names including one explicitly uncompressed.
+# [x] means a compression pointer pointing to offset 'x'.
+#
+# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (bytes)
+#(1) a (7) e x a m p l e (3) c o m .
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+
+#[02] pointing to -> "example.com."
+ c0 02
diff --git a/src/lib/dns/tests/testdata/name_toWire8 b/src/lib/dns/tests/testdata/name_toWire8
new file mode 100644
index 0000000..d01093b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire8
@@ -0,0 +1,7 @@
+#
+# Rendering names.
+# [x] means a compression pointer pointing to offset 'x'.
+#
+# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 (bytes)
+#(1) a (7) e x a m p l e (3) c o m
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d
diff --git a/src/lib/dns/tests/testdata/name_toWire9 b/src/lib/dns/tests/testdata/name_toWire9
new file mode 100644
index 0000000..51a1987
--- /dev/null
+++ b/src/lib/dns/tests/testdata/name_toWire9
@@ -0,0 +1,13 @@
+#
+# Rendering names including one explicitly uncompressed.
+# [x] means a compression pointer pointing to offset 'x'.
+#
+# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (bytes)
+#(1) a (7) e x a m p l e (3) c o m .
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#(1) a (7) e x a m p l e (3) c o m
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d
+#(1) a (7) e x a m p l e
+ 01 61 07 65 78 61 6d 70 6c 65
+#[1f] pointing to ^^ "example"
+ c0 1f
diff --git a/src/lib/dns/tests/testdata/omitcheck.txt b/src/lib/dns/tests/testdata/omitcheck.txt
new file mode 100644
index 0000000..580cab4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/omitcheck.txt
@@ -0,0 +1 @@
+ 1H IN A 192.0.2.1
diff --git a/src/lib/dns/tests/testdata/origincheck.txt b/src/lib/dns/tests/testdata/origincheck.txt
new file mode 100644
index 0000000..c370ed2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/origincheck.txt
@@ -0,0 +1,5 @@
+; We change the origin here. We want to check it is not propagated
+; outside of the included file.
+$ORIGIN www.example.org.
+
+@ 1H IN A 192.0.2.1
diff --git a/src/lib/dns/tests/testdata/question_fromWire b/src/lib/dns/tests/testdata/question_fromWire
new file mode 100644
index 0000000..cbc28c0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/question_fromWire
@@ -0,0 +1,33 @@
+#
+# Wire-format data of a sequence of DNS questions.
+# foo.example.com. IN NS
+# bar.example.com. CH A (owner name is compressed)
+# and some pathological cases
+#
+# 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 (-th byte)
+#(3) f o o (7) e x a m p l e (3) c o m .
+ 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#7 8 9 20
+# type/class: NS = 2, IN = 1
+00 02 00 01
+
+# 1 2 3 4 5 6
+#(3) b a r [ptr=0x04]
+ 03 62 61 72 c0 04
+#7 8 9 30
+# type/class: A = 1, CH = 3
+00 01 00 03
+
+# owner name is broken
+#1
+# invalid label type
+ff
+#2 3 4 5
+#type/class IN/A
+00 01 00 01
+
+# short buffer
+# (root name)
+00
+#class is missing
+00 01
diff --git a/src/lib/dns/tests/testdata/question_toWire1 b/src/lib/dns/tests/testdata/question_toWire1
new file mode 100644
index 0000000..77886db
--- /dev/null
+++ b/src/lib/dns/tests/testdata/question_toWire1
@@ -0,0 +1,14 @@
+#
+# Rendering two DNS Questions without name compression
+# foo.example.com. IN NS
+# bar.example.com. CH A
+#
+#(3) f o o (7) e x a m p l e (3) c o m .
+ 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# type/class: NS = 2, IN = 1
+00 02 00 01
+#(3) b a r (7) e x a m p l e (3) c o m .
+ 03 62 61 72 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#7 8 9 30
+# type/class: A = 1, CH = 3
+00 01 00 03
diff --git a/src/lib/dns/tests/testdata/question_toWire2 b/src/lib/dns/tests/testdata/question_toWire2
new file mode 100644
index 0000000..9117ab2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/question_toWire2
@@ -0,0 +1,14 @@
+#
+# Rendering two DNS Questions with name compression
+# foo.example.com. IN NS
+# bar.example.com. CH A
+#
+# 0 1 2 3 4 ... (-th byte)
+#(3) f o o (7) e x a m p l e (3) c o m .
+ 03 66 6f 6f 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# type/class: NS = 2, IN = 1
+00 02 00 01
+#(3) b a r [ptr=0x04]
+ 03 62 61 72 c0 04
+# type/class: A = 1, CH = 3
+00 01 00 03
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.spec
new file mode 100644
index 0000000..f831313
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.spec
@@ -0,0 +1,3 @@
+[custom]
+sections: afsdb
+[afsdb]
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.wire b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.wire
new file mode 100644
index 0000000..b32776b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_afsdb_fromWire1.spec
+###
+
+# AFSDB RDATA, RDLEN=21
+0015
+# SUBTYPE=1 SERVER=afsdb.example.com
+0001 056166736462076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.spec
new file mode 100644
index 0000000..f33e768
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.spec
@@ -0,0 +1,6 @@
+[custom]
+sections: name:afsdb
+[name]
+name: example.com
+[afsdb]
+server: afsdb.ptr=0
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.wire
new file mode 100644
index 0000000..fdc53c5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire2.wire
@@ -0,0 +1,11 @@
+###
+### This data file was auto-generated from rdata_afsdb_fromWire2.spec
+###
+
+# DNS Name: example.com
+076578616d706c6503636f6d00
+
+# AFSDB RDATA, RDLEN=10
+000a
+# SUBTYPE=1 SERVER=afsdb.ptr=0
+0001 056166736462c000
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.spec
new file mode 100644
index 0000000..993032f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.spec
@@ -0,0 +1,4 @@
+[custom]
+sections: afsdb
+[afsdb]
+rdlen: 3
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.wire
new file mode 100644
index 0000000..7ea4342
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire3.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_afsdb_fromWire3.spec
+###
+
+# AFSDB RDATA, RDLEN=3
+0003
+# SUBTYPE=1 SERVER=afsdb.example.com
+0001 056166736462076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.spec
new file mode 100644
index 0000000..37abf13
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.spec
@@ -0,0 +1,4 @@
+[custom]
+sections: afsdb
+[afsdb]
+rdlen: 80
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.wire
new file mode 100644
index 0000000..79ff6c2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire4.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_afsdb_fromWire4.spec
+###
+
+# AFSDB RDATA, RDLEN=80
+0050
+# SUBTYPE=1 SERVER=afsdb.example.com
+0001 056166736462076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.spec
new file mode 100644
index 0000000..0ea79dd
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.spec
@@ -0,0 +1,4 @@
+[custom]
+sections: afsdb
+[afsdb]
+server: "01234567890123456789012345678901234567890123456789012345678901234"
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.wire
new file mode 100644
index 0000000..13eb016
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_fromWire5.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_afsdb_fromWire5.spec
+###
+
+# AFSDB RDATA, RDLEN=71
+0047
+# SUBTYPE=1 SERVER="01234567890123456789012345678901234567890123456789012345678901234"
+0001 432230313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233342200
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_toWire1.spec b/src/lib/dns/tests/testdata/rdata_afsdb_toWire1.spec
new file mode 100644
index 0000000..1946458
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_toWire1.spec
@@ -0,0 +1,4 @@
+[custom]
+sections: afsdb
+[afsdb]
+rdlen: -1
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_toWire1.wire b/src/lib/dns/tests/testdata/rdata_afsdb_toWire1.wire
new file mode 100644
index 0000000..7746fa6
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_toWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_afsdb_toWire1.spec
+###
+
+# AFSDB RDATA
+
+# SUBTYPE=1 SERVER=afsdb.example.com
+0001 056166736462076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_toWire2.spec b/src/lib/dns/tests/testdata/rdata_afsdb_toWire2.spec
new file mode 100644
index 0000000..c80011a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_toWire2.spec
@@ -0,0 +1,8 @@
+[custom]
+sections: name:afsdb
+[name]
+name: example.com.
+[afsdb]
+subtype: 0
+server: root.example.com
+rdlen: -1
diff --git a/src/lib/dns/tests/testdata/rdata_afsdb_toWire2.wire b/src/lib/dns/tests/testdata/rdata_afsdb_toWire2.wire
new file mode 100644
index 0000000..7f01512
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_afsdb_toWire2.wire
@@ -0,0 +1,11 @@
+###
+### This data file was auto-generated from rdata_afsdb_toWire2.spec
+###
+
+# DNS Name: example.com.
+076578616d706c6503636f6d00
+
+# AFSDB RDATA
+
+# SUBTYPE=0 SERVER=root.example.com
+0000 04726f6f74076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec
new file mode 100644
index 0000000..d21987c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec
@@ -0,0 +1,6 @@
+#
+# The simplest form of CAA: all default parameters
+#
+[custom]
+sections: caa
+[caa]
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire1.wire b/src/lib/dns/tests/testdata/rdata_caa_fromWire1.wire
new file mode 100644
index 0000000..780bd8d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_caa_fromWire1.spec
+###
+
+# CAA RDATA, RDLEN=21
+0015
+# FLAGS=0 TAG=issue VALUE=ca.example.net
+00 05 697373756563612e6578616d706c652e6e6574
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec
new file mode 100644
index 0000000..867e43d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec
@@ -0,0 +1,7 @@
+#
+# Mixed case CAA tag field.
+#
+[custom]
+sections: caa
+[caa]
+tag: 'ISSue'
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_caa_fromWire2.wire
new file mode 100644
index 0000000..09ca24d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire2.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_caa_fromWire2.spec
+###
+
+# CAA RDATA, RDLEN=21
+0015
+# FLAGS=0 TAG=ISSue VALUE=ca.example.net
+00 05 495353756563612e6578616d706c652e6e6574
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec
new file mode 100644
index 0000000..9297151
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec
@@ -0,0 +1,7 @@
+#
+# Missing CAA value field.
+#
+[custom]
+sections: caa
+[caa]
+value: ''
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_caa_fromWire3.wire
new file mode 100644
index 0000000..16b5c43
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire3.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_caa_fromWire3.spec
+###
+
+# CAA RDATA, RDLEN=7
+0007
+# FLAGS=0 TAG=issue VALUE=
+00 05 6973737565
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec
new file mode 100644
index 0000000..53e16b1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec
@@ -0,0 +1,7 @@
+#
+# Missing CAA value field.
+#
+[custom]
+sections: caa
+[caa]
+tag: ''
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_caa_fromWire4.wire
new file mode 100644
index 0000000..3225e60
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire4.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_caa_fromWire4.spec
+###
+
+# CAA RDATA, RDLEN=16
+0010
+# FLAGS=0 TAG= VALUE=ca.example.net
+00 00 63612e6578616d706c652e6e6574
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire5 b/src/lib/dns/tests/testdata/rdata_caa_fromWire5
new file mode 100644
index 0000000..123011f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire5
@@ -0,0 +1,6 @@
+# Test where CAA value field is shorter than the RDATA length
+
+# CAA RDATA, RDLEN=32
+0020
+# FLAGS=0 TAG=c VALUE=ca.example.net
+00 01 63 63612e6578616d706c652e6e6574
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire6 b/src/lib/dns/tests/testdata/rdata_caa_fromWire6
new file mode 100644
index 0000000..1a35a1a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire6
@@ -0,0 +1,4 @@
+# Test where RDATA is completely missing
+
+# CAA RDATA, RDLEN=32
+0020
diff --git a/src/lib/dns/tests/testdata/rdata_cname_fromWire b/src/lib/dns/tests/testdata/rdata_cname_fromWire
new file mode 100644
index 0000000..57eae13
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_cname_fromWire
@@ -0,0 +1,44 @@
+#
+# various kinds of CNAME RDATA stored in an input buffer
+#
+# Valid non-compressed RDATA for cn.example.com.
+# RDLENGTH=16 bytes
+# 0 1
+ 00 10
+# 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7(bytes)
+#(2) c n (7) e x a m p l e (3) c o m .
+ 02 63 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# short length
+# 8 9
+ 00 0f
+#20 1 2 3 4 5 6 7 8 9 30 1 2 3 4 5
+ 02 63 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# length too long
+# 6 7
+ 00 11
+#
+# 8 9 40 1 2 3 4 5 6 7 8 9 50 1 2 3 4
+ 02 63 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00
+#
+# Valid compressed CNAME name: 'cn2' + pointer
+# 5 6
+ 00 06
+# 7 8 9 60 1 2
+#(3) c n 2 ptr=5
+ 03 63 6e 32 c0 05
+#
+# Valid compressed CNAME name but RDLENGTH is incorrect: it must be the length
+# of the sequence from the head to the pointer, not the decompressed name
+# length.
+# 3 4
+ 00 11
+# 5 6 7 8 9 70
+ 03 63 6e 32 c0 05
+# incomplete name (no trailing dot). this can be tested only at the end of
+# the buffer.
+# 1 2
+ 00 0f
+# 3 4 5 6 7 8 9 80 1 2 3 4 5 6 7
+ 02 63 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d
diff --git a/src/lib/dns/tests/testdata/rdata_dhcid_fromWire b/src/lib/dns/tests/testdata/rdata_dhcid_fromWire
new file mode 100644
index 0000000..b28b5b3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_dhcid_fromWire
@@ -0,0 +1,12 @@
+#
+# DHCID RDATA stored in an input buffer
+#
+# Valid RDATA for 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA=
+#
+# RDLENGTH=41 bytes
+# 0 1
+ 00 29
+# 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA=
+d0 b2 20 d0 bb d0 b5 d1 81 d1 83 20 d1 80 d0 be
+d0 b4 d0 b8 d0 bb d0 b0 d1 81 d1 8c 20 d1 91 d0
+bb d0 be d1 87 d0 ba d0 b0
diff --git a/src/lib/dns/tests/testdata/rdata_dhcid_toWire b/src/lib/dns/tests/testdata/rdata_dhcid_toWire
new file mode 100644
index 0000000..99ec229
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_dhcid_toWire
@@ -0,0 +1,7 @@
+#
+# DHCID RDATA stored in an output buffer
+#
+# 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA=
+d0 b2 20 d0 bb d0 b5 d1 81 d1 83 20 d1 80 d0 be
+d0 b4 d0 b8 d0 bb d0 b0 d1 81 d1 8c 20 d1 91 d0
+bb d0 be d1 87 d0 ba d0 b0
diff --git a/src/lib/dns/tests/testdata/rdata_dname_fromWire b/src/lib/dns/tests/testdata/rdata_dname_fromWire
new file mode 100644
index 0000000..1c899bf
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_dname_fromWire
@@ -0,0 +1,44 @@
+#
+# various kinds of DNAME RDATA stored in an input buffer
+#
+# Valid non-compressed RDATA for dn.example.com.
+# RDLENGTH=16 bytes
+# 0 1
+ 00 10
+# 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7(bytes)
+#(2) d n (7) e x a m p l e (3) c o m .
+ 02 64 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# short length
+# 8 9
+ 00 0f
+#20 1 2 3 4 5 6 7 8 9 30 1 2 3 4 5
+ 02 64 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# length too long
+# 6 7
+ 00 11
+#
+# 8 9 40 1 2 3 4 5 6 7 8 9 50 1 2 3 4
+ 02 64 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00
+#
+# Valid compressed DNAME name: 'dn2' + pointer
+# 5 6
+ 00 06
+# 7 8 9 60 1 2
+#(3) d n 2 ptr=5
+ 03 64 6e 32 c0 05
+#
+# Valid compressed DNAME name but RDLENGTH is incorrect: it must be the length
+# of the sequence from the head to the pointer, not the decompressed name
+# length.
+# 3 4
+ 00 11
+# 5 6 7 8 9 70
+ 03 64 6e 32 c0 05
+# incomplete name (no trailing dot). this can be tested only at the end of
+# the buffer.
+# 1 2
+ 00 0f
+# 3 4 5 6 7 8 9 80 1 2 3 4 5 6 7
+ 02 64 6e 07 65 78 61 6d 70 6c 65 03 63 6f 6d
diff --git a/src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.spec b/src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.spec
new file mode 100644
index 0000000..b65271d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.spec
@@ -0,0 +1,7 @@
+# DNSKEY test data with empty digest
+
+[custom]
+sections: dnskey
+
+[dnskey]
+digest:
diff --git a/src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.wire b/src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.wire
new file mode 100644
index 0000000..35388b1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_dnskey_empty_keydata_fromWire.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_dnskey_empty_keydata_fromWire.spec
+###
+
+# DNSKEY RDATA, RDLEN=4
+0004
+# FLAGS=257
+0101
+# PROTOCOL=3
+03
+# ALGORITHM=5
+05
+# DIGEST=
+
diff --git a/src/lib/dns/tests/testdata/rdata_dnskey_fromWire.spec b/src/lib/dns/tests/testdata/rdata_dnskey_fromWire.spec
new file mode 100644
index 0000000..87e66db
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_dnskey_fromWire.spec
@@ -0,0 +1,7 @@
+# DNSKEY test data
+
+[custom]
+sections: dnskey
+
+[dnskey]
+digest: BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjGrhhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA+u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy347cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQzBkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysyLKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/bByBNsO70aEFTd
diff --git a/src/lib/dns/tests/testdata/rdata_dnskey_fromWire.wire b/src/lib/dns/tests/testdata/rdata_dnskey_fromWire.wire
new file mode 100644
index 0000000..0a2e41f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_dnskey_fromWire.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_dnskey_fromWire.spec
+###
+
+# DNSKEY RDATA, RDLEN=265
+0109
+# FLAGS=257
+0101
+# PROTOCOL=3
+03
+# ALGORITHM=5
+05
+# DIGEST=BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjGrhhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA+u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy347cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQzBkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysyLKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/bByBNsO70aEFTd
+0440000003a11d00c1ae141bb69860ab6c10529110e6de03b541f1a0c545bb68562c332fa0e3115e31ab86109e16f0198a1ef22477fc6467d6ea1777f215c6ff1ca56023ba2aba5b7688f0c7c60c5cb039fe403ebb9d1620bf1947547a2936ec61531ffd0c7946235b3c2970faf4fe53c79710998edb48c84b550b82acb7e3b701075ccc9e7cffe0b26903475af426ca8f7036e784f9d79b0d20c730b01f3fdbed84eb7ff366b4330648f406b37ff417b18e98a4b378d18596ad12c5e7ddd4f2e3b474f548b1e56709b7ec73a99efecacc8b28e39e752dfd67b4839ac9f6780d052ad429c00e8b5de1b6c3e8f19b0de803c95552011ffebcde0bf6c1c8136c3bbd1a1054dd
diff --git a/src/lib/dns/tests/testdata/rdata_ds_fromWire b/src/lib/dns/tests/testdata/rdata_ds_fromWire
new file mode 100644
index 0000000..81c412c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_ds_fromWire
@@ -0,0 +1,6 @@
+# RDLENGTH 36 bytes
+00 24
+# DS record, keyid 12892
+32 5c 05 02 f1 e1 84 c0 e1 d6 15 d2 0e b3 c2 23
+ac ed 3b 03 c7 73 dd 95 2d 5f 0e b5 c7 77 58 6d
+e1 8d a6 b5
diff --git a/src/lib/dns/tests/testdata/rdata_in_a_fromWire b/src/lib/dns/tests/testdata/rdata_in_a_fromWire
new file mode 100644
index 0000000..12f508b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_in_a_fromWire
@@ -0,0 +1,19 @@
+#
+# various kinds of IN/A RDATA stored in an input buffer
+#
+# valid RDATA for 192.0.2.1
+#
+# 0 1 2 3 4 5 (bytes)
+ 00 04 c0 00 02 01
+#
+# short length
+# 6 7 8 9 10 11 (bytes)
+ 00 03 c0 00 02 01
+#
+# length too long
+#12 13 14 15 16 17 18
+ 00 05 c0 00 02 01 00
+#
+# short buffer (this can be tested only at the end of the buffer)
+#19 20 21 22 23
+ 00 04 c0 00 02
diff --git a/src/lib/dns/tests/testdata/rdata_in_aaaa_fromWire b/src/lib/dns/tests/testdata/rdata_in_aaaa_fromWire
new file mode 100644
index 0000000..22fdd1f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_in_aaaa_fromWire
@@ -0,0 +1,18 @@
+#
+# various kinds of IN/AAAA RDATA stored in an input buffer
+#
+# valid RDATA for 2001:db8::1234
+#
+#RDLENGTH=16
+0010
+#IPv6 address (18 bytes)
+2001 0db8 0000 0000 0000 0000 0000 1234
+#
+# short length (36 bytes)
+0008 2001 0db8 0000 0000 0000 0000 0000 1234
+#
+# length too long (55 bytes)
+0011 2001 0db8 0000 0000 0000 0000 0000 1234 ff
+#
+# short buffer (this can be tested only at the end of the buffer)
+0010 2001 0db8
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_minfo_fromWire1.spec
new file mode 100644
index 0000000..2c43db0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire1.spec
@@ -0,0 +1,3 @@
+[custom]
+sections: minfo
+[minfo]
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire1.wire b/src/lib/dns/tests/testdata/rdata_minfo_fromWire1.wire
new file mode 100644
index 0000000..3483e9b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_fromWire1.spec
+###
+
+# MINFO RDATA, RDLEN=44
+002c
+# RMAILBOX=rmailbox.example.com EMAILBOX=emailbox.example.com
+08726d61696c626f78076578616d706c6503636f6d00 08656d61696c626f78076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_minfo_fromWire2.spec
new file mode 100644
index 0000000..d781cac
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire2.spec
@@ -0,0 +1,7 @@
+[custom]
+sections: name:minfo
+[name]
+name: a.example.com.
+[minfo]
+rmailbox: rmailbox.ptr=02
+emailbox: emailbox.ptr=02
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_minfo_fromWire2.wire
new file mode 100644
index 0000000..d79e936
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire2.wire
@@ -0,0 +1,11 @@
+###
+### This data file was auto-generated from rdata_minfo_fromWire2.spec
+###
+
+# DNS Name: a.example.com.
+0161076578616d706c6503636f6d00
+
+# MINFO RDATA, RDLEN=22
+0016
+# RMAILBOX=rmailbox.ptr=02 EMAILBOX=emailbox.ptr=02
+08726d61696c626f78c002 08656d61696c626f78c002
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_minfo_fromWire3.spec
new file mode 100644
index 0000000..a1d4b76
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire3.spec
@@ -0,0 +1,6 @@
+[custom]
+sections: minfo
+# rdlength too short
+[minfo]
+emailbox: emailbox.ptr=11
+rdlen: 3
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_minfo_fromWire3.wire
new file mode 100644
index 0000000..55df1a2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire3.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_fromWire3.spec
+###
+
+# MINFO RDATA, RDLEN=3
+0003
+# RMAILBOX=rmailbox.example.com EMAILBOX=emailbox.ptr=11
+08726d61696c626f78076578616d706c6503636f6d00 08656d61696c626f78c00b
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_minfo_fromWire4.spec
new file mode 100644
index 0000000..269a6ce
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire4.spec
@@ -0,0 +1,6 @@
+[custom]
+sections: minfo
+# rdlength too long
+[minfo]
+emailbox: emailbox.ptr=11
+rdlen: 80
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_minfo_fromWire4.wire
new file mode 100644
index 0000000..746f55a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire4.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_fromWire4.spec
+###
+
+# MINFO RDATA, RDLEN=80
+0050
+# RMAILBOX=rmailbox.example.com EMAILBOX=emailbox.ptr=11
+08726d61696c626f78076578616d706c6503636f6d00 08656d61696c626f78c00b
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_minfo_fromWire5.spec
new file mode 100644
index 0000000..3a888e3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire5.spec
@@ -0,0 +1,5 @@
+[custom]
+sections: minfo
+# bogus rmailbox name
+[minfo]
+rmailbox: "01234567890123456789012345678901234567890123456789012345678901234"
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_minfo_fromWire5.wire
new file mode 100644
index 0000000..dacd9a0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire5.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_fromWire5.spec
+###
+
+# MINFO RDATA, RDLEN=91
+005b
+# RMAILBOX="01234567890123456789012345678901234567890123456789012345678901234" EMAILBOX=emailbox.example.com
+432230313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233342200 08656d61696c626f78076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_minfo_fromWire6.spec
new file mode 100644
index 0000000..c75ed8e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire6.spec
@@ -0,0 +1,5 @@
+[custom]
+sections: minfo
+# bogus emailbox name
+[minfo]
+emailbox: "01234567890123456789012345678901234567890123456789012345678901234"
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_minfo_fromWire6.wire
new file mode 100644
index 0000000..4199fee
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_fromWire6.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_fromWire6.spec
+###
+
+# MINFO RDATA, RDLEN=91
+005b
+# RMAILBOX=rmailbox.example.com EMAILBOX="01234567890123456789012345678901234567890123456789012345678901234"
+08726d61696c626f78076578616d706c6503636f6d00 432230313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233342200
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWire1.spec b/src/lib/dns/tests/testdata/rdata_minfo_toWire1.spec
new file mode 100644
index 0000000..7b340a3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWire1.spec
@@ -0,0 +1,5 @@
+[custom]
+sections: minfo
+[minfo]
+emailbox: emailbox.ptr=09
+rdlen: -1
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWire1.wire b/src/lib/dns/tests/testdata/rdata_minfo_toWire1.wire
new file mode 100644
index 0000000..8ac4afe
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_toWire1.spec
+###
+
+# MINFO RDATA
+
+# RMAILBOX=rmailbox.example.com EMAILBOX=emailbox.ptr=09
+08726d61696c626f78076578616d706c6503636f6d00 08656d61696c626f78c009
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWire2.spec b/src/lib/dns/tests/testdata/rdata_minfo_toWire2.spec
new file mode 100644
index 0000000..132f118
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWire2.spec
@@ -0,0 +1,6 @@
+[custom]
+sections: minfo
+[minfo]
+rmailbox: root.example.com.
+emailbox: emailbox.ptr=05
+rdlen: -1
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWire2.wire b/src/lib/dns/tests/testdata/rdata_minfo_toWire2.wire
new file mode 100644
index 0000000..7fb847c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWire2.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_toWire2.spec
+###
+
+# MINFO RDATA
+
+# RMAILBOX=root.example.com. EMAILBOX=emailbox.ptr=05
+04726f6f74076578616d706c6503636f6d00 08656d61696c626f78c005
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.spec b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.spec
new file mode 100644
index 0000000..d99a381
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.spec
@@ -0,0 +1,7 @@
+#
+# A simplest form of MINFO: all default parameters
+#
+[custom]
+sections: minfo
+[minfo]
+rdlen: -1
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.wire b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.wire
new file mode 100644
index 0000000..6de233e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_toWireUncompressed1.spec
+###
+
+# MINFO RDATA
+
+# RMAILBOX=rmailbox.example.com EMAILBOX=emailbox.example.com
+08726d61696c626f78076578616d706c6503636f6d00 08656d61696c626f78076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.spec b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.spec
new file mode 100644
index 0000000..0f78fcc
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.spec
@@ -0,0 +1,8 @@
+#
+# A simplest form of MINFO: custom rmailbox and default emailbox
+#
+[custom]
+sections: minfo
+[minfo]
+rmailbox: root.example.com.
+rdlen: -1
diff --git a/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.wire b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.wire
new file mode 100644
index 0000000..51e9e35
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_minfo_toWireUncompressed2.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_minfo_toWireUncompressed2.spec
+###
+
+# MINFO RDATA
+
+# RMAILBOX=root.example.com. EMAILBOX=emailbox.example.com
+04726f6f74076578616d706c6503636f6d00 08656d61696c626f78076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_mx_fromWire b/src/lib/dns/tests/testdata/rdata_mx_fromWire
new file mode 100644
index 0000000..8e09154
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_mx_fromWire
@@ -0,0 +1,15 @@
+#
+# various kinds of MX RDATA stored in an input buffer
+#
+# Valid RDATA for "10 mail.example.com"
+#
+# RDLENGTH=18 bytes
+# 0 1
+ 00 12
+# 2 3
+# PREFERENCE: 10
+ 00 0a
+# EXCHANGE: non compressed
+# 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 (bytes)
+#(2) m x (7) e x a m p l e (3) c o m .
+ 02 6d 78 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
diff --git a/src/lib/dns/tests/testdata/rdata_mx_toWire1 b/src/lib/dns/tests/testdata/rdata_mx_toWire1
new file mode 100644
index 0000000..3049373
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_mx_toWire1
@@ -0,0 +1,12 @@
+#
+# compressed MX RDATA stored in an output buffer
+#
+# sentinel name: example.com.
+# 0 1 2 3 4 5 6 7 8 9 10 1 2 (bytes)
+#(7) e x a m p l e (3) c o m .
+ 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# PREFERENCE: 10
+ 00 0a
+# EXCHANGE: compressed
+#(4) m x ptr=0
+ 02 6d 78 c0 00
diff --git a/src/lib/dns/tests/testdata/rdata_mx_toWire2 b/src/lib/dns/tests/testdata/rdata_mx_toWire2
new file mode 100644
index 0000000..ebd2f27
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_mx_toWire2
@@ -0,0 +1,12 @@
+#
+# compressed MX RDATA stored in an output buffer
+#
+# sentinel name: example.com.
+# 0 1 2 3 4 5 6 7 8 9 10 1 2 (bytes)
+#(7) e x a m p l e (3) c o m .
+ 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# PREFERENCE: 10
+ 00 0a
+# EXCHANGE: not compressed
+#(4) m x ptr=0
+ 02 6d 78 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
diff --git a/src/lib/dns/tests/testdata/rdata_ns_fromWire b/src/lib/dns/tests/testdata/rdata_ns_fromWire
new file mode 100644
index 0000000..973365f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_ns_fromWire
@@ -0,0 +1,44 @@
+#
+# various kinds of NS RDATA stored in an input buffer
+#
+# Valid non-compressed RDATA for ns.example.com.
+# RDLENGTH=16 bytes
+# 0 1
+ 00 10
+# 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7(bytes)
+#(2) n s (7) e x a m p l e (3) c o m .
+ 02 6e 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# short length
+# 8 9
+ 00 0f
+#20 1 2 3 4 5 6 7 8 9 30 1 2 3 4 5
+ 02 6e 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# length too long
+# 6 7
+ 00 11
+#
+# 8 9 40 1 2 3 4 5 6 7 8 9 50 1 2 3 4
+ 02 6e 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00
+#
+# Valid compressed NS name: 'ns2' + pointer
+# 5 6
+ 00 06
+# 7 8 9 60 1 2
+#(3) n s 2 ptr=5
+ 03 6e 73 32 c0 05
+#
+# Valid compressed NS name but RDLENGTH is incorrect: it must be the length
+# of the sequence from the head to the pointer, not the decompressed name
+# length.
+# 3 4
+ 00 11
+# 5 6 7 8 9 70
+ 03 6e 73 32 c0 05
+# incomplete name (no trailing dot). this can be tested only at the end of
+# the buffer.
+# 1 2
+ 00 0f
+# 3 4 5 6 7 8 9 80 1 2 3 4 5 6 7
+ 02 6e 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1 b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1
new file mode 100644
index 0000000..1dd5f52
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1
@@ -0,0 +1,7 @@
+# RDLENGTH, 39 bytes
+00 27
+# NSEC3 record:
+# 1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 NS SOA RRSIG DNSKEY NSEC3PARAM
+01 01 00 01 04 d3 99 ea ab 14 8a 77 c7 ac ef cb
+c5 54 46 03 2b 2d 96 1c c5 eb 68 21 ef 26 00 07
+22 00 00 00 00 02 90
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec
new file mode 100644
index 0000000..39a78d7
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec
@@ -0,0 +1,7 @@
+#
+# A malformed NSEC3 RDATA: bit map length is too large, causing overflow
+#
+
+[custom]
+sections: nsec3
+[nsec3]
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec
new file mode 100644
index 0000000..30417f5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC3 RDATA: a bitmap block containing empty bytes
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+bitmap: '01000000'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.wire
new file mode 100644
index 0000000..99c5afd
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire10.spec
+###
+
+# NSEC3 RDATA, RDLEN=37
+0025
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=4
+00 04 01000000
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec
new file mode 100644
index 0000000..80ec59f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC3 RDATA: Saltlen is too large
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 7
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.wire
new file mode 100644
index 0000000..48dc589
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire11.spec
+###
+
+# NSEC3 RDATA, RDLEN=7
+0007
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=6
+00 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec
new file mode 100644
index 0000000..1e01655
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec
@@ -0,0 +1,9 @@
+#
+# An invalid NSEC3 RDATA: Hash length is too large
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+# only contains the first byte of hash
+rdlen: 12
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.wire
new file mode 100644
index 0000000..e880d55
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire12.spec
+###
+
+# NSEC3 RDATA, RDLEN=12
+000c
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=6
+00 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec
new file mode 100644
index 0000000..fcc9d53
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec
@@ -0,0 +1,9 @@
+#
+# A valid (but unusual) NSEC3 RDATA: salt is empty.
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+saltlen: 0
+salt: ''
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.wire
new file mode 100644
index 0000000..86a06c5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire13.spec
+###
+
+# NSEC3 RDATA, RDLEN=34
+0022
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=0, Salt=''
+00
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=6
+00 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec
new file mode 100644
index 0000000..a0550d5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec
@@ -0,0 +1,9 @@
+#
+# An invalid NSEC3 RDATA: empty hash
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+hashlen: 0
+hash: ''
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.wire
new file mode 100644
index 0000000..9d76b5a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire14.spec
+###
+
+# NSEC3 RDATA, RDLEN=19
+0013
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=0, Hash=''
+00
+# Bitmap: Block=0, Length=6
+00 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec
new file mode 100644
index 0000000..4993e03
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec
@@ -0,0 +1,10 @@
+#
+# NSEC3 RDATA with empty type bitmap. It's okay.
+# The test data includes bytes for a bitmap field, but RDLEN indicates
+# it's not part of the RDATA and so it will be ignored.
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 31
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.wire
new file mode 100644
index 0000000..bd636a7
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire15.spec
+###
+
+# NSEC3 RDATA, RDLEN=31
+001f
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=6
+00 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.spec
new file mode 100644
index 0000000..dac14ea
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.spec
@@ -0,0 +1,8 @@
+#
+# NSEC3 RDATA with an empty bitmap
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+nbitmap: 0
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.wire
new file mode 100644
index 0000000..bab957e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire16.wire
@@ -0,0 +1,12 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire16.spec
+###
+
+# NSEC3 RDATA, RDLEN=31
+001f
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.spec
new file mode 100644
index 0000000..4253349
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC3 RDATA: RDLEN is too short to include the hash len field.
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 10
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.wire
new file mode 100644
index 0000000..f7972a0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire17.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire17.spec
+###
+
+# NSEC3 RDATA, RDLEN=10
+000a
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=6
+00 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec
new file mode 100644
index 0000000..f35de83
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec
@@ -0,0 +1,9 @@
+#
+# A malformed NSEC3 RDATA: RDLEN indicates it doesn't even contain the fixed
+# 5 octets
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 4
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.wire
new file mode 100644
index 0000000..ec14a58
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire2.spec
+###
+
+# NSEC3 RDATA, RDLEN=4
+0004
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=6
+00 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire3 b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire3
new file mode 100644
index 0000000..a0c8f59
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire3
@@ -0,0 +1,6 @@
+# RDLENGTH, 39 bytes
+00 27
+# NSEC3 record with a broken type bitmap
+01 01 00 01 04 d3 99 ea ab 14 8a 77 c7 ac ef cb
+c5 54 46 03 2b 2d 96 1c c5 eb 68 21 ef 26 00 ff
+22 00 00 00 00 02 90
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec
new file mode 100644
index 0000000..06d6eb4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec
@@ -0,0 +1,9 @@
+#
+# A malformed NSEC3 RDATA: bit map length is too large, causing overflow
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+maplen: 31
+bitmap: '01'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.wire
new file mode 100644
index 0000000..527860c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire4.spec
+###
+
+# NSEC3 RDATA, RDLEN=34
+0022
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=31
+00 1f 01
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.spec
new file mode 100644
index 0000000..2d5713c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.spec
@@ -0,0 +1,13 @@
+#
+# A malformed NSEC3 RDATA: incomplete bit map field
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+# only containing the block field of the bitmap
+rdlen: 32
+#dummy data
+maplen: 31
+#dummy data
+bitmap: '00'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.wire
new file mode 100644
index 0000000..97b798b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire5.spec
+###
+
+# NSEC3 RDATA, RDLEN=32
+0020
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=31
+00 1f 00
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec
new file mode 100644
index 0000000..36e9e59
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec
@@ -0,0 +1,11 @@
+#
+# A malformed NSEC3 RDATA: bit map length being 0
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 33
+maplen: 0
+# dummy data:
+bitmap: '01'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.wire
new file mode 100644
index 0000000..4cf1189
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire6.spec
+###
+
+# NSEC3 RDATA, RDLEN=33
+0021
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=0
+00 00 01
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.spec
new file mode 100644
index 0000000..338c0c9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.spec
@@ -0,0 +1,9 @@
+#
+# NSEC3 RDATA with a longest bitmap field (32 bitmap bytes)
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+maplen: 32
+bitmap: '0101010101010101010101010101010101010101010101010101010101010101'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.wire
new file mode 100644
index 0000000..1fddd58
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire7.spec
+###
+
+# NSEC3 RDATA, RDLEN=65
+0041
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=32
+00 20 0101010101010101010101010101010101010101010101010101010101010101
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.spec
new file mode 100644
index 0000000..041714e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.spec
@@ -0,0 +1,9 @@
+#
+# An invalid NSEC3 RDATA with an oversized bitmap field (33 bitmap bytes)
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+maplen: 33
+bitmap: '010101010101010101010101010101010101010101010101010101010101010101'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.wire
new file mode 100644
index 0000000..9569094
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire8.spec
+###
+
+# NSEC3 RDATA, RDLEN=66
+0042
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=0, Length=33
+00 21 010101010101010101010101010101010101010101010101010101010101010101
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec
new file mode 100644
index 0000000..b04c84f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec
@@ -0,0 +1,10 @@
+#
+# An invalid NSEC3 RDATA: disordered bitmap blocks
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+nbitmap: 2
+block0: 2
+block1: 1
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.wire b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.wire
new file mode 100644
index 0000000..9c0de10
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.wire
@@ -0,0 +1,16 @@
+###
+### This data file was auto-generated from rdata_nsec3_fromWire9.spec
+###
+
+# NSEC3 RDATA, RDLEN=47
+002f
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
+# Hash Len=20, Hash='hhhhhhhhhhhhhhhhhhhh'
+14 6868686868686868686868686868686868686868
+# Bitmap: Block=2, Length=6
+02 06 040000000003
+# Bitmap: Block=1, Length=6
+01 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire1 b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire1
new file mode 100644
index 0000000..1b8697f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire1
@@ -0,0 +1,5 @@
+# RDLENGTH, 9 bytes
+00 09
+# NSEC3PARAM record
+# 1 1 1 D399EAAB
+01 01 00 01 04 d3 99 ea ab
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.spec b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.spec
new file mode 100644
index 0000000..41e1784
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC3PARAM RDATA: Saltlen is too large
+#
+
+[custom]
+sections: nsec3param
+[nsec3param]
+rdlen: 7
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.wire b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.wire
new file mode 100644
index 0000000..e9ffb46
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire11.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec3param_fromWire11.spec
+###
+
+# NSEC3PARAM RDATA, RDLEN=7
+0007
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.spec b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.spec
new file mode 100644
index 0000000..311b2dd
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.spec
@@ -0,0 +1,9 @@
+#
+# A valid (but unusual) NSEC3PARAM RDATA: salt is empty.
+#
+
+[custom]
+sections: nsec3param
+[nsec3param]
+saltlen: 0
+salt: ''
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.wire b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.wire
new file mode 100644
index 0000000..511da87
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire13.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec3param_fromWire13.spec
+###
+
+# NSEC3PARAM RDATA, RDLEN=5
+0005
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=0, Salt=''
+00
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.spec
new file mode 100644
index 0000000..e04b818
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.spec
@@ -0,0 +1,9 @@
+#
+# A malformed NSEC3PARAM RDATA: RDLEN indicates it doesn't even contain the
+# fixed 5 octets
+#
+
+[custom]
+sections: nsec3param
+[nsec3param]
+rdlen: 4
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.wire
new file mode 100644
index 0000000..adc5ea9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3param_fromWire2.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec3param_fromWire2.spec
+###
+
+# NSEC3PARAM RDATA, RDLEN=4
+0004
+# Hash Alg=SHA1(1), Opt-Out=0, Other Flags=0, Iterations=1
+01 00 0001
+# Salt Len=5, Salt='sssss'
+05 7373737373
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire1 b/src/lib/dns/tests/testdata/rdata_nsec_fromWire1
new file mode 100644
index 0000000..9c34394
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire1
@@ -0,0 +1,6 @@
+# RDLENGTH, 22 bytes
+00 16
+# NSEC record
+# www2.isc.org. CNAME RRSIG NSEC
+04 77 77 77 32 03 69 73 63 03 6f 72 67 00 00 06
+04 00 00 00 00 03
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire10.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire10.spec
new file mode 100644
index 0000000..39d19ae
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire10.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC RDATA: a bitmap block containing empty bytes
+#
+
+[custom]
+sections: nsec
+[nsec]
+bitmap: '01000000'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire10.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire10.wire
new file mode 100644
index 0000000..1145dbd
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire10.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire10.spec
+###
+
+# NSEC RDATA, RDLEN=24
+0018
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
+# Bitmap: Block=0, Length=4
+00 04 01000000
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire16.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire16.spec
new file mode 100644
index 0000000..d7faeed
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire16.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC RDATA: with an empty bitmap
+#
+
+[custom]
+sections: nsec
+[nsec]
+nbitmap: 0
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire16.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire16.wire
new file mode 100644
index 0000000..943601a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire16.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire16.spec
+###
+
+# NSEC RDATA, RDLEN=18
+0012
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire2 b/src/lib/dns/tests/testdata/rdata_nsec_fromWire2
new file mode 100644
index 0000000..e9b41e2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire2
@@ -0,0 +1,10 @@
+#
+# NSEC RDATA with a bogus RDLEN (too short)
+#
+
+# RDLENGTH, 13 bytes (should be 22)
+00 0d
+# NSEC record
+# www2.isc.org. CNAME RRSIG NSEC
+04 77 77 77 32 03 69 73 63 03 6f 72 67 00 00 06
+04 00 00 00 00 03
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire3 b/src/lib/dns/tests/testdata/rdata_nsec_fromWire3
new file mode 100644
index 0000000..67e6b3f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire3
@@ -0,0 +1,10 @@
+#
+# NSEC RDATA with an invalid type bitmap
+#
+
+# RDLENGTH, 22 bytes
+00 16
+# NSEC record
+# www2.isc.org. followed by a broken bitmap
+04 77 77 77 32 03 69 73 63 03 6f 72 67 00 00 ff
+00 00 00 00 00 00
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire4.spec
new file mode 100644
index 0000000..a5744c1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire4.spec
@@ -0,0 +1,9 @@
+#
+# A malformed NSEC RDATA: bit map length is too large, causing overflow
+#
+
+[custom]
+sections: nsec
+[nsec]
+maplen: 31
+bitmap: '01'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire4.wire
new file mode 100644
index 0000000..1c4d4a4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire4.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire4.spec
+###
+
+# NSEC RDATA, RDLEN=21
+0015
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
+# Bitmap: Block=0, Length=31
+00 1f 01
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire5.spec
new file mode 100644
index 0000000..795d1e0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire5.spec
@@ -0,0 +1,13 @@
+#
+# A malformed NSEC RDATA: incomplete bit map field
+#
+
+[custom]
+sections: nsec
+[nsec]
+# only containing the block field of the bitmap
+rdlen: 19
+#dummy data
+maplen: 31
+#dummy data
+bitmap: '00'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire5.wire
new file mode 100644
index 0000000..104a2b9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire5.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire5.spec
+###
+
+# NSEC RDATA, RDLEN=19
+0013
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
+# Bitmap: Block=0, Length=31
+00 1f 00
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire6.spec
new file mode 100644
index 0000000..cb864ab
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire6.spec
@@ -0,0 +1,11 @@
+#
+# A malformed NSEC RDATA: bit map length being 0
+#
+
+[custom]
+sections: nsec
+[nsec]
+rdlen: 20
+maplen: 0
+# dummy data:
+bitmap: '01'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire6.wire
new file mode 100644
index 0000000..3108ed7
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire6.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire6.spec
+###
+
+# NSEC RDATA, RDLEN=20
+0014
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
+# Bitmap: Block=0, Length=0
+00 00 01
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire7.spec
new file mode 100644
index 0000000..46b521b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire7.spec
@@ -0,0 +1,9 @@
+#
+# NSEC RDATA with a longest bitmap field (32 bitmap bytes)
+#
+
+[custom]
+sections: nsec
+[nsec]
+maplen: 32
+bitmap: '0101010101010101010101010101010101010101010101010101010101010101'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire7.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire7.wire
new file mode 100644
index 0000000..e265a3b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire7.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire7.spec
+###
+
+# NSEC RDATA, RDLEN=52
+0034
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
+# Bitmap: Block=0, Length=32
+00 20 0101010101010101010101010101010101010101010101010101010101010101
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire8.spec
new file mode 100644
index 0000000..3f957a3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire8.spec
@@ -0,0 +1,9 @@
+#
+# An invalid NSEC RDATA with an oversized bitmap field (33 bitmap bytes)
+#
+
+[custom]
+sections: nsec
+[nsec]
+maplen: 33
+bitmap: '010101010101010101010101010101010101010101010101010101010101010101'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire8.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire8.wire
new file mode 100644
index 0000000..066cd70
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire8.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire8.spec
+###
+
+# NSEC RDATA, RDLEN=53
+0035
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
+# Bitmap: Block=0, Length=33
+00 21 010101010101010101010101010101010101010101010101010101010101010101
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire9.spec b/src/lib/dns/tests/testdata/rdata_nsec_fromWire9.spec
new file mode 100644
index 0000000..a3bd0c9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire9.spec
@@ -0,0 +1,10 @@
+#
+# An invalid NSEC RDATA: disordered bitmap blocks
+#
+
+[custom]
+sections: nsec
+[nsec]
+nbitmap: 2
+block0: 2
+block1: 1
diff --git a/src/lib/dns/tests/testdata/rdata_nsec_fromWire9.wire b/src/lib/dns/tests/testdata/rdata_nsec_fromWire9.wire
new file mode 100644
index 0000000..53ad6cc
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec_fromWire9.wire
@@ -0,0 +1,12 @@
+###
+### This data file was auto-generated from rdata_nsec_fromWire9.spec
+###
+
+# NSEC RDATA, RDLEN=34
+0022
+# Next Name=next.example.com (18 bytes)
+046e657874076578616d706c6503636f6d00
+# Bitmap: Block=2, Length=6
+02 06 040000000003
+# Bitmap: Block=1, Length=6
+01 06 040000000003
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire1 b/src/lib/dns/tests/testdata/rdata_opt_fromWire1
new file mode 100644
index 0000000..f2eb680
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire1
@@ -0,0 +1,15 @@
+# Various kinds of OPT RDATA stored in an input buffer
+#
+# Empty RDATA (which is okay)
+#
+# 0 1 (bytes)
+ 00 00
+#
+# An OPT RR containing an NSID Option
+# code=3 len=3 ID value (opaque)
+# 2 3 4 5 6 7 8 9 10
+ 00 07 00 2a 00 03 00 01 02
+#
+# Short buffer (this can be tested only at the end of the buffer)
+# 1 2 3 4 5
+ 00 04 c0 00 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire2 b/src/lib/dns/tests/testdata/rdata_opt_fromWire2
new file mode 100644
index 0000000..2c5a11f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire2
@@ -0,0 +1,4 @@
+# Short RDATA length
+#
+# OPT RDATA, RDLEN=1
+0001
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire3 b/src/lib/dns/tests/testdata/rdata_opt_fromWire3
new file mode 100644
index 0000000..52db1d8
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire3
@@ -0,0 +1,8 @@
+# Short RDATA length (in second pseudo RR)
+#
+# OPT RDATA, RDLEN=8
+0008
+# Pseudo RR 1 of size 7 (code=3, len=3)
+00 03 00 03 00 01 02
+# Pseudo RR 2 of size 7 exhausts RDLEN (code=4, len=3)
+00 04 00 03 00 01 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire4 b/src/lib/dns/tests/testdata/rdata_opt_fromWire4
new file mode 100644
index 0000000..a302127
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire4
@@ -0,0 +1,9 @@
+# Sum of option lengths would overflow RDLEN
+#
+# OPT RDATA, RDLEN=14 (0x000e)
+000e
+# Pseudo RR 1 (code=3, len=3)
+00 03 00 03 00 01 02
+# Pseudo RR 2 (code=4, len=65535 overflows RDLEN)
+00 04 ff ff 00 01 02
+# Rest of option data is omitted...
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_rp_fromWire1.spec
new file mode 100644
index 0000000..edb9f34
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire1.spec
@@ -0,0 +1,6 @@
+#
+# A simplest form of RP: all default parameters
+#
+[custom]
+sections: rp
+[rp]
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire1.wire b/src/lib/dns/tests/testdata/rdata_rp_fromWire1.wire
new file mode 100644
index 0000000..aa93986
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_rp_fromWire1.spec
+###
+
+# RP RDATA, RDLEN=39
+0027
+# MAILBOX=root.example.com TEXT=rp-text.example.com
+04726f6f74076578616d706c6503636f6d00 0772702d74657874076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_rp_fromWire2.spec
new file mode 100644
index 0000000..57adb5a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire2.spec
@@ -0,0 +1,12 @@
+#
+# A simplest form of RP: names are compressed.
+#
+[custom]
+sections: name/1:name/2:rp
+[name/1]
+name: a.example.com
+[name/2]
+name: b.example.net
+[rp]
+mailbox: root.ptr=2
+text: rp-text.ptr=17
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_rp_fromWire2.wire
new file mode 100644
index 0000000..507bb1a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire2.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_rp_fromWire2.spec
+###
+
+# DNS Name: a.example.com
+0161076578616d706c6503636f6d00
+
+# DNS Name: b.example.net
+0162076578616d706c65036e657400
+
+# RP RDATA, RDLEN=17
+0011
+# MAILBOX=root.ptr=2 TEXT=rp-text.ptr=17
+04726f6f74c002 0772702d74657874c011
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_rp_fromWire3.spec
new file mode 100644
index 0000000..a238b7e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire3.spec
@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but RDLEN is too short.
+#
+[custom]
+sections: rp
+[rp]
+rdlen: 38
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_rp_fromWire3.wire
new file mode 100644
index 0000000..c2a7086
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire3.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_rp_fromWire3.spec
+###
+
+# RP RDATA, RDLEN=38
+0026
+# MAILBOX=root.example.com TEXT=rp-text.example.com
+04726f6f74076578616d706c6503636f6d00 0772702d74657874076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_rp_fromWire4.spec
new file mode 100644
index 0000000..6f3abd1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire4.spec
@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but RDLEN is too long.
+#
+[custom]
+sections: rp
+[rp]
+rdlen: 40
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_rp_fromWire4.wire
new file mode 100644
index 0000000..56c643e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire4.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_rp_fromWire4.spec
+###
+
+# RP RDATA, RDLEN=40
+0028
+# MAILBOX=root.example.com TEXT=rp-text.example.com
+04726f6f74076578616d706c6503636f6d00 0772702d74657874076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_rp_fromWire5.spec
new file mode 100644
index 0000000..b8d5e29
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire5.spec
@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but mailbox name is broken.
+#
+[custom]
+sections: rp
+[rp]
+mailbox: "01234567890123456789012345678901234567890123456789012345678901234"
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_rp_fromWire5.wire
new file mode 100644
index 0000000..1127047
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire5.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_rp_fromWire5.spec
+###
+
+# RP RDATA, RDLEN=90
+005a
+# MAILBOX="01234567890123456789012345678901234567890123456789012345678901234" TEXT=rp-text.example.com
+432230313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233342200 0772702d74657874076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_rp_fromWire6.spec
new file mode 100644
index 0000000..e9e79f3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire6.spec
@@ -0,0 +1,7 @@
+#
+# RP-like RDATA but text name is broken.
+#
+[custom]
+sections: rp
+[rp]
+text: "01234567890123456789012345678901234567890123456789012345678901234"
diff --git a/src/lib/dns/tests/testdata/rdata_rp_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_rp_fromWire6.wire
new file mode 100644
index 0000000..49aedc6
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_fromWire6.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_rp_fromWire6.spec
+###
+
+# RP RDATA, RDLEN=87
+0057
+# MAILBOX=root.example.com TEXT="01234567890123456789012345678901234567890123456789012345678901234"
+04726f6f74076578616d706c6503636f6d00 432230313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233342200
diff --git a/src/lib/dns/tests/testdata/rdata_rp_toWire1.spec b/src/lib/dns/tests/testdata/rdata_rp_toWire1.spec
new file mode 100644
index 0000000..948bd1a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_toWire1.spec
@@ -0,0 +1,8 @@
+#
+# A simplest form of RP for toWire test: all default parameters except rdlen,
+# which is to be omitted.
+#
+[custom]
+sections: rp
+[rp]
+rdlen: -1
diff --git a/src/lib/dns/tests/testdata/rdata_rp_toWire1.wire b/src/lib/dns/tests/testdata/rdata_rp_toWire1.wire
new file mode 100644
index 0000000..dcadb15
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_toWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_rp_toWire1.spec
+###
+
+# RP RDATA
+
+# MAILBOX=root.example.com TEXT=rp-text.example.com
+04726f6f74076578616d706c6503636f6d00 0772702d74657874076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdata_rp_toWire2.spec b/src/lib/dns/tests/testdata/rdata_rp_toWire2.spec
new file mode 100644
index 0000000..09a7ddc
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_toWire2.spec
@@ -0,0 +1,14 @@
+#
+# A simple form of RP: names could be compressed (but MUST NOT).
+# rdlen is omitted for the "to wire" test.
+#
+[custom]
+sections: name/1:name/2:rp
+[name/1]
+name: a.example.com
+[name/2]
+name: b.example.net
+[rp]
+rdlen: -1
+mailbox: root.example.com
+text: rp-text.example.net
diff --git a/src/lib/dns/tests/testdata/rdata_rp_toWire2.wire b/src/lib/dns/tests/testdata/rdata_rp_toWire2.wire
new file mode 100644
index 0000000..38057ef
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rp_toWire2.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_rp_toWire2.spec
+###
+
+# DNS Name: a.example.com
+0161076578616d706c6503636f6d00
+
+# DNS Name: b.example.net
+0162076578616d706c65036e657400
+
+# RP RDATA
+
+# MAILBOX=root.example.com TEXT=rp-text.example.net
+04726f6f74076578616d706c6503636f6d00 0772702d74657874076578616d706c65036e657400
diff --git a/src/lib/dns/tests/testdata/rdata_rrsig_fromWire1 b/src/lib/dns/tests/testdata/rdata_rrsig_fromWire1
new file mode 100644
index 0000000..1b799c2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rrsig_fromWire1
@@ -0,0 +1,13 @@
+# RDLENGTH 155 bytes
+00 9b
+# RRSIG record
+00 01 05 02 00 00 a8 c0 4b ad ad 5d 4b 86 20 5d
+0a 62 03 69 73 63 03 6f 72 67 00 1e 42 64 ff 16
+53 bf 37 8f 53 c3 44 36 5f e5 7b 2f 1b 6d 4b a6
+86 4d 61 5d c8 b2 aa 12 e7 cf 55 50 17 39 03 a2
+87 a3 ea 77 97 66 05 99 cd 02 9e 4c a3 ce 61 6a
+e7 62 d7 59 5b 83 e7 3d 01 5e 52 5d e8 ae 02 de
+bf b1 7c 27 a1 59 94 39 f4 cb f2 7f 4e 14 79 9b
+7e 8c a3 6f c6 77 18 e3 f2 52 7f 22 33 d5 91 da
+4a c8 1a 5c 9d 83 43 f0 a1 08 99 ae 4c c8 d0 8d
+7b 23 b5 52 47 cf 41 91 87 35 24
diff --git a/src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.spec
new file mode 100644
index 0000000..582975a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.spec
@@ -0,0 +1,8 @@
+#
+# RRSIG RDATA with a bogus RDLEN (too short)
+#
+
+[custom]
+sections: rrsig
+[rrsig]
+rdlen: 19
diff --git a/src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.wire
new file mode 100644
index 0000000..b3601a1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_rrsig_fromWire2.wire
@@ -0,0 +1,12 @@
+###
+### This data file was auto-generated from rdata_rrsig_fromWire2.spec
+###
+
+# RRSIG RDATA, RDLEN=19
+0013
+# Covered=A(1) Algorithm=RSASHA1(5) Labels=2 OrigTTL=3600
+0001 05 02 00000e10
+# Expiration=1264935600, Inception=1262343600
+4b6562b0 4b3dd5b0
+# Tag=4149 Signer=example.com and Signature
+1035 076578616d706c6503636f6d00 123456789abcdef123456789abcdef
diff --git a/src/lib/dns/tests/testdata/rdata_soa_fromWire b/src/lib/dns/tests/testdata/rdata_soa_fromWire
new file mode 100644
index 0000000..5cd67f0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_soa_fromWire
@@ -0,0 +1,20 @@
+#
+# A common style of SOA RDATA stored in an input buffer
+#
+# Valid compressed RDATA for "(ns.example.com. root.example.com.
+# 2010012601 3600 300 3600000 1200)"
+# RDLENGTH=43 bytes
+# 0 1
+ 00 2b
+# MNAME: non compressed
+# 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7(bytes)
+#(2) n s (7) e x a m p l e (3) c o m .
+ 02 6e 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# RNAME: compressed
+# 8 9 20 1 2 3 4
+#(4) r o o t ptr=5
+ 04 72 6f 6f 74 c0 05
+# other numeric parameters
+# 28 32 36 40 44
+# serial, refresh, retry, expire, minimum
+ 77ce5bb9 00000e10 0000012c 0036ee80 000004b0
diff --git a/src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.spec b/src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.spec
new file mode 100644
index 0000000..389cec9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.spec
@@ -0,0 +1,7 @@
+#
+# A simple SOA RDATA without name compression
+#
+
+[custom]
+sections: soa
+[soa]
diff --git a/src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.wire b/src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.wire
new file mode 100644
index 0000000..4b6442f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_soa_toWireUncompressed.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_soa_toWireUncompressed.spec
+###
+
+# SOA RDATA, RDLEN=54
+0036
+# NNAME=ns.example.com RNAME=root.example.com
+026e73076578616d706c6503636f6d00 04726f6f74076578616d706c6503636f6d00
+# SERIAL(2010012601) REFRESH(3600) RETRY(300) EXPIRE(3600000) MINIMUM(1200)
+77ce5bb9 00000e10 0000012c 0036ee80 000004b0
diff --git a/src/lib/dns/tests/testdata/rdata_srv_fromWire b/src/lib/dns/tests/testdata/rdata_srv_fromWire
new file mode 100644
index 0000000..0f1e4ec
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_srv_fromWire
@@ -0,0 +1,36 @@
+#
+# various kinds of SRV RDATA stored in an input buffer
+#
+# RDLENGTH=21 bytes
+# 0 1
+ 00 15
+# 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2(bytes)
+ 00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# short length
+# 3 4
+ 00 12
+# 5 6 7 8 9 30 1 2 3 4 5 6 7 8 9 40 1 2 3 4 5
+ 00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+# length too long
+# 6 7
+ 00 19
+#
+# 8 9 50 1 2 3 4 5 6 7 8 9 60 1 2 3 4 5 6 7 8
+ 00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+#
+#
+# incomplete target name
+# 9 70
+ 00 12
+# 1 2 3 4 5 6 7 8 9 80 1 2 3 4 5 6 7 8
+ 00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63
+#
+#
+# Valid compressed target name: 'a' + pointer
+# 9 90
+ 00 0a
+#
+# 1 2 3 4 5 6 7 8 9 100
+ 00 01 00 05 05 dc 01 61 c0 0a
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire
new file mode 100644
index 0000000..added40
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire
@@ -0,0 +1,4 @@
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=2 FINGERPRINT_TYPE=1 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+02 01 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.spec
new file mode 100644
index 0000000..e28a62f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.spec
@@ -0,0 +1,6 @@
+#
+# A simplest form of SSHFP: all default parameters
+#
+[custom]
+sections: sshfp
+[sshfp]
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.wire
new file mode 100644
index 0000000..c7059e1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire1.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire1.spec
+###
+
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=2 FINGERPRINT_TYPE=1 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+02 01 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire10 b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire10
new file mode 100644
index 0000000..220e570
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire10
@@ -0,0 +1,6 @@
+# Test where fingerprint is missing
+
+# SSHFP RDATA, RDLEN=32
+0020
+# ALGORITHM=2 FINGERPRINT_TYPE=1 FINGERPRINT=(none)
+02 01
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire11 b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire11
new file mode 100644
index 0000000..a2f8636
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire11
@@ -0,0 +1,4 @@
+# Test where RDATA is completely missing
+
+# SSHFP RDATA, RDLEN=32
+0020
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire12 b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire12
new file mode 100644
index 0000000..eabd06b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire12
@@ -0,0 +1,4 @@
+# SSHFP RDATA, RDLEN=02
+0002
+# ALGORITHM=4 FINGERPRINT_TYPE=9
+04 09
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2 b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2
new file mode 100644
index 0000000..a695548
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2
@@ -0,0 +1,4 @@
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=2 FINGERPRINT_TYPE=1 FINGERPRINT=123456789ABCDEF67890123456789abcdef67890
+02 01 123456789ABCDEF67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.spec
new file mode 100644
index 0000000..59a336e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.spec
@@ -0,0 +1,7 @@
+#
+# SSHFP RDATA
+#
+[custom]
+sections: sshfp
+[sshfp]
+fingerprint: 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.wire
new file mode 100644
index 0000000..e492316
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire2.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire2.spec
+###
+
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=2 FINGERPRINT_TYPE=1 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+02 01 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.spec
new file mode 100644
index 0000000..d111afd
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.spec
@@ -0,0 +1,8 @@
+#
+# SSHFP RDATA
+#
+[custom]
+sections: sshfp
+[sshfp]
+algorithm: 1
+fingerprint_type: 1
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.wire
new file mode 100644
index 0000000..daa102f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire3.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire3.spec
+###
+
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=1 FINGERPRINT_TYPE=1 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+01 01 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.spec
new file mode 100644
index 0000000..b9b2658
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.spec
@@ -0,0 +1,8 @@
+#
+# SSHFP RDATA
+#
+[custom]
+sections: sshfp
+[sshfp]
+algorithm: 255
+fingerprint_type: 1
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.wire
new file mode 100644
index 0000000..f05faad
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire4.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire4.spec
+###
+
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=255 FINGERPRINT_TYPE=1 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+ff 01 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.spec
new file mode 100644
index 0000000..b3a19fa
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.spec
@@ -0,0 +1,8 @@
+#
+# SSHFP RDATA
+#
+[custom]
+sections: sshfp
+[sshfp]
+algorithm: 0
+fingerprint_type: 1
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.wire
new file mode 100644
index 0000000..ddc8edb
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire5.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire5.spec
+###
+
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=0 FINGERPRINT_TYPE=1 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+00 01 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.spec
new file mode 100644
index 0000000..437e282
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.spec
@@ -0,0 +1,8 @@
+#
+# SSHFP RDATA
+#
+[custom]
+sections: sshfp
+[sshfp]
+algorithm: 5
+fingerprint_type: 0
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.wire
new file mode 100644
index 0000000..d4e591e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire6.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire6.spec
+###
+
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=5 FINGERPRINT_TYPE=0 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+05 00 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.spec
new file mode 100644
index 0000000..8e21d11
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.spec
@@ -0,0 +1,8 @@
+#
+# SSHFP RDATA
+#
+[custom]
+sections: sshfp
+[sshfp]
+algorithm: 255
+fingerprint_type: 255
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.wire
new file mode 100644
index 0000000..c8b9d8b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire7.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire7.spec
+###
+
+# SSHFP RDATA, RDLEN=22
+0016
+# ALGORITHM=255 FINGERPRINT_TYPE=255 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+ff ff 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.spec
new file mode 100644
index 0000000..98aa00f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.spec
@@ -0,0 +1,9 @@
+#
+# SSHFP RDATA
+#
+[custom]
+sections: sshfp
+[sshfp]
+fingerprint: 082359342fd9
+algorithm: 255
+fingerprint_type: 255
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.wire b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.wire
new file mode 100644
index 0000000..32cede8
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire8.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_sshfp_fromWire8.spec
+###
+
+# SSHFP RDATA, RDLEN=8
+0008
+# ALGORITHM=255 FINGERPRINT_TYPE=255 FINGERPRINT=082359342fd9
+ff ff 082359342fd9
diff --git a/src/lib/dns/tests/testdata/rdata_sshfp_fromWire9 b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire9
new file mode 100644
index 0000000..05fc806
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_sshfp_fromWire9
@@ -0,0 +1,6 @@
+# Test where fingerprint length is smaller than what RDATA len indicates
+
+# SSHFP RDATA, RDLEN=32
+0020
+# ALGORITHM=2 FINGERPRINT_TYPE=1 FINGERPRINT=123456789abcdef67890123456789abcdef67890
+02 01 123456789abcdef67890123456789abcdef67890
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire1.spec
new file mode 100644
index 0000000..e46d9b3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire1.spec
@@ -0,0 +1,6 @@
+#
+# A simplest form of TKEY: all default parameters
+#
+[custom]
+sections: tkey
+[tkey]
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire1.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire1.wire
new file mode 100644
index 0000000..e8ee944
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire1.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire1.spec
+###
+
+# TKEY RDATA, RDLEN=58
+003a
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=32 Key=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire2.spec
new file mode 100644
index 0000000..e4a1920
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire2.spec
@@ -0,0 +1,8 @@
+#
+# TKEY with other data
+#
+[custom]
+sections: tkey
+[tkey]
+other_len: 8
+other_data: abcd0123
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire2.wire
new file mode 100644
index 0000000..614844f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire2.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire2.spec
+###
+
+# TKEY RDATA, RDLEN=66
+0042
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=32 Key=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Other-Len=8 Other-Data=(see hex)
+0008 6162636430313233
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire3.spec
new file mode 100644
index 0000000..2566b58
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire3.spec
@@ -0,0 +1,9 @@
+#
+# TKEY without Key
+#
+[custom]
+sections: tkey
+[tkey]
+key_len: 0
+other_len: 8
+other_data: abcd0123
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire3.wire
new file mode 100644
index 0000000..df27910
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire3.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire3.spec
+###
+
+# TKEY RDATA, RDLEN=34
+0022
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=0 Key=(see hex)
+0000
+# Other-Len=8 Other-Data=(see hex)
+0008 6162636430313233
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire4.spec
new file mode 100644
index 0000000..33459eb
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire4.spec
@@ -0,0 +1,11 @@
+#
+# A simplest form of TKEY, but the algorithm name is compressed (quite
+# pathological, but we accept it)
+#
+[custom]
+sections: name:tkey
+[name]
+name: gss-tsig
+[tkey]
+algorithm: ptr=0
+key_len: 32
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire4.wire
new file mode 100644
index 0000000..550052e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire4.wire
@@ -0,0 +1,17 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire4.spec
+###
+
+# DNS Name: gss-tsig
+086773732d7473696700
+
+# TKEY RDATA, RDLEN=50
+0032
+# Algorithm=ptr=0
+c000
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=32 Key=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire5.spec
new file mode 100644
index 0000000..6cfa4b4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire5.spec
@@ -0,0 +1,7 @@
+#
+# TKEY-like RDATA but RDLEN is too short.
+#
+[custom]
+sections: tkey
+[tkey]
+rdlen: 57
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire5.wire
new file mode 100644
index 0000000..fa32566
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire5.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire5.spec
+###
+
+# TKEY RDATA, RDLEN=57
+0039
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=32 Key=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire6.spec
new file mode 100644
index 0000000..87460a2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire6.spec
@@ -0,0 +1,7 @@
+#
+# TKEY-like RDATA but RDLEN is too long.
+#
+[custom]
+sections: tkey
+[tkey]
+rdlen: 60
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire6.wire
new file mode 100644
index 0000000..7f5f112
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire6.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire6.spec
+###
+
+# TKEY RDATA, RDLEN=60
+003c
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=32 Key=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire7.spec
new file mode 100644
index 0000000..3fc0929
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire7.spec
@@ -0,0 +1,8 @@
+#
+# TKEY-like RDATA but algorithm name is broken.
+#
+[custom]
+sections: tkey
+[tkey]
+algorithm: "01234567890123456789012345678901234567890123456789012345678901234"
+key_len: 32
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire7.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire7.wire
new file mode 100644
index 0000000..73b277c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire7.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire7.spec
+###
+
+# TKEY RDATA, RDLEN=117
+0075
+# Algorithm="01234567890123456789012345678901234567890123456789012345678901234"
+432230313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233342200
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=32 Key=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire8.spec
new file mode 100644
index 0000000..8338279
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire8.spec
@@ -0,0 +1,8 @@
+#
+# TKEY-like RDATA but Key len is bogus
+#
+[custom]
+sections: tkey
+[tkey]
+key_len: 65535
+key: "dummy data"
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire8.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire8.wire
new file mode 100644
index 0000000..abeb95b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire8.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire8.spec
+###
+
+# TKEY RDATA, RDLEN=38
+0026
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=65535 Key=(see hex)
+ffff 2264756d6d79206461746122
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire9.spec b/src/lib/dns/tests/testdata/rdata_tkey_fromWire9.spec
new file mode 100644
index 0000000..9fb63e0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire9.spec
@@ -0,0 +1,8 @@
+#
+# TKEY-like RDATA but Other-Data length is bogus
+#
+[custom]
+sections: tkey
+[tkey]
+other_len: 65535
+otherdata: "dummy data"
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_fromWire9.wire b/src/lib/dns/tests/testdata/rdata_tkey_fromWire9.wire
new file mode 100644
index 0000000..8e5f943
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_fromWire9.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_fromWire9.spec
+###
+
+# TKEY RDATA, RDLEN=58
+003a
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=32 Key=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Other-Len=65535 Other-Data=(see hex)
+ffff
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire1.spec b/src/lib/dns/tests/testdata/rdata_tkey_toWire1.spec
new file mode 100644
index 0000000..42521a3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire1.spec
@@ -0,0 +1,8 @@
+#
+# An artificial TKEY RDATA for toWire test.
+#
+[custom]
+sections: tkey
+[tkey]
+algorithm: gss-tsig
+key_len: 0
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire1.wire b/src/lib/dns/tests/testdata/rdata_tkey_toWire1.wire
new file mode 100644
index 0000000..3f49a69
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire1.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_toWire1.spec
+###
+
+# TKEY RDATA, RDLEN=26
+001a
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=0 Key=(see hex)
+0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire2.spec b/src/lib/dns/tests/testdata/rdata_tkey_toWire2.spec
new file mode 100644
index 0000000..25d47e5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire2.spec
@@ -0,0 +1,11 @@
+#
+# An artificial TKEY RDATA for toWire test.
+#
+[custom]
+sections: tkey
+[tkey]
+algorithm: GSS-TSIG
+error: 16
+key_len: 12
+# 0x1402... would be FAKEFAKE... if encoded in BASE64
+key: 0x140284140284140284140284
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire2.wire b/src/lib/dns/tests/testdata/rdata_tkey_toWire2.wire
new file mode 100644
index 0000000..a1fdb9a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire2.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_toWire2.spec
+###
+
+# TKEY RDATA, RDLEN=38
+0026
+# Algorithm=GSS-TSIG
+084753532d5453494700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=16
+608d42c0 608d50d0 0003 0010
+# Key Len=12 Key=(see hex)
+000c 140284140284140284140284
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire3.spec b/src/lib/dns/tests/testdata/rdata_tkey_toWire3.spec
new file mode 100644
index 0000000..b3ea3db
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire3.spec
@@ -0,0 +1,13 @@
+#
+# An artificial TKEY RDATA for toWire test.
+#
+[custom]
+sections: tkey
+[tkey]
+algorithm: gss.tsig
+error: 16
+key_len: 12
+# 0x1402... would be FAKEFAKE... if encoded in BASE64
+key: 0x140284140284140284140284
+other_len: 6
+other_data: 0x140284140284
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire3.wire b/src/lib/dns/tests/testdata/rdata_tkey_toWire3.wire
new file mode 100644
index 0000000..f2f8a6f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire3.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tkey_toWire3.spec
+###
+
+# TKEY RDATA, RDLEN=44
+002c
+# Algorithm=gss.tsig
+03677373047473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=16
+608d42c0 608d50d0 0003 0010
+# Key Len=12 Key=(see hex)
+000c 140284140284140284140284
+# Other-Len=6 Other-Data=(see hex)
+0006 140284140284
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire4.spec b/src/lib/dns/tests/testdata/rdata_tkey_toWire4.spec
new file mode 100644
index 0000000..e403c00
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire4.spec
@@ -0,0 +1,10 @@
+#
+# An artificial TKEY RDATA for toWire test.
+#
+[custom]
+sections: name:tkey
+[name]
+name: gss-tsig
+[tkey]
+algorithm: gss-tsig
+key_len: 0
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire4.wire b/src/lib/dns/tests/testdata/rdata_tkey_toWire4.wire
new file mode 100644
index 0000000..81a1443
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire4.wire
@@ -0,0 +1,17 @@
+###
+### This data file was auto-generated from rdata_tkey_toWire4.spec
+###
+
+# DNS Name: gss-tsig
+086773732d7473696700
+
+# TKEY RDATA, RDLEN=26
+001a
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=0 Key=(see hex)
+0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire5.spec b/src/lib/dns/tests/testdata/rdata_tkey_toWire5.spec
new file mode 100644
index 0000000..b4a1bca
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire5.spec
@@ -0,0 +1,10 @@
+#
+# An artificial TKEY RDATA for toWire test.
+#
+[custom]
+sections: tkey:name
+[tkey]
+algorithm: gss-tsig
+key_len: 0
+[name]
+name: ptr=2
diff --git a/src/lib/dns/tests/testdata/rdata_tkey_toWire5.wire b/src/lib/dns/tests/testdata/rdata_tkey_toWire5.wire
new file mode 100644
index 0000000..e59a1f0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tkey_toWire5.wire
@@ -0,0 +1,17 @@
+###
+### This data file was auto-generated from rdata_tkey_toWire5.spec
+###
+
+# TKEY RDATA, RDLEN=26
+001a
+# Algorithm=gss-tsig
+086773732d7473696700
+# Inception=1619870400 Expire=1619874000 Mode=3 Error=0
+608d42c0 608d50d0 0003 0000
+# Key Len=0 Key=(see hex)
+0000
+# Other-Len=0 Other-Data=(see hex)
+0000
+
+# DNS Name: ptr=2
+c002
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire
new file mode 100644
index 0000000..38e279c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire
@@ -0,0 +1,4 @@
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=...
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire10 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire10
new file mode 100644
index 0000000..67cecb1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire10
@@ -0,0 +1,6 @@
+# Test where certificate association data is missing.
+
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(missing)
+00 00 01
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire11 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire11
new file mode 100644
index 0000000..4b8ec93
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire11
@@ -0,0 +1,4 @@
+# Test where RDATA is completely missing
+
+# TLSA RDATA, RDLEN=35
+0023
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire12 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire12
new file mode 100644
index 0000000..71c7b9c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire12
@@ -0,0 +1,4 @@
+# TLSA RDATA, RDLEN=3
+0003
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(none)
+03 01 02
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire2 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire2
new file mode 100644
index 0000000..36ce278
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire2
@@ -0,0 +1,4 @@
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=...
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983A1D16E8A410E4561CB106618E971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec
new file mode 100644
index 0000000..39c8057
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 0
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.wire
new file mode 100644
index 0000000..6a8b552
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_tlsa_fromWire3.spec
+###
+
+# TLSA RDATA, RDLEN=34
+0022
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec
new file mode 100644
index 0000000..d97ae6a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 255
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.wire
new file mode 100644
index 0000000..b5a39c8
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_tlsa_fromWire4.spec
+###
+
+# TLSA RDATA, RDLEN=34
+0022
+# CERTIFICATE_USAGE=255 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
+ff 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec
new file mode 100644
index 0000000..cc3e296
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+selector: 255
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.wire
new file mode 100644
index 0000000..b79f97d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_tlsa_fromWire5.spec
+###
+
+# TLSA RDATA, RDLEN=34
+0022
+# CERTIFICATE_USAGE=0 SELECTOR=255 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
+00 ff 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec
new file mode 100644
index 0000000..eed0ab9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+matching_type: 255
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.wire
new file mode 100644
index 0000000..02afe27
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_tlsa_fromWire6.spec
+###
+
+# TLSA RDATA, RDLEN=34
+0022
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=255 CERTIFICATE_ASSOCIATION_DATA=d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
+00 00 ff d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec
new file mode 100644
index 0000000..576df1e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec
@@ -0,0 +1,9 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 3
+selector: 1
+matching_type: 2
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.wire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.wire
new file mode 100644
index 0000000..e5c23a4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_tlsa_fromWire7.spec
+###
+
+# TLSA RDATA, RDLEN=34
+0022
+# CERTIFICATE_USAGE=3 SELECTOR=1 MATCHING_TYPE=2 CERTIFICATE_ASSOCIATION_DATA=d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
+03 01 02 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec
new file mode 100644
index 0000000..ef5c108
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_association_data: '0123'
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.wire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.wire
new file mode 100644
index 0000000..dc29a0b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_tlsa_fromWire8.spec
+###
+
+# TLSA RDATA, RDLEN=4
+0004
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=0123
+00 00 01 0123
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire9 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire9
new file mode 100644
index 0000000..fc4560a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire9
@@ -0,0 +1,7 @@
+# Test where certificate association data length is smaller than what
+# RDATA length indicates.
+
+# TLSA RDATA, RDLEN=64
+0040
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(32 bytes)
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire1.spec
new file mode 100644
index 0000000..a30c371
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire1.spec
@@ -0,0 +1,6 @@
+#
+# A simplest form of TSIG: all default parameters
+#
+[custom]
+sections: tsig
+[tsig]
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire1.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire1.wire
new file mode 100644
index 0000000..cec3a0f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire1.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire1.spec
+###
+
+# TSIG RDATA, RDLEN=61
+003d
+# Algorithm=hmac-sha256 Time-Signed=1286978795 Fudge=300
+0b686d61632d73686132353600 00004cb5bceb 012c
+# MAC Size=32 MAC=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Original-ID=2845 Error=0
+0b1d 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire2.spec
new file mode 100644
index 0000000..d1e49a5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire2.spec
@@ -0,0 +1,8 @@
+#
+# TSIG with other data (error = BADTIME(18))
+#
+[custom]
+sections: tsig
+[tsig]
+mac_size: 0
+error: 18
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire2.wire
new file mode 100644
index 0000000..ca85df4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire2.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire2.spec
+###
+
+# TSIG RDATA, RDLEN=35
+0023
+# Algorithm=hmac-sha256 Time-Signed=1286978795 Fudge=300
+0b686d61632d73686132353600 00004cb5bceb 012c
+# MAC Size=0 MAC=(see hex)
+0000
+# Original-ID=2845 Error=18
+0b1d 0012
+# Other-Len=6 Other-Data=(see hex)
+0006 00004cb5be18
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire3.spec
new file mode 100644
index 0000000..57f8e83
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire3.spec
@@ -0,0 +1,8 @@
+#
+# TSIG without MAC (error = BADSIG(16))
+#
+[custom]
+sections: tsig
+[tsig]
+mac_size: 0
+error: 16
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire3.wire
new file mode 100644
index 0000000..16c3e39
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire3.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire3.spec
+###
+
+# TSIG RDATA, RDLEN=29
+001d
+# Algorithm=hmac-sha256 Time-Signed=1286978795 Fudge=300
+0b686d61632d73686132353600 00004cb5bceb 012c
+# MAC Size=0 MAC=(see hex)
+0000
+# Original-ID=2845 Error=16
+0b1d 0010
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire4.spec
new file mode 100644
index 0000000..8c38e9e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire4.spec
@@ -0,0 +1,11 @@
+#
+# A simplest form of TSIG, but the algorithm name is compressed (quite
+# pathological, but we accept it)
+#
+[custom]
+sections: name:tsig
+[name]
+name: hmac-sha256
+[tsig]
+algorithm: ptr=0
+mac_size: 32
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire4.wire
new file mode 100644
index 0000000..6b8e0f3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire4.wire
@@ -0,0 +1,17 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire4.spec
+###
+
+# DNS Name: hmac-sha256
+0b686d61632d73686132353600
+
+# TSIG RDATA, RDLEN=50
+0032
+# Algorithm=ptr=0 Time-Signed=1286978795 Fudge=300
+c000 00004cb5bceb 012c
+# MAC Size=32 MAC=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Original-ID=2845 Error=0
+0b1d 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire5.spec
new file mode 100644
index 0000000..da90b18
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire5.spec
@@ -0,0 +1,7 @@
+#
+# TSIG-like RDATA but RDLEN is too short.
+#
+[custom]
+sections: tsig
+[tsig]
+rdlen: 60
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire5.wire
new file mode 100644
index 0000000..9656ce2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire5.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire5.spec
+###
+
+# TSIG RDATA, RDLEN=60
+003c
+# Algorithm=hmac-sha256 Time-Signed=1286978795 Fudge=300
+0b686d61632d73686132353600 00004cb5bceb 012c
+# MAC Size=32 MAC=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Original-ID=2845 Error=0
+0b1d 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire6.spec
new file mode 100644
index 0000000..9d2f627
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire6.spec
@@ -0,0 +1,7 @@
+#
+# TSIG-like RDATA but RDLEN is too long.
+#
+[custom]
+sections: tsig
+[tsig]
+rdlen: 63
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire6.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire6.wire
new file mode 100644
index 0000000..bb1ecfb
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire6.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire6.spec
+###
+
+# TSIG RDATA, RDLEN=63
+003f
+# Algorithm=hmac-sha256 Time-Signed=1286978795 Fudge=300
+0b686d61632d73686132353600 00004cb5bceb 012c
+# MAC Size=32 MAC=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Original-ID=2845 Error=0
+0b1d 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire7.spec
new file mode 100644
index 0000000..ed7a81c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire7.spec
@@ -0,0 +1,8 @@
+#
+# TSIG-like RDATA but algorithm name is broken.
+#
+[custom]
+sections: tsig
+[tsig]
+algorithm: "01234567890123456789012345678901234567890123456789012345678901234"
+mac_size: 32
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire7.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire7.wire
new file mode 100644
index 0000000..327211f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire7.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire7.spec
+###
+
+# TSIG RDATA, RDLEN=117
+0075
+# Algorithm="01234567890123456789012345678901234567890123456789012345678901234" Time-Signed=1286978795 Fudge=300
+432230313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233342200 00004cb5bceb 012c
+# MAC Size=32 MAC=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Original-ID=2845 Error=0
+0b1d 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire8.spec
new file mode 100644
index 0000000..0b44f87
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire8.spec
@@ -0,0 +1,8 @@
+#
+# TSIG-like RDATA but MAC size is bogus
+#
+[custom]
+sections: tsig
+[tsig]
+mac_size: 65535
+mac: "dummy data"
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire8.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire8.wire
new file mode 100644
index 0000000..a4209f9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire8.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire8.spec
+###
+
+# TSIG RDATA, RDLEN=41
+0029
+# Algorithm=hmac-sha256 Time-Signed=1286978795 Fudge=300
+0b686d61632d73686132353600 00004cb5bceb 012c
+# MAC Size=65535 MAC=(see hex)
+ffff 2264756d6d79206461746122
+# Original-ID=2845 Error=0
+0b1d 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire9.spec b/src/lib/dns/tests/testdata/rdata_tsig_fromWire9.spec
new file mode 100644
index 0000000..f512fb4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire9.spec
@@ -0,0 +1,8 @@
+#
+# TSIG-like RDATA but Other-Data length is bogus
+#
+[custom]
+sections: tsig
+[tsig]
+other_len: 65535
+otherdata: "dummy data"
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_fromWire9.wire b/src/lib/dns/tests/testdata/rdata_tsig_fromWire9.wire
new file mode 100644
index 0000000..b356825
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_fromWire9.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_fromWire9.spec
+###
+
+# TSIG RDATA, RDLEN=61
+003d
+# Algorithm=hmac-sha256 Time-Signed=1286978795 Fudge=300
+0b686d61632d73686132353600 00004cb5bceb 012c
+# MAC Size=32 MAC=(see hex)
+0020 7878787878787878787878787878787878787878787878787878787878787878
+# Original-ID=2845 Error=0
+0b1d 0000
+# Other-Len=65535 Other-Data=(see hex)
+ffff
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire1.spec b/src/lib/dns/tests/testdata/rdata_tsig_toWire1.spec
new file mode 100644
index 0000000..eb74000
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire1.spec
@@ -0,0 +1,11 @@
+#
+# An artificial TSIG RDATA for toWire test.
+#
+[custom]
+sections: tsig
+[tsig]
+algorithm: hmac-md5
+time_signed: 1286779327
+mac_size: 0
+original_id: 16020
+error: 17
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire1.wire b/src/lib/dns/tests/testdata/rdata_tsig_toWire1.wire
new file mode 100644
index 0000000..c368853
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire1.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_toWire1.spec
+###
+
+# TSIG RDATA, RDLEN=42
+002a
+# Algorithm=hmac-md5 Time-Signed=1286779327 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004cb2b1bf 012c
+# MAC Size=0 MAC=(see hex)
+0000
+# Original-ID=16020 Error=17
+3e94 0011
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire2.spec b/src/lib/dns/tests/testdata/rdata_tsig_toWire2.spec
new file mode 100644
index 0000000..b2c38e9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire2.spec
@@ -0,0 +1,13 @@
+#
+# An artificial TSIG RDATA for toWire test.
+#
+[custom]
+sections: tsig
+[tsig]
+algorithm: hmac-sha256
+time_signed: 1286779327
+mac_size: 12
+# 0x1402... would be FAKEFAKE... if encoded in BASE64
+mac: 0x140284140284140284140284
+original_id: 16020
+error: 16
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire2.wire b/src/lib/dns/tests/testdata/rdata_tsig_toWire2.wire
new file mode 100644
index 0000000..7ea336d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire2.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_toWire2.spec
+###
+
+# TSIG RDATA, RDLEN=41
+0029
+# Algorithm=hmac-sha256 Time-Signed=1286779327 Fudge=300
+0b686d61632d73686132353600 00004cb2b1bf 012c
+# MAC Size=12 MAC=(see hex)
+000c 140284140284140284140284
+# Original-ID=16020 Error=16
+3e94 0010
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire3.spec b/src/lib/dns/tests/testdata/rdata_tsig_toWire3.spec
new file mode 100644
index 0000000..6520a08
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire3.spec
@@ -0,0 +1,15 @@
+#
+# An artificial TSIG RDATA for toWire test.
+#
+[custom]
+sections: tsig
+[tsig]
+algorithm: hmac-sha1
+time_signed: 1286779327
+mac_size: 12
+# 0x1402... would be FAKEFAKE... if encoded in BASE64
+mac: 0x140284140284140284140284
+original_id: 16020
+error: 18
+other_len: 6
+other_data: 0x140284140284
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire3.wire b/src/lib/dns/tests/testdata/rdata_tsig_toWire3.wire
new file mode 100644
index 0000000..535a83b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire3.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from rdata_tsig_toWire3.spec
+###
+
+# TSIG RDATA, RDLEN=45
+002d
+# Algorithm=hmac-sha1 Time-Signed=1286779327 Fudge=300
+09686d61632d7368613100 00004cb2b1bf 012c
+# MAC Size=12 MAC=(see hex)
+000c 140284140284140284140284
+# Original-ID=16020 Error=18
+3e94 0012
+# Other-Len=6 Other-Data=(see hex)
+0006 140284140284
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire4.spec b/src/lib/dns/tests/testdata/rdata_tsig_toWire4.spec
new file mode 100644
index 0000000..d95cd23
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire4.spec
@@ -0,0 +1,13 @@
+#
+# An artificial TSIG RDATA for toWire test.
+#
+[custom]
+sections: name:tsig
+[name]
+name: hmac-md5.sig-alg.reg.int.
+[tsig]
+algorithm: hmac-md5
+time_signed: 1286779327
+mac_size: 0
+original_id: 16020
+error: 17
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire4.wire b/src/lib/dns/tests/testdata/rdata_tsig_toWire4.wire
new file mode 100644
index 0000000..5e8f68b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire4.wire
@@ -0,0 +1,17 @@
+###
+### This data file was auto-generated from rdata_tsig_toWire4.spec
+###
+
+# DNS Name: hmac-md5.sig-alg.reg.int.
+08686d61632d6d6435077369672d616c670372656703696e7400
+
+# TSIG RDATA, RDLEN=42
+002a
+# Algorithm=hmac-md5 Time-Signed=1286779327 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004cb2b1bf 012c
+# MAC Size=0 MAC=(see hex)
+0000
+# Original-ID=16020 Error=17
+3e94 0011
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire5.spec b/src/lib/dns/tests/testdata/rdata_tsig_toWire5.spec
new file mode 100644
index 0000000..81e3a78
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire5.spec
@@ -0,0 +1,13 @@
+#
+# An artificial TSIG RDATA for toWire test.
+#
+[custom]
+sections: tsig:name
+[tsig]
+algorithm: hmac-md5
+time_signed: 1286779327
+mac_size: 0
+original_id: 16020
+error: 17
+[name]
+name: ptr=2
diff --git a/src/lib/dns/tests/testdata/rdata_tsig_toWire5.wire b/src/lib/dns/tests/testdata/rdata_tsig_toWire5.wire
new file mode 100644
index 0000000..bc83de6
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tsig_toWire5.wire
@@ -0,0 +1,17 @@
+###
+### This data file was auto-generated from rdata_tsig_toWire5.spec
+###
+
+# TSIG RDATA, RDLEN=42
+002a
+# Algorithm=hmac-md5 Time-Signed=1286779327 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004cb2b1bf 012c
+# MAC Size=0 MAC=(see hex)
+0000
+# Original-ID=16020 Error=17
+3e94 0011
+# Other-Len=0 Other-Data=(see hex)
+0000
+
+# DNS Name: ptr=2
+c002
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire1 b/src/lib/dns/tests/testdata/rdata_txt_fromWire1
new file mode 100644
index 0000000..547d76f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire1
@@ -0,0 +1,9 @@
+#
+# various kinds of TXT RDATA stored in an input buffer
+#
+# Valid RDATA for "Test-String"
+#
+# RDLENGTH=12 bytes
+ 00 0c
+# T e s t - S t r i n g
+ 0b 54 65 73 74 2d 53 74 72 69 6e 67
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_txt_fromWire2.spec
new file mode 100644
index 0000000..c5829d9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire2.spec
@@ -0,0 +1,8 @@
+#
+# TXT RDATA with empty character-string. unusual, but valid.
+#
+
+[custom]
+sections: txt
+[txt]
+string: ''
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire2.wire b/src/lib/dns/tests/testdata/rdata_txt_fromWire2.wire
new file mode 100644
index 0000000..83ebea3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire2.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_txt_fromWire2.spec
+###
+
+# TXT RDATA, RDLEN=1
+0001
+# String Len=0, String=""
+00
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_txt_fromWire3.spec
new file mode 100644
index 0000000..fe5c129
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire3.spec
@@ -0,0 +1,8 @@
+#
+# TXT RDATA with multiple character-strings.
+#
+
+[custom]
+sections: txt
+[txt]
+nstring: 2
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire3.wire b/src/lib/dns/tests/testdata/rdata_txt_fromWire3.wire
new file mode 100644
index 0000000..42fdf76
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire3.wire
@@ -0,0 +1,10 @@
+###
+### This data file was auto-generated from rdata_txt_fromWire3.spec
+###
+
+# TXT RDATA, RDLEN=24
+0018
+# String Len=11, String="Test-String"
+0b 546573742d537472696e67
+# String Len=11, String="Test-String"
+0b 546573742d537472696e67
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_txt_fromWire4.spec
new file mode 100644
index 0000000..0e015d4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire4.spec
@@ -0,0 +1,9 @@
+#
+# Malformed TXT RDATA: RDLEN is 0
+#
+
+[custom]
+sections: txt
+[txt]
+rdlen: 0
+# following data is provided, but that doesn't matter.
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire4.wire b/src/lib/dns/tests/testdata/rdata_txt_fromWire4.wire
new file mode 100644
index 0000000..6ac73b8
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire4.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_txt_fromWire4.spec
+###
+
+# TXT RDATA, RDLEN=0
+0000
+# String Len=11, String="Test-String"
+0b 546573742d537472696e67
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_txt_fromWire5.spec
new file mode 100644
index 0000000..7710cdf
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire5.spec
@@ -0,0 +1,9 @@
+#
+# Malformed TXT RDATA: character-string length is too large
+#
+
+[custom]
+sections: txt
+[txt]
+stringlen: 255
+string: 'too short'
diff --git a/src/lib/dns/tests/testdata/rdata_txt_fromWire5.wire b/src/lib/dns/tests/testdata/rdata_txt_fromWire5.wire
new file mode 100644
index 0000000..ea7a9cf
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_txt_fromWire5.wire
@@ -0,0 +1,8 @@
+###
+### This data file was auto-generated from rdata_txt_fromWire5.spec
+###
+
+# TXT RDATA, RDLEN=10
+000a
+# String Len=255, String="too short"
+ff 746f6f2073686f7274
diff --git a/src/lib/dns/tests/testdata/rdata_unknown_fromWire b/src/lib/dns/tests/testdata/rdata_unknown_fromWire
new file mode 100644
index 0000000..69ea8ff
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_unknown_fromWire
@@ -0,0 +1,13 @@
+#
+# various kinds of "unknown" RDATA stored in an input buffer
+#
+# 0 1 2 3 4 5 (bytes)
+ 00 04 a1 b2 c3 0d
+#
+# 0-length data
+# 6 7
+ 00 00
+#
+# short buffer (this can be tested only at the end of the buffer)
+# 8 9 10 1 2
+ 00 04 a1 b2 c3
diff --git a/src/lib/dns/tests/testdata/rdatafields1.spec b/src/lib/dns/tests/testdata/rdatafields1.spec
new file mode 100644
index 0000000..6e105fb
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields1.spec
@@ -0,0 +1,10 @@
+#
+# A sequence of names that could be compressed (but not compressed)
+#
+
+[custom]
+sections: name/1:name/2
+[name/1]
+name: www.example.com
+[name/2]
+name: example.com
diff --git a/src/lib/dns/tests/testdata/rdatafields1.wire b/src/lib/dns/tests/testdata/rdatafields1.wire
new file mode 100644
index 0000000..42028c1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields1.wire
@@ -0,0 +1,9 @@
+###
+### This data file was auto-generated from rdatafields1.spec
+###
+
+# DNS Name: www.example.com
+03777777076578616d706c6503636f6d00
+
+# DNS Name: example.com
+076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdatafields2.spec b/src/lib/dns/tests/testdata/rdatafields2.spec
new file mode 100644
index 0000000..920dc95
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields2.spec
@@ -0,0 +1,11 @@
+#
+# A sequence of names that can be compressed.
+#
+
+[custom]
+sections: name/1:name/2
+[name/1]
+name: www.example.com
+[name/2]
+name: ''
+pointer: 4
diff --git a/src/lib/dns/tests/testdata/rdatafields2.wire b/src/lib/dns/tests/testdata/rdatafields2.wire
new file mode 100644
index 0000000..cbb0ce0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields2.wire
@@ -0,0 +1,9 @@
+###
+### This data file was auto-generated from rdatafields2.spec
+###
+
+# DNS Name: www.example.com
+03777777076578616d706c6503636f6d00
+
+# DNS Name: + compression pointer: 4
+c004
diff --git a/src/lib/dns/tests/testdata/rdatafields3.spec b/src/lib/dns/tests/testdata/rdatafields3.spec
new file mode 100644
index 0000000..b37fca3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields3.spec
@@ -0,0 +1,11 @@
+#
+# TXT RDATA with multiple character-strings.
+#
+
+[custom]
+sections: txt
+[txt]
+nstring: 3
+string0: 'first string'
+string1: 'second string'
+string2: 'last string'
diff --git a/src/lib/dns/tests/testdata/rdatafields3.wire b/src/lib/dns/tests/testdata/rdatafields3.wire
new file mode 100644
index 0000000..3ff32f1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields3.wire
@@ -0,0 +1,12 @@
+###
+### This data file was auto-generated from rdatafields3.spec
+###
+
+# TXT RDATA, RDLEN=39
+0027
+# String Len=12, String="first string"
+0c 666972737420737472696e67
+# String Len=13, String="second string"
+0d 7365636f6e6420737472696e67
+# String Len=11, String="last string"
+0b 6c61737420737472696e67
diff --git a/src/lib/dns/tests/testdata/rdatafields4.spec b/src/lib/dns/tests/testdata/rdatafields4.spec
new file mode 100644
index 0000000..24b59aa
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields4.spec
@@ -0,0 +1,7 @@
+#
+# Simple form of RRSIG (all fields use the default of generator script)
+#
+
+[custom]
+sections: rrsig
+[rrsig]
diff --git a/src/lib/dns/tests/testdata/rdatafields4.wire b/src/lib/dns/tests/testdata/rdatafields4.wire
new file mode 100644
index 0000000..e574426
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields4.wire
@@ -0,0 +1,12 @@
+###
+### This data file was auto-generated from rdatafields4.spec
+###
+
+# RRSIG RDATA, RDLEN=46
+002e
+# Covered=A(1) Algorithm=RSASHA1(5) Labels=2 OrigTTL=3600
+0001 05 02 00000e10
+# Expiration=1264935600, Inception=1262343600
+4b6562b0 4b3dd5b0
+# Tag=4149 Signer=example.com and Signature
+1035 076578616d706c6503636f6d00 123456789abcdef123456789abcdef
diff --git a/src/lib/dns/tests/testdata/rdatafields5.spec b/src/lib/dns/tests/testdata/rdatafields5.spec
new file mode 100644
index 0000000..2c78282
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields5.spec
@@ -0,0 +1,12 @@
+#
+# Names and RDATA (RRSIG) with an incompressible name. All names are
+# rendered without compression.
+#
+
+[custom]
+sections: name/1:rrsig:name/2
+[name/1]
+name: com
+[rrsig]
+[name/2]
+name: www.example.com
diff --git a/src/lib/dns/tests/testdata/rdatafields5.wire b/src/lib/dns/tests/testdata/rdatafields5.wire
new file mode 100644
index 0000000..d0cebc9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields5.wire
@@ -0,0 +1,18 @@
+###
+### This data file was auto-generated from rdatafields5.spec
+###
+
+# DNS Name: com
+03636f6d00
+
+# RRSIG RDATA, RDLEN=46
+002e
+# Covered=A(1) Algorithm=RSASHA1(5) Labels=2 OrigTTL=3600
+0001 05 02 00000e10
+# Expiration=1264935600, Inception=1262343600
+4b6562b0 4b3dd5b0
+# Tag=4149 Signer=example.com and Signature
+1035 076578616d706c6503636f6d00 123456789abcdef123456789abcdef
+
+# DNS Name: www.example.com
+03777777076578616d706c6503636f6d00
diff --git a/src/lib/dns/tests/testdata/rdatafields6.spec b/src/lib/dns/tests/testdata/rdatafields6.spec
new file mode 100644
index 0000000..f9f0da1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields6.spec
@@ -0,0 +1,13 @@
+#
+# Names and RDATA (RRSIG) with an incompressible name. The name in RRSIG
+# isn't compressed, but it's used as the compression target.
+#
+
+[custom]
+sections: name/1:rrsig:name/2
+[name/1]
+name: com
+[rrsig]
+[name/2]
+name: www
+pointer: 25
diff --git a/src/lib/dns/tests/testdata/rdatafields6.wire b/src/lib/dns/tests/testdata/rdatafields6.wire
new file mode 100644
index 0000000..0e8b3d9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdatafields6.wire
@@ -0,0 +1,18 @@
+###
+### This data file was auto-generated from rdatafields6.spec
+###
+
+# DNS Name: com
+03636f6d00
+
+# RRSIG RDATA, RDLEN=46
+002e
+# Covered=A(1) Algorithm=RSASHA1(5) Labels=2 OrigTTL=3600
+0001 05 02 00000e10
+# Expiration=1264935600, Inception=1262343600
+4b6562b0 4b3dd5b0
+# Tag=4149 Signer=example.com and Signature
+1035 076578616d706c6503636f6d00 123456789abcdef123456789abcdef
+
+# DNS Name: www + compression pointer: 25
+03777777c019
diff --git a/src/lib/dns/tests/testdata/rrcode16_fromWire1 b/src/lib/dns/tests/testdata/rrcode16_fromWire1
new file mode 100644
index 0000000..df2a177
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrcode16_fromWire1
@@ -0,0 +1,4 @@
+#
+# a 16 bit wire-format data (network byte order)
+#
+1234
diff --git a/src/lib/dns/tests/testdata/rrcode16_fromWire2 b/src/lib/dns/tests/testdata/rrcode16_fromWire2
new file mode 100644
index 0000000..fec2dd0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrcode16_fromWire2
@@ -0,0 +1,4 @@
+#
+# an incomplete segment for a 16 bit wire-format data
+#
+12
diff --git a/src/lib/dns/tests/testdata/rrcode32_fromWire1 b/src/lib/dns/tests/testdata/rrcode32_fromWire1
new file mode 100644
index 0000000..fb2818f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrcode32_fromWire1
@@ -0,0 +1,4 @@
+#
+# a 32 bit wire-format data (network byte order)
+#
+12345678
diff --git a/src/lib/dns/tests/testdata/rrcode32_fromWire2 b/src/lib/dns/tests/testdata/rrcode32_fromWire2
new file mode 100644
index 0000000..504d9d2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrcode32_fromWire2
@@ -0,0 +1,4 @@
+#
+# an incomplete segment for a 32 bit wire-format data
+#
+123456
diff --git a/src/lib/dns/tests/testdata/rrset_toWire1 b/src/lib/dns/tests/testdata/rrset_toWire1
new file mode 100644
index 0000000..8f81a0e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrset_toWire1
@@ -0,0 +1,23 @@
+#
+# Rendering an IN/A RRset containing 2 RRs:
+# test.example.com. 3600 IN A 192.0.2.1
+# test.example.com. 3600 IN A 192.0.2.2
+#
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# type/class: A = 1, IN = 1
+00 01 00 01
+# TTL: 3600
+00 00 0e 10
+#6 7
+# RDLENGTH: 4
+00 04
+# RDATA: 192.0.2.1
+c0 00 02 01
+#
+# 2nd RR: mostly the same except the RDATA
+04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+00 01 00 01
+00 00 0e 10
+00 04
+c0 00 02 02
diff --git a/src/lib/dns/tests/testdata/rrset_toWire2 b/src/lib/dns/tests/testdata/rrset_toWire2
new file mode 100644
index 0000000..ca6483f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrset_toWire2
@@ -0,0 +1,38 @@
+#
+# Rendering an IN/A RRset and NS RRset as follows:
+# test.example.com. 3600 IN A 192.0.2.1
+# test.example.com. 3600 IN A 192.0.2.2
+# example.com. 1D IN NS ns.example.com.
+# Names will be compressed when possible.
+#
+# 0 1 2 3 4 5
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# type/class: A = 1, IN = 1
+00 01 00 01
+# TTL: 3600
+00 00 0e 10
+#6 7
+# RDLENGTH: 4
+00 04
+# RDATA: 192.0.2.1
+c0 00 02 01
+#
+# 2nd RR: the owner name is compressed
+c0 00
+00 01 00 01
+00 00 0e 10
+00 04
+c0 00 02 02
+# 3rd RR: the owner name and NS name are compressed
+# pointing to the 5th octet of the owner name of the 1st RR
+c0 05
+# type/class: NS = 2, IN = 1
+00 02 00 01
+# TTL: 1D = 86400sec = 0x15180
+00 01 51 80
+# RDLENGTH: 5 octets
+00 05
+# NSDNAME: "ns." + compression pointer
+#(2) n s
+ 02 6e 73 c0 05
diff --git a/src/lib/dns/tests/testdata/rrset_toWire3 b/src/lib/dns/tests/testdata/rrset_toWire3
new file mode 100644
index 0000000..47f8e6b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrset_toWire3
@@ -0,0 +1,12 @@
+#
+# Rendering an empty IN/A RRset
+#
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# type/class: A = 1, ANY = 255
+00 01 00 ff
+# TTL: 3600
+00 00 0e 10
+#6 7
+# RDLENGTH: 0
+00 00
diff --git a/src/lib/dns/tests/testdata/rrset_toWire4 b/src/lib/dns/tests/testdata/rrset_toWire4
new file mode 100644
index 0000000..6fb409c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rrset_toWire4
@@ -0,0 +1,12 @@
+#
+# Rendering an empty IN/A RRset
+#
+#(4) t e s t (7) e x a m p l e (3) c o m .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# type/class: A = 1, ANY = 255
+00 01 00 fe
+# TTL: 3600
+00 00 0e 10
+#6 7
+# RDLENGTH: 0
+00 00
diff --git a/src/lib/dns/tests/testdata/tsig_verify1.spec b/src/lib/dns/tests/testdata/tsig_verify1.spec
new file mode 100644
index 0000000..687013a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify1.spec
@@ -0,0 +1,19 @@
+#
+# An example of signed AXFR request
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x3410
+arcount: 1
+[question]
+rrtype: AXFR
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8e951
+mac_size: 16
+mac: 0x35b2fd08268781634400c7c8a5533b13
+original_id: 0x3410
diff --git a/src/lib/dns/tests/testdata/tsig_verify1.wire b/src/lib/dns/tests/testdata/tsig_verify1.wire
new file mode 100644
index 0000000..b2d12f1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify1.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from tsig_verify1.spec
+###
+
+# Header Section
+# ID=13328 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0)
+3410 0000
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=example.com. QTYPE=AXFR(252) QCLASS=IN(1)
+076578616d706c6503636f6d00 00fc 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302915409 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8e951 012c
+# MAC Size=16 MAC=(see hex)
+0010 35b2fd08268781634400c7c8a5533b13
+# Original-ID=13328 Error=0
+3410 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify10.spec b/src/lib/dns/tests/testdata/tsig_verify10.spec
new file mode 100644
index 0000000..33ce83e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify10.spec
@@ -0,0 +1,22 @@
+#
+# A simple DNS query message with TSIG signed whose MAC is too short
+# (only 1 byte)
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 1
+mac: 0x22
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify10.wire b/src/lib/dns/tests/testdata/tsig_verify10.wire
new file mode 100644
index 0000000..9ffe4ea
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify10.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from tsig_verify10.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=43)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 002b
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=1 MAC=(see hex)
+0001 22
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify11.spec b/src/lib/dns/tests/testdata/tsig_verify11.spec
new file mode 100644
index 0000000..9927b48
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify11.spec
@@ -0,0 +1,24 @@
+#
+# A simple DNS query message with TSIG signed with truncated MAC
+# using common HMAC-SHA512-256
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-sha512
+time_signed: 0x4da8877a
+#mac_size: 64
+mac_size: 32
+#mac: 0xc4bc4053572d62dd1b26998111565c18056be773dedc6ecea60dff31db2f25966e5d9bafbaaed56efbd5ee2d7e2a12ede4caad630ddf69846c980409724da34e
+mac: 0xc4bc4053572d62dd1b26998111565c18056be773dedc6ecea60dff31db2f2596
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify11.wire b/src/lib/dns/tests/testdata/tsig_verify11.wire
new file mode 100644
index 0000000..f0a8f4f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify11.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from tsig_verify11.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=61)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003d
+# Algorithm=hmac-sha512 Time-Signed=1302890362 Fudge=300
+0b686d61632d73686135313200 00004da8877a 012c
+# MAC Size=32 MAC=(see hex)
+0020 c4bc4053572d62dd1b26998111565c18056be773dedc6ecea60dff31db2f2596
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify2.spec b/src/lib/dns/tests/testdata/tsig_verify2.spec
new file mode 100644
index 0000000..ff98ca3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify2.spec
@@ -0,0 +1,32 @@
+#
+# An example of signed AXFR response
+#
+
+[custom]
+sections: header:question:soa:tsig
+[header]
+id: 0x3410
+aa: 1
+qr: 1
+ancount: 1
+arcount: 1
+[question]
+rrtype: AXFR
+[soa]
+# note that names are compressed in this RR
+as_rr: True
+rr_name: ptr=12
+mname: ns.ptr=12
+rname: root.ptr=12
+serial: 2011041503
+refresh: 7200
+retry: 3600
+expire: 2592000
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8e951
+mac_size: 16
+mac: 0xbdd612cd2c7f9e0648bd6dc23713e83c
+original_id: 0x3410
diff --git a/src/lib/dns/tests/testdata/tsig_verify2.wire b/src/lib/dns/tests/testdata/tsig_verify2.wire
new file mode 100644
index 0000000..65f5f89
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify2.wire
@@ -0,0 +1,31 @@
+###
+### This data file was auto-generated from tsig_verify2.spec
+###
+
+# Header Section
+# ID=13328 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA
+3410 8400
+# QDCNT=1, ANCNT=1, NSCNT=0, ARCNT=1
+0001 0001 0000 0001
+
+# Question Section
+# QNAME=example.com. QTYPE=AXFR(252) QCLASS=IN(1)
+076578616d706c6503636f6d00 00fc 0001
+
+# SOA RR (QNAME=ptr=12 Class=IN(1) TTL=86400, RDLEN=32)
+c00c 0006 0001 00015180 0020
+# NNAME=ns.ptr=12 RNAME=root.ptr=12
+026e73c00c 04726f6f74c00c
+# SERIAL(2011041503) REFRESH(7200) RETRY(3600) EXPIRE(2592000) MINIMUM(1200)
+77de0edf 00001c20 00000e10 00278d00 000004b0
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302915409 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8e951 012c
+# MAC Size=16 MAC=(see hex)
+0010 bdd612cd2c7f9e0648bd6dc23713e83c
+# Original-ID=13328 Error=0
+3410 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify3.spec b/src/lib/dns/tests/testdata/tsig_verify3.spec
new file mode 100644
index 0000000..7e2f797
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify3.spec
@@ -0,0 +1,26 @@
+#
+# An example of signed AXFR response (continued)
+#
+
+[custom]
+sections: header:ns:tsig
+[header]
+id: 0x3410
+aa: 1
+qr: 1
+qdcount: 0
+ancount: 1
+arcount: 1
+[ns]
+# note that names are compressed in this RR
+as_rr: True
+rr_name: example.com.
+nsname: ns.ptr=12
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8e951
+mac_size: 16
+mac: 0x102458f7f62ddd7d638d746034130968
+original_id: 0x3410
diff --git a/src/lib/dns/tests/testdata/tsig_verify3.wire b/src/lib/dns/tests/testdata/tsig_verify3.wire
new file mode 100644
index 0000000..c479ac3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify3.wire
@@ -0,0 +1,25 @@
+###
+### This data file was auto-generated from tsig_verify3.spec
+###
+
+# Header Section
+# ID=13328 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA
+3410 8400
+# QDCNT=0, ANCNT=1, NSCNT=0, ARCNT=1
+0000 0001 0000 0001
+
+# NS RR (QNAME=example.com. Class=IN(1) TTL=86400, RDLEN=5)
+076578616d706c6503636f6d00 0002 0001 00015180 0005
+# NS name=ns.ptr=12
+026e73c00c
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302915409 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8e951 012c
+# MAC Size=16 MAC=(see hex)
+0010 102458f7f62ddd7d638d746034130968
+# Original-ID=13328 Error=0
+3410 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify4.spec b/src/lib/dns/tests/testdata/tsig_verify4.spec
new file mode 100644
index 0000000..4ffbbcf
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify4.spec
@@ -0,0 +1,27 @@
+#
+# An example of signed DNS response with bogus MAC
+#
+
+[custom]
+sections: header:question:a:tsig
+[header]
+id: 0x2d65
+aa: 1
+qr: 1
+rd: 1
+ancount: 1
+arcount: 1
+[question]
+name: www.example.com
+[a]
+as_rr: True
+rr_name: ptr=12
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+# bogus MAC
+mac: 0xdeadbeefdeadbeefdeadbeefdeadbeef
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify4.wire b/src/lib/dns/tests/testdata/tsig_verify4.wire
new file mode 100644
index 0000000..de5e050
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify4.wire
@@ -0,0 +1,29 @@
+###
+### This data file was auto-generated from tsig_verify4.spec
+###
+
+# Header Section
+# ID=11621 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA RD
+2d65 8500
+# QDCNT=1, ANCNT=1, NSCNT=0, ARCNT=1
+0001 0001 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# A RR (QNAME=ptr=12 Class=IN(1) TTL=86400, RDLEN=4)
+c00c 0001 0001 00015180 0004
+# Address=192.0.2.1
+c0000201
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 deadbeefdeadbeefdeadbeefdeadbeef
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify5.spec b/src/lib/dns/tests/testdata/tsig_verify5.spec
new file mode 100644
index 0000000..a6cc643
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify5.spec
@@ -0,0 +1,26 @@
+#
+# An example of signed DNS response
+#
+
+[custom]
+sections: header:question:a:tsig
+[header]
+id: 0x2d65
+aa: 1
+qr: 1
+rd: 1
+ancount: 1
+arcount: 1
+[question]
+name: www.example.com
+[a]
+as_rr: True
+rr_name: ptr=12
+[tsig]
+as_rr: True
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x8fcda66a7cd1a3b9948eb1869d384a9f
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify5.wire b/src/lib/dns/tests/testdata/tsig_verify5.wire
new file mode 100644
index 0000000..3cfb89b
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify5.wire
@@ -0,0 +1,29 @@
+###
+### This data file was auto-generated from tsig_verify5.spec
+###
+
+# Header Section
+# ID=11621 QR=Response Opcode=QUERY(0) Rcode=NOERROR(0) AA RD
+2d65 8500
+# QDCNT=1, ANCNT=1, NSCNT=0, ARCNT=1
+0001 0001 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# A RR (QNAME=ptr=12 Class=IN(1) TTL=86400, RDLEN=4)
+c00c 0001 0001 00015180 0004
+# Address=192.0.2.1
+c0000201
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 8fcda66a7cd1a3b9948eb1869d384a9f
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify6.spec b/src/lib/dns/tests/testdata/tsig_verify6.spec
new file mode 100644
index 0000000..32e0818
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify6.spec
@@ -0,0 +1,21 @@
+#
+# Forwarded DNS query message with TSIG signed (header ID != orig ID)
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x1035
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify6.wire b/src/lib/dns/tests/testdata/tsig_verify6.wire
new file mode 100644
index 0000000..9e3e5b4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify6.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from tsig_verify6.spec
+###
+
+# Header Section
+# ID=4149 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+1035 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify7.spec b/src/lib/dns/tests/testdata/tsig_verify7.spec
new file mode 100644
index 0000000..377578e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify7.spec
@@ -0,0 +1,21 @@
+#
+# DNS query message with TSIG that has empty MAC (invalidly)
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 0
+mac: ''
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify7.wire b/src/lib/dns/tests/testdata/tsig_verify7.wire
new file mode 100644
index 0000000..4de7d24
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify7.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from tsig_verify7.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=42)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 002a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=0 MAC=(see hex)
+0000
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify8.spec b/src/lib/dns/tests/testdata/tsig_verify8.spec
new file mode 100644
index 0000000..5432d4a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify8.spec
@@ -0,0 +1,23 @@
+#
+# DNS query message with TSIG that has empty MAC + BADKEY error
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 0
+mac: ''
+# 17: BADKEY
+error: 17
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify8.wire b/src/lib/dns/tests/testdata/tsig_verify8.wire
new file mode 100644
index 0000000..50845eb
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify8.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from tsig_verify8.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=42)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 002a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=0 MAC=(see hex)
+0000
+# Original-ID=11621 Error=17
+2d65 0011
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsig_verify9.spec b/src/lib/dns/tests/testdata/tsig_verify9.spec
new file mode 100644
index 0000000..5888455
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify9.spec
@@ -0,0 +1,21 @@
+#
+# A simple DNS query message with TSIG signed, but TSIG key and algorithm
+# names have upper case characters (unusual)
+#
+
+[custom]
+sections: header:question:tsig
+[header]
+id: 0x2d65
+rd: 1
+arcount: 1
+[question]
+name: www.example.com
+[tsig]
+as_rr: True
+rr_name: WWW.EXAMPLE.COM
+algorithm: HMAC-MD5.SIG-ALG.REG.INT
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0x227026ad297beee721ce6c6fff1e9ef3
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsig_verify9.wire b/src/lib/dns/tests/testdata/tsig_verify9.wire
new file mode 100644
index 0000000..163fcee
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsig_verify9.wire
@@ -0,0 +1,24 @@
+###
+### This data file was auto-generated from tsig_verify9.spec
+###
+
+# Header Section
+# ID=11621 QR=Query Opcode=QUERY(0) Rcode=NOERROR(0) RD
+2d65 0100
+# QDCNT=1, ANCNT=0, NSCNT=0, ARCNT=1
+0001 0000 0000 0001
+
+# Question Section
+# QNAME=www.example.com QTYPE=A(1) QCLASS=IN(1)
+03777777076578616d706c6503636f6d00 0001 0001
+
+# TSIG RR (QNAME=WWW.EXAMPLE.COM Class=ANY(255) TTL=0, RDLEN=58)
+03575757074558414d504c4503434f4d00 00fa 00ff 00000000 003a
+# Algorithm=HMAC-MD5.SIG-ALG.REG.INT Time-Signed=1302890362 Fudge=300
+08484d41432d4d4435075349472d414c470352454703494e5400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 227026ad297beee721ce6c6fff1e9ef3
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsigrecord_toWire1.spec b/src/lib/dns/tests/testdata/tsigrecord_toWire1.spec
new file mode 100644
index 0000000..a25dc46
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsigrecord_toWire1.spec
@@ -0,0 +1,16 @@
+#
+# A simple TSIG RR (some of the parameters are taken from a live example
+# and don't have a specific meaning)
+#
+
+[custom]
+sections: tsig
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0xdadadadadadadadadadadadadadadada
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsigrecord_toWire1.wire b/src/lib/dns/tests/testdata/tsigrecord_toWire1.wire
new file mode 100644
index 0000000..a125e3d
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsigrecord_toWire1.wire
@@ -0,0 +1,14 @@
+###
+### This data file was auto-generated from tsigrecord_toWire1.spec
+###
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 dadadadadadadadadadadadadadadada
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/testdata/tsigrecord_toWire2.spec b/src/lib/dns/tests/testdata/tsigrecord_toWire2.spec
new file mode 100644
index 0000000..f667e4c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsigrecord_toWire2.spec
@@ -0,0 +1,19 @@
+#
+# TSIG RR after some names that could (unexpectedly) cause name compression
+#
+
+[custom]
+sections: name/1:name/2:tsig
+[name/1]
+name: hmac-md5.sig-alg.reg.int
+[name/2]
+name: foo.example.com
+[tsig]
+as_rr: True
+# TSIG QNAME won't be compressed
+rr_name: www.example.com
+algorithm: hmac-md5
+time_signed: 0x4da8877a
+mac_size: 16
+mac: 0xdadadadadadadadadadadadadadadada
+original_id: 0x2d65
diff --git a/src/lib/dns/tests/testdata/tsigrecord_toWire2.wire b/src/lib/dns/tests/testdata/tsigrecord_toWire2.wire
new file mode 100644
index 0000000..980e1f1
--- /dev/null
+++ b/src/lib/dns/tests/testdata/tsigrecord_toWire2.wire
@@ -0,0 +1,20 @@
+###
+### This data file was auto-generated from tsigrecord_toWire2.spec
+###
+
+# DNS Name: hmac-md5.sig-alg.reg.int
+08686d61632d6d6435077369672d616c670372656703696e7400
+
+# DNS Name: foo.example.com
+03666f6f076578616d706c6503636f6d00
+
+# TSIG RR (QNAME=www.example.com Class=ANY(255) TTL=0, RDLEN=58)
+03777777076578616d706c6503636f6d00 00fa 00ff 00000000 003a
+# Algorithm=hmac-md5 Time-Signed=1302890362 Fudge=300
+08686d61632d6d6435077369672d616c670372656703696e7400 00004da8877a 012c
+# MAC Size=16 MAC=(see hex)
+0010 dadadadadadadadadadadadadadadada
+# Original-ID=11621 Error=0
+2d65 0000
+# Other-Len=0 Other-Data=(see hex)
+0000
diff --git a/src/lib/dns/tests/tsig_unittest.cc b/src/lib/dns/tests/tsig_unittest.cc
new file mode 100644
index 0000000..fde67bc
--- /dev/null
+++ b/src/lib/dns/tests/tsig_unittest.cc
@@ -0,0 +1,1185 @@
+// Copyright (C) 2011-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <time.h>
+#include <string>
+#include <stdexcept>
+#include <vector>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <gtest/gtest.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+#include <util/unittests/newhook.h>
+#include <util/time_utilities.h>
+
+#include <dns/message.h>
+#include <dns/messagerenderer.h>
+#include <dns/question.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+#include <dns/tsig.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigrecord.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata;
+using namespace isc::dns::rdata::any;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+// @note: blocks and SCOPED_TRACE can make buggy cppchecks raise
+// a spurious syntax error...
+
+// See dnssectime.cc
+namespace isc {
+namespace util {
+namespace detail {
+extern int64_t (*gettimeFunction)();
+}
+}
+}
+
+namespace {
+// See dnssectime_unittest.cc
+template <int64_t NOW>
+int64_t
+testGetTime() {
+ return (NOW);
+}
+
+// Thin wrapper around TSIGContext to allow access to the
+// update method.
+class TestTSIGContext : public TSIGContext {
+public:
+ TestTSIGContext(const TSIGKey& key) :
+ TSIGContext(key)
+ {}
+ TestTSIGContext(const Name& key_name, const Name& algorithm_name,
+ const TSIGKeyRing& keyring) :
+ TSIGContext(key_name, algorithm_name, keyring)
+ {}
+ void update(const void* const data, size_t len) {
+ TSIGContext::update(data, len);
+ }
+};
+
+class TSIGTest : public ::testing::Test {
+protected:
+ TSIGTest() :
+ tsig_ctx(NULL), qid(0x2d65), test_name("www.example.com"),
+ badkey_name("badkey.example.com"), test_class(RRClass::IN()),
+ test_ttl(86400), message(Message::RENDER),
+ dummy_data(1024, 0xdd), // should be sufficiently large for all tests
+ dummy_record(badkey_name, TSIG(TSIGKey::HMACMD5_NAME(), 0x4da8877a,
+ TSIGContext::DEFAULT_FUDGE, 0, NULL, qid, 0, 0, NULL))
+ {
+ // Make sure we use the system time by default so that we won't be
+ // confused due to other tests that tweak the time.
+ isc::util::detail::gettimeFunction = NULL;
+
+ decodeBase64("SFuWd/q99SzF8Yzd1QbB9g==", secret);
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACMD5_NAME(),
+ &secret[0],
+ secret.size())));
+ tsig_verify_ctx.reset(new TSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACMD5_NAME(),
+ &secret[0],
+ secret.size())));
+ }
+ ~TSIGTest() {
+ isc::util::detail::gettimeFunction = NULL;
+ }
+
+ // Many of the tests below create some DNS message and sign it under
+ // some specific TSIG context. This helper method unifies the common
+ // logic with slightly different parameters.
+ ConstTSIGRecordPtr createMessageAndSign(uint16_t qid, const Name& qname,
+ TSIGContext* ctx,
+ unsigned int message_flags =
+ RD_FLAG,
+ RRType qtype = RRType::A(),
+ const char* answer_data = NULL,
+ const RRType* answer_type = NULL,
+ bool add_question = true,
+ Rcode rcode = Rcode::NOERROR());
+
+ void createMessageFromFile(const char* datafile);
+
+ // bit-wise constant flags to configure DNS header flags for test
+ // messages.
+ static const unsigned int QR_FLAG = 0x1;
+ static const unsigned int AA_FLAG = 0x2;
+ static const unsigned int RD_FLAG = 0x4;
+
+ boost::scoped_ptr<TestTSIGContext> tsig_ctx;
+ boost::scoped_ptr<TSIGContext> tsig_verify_ctx;
+ TSIGKeyRing keyring;
+ const uint16_t qid;
+ const Name test_name;
+ const Name badkey_name;
+ const RRClass test_class;
+ const RRTTL test_ttl;
+ Message message;
+ MessageRenderer renderer;
+ vector<uint8_t> secret;
+ vector<uint8_t> dummy_data;
+ const TSIGRecord dummy_record;
+ vector<uint8_t> received_data;
+};
+
+ConstTSIGRecordPtr
+TSIGTest::createMessageAndSign(uint16_t id, const Name& qname,
+ TSIGContext* ctx, unsigned int message_flags,
+ RRType qtype, const char* answer_data,
+ const RRType* answer_type, bool add_question,
+ Rcode rcode)
+{
+ message.clear(Message::RENDER);
+ message.setQid(id);
+ message.setOpcode(Opcode::QUERY());
+ message.setRcode(rcode);
+ if ((message_flags & QR_FLAG) != 0) {
+ message.setHeaderFlag(Message::HEADERFLAG_QR);
+ }
+ if ((message_flags & AA_FLAG) != 0) {
+ message.setHeaderFlag(Message::HEADERFLAG_AA);
+ }
+ if ((message_flags & RD_FLAG) != 0) {
+ message.setHeaderFlag(Message::HEADERFLAG_RD);
+ }
+ if (add_question) {
+ message.addQuestion(Question(qname, test_class, qtype));
+ }
+ if (answer_data != NULL) {
+ if (answer_type == NULL) {
+ answer_type = &qtype;
+ }
+ RRsetPtr answer_rrset(new RRset(qname, test_class, *answer_type,
+ test_ttl));
+ answer_rrset->addRdata(createRdata(*answer_type, test_class,
+ answer_data));
+ message.addRRset(Message::SECTION_ANSWER, answer_rrset);
+ }
+ renderer.clear();
+
+ TSIGContext::State expected_new_state =
+ (ctx->getState() == TSIGContext::INIT) ?
+ TSIGContext::SENT_REQUEST : TSIGContext::SENT_RESPONSE;
+
+ message.toWire(renderer, ctx);
+
+ message.clear(Message::PARSE);
+ InputBuffer buffer(renderer.getData(), renderer.getLength());
+ message.fromWire(buffer);
+
+ EXPECT_EQ(expected_new_state, ctx->getState());
+
+ return (ConstTSIGRecordPtr(new TSIGRecord(*message.getTSIGRecord())));
+}
+
+void
+TSIGTest::createMessageFromFile(const char* datafile) {
+ message.clear(Message::PARSE);
+ received_data.clear();
+ UnitTestUtil::readWireData(datafile, received_data);
+ InputBuffer buffer(&received_data[0], received_data.size());
+ message.fromWire(buffer);
+}
+
+void
+commonSignChecks(ConstTSIGRecordPtr tsig, uint16_t expected_qid,
+ uint64_t expected_timesigned,
+ const uint8_t* expected_mac, size_t expected_maclen,
+ uint16_t expected_error = 0,
+ uint16_t expected_otherlen = 0,
+ const uint8_t* expected_otherdata = NULL,
+ const Name& expected_algorithm = TSIGKey::HMACMD5_NAME())
+{
+ ASSERT_TRUE(tsig != NULL);
+ const TSIG& tsig_rdata = tsig->getRdata();
+
+ EXPECT_EQ(expected_algorithm, tsig_rdata.getAlgorithm());
+ EXPECT_EQ(expected_timesigned, tsig_rdata.getTimeSigned());
+ EXPECT_EQ(300, tsig_rdata.getFudge());
+ EXPECT_EQ(expected_maclen, tsig_rdata.getMACSize());
+ matchWireData(expected_mac, expected_maclen,
+ tsig_rdata.getMAC(), tsig_rdata.getMACSize());
+
+ EXPECT_EQ(expected_qid, tsig_rdata.getOriginalID());
+ EXPECT_EQ(expected_error, tsig_rdata.getError());
+ EXPECT_EQ(expected_otherlen, tsig_rdata.getOtherLen());
+ matchWireData(expected_otherdata, expected_otherlen,
+ tsig_rdata.getOtherData(), tsig_rdata.getOtherLen());
+}
+
+void
+commonVerifyChecks(TSIGContext& ctx, const TSIGRecord* record,
+ const void* data, size_t data_len, TSIGError expected_error,
+ TSIGContext::State expected_new_state =
+ TSIGContext::VERIFIED_RESPONSE,
+ bool last_should_throw = false)
+{
+ EXPECT_EQ(expected_error, ctx.verify(record, data, data_len));
+ EXPECT_EQ(expected_error, ctx.getError());
+ EXPECT_EQ(expected_new_state, ctx.getState());
+ if (last_should_throw) {
+ EXPECT_THROW(ctx.lastHadSignature(), TSIGContextError);
+ } else {
+ EXPECT_EQ(record != NULL, ctx.lastHadSignature());
+ }
+}
+
+TEST_F(TSIGTest, initialState) {
+ // Until signing or verifying, the state should be INIT
+ EXPECT_EQ(TSIGContext::INIT, tsig_ctx->getState());
+
+ // And there should be no error code.
+ EXPECT_EQ(TSIGError(Rcode::NOERROR()), tsig_ctx->getError());
+
+ // Nothing verified yet
+ EXPECT_THROW(tsig_ctx->lastHadSignature(), TSIGContextError);
+}
+
+TEST_F(TSIGTest, constructFromKeyRing) {
+ // Construct a TSIG context with an empty key ring. Key shouldn't be
+ // found, and the BAD_KEY error should be recorded.
+ TSIGContext ctx1(test_name, TSIGKey::HMACMD5_NAME(), keyring);
+ EXPECT_EQ(TSIGContext::INIT, ctx1.getState());
+ EXPECT_EQ(TSIGError::BAD_KEY(), ctx1.getError());
+
+ // Add a matching key (we don't use the secret so leave it empty), and
+ // construct it again. This time it should be constructed with a valid
+ // key.
+ keyring.add(TSIGKey(test_name, TSIGKey::HMACMD5_NAME(), NULL, 0));
+ TSIGContext ctx2(test_name, TSIGKey::HMACMD5_NAME(), keyring);
+ EXPECT_EQ(TSIGContext::INIT, ctx2.getState());
+ EXPECT_EQ(TSIGError::NOERROR(), ctx2.getError());
+
+ // Similar to the first case except that the key ring isn't empty but
+ // it doesn't contain a matching key.
+ TSIGContext ctx3(test_name, TSIGKey::HMACSHA1_NAME(), keyring);
+ EXPECT_EQ(TSIGContext::INIT, ctx3.getState());
+ EXPECT_EQ(TSIGError::BAD_KEY(), ctx3.getError());
+
+ TSIGContext ctx4(Name("different-key.example"), TSIGKey::HMACMD5_NAME(),
+ keyring);
+ EXPECT_EQ(TSIGContext::INIT, ctx4.getState());
+ EXPECT_EQ(TSIGError::BAD_KEY(), ctx4.getError());
+
+ // "Unknown" algorithm name will result in BADKEY, too.
+ TSIGContext ctx5(test_name, Name("unknown.algorithm"), keyring);
+ EXPECT_EQ(TSIGContext::INIT, ctx5.getState());
+ EXPECT_EQ(TSIGError::BAD_KEY(), ctx5.getError());
+}
+
+// Example output generated by
+// "dig -y www.example.com:SFuWd/q99SzF8Yzd1QbB9g== www.example.com
+// QID: 0x2d65
+// Time Signed: 0x00004da8877a
+// MAC: 227026ad297beee721ce6c6fff1e9ef3
+const uint8_t common_expected_mac[] = {
+ 0x22, 0x70, 0x26, 0xad, 0x29, 0x7b, 0xee, 0xe7,
+ 0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3
+};
+TEST_F(TSIGTest, sign) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ {
+ SCOPED_TRACE("Sign test for query");
+ commonSignChecks(createMessageAndSign(qid, test_name, tsig_ctx.get()),
+ qid, 0x4da8877a, common_expected_mac,
+ sizeof(common_expected_mac));
+ }
+}
+
+// Same test as sign, but specifying the key name with upper-case (i.e.
+// non canonical) characters. The digest must be the same. It should actually
+// be ensured at the level of TSIGKey, but we confirm that at this level, too.
+TEST_F(TSIGTest, signUsingUpperCasedKeyName) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ TSIGContext cap_ctx(TSIGKey(Name("WWW.EXAMPLE.COM"),
+ TSIGKey::HMACMD5_NAME(),
+ &secret[0], secret.size()));
+
+ {
+ SCOPED_TRACE("Sign test for query using non canonical key name");
+ commonSignChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid,
+ 0x4da8877a, common_expected_mac,
+ sizeof(common_expected_mac));
+ }
+}
+
+// Same as the previous test, but for the algorithm name.
+TEST_F(TSIGTest, signUsingUpperCasedAlgorithmName) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ TSIGContext cap_ctx(TSIGKey(test_name,
+ Name("HMAC-md5.SIG-alg.REG.int"),
+ &secret[0], secret.size()));
+
+ {
+ SCOPED_TRACE("Sign test for query using non canonical algorithm name");
+ commonSignChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid,
+ 0x4da8877a, common_expected_mac,
+ sizeof(common_expected_mac));
+ }
+}
+
+TEST_F(TSIGTest, signAtActualTime) {
+ // Sign the message using the actual time, and check the accuracy of it.
+ // We cannot reasonably predict the expected MAC, so don't bother to
+ // check it.
+ const uint64_t now = static_cast<uint64_t>(time(NULL));
+
+ {
+ SCOPED_TRACE("Sign test for query at actual time");
+ ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+ tsig_ctx.get());
+ const TSIG& tsig_rdata = tsig->getRdata();
+
+ // Check the resulted time signed is in the range of [now, now + 5]
+ // (5 is an arbitrary choice). Note that due to the order of the call
+ // to time() and sign(), time signed must not be smaller than the
+ // current time.
+ EXPECT_LE(now, tsig_rdata.getTimeSigned());
+ EXPECT_GE(now + 5, tsig_rdata.getTimeSigned());
+ }
+}
+
+TEST_F(TSIGTest, signBadData) {
+ // some specific bad data should be rejected proactively.
+ const unsigned char dummy_data = 0;
+ EXPECT_THROW(tsig_ctx->sign(0, NULL, 10), InvalidParameter);
+ EXPECT_THROW(tsig_ctx->sign(0, &dummy_data, 0), InvalidParameter);
+}
+
+TEST_F(TSIGTest, verifyBadData) {
+ // the data must at least hold the DNS message header and the specified
+ // TSIG.
+ EXPECT_THROW(tsig_ctx->verify(&dummy_record, &dummy_data[0],
+ 12 + dummy_record.getLength() - 1),
+ InvalidParameter);
+
+ // Still nothing verified
+ EXPECT_THROW(tsig_ctx->lastHadSignature(), TSIGContextError);
+
+ // And the data must not be NULL.
+ EXPECT_THROW(tsig_ctx->verify(&dummy_record, NULL,
+ 12 + dummy_record.getLength()),
+ InvalidParameter);
+
+ // Still nothing verified
+ EXPECT_THROW(tsig_ctx->lastHadSignature(), TSIGContextError);
+
+}
+
+#ifdef ENABLE_CUSTOM_OPERATOR_NEW
+// We enable this test only when we enable custom new/delete at build time
+// We could enable/disable the test runtime using the gtest filter, but
+// we'd basically like to minimize the number of disabled tests (they
+// should generally be considered tests that temporarily fail and should
+// be fixed).
+TEST_F(TSIGTest, signExceptionSafety) {
+ // Check sign() provides the strong exception guarantee for the simpler
+ // case (with a key error and empty MAC). The general case is more
+ // complicated and involves more memory allocation, so the test result
+ // won't be reliable.
+
+ commonVerifyChecks(*tsig_verify_ctx, &dummy_record, &dummy_data[0],
+ dummy_data.size(), TSIGError::BAD_KEY(),
+ TSIGContext::RECEIVED_REQUEST);
+
+ try {
+ int dummydata;
+ isc::util::unittests::force_throw_on_new = true;
+ isc::util::unittests::throw_size_on_new = sizeof(TSIGRecord);
+ tsig_verify_ctx->sign(0, &dummydata, sizeof(dummydata));
+ isc::util::unittests::force_throw_on_new = false;
+ ASSERT_FALSE(true) << "Expected throw on new, but it didn't happen";
+ } catch (const std::bad_alloc&) {
+ isc::util::unittests::force_throw_on_new = false;
+
+ // sign() threw, so the state should still be RECEIVED_REQUEST
+ EXPECT_EQ(TSIGContext::RECEIVED_REQUEST, tsig_verify_ctx->getState());
+ }
+ isc::util::unittests::force_throw_on_new = false;
+}
+#endif // ENABLE_CUSTOM_OPERATOR_NEW
+
+// Same test as "sign" but use a different algorithm just to confirm we don't
+// naively hardcode constants specific to a particular algorithm.
+// Test data generated by
+// "dig -y hmac-sha1:www.example.com:MA+QDhXbyqUak+qnMFyTyEirzng= www.example.com"
+// QID: 0x0967, RDflag
+// Current Time: 00004da8be86
+// Time Signed: 00004dae7d5f
+// HMAC Size: 20
+// HMAC: 415340c7daf824ed684ee586f7b5a67a2febc0d3
+TEST_F(TSIGTest, signUsingHMACSHA1) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>;
+
+ secret.clear();
+ decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret);
+ TSIGContext sha1_ctx(TSIGKey(test_name, TSIGKey::HMACSHA1_NAME(),
+ &secret[0], secret.size()));
+
+ const uint16_t sha1_qid = 0x0967;
+ const uint8_t expected_mac[] = {
+ 0x41, 0x53, 0x40, 0xc7, 0xda, 0xf8, 0x24, 0xed, 0x68, 0x4e,
+ 0xe5, 0x86, 0xf7, 0xb5, 0xa6, 0x7a, 0x2f, 0xeb, 0xc0, 0xd3
+ };
+ {
+ SCOPED_TRACE("Sign test using HMAC-SHA1");
+ commonSignChecks(createMessageAndSign(sha1_qid, test_name, &sha1_ctx),
+ sha1_qid, 0x4dae7d5f, expected_mac,
+ sizeof(expected_mac), 0, 0, NULL,
+ TSIGKey::HMACSHA1_NAME());
+ }
+}
+
+TEST_F(TSIGTest, signUsingHMACSHA224) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>;
+
+ secret.clear();
+ decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret);
+ TSIGContext sha1_ctx(TSIGKey(test_name, TSIGKey::HMACSHA224_NAME(),
+ &secret[0], secret.size()));
+
+ const uint16_t sha1_qid = 0x0967;
+ const uint8_t expected_mac[] = {
+ 0x3b, 0x93, 0xd3, 0xc5, 0xf9, 0x64, 0xb9, 0xc5, 0x00, 0x35,
+ 0x02, 0x69, 0x9f, 0xfc, 0x44, 0xd6, 0xe2, 0x66, 0xf4, 0x08,
+ 0xef, 0x33, 0xa2, 0xda, 0xa1, 0x48, 0x71, 0xd3
+ };
+ {
+ SCOPED_TRACE("Sign test using HMAC-SHA224");
+ commonSignChecks(createMessageAndSign(sha1_qid, test_name, &sha1_ctx),
+ sha1_qid, 0x4dae7d5f, expected_mac,
+ sizeof(expected_mac), 0, 0, NULL,
+ TSIGKey::HMACSHA224_NAME());
+ }
+}
+
+// The first part of this test checks verifying the signed query used for
+// the "sign" test.
+// The second part of this test generates a signed response to the signed
+// query as follows:
+// Answer: www.example.com. 86400 IN A 192.0.2.1
+// MAC: 8fcda66a7cd1a3b9948eb1869d384a9f
+TEST_F(TSIGTest, verifyThenSignResponse) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ // This test data for the message test has the same wire format data
+ // as the message used in the "sign" test.
+ createMessageFromFile("message_toWire2.wire");
+ {
+ SCOPED_TRACE("Verify test for request");
+ commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST);
+ }
+
+ // Transform the original message to a response, then sign the response
+ // with the context of "verified state".
+ ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+ tsig_verify_ctx.get(),
+ QR_FLAG|AA_FLAG|RD_FLAG,
+ RRType::A(), "192.0.2.1");
+ const uint8_t expected_mac[] = {
+ 0x8f, 0xcd, 0xa6, 0x6a, 0x7c, 0xd1, 0xa3, 0xb9,
+ 0x94, 0x8e, 0xb1, 0x86, 0x9d, 0x38, 0x4a, 0x9f
+ };
+ {
+ SCOPED_TRACE("Sign test for response");
+ commonSignChecks(tsig, qid, 0x4da8877a, expected_mac,
+ sizeof(expected_mac));
+ }
+}
+
+TEST_F(TSIGTest, verifyUpperCaseNames) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ // This test data for the message test has the same wire format data
+ // as the message used in the "sign" test.
+ createMessageFromFile("tsig_verify9.wire");
+ {
+ SCOPED_TRACE("Verify test for request");
+ commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST);
+ }
+}
+
+TEST_F(TSIGTest, verifyForwardedMessage) {
+ // Similar to the first part of the previous test, but this test emulates
+ // the "forward" case, where the ID of the Header and the original ID in
+ // TSIG is different.
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ createMessageFromFile("tsig_verify6.wire");
+ {
+ SCOPED_TRACE("Verify test for forwarded request");
+ commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST);
+ }
+}
+
+// Example of signing multiple messages in a single TCP stream,
+// taken from data using BIND 9's "one-answer" transfer-format.
+// Request:
+// QID: 0x3410, flags (none)
+// Question: example.com/IN/AXFR
+// Time Signed: 0x4da8e951
+// MAC: 35b2fd08268781634400c7c8a5533b13
+// First message:
+// QID: 0x3410, flags QR, AA
+// Question: example.com/IN/AXFR
+// Answer: example.com. 86400 IN SOA ns.example.com. root.example.com. (
+// 2011041503 7200 3600 2592000 1200)
+// MAC: bdd612cd2c7f9e0648bd6dc23713e83c
+// Second message:
+// Answer: example.com. 86400 IN NS ns.example.com.
+// MAC: 102458f7f62ddd7d638d746034130968
+TEST_F(TSIGTest, signContinuation) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8e951>;
+
+ const uint16_t axfr_qid = 0x3410;
+ const Name zone_name("example.com");
+
+ // Create and sign the AXFR request
+ ConstTSIGRecordPtr tsig = createMessageAndSign(axfr_qid, zone_name,
+ tsig_ctx.get(), 0,
+ RRType::AXFR());
+ // Then verify it (the wire format test data should contain the same
+ // message data, and verification should succeed).
+ received_data.clear();
+ UnitTestUtil::readWireData("tsig_verify1.wire", received_data);
+ {
+ SCOPED_TRACE("Verify AXFR query");
+ commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &received_data[0],
+ received_data.size(), TSIGError::NOERROR(),
+ TSIGContext::RECEIVED_REQUEST);
+ }
+
+ // Create and sign the first response message
+ tsig = createMessageAndSign(axfr_qid, zone_name, tsig_verify_ctx.get(),
+ AA_FLAG|QR_FLAG, RRType::AXFR(),
+ "ns.example.com. root.example.com. "
+ "2011041503 7200 3600 2592000 1200",
+ &RRType::SOA());
+
+ // Then verify it at the requester side.
+ received_data.clear();
+ UnitTestUtil::readWireData("tsig_verify2.wire", received_data);
+ {
+ SCOPED_TRACE("Verify first AXFR response");
+ commonVerifyChecks(*tsig_ctx, tsig.get(), &received_data[0],
+ received_data.size(), TSIGError::NOERROR());
+ }
+
+ // Create and sign the second response message
+ const uint8_t expected_mac[] = {
+ 0x10, 0x24, 0x58, 0xf7, 0xf6, 0x2d, 0xdd, 0x7d,
+ 0x63, 0x8d, 0x74, 0x60, 0x34, 0x13, 0x09, 0x68
+ };
+ {
+ SCOPED_TRACE("Sign test for continued response in TCP stream");
+ tsig = createMessageAndSign(axfr_qid, zone_name, tsig_verify_ctx.get(),
+ AA_FLAG|QR_FLAG, RRType::AXFR(),
+ "ns.example.com.", &RRType::NS(), false);
+ commonSignChecks(tsig, axfr_qid, 0x4da8e951, expected_mac,
+ sizeof(expected_mac));
+ }
+
+ // Then verify it at the requester side.
+ received_data.clear();
+ UnitTestUtil::readWireData("tsig_verify3.wire", received_data);
+ {
+ SCOPED_TRACE("Verify second AXFR response");
+ commonVerifyChecks(*tsig_ctx, tsig.get(), &received_data[0],
+ received_data.size(), TSIGError::NOERROR());
+ }
+}
+
+// BADTIME example, taken from data using specially hacked BIND 9's nsupdate
+// Query:
+// QID: 0x1830, RD flag
+// Current Time: 00004da8be86
+// Time Signed: 00004da8b9d6
+// Question: www.example.com/IN/SOA
+//(mac) 8406 7d50 b8e7 d054 3d50 5bd9 de2a bb68
+// Response:
+// QRbit, RCODE=9(NOTAUTH)
+// Time Signed: 00004da8b9d6 (the one in the query)
+// MAC: d4b043f6f44495ec8a01260e39159d76
+// Error: 0x12 (BADTIME), Other Len: 6
+// Other data: 00004da8be86
+TEST_F(TSIGTest, badtimeResponse) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
+
+ const uint16_t test_qid = 0x7fc4;
+ ConstTSIGRecordPtr tsig = createMessageAndSign(test_qid, test_name,
+ tsig_ctx.get(), 0,
+ RRType::SOA());
+
+ // "advance the clock" and try validating, which should fail due to BADTIME
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8be86>;
+ {
+ SCOPED_TRACE("Verify resulting in BADTIME due to expired SIG");
+ commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &dummy_data[0],
+ dummy_data.size(), TSIGError::BAD_TIME(),
+ TSIGContext::RECEIVED_REQUEST);
+ }
+
+ // make and sign a response in the context of TSIG error.
+ tsig = createMessageAndSign(test_qid, test_name, tsig_verify_ctx.get(),
+ QR_FLAG, RRType::SOA(), NULL, NULL,
+ true, Rcode::NOTAUTH());
+ const uint8_t expected_otherdata[] = { 0, 0, 0x4d, 0xa8, 0xbe, 0x86 };
+ const uint8_t expected_mac[] = {
+ 0xd4, 0xb0, 0x43, 0xf6, 0xf4, 0x44, 0x95, 0xec,
+ 0x8a, 0x01, 0x26, 0x0e, 0x39, 0x15, 0x9d, 0x76
+ };
+ {
+ SCOPED_TRACE("Sign test for response with BADTIME");
+ commonSignChecks(tsig, message.getQid(), 0x4da8b9d6,
+ expected_mac, sizeof(expected_mac),
+ 18, // error: BADTIME
+ sizeof(expected_otherdata),
+ expected_otherdata);
+ }
+}
+
+TEST_F(TSIGTest, badtimeResponse2) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
+
+ ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+ tsig_ctx.get(), 0,
+ RRType::SOA());
+
+ // "rewind the clock" and try validating, which should fail due to BADTIME
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 600>;
+ {
+ SCOPED_TRACE("Verify resulting in BADTIME due to too future SIG");
+ commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &dummy_data[0],
+ dummy_data.size(), TSIGError::BAD_TIME(),
+ TSIGContext::RECEIVED_REQUEST);
+ }
+}
+
+TEST_F(TSIGTest, badtimeBoundaries) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>;
+
+ // Test various boundary conditions. We intentionally use the magic
+ // number of 300 instead of the constant variable for testing.
+ // In the okay cases, signature is not correct, but it's sufficient to
+ // check the error code isn't BADTIME for the purpose of this test.
+ ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+ tsig_ctx.get(), 0,
+ RRType::SOA());
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 + 301>;
+ EXPECT_EQ(TSIGError::BAD_TIME(),
+ tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
+ dummy_data.size()));
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 + 300>;
+ EXPECT_NE(TSIGError::BAD_TIME(),
+ tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
+ dummy_data.size()));
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 301>;
+ EXPECT_EQ(TSIGError::BAD_TIME(),
+ tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
+ dummy_data.size()));
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 300>;
+ EXPECT_NE(TSIGError::BAD_TIME(),
+ tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
+ dummy_data.size()));
+}
+
+TEST_F(TSIGTest, badtimeOverflow) {
+ isc::util::detail::gettimeFunction = testGetTime<200>;
+ ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+ tsig_ctx.get(), 0,
+ RRType::SOA());
+
+ // This should be in the okay range, but since "200 - fudge" overflows
+ // and we compare them as 64-bit unsigned integers, it results in a false
+ // positive (we intentionally accept that).
+ isc::util::detail::gettimeFunction = testGetTime<100>;
+ EXPECT_EQ(TSIGError::BAD_TIME(),
+ tsig_verify_ctx->verify(tsig.get(), &dummy_data[0],
+ dummy_data.size()));
+}
+
+TEST_F(TSIGTest, badsigResponse) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ // Try to sign a simple message with bogus secret. It should fail
+ // with BADSIG.
+ createMessageFromFile("message_toWire2.wire");
+ TSIGContext bad_ctx(TSIGKey(test_name, TSIGKey::HMACMD5_NAME(),
+ &dummy_data[0], dummy_data.size()));
+ {
+ SCOPED_TRACE("Verify resulting in BADSIG");
+ commonVerifyChecks(bad_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST);
+ }
+
+ // Sign the same message (which doesn't matter for this test) with the
+ // context of "checked state".
+ {
+ SCOPED_TRACE("Sign test for response with BADSIG error");
+ commonSignChecks(createMessageAndSign(qid, test_name, &bad_ctx),
+ message.getQid(), 0x4da8877a, NULL, 0,
+ 16); // 16: BADSIG
+ }
+}
+
+TEST_F(TSIGTest, badkeyResponse) {
+ // A similar test as badsigResponse but for BADKEY
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+ tsig_ctx.reset(new TestTSIGContext(badkey_name, TSIGKey::HMACMD5_NAME(),
+ keyring));
+ {
+ SCOPED_TRACE("Verify resulting in BADKEY");
+ commonVerifyChecks(*tsig_ctx, &dummy_record, &dummy_data[0],
+ dummy_data.size(), TSIGError::BAD_KEY(),
+ TSIGContext::RECEIVED_REQUEST);
+ }
+
+ {
+ SCOPED_TRACE("Sign test for response with BADKEY error");
+ ConstTSIGRecordPtr sig = createMessageAndSign(qid, test_name,
+ tsig_ctx.get());
+ EXPECT_EQ(badkey_name, sig->getName());
+ commonSignChecks(sig, qid, 0x4da8877a, NULL, 0, 17); // 17: BADKEY
+ }
+}
+
+TEST_F(TSIGTest, badkeyForResponse) {
+ // "BADKEY" case for a response to a signed message
+ createMessageAndSign(qid, test_name, tsig_ctx.get());
+ {
+ SCOPED_TRACE("Verify a response resulting in BADKEY");
+ commonVerifyChecks(*tsig_ctx, &dummy_record, &dummy_data[0],
+ dummy_data.size(), TSIGError::BAD_KEY(),
+ TSIGContext::SENT_REQUEST);
+ }
+
+ // A similar case with a different algorithm
+ const TSIGRecord dummy_record2(test_name, TSIG(TSIGKey::HMACSHA1_NAME(),
+ 0x4da8877a,
+ TSIGContext::DEFAULT_FUDGE,
+ 0, NULL, qid, 0, 0, NULL));
+ {
+ SCOPED_TRACE("Verify a response resulting in BADKEY due to bad alg");
+ commonVerifyChecks(*tsig_ctx, &dummy_record2, &dummy_data[0],
+ dummy_data.size(), TSIGError::BAD_KEY(),
+ TSIGContext::SENT_REQUEST);
+ }
+}
+
+TEST_F(TSIGTest, badsigThenValidate) {
+ // According to RFC2845 4.6, if TSIG verification fails the client
+ // should discard that message and wait for another signed response.
+ // This test emulates that situation.
+
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ createMessageAndSign(qid, test_name, tsig_ctx.get());
+
+ createMessageFromFile("tsig_verify4.wire");
+ {
+ SCOPED_TRACE("Verify a response that should fail due to BADSIG");
+ commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::BAD_SIG(), TSIGContext::SENT_REQUEST);
+ }
+
+ createMessageFromFile("tsig_verify5.wire");
+ {
+ SCOPED_TRACE("Verify a response after a BADSIG failure");
+ commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::NOERROR(),
+ TSIGContext::VERIFIED_RESPONSE);
+ }
+}
+
+TEST_F(TSIGTest, nosigThenValidate) {
+ // Similar to the previous test, but the first response doesn't contain
+ // TSIG.
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ createMessageAndSign(qid, test_name, tsig_ctx.get());
+
+ {
+ SCOPED_TRACE("Verify a response without TSIG that should exist");
+ commonVerifyChecks(*tsig_ctx, NULL, &dummy_data[0],
+ dummy_data.size(), TSIGError::FORMERR(),
+ TSIGContext::SENT_REQUEST, true);
+ }
+
+ createMessageFromFile("tsig_verify5.wire");
+ {
+ SCOPED_TRACE("Verify a response after a FORMERR failure");
+ commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::NOERROR(),
+ TSIGContext::VERIFIED_RESPONSE);
+ }
+}
+
+TEST_F(TSIGTest, badtimeThenValidate) {
+ // Similar to the previous test, but the first response results in BADTIME.
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name,
+ tsig_ctx.get());
+
+ // "advance the clock" and try validating, which should fail due to BADTIME
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a + 600>;
+ {
+ SCOPED_TRACE("Verify resulting in BADTIME due to expired SIG");
+ commonVerifyChecks(*tsig_ctx, tsig.get(), &dummy_data[0],
+ dummy_data.size(), TSIGError::BAD_TIME(),
+ TSIGContext::SENT_REQUEST);
+ }
+
+ // revert the clock again.
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+ createMessageFromFile("tsig_verify5.wire");
+ {
+ SCOPED_TRACE("Verify a response after a BADTIME failure");
+ commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::NOERROR(),
+ TSIGContext::VERIFIED_RESPONSE);
+ }
+}
+
+TEST_F(TSIGTest, emptyMAC) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ // We don't allow empty MAC unless the TSIG error is BADSIG or BADKEY.
+ createMessageFromFile("tsig_verify7.wire");
+ {
+ SCOPED_TRACE("Verify test for request");
+ commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST);
+ }
+
+ // If the empty MAC comes with a BADKEY error, the error is passed
+ // transparently.
+ createMessageFromFile("tsig_verify8.wire");
+ {
+ SCOPED_TRACE("Verify test for request");
+ commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::BAD_KEY(), TSIGContext::RECEIVED_REQUEST);
+ }
+}
+
+TEST_F(TSIGTest, verifyAfterSendResponse) {
+ // Once the context is used for sending a signed response, it shouldn't
+ // be used for further verification.
+
+ // The following are essentially the same as what verifyThenSignResponse
+ // does with simplification.
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+ createMessageFromFile("message_toWire2.wire");
+ tsig_verify_ctx->verify(message.getTSIGRecord(), &received_data[0],
+ received_data.size());
+ EXPECT_EQ(TSIGContext::RECEIVED_REQUEST, tsig_verify_ctx->getState());
+ createMessageAndSign(qid, test_name, tsig_verify_ctx.get(),
+ QR_FLAG|AA_FLAG|RD_FLAG, RRType::A(), "192.0.2.1");
+ EXPECT_EQ(TSIGContext::SENT_RESPONSE, tsig_verify_ctx->getState());
+
+ // Now trying further verification.
+ createMessageFromFile("message_toWire2.wire");
+ EXPECT_THROW(tsig_verify_ctx->verify(message.getTSIGRecord(),
+ &received_data[0],
+ received_data.size()),
+ TSIGContextError);
+}
+
+TEST_F(TSIGTest, signAfterVerified) {
+ // Likewise, once the context verifies a response, it shouldn't for
+ // signing any more.
+
+ // The following are borrowed from badsigThenValidate (without the
+ // intermediate failure)
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+ createMessageAndSign(qid, test_name, tsig_ctx.get());
+ createMessageFromFile("tsig_verify5.wire");
+ tsig_ctx->verify(message.getTSIGRecord(), &received_data[0],
+ received_data.size());
+ EXPECT_EQ(TSIGContext::VERIFIED_RESPONSE, tsig_ctx->getState());
+
+ // Now trying further signing.
+ EXPECT_THROW(createMessageAndSign(qid, test_name, tsig_ctx.get()),
+ TSIGContextError);
+}
+
+TEST_F(TSIGTest, tooShortMAC) {
+ // Too short MAC should be rejected.
+
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+ createMessageFromFile("tsig_verify10.wire");
+ {
+ SCOPED_TRACE("Verify test for request");
+ commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::FORMERR(), TSIGContext::RECEIVED_REQUEST);
+ }
+}
+
+TEST_F(TSIGTest, truncatedMAC) {
+ // Check truncated MAC support with HMAC-SHA512-256
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ secret.clear();
+ decodeBase64("jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==", secret);
+ TSIGContext sha_ctx(TSIGKey(test_name, TSIGKey::HMACSHA512_NAME(),
+ &secret[0], secret.size(), 256));
+
+ createMessageFromFile("tsig_verify11.wire");
+ {
+ SCOPED_TRACE("Verify test for request");
+ commonVerifyChecks(sha_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST);
+ }
+
+ // Try with HMAC-SHA512-264 (should fail)
+ TSIGContext bad_sha_ctx(TSIGKey(test_name, TSIGKey::HMACSHA512_NAME(),
+ &secret[0], secret.size(), 264));
+ {
+ SCOPED_TRACE("Verify test for request");
+ commonVerifyChecks(bad_sha_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::BAD_TRUNC(), TSIGContext::RECEIVED_REQUEST);
+ }
+}
+
+TEST_F(TSIGTest, getTSIGLength) {
+ // Check for the most common case with various algorithms
+ // See the comment in TSIGContext::getTSIGLength() for calculation and
+ // parameter notation.
+ // The key name (www.example.com) is the same for most cases, where n1=17
+
+ // hmac-md5.sig-alg.reg.int.: n2=26, x=16
+ EXPECT_EQ(85, tsig_ctx->getTSIGLength());
+
+ // hmac-md5-80: n2=26, x=10
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACMD5_NAME(),
+ &dummy_data[0], 10, 80)));
+ EXPECT_EQ(79, tsig_ctx->getTSIGLength());
+
+ // hmac-sha1: n2=11, x=20
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACSHA1_NAME(),
+ &dummy_data[0], 20)));
+ EXPECT_EQ(74, tsig_ctx->getTSIGLength());
+
+ // hmac-sha256: n2=13, x=32
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACSHA256_NAME(),
+ &dummy_data[0], 32)));
+ EXPECT_EQ(88, tsig_ctx->getTSIGLength());
+
+ // hmac-sha224: n2=13, x=28
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACSHA224_NAME(),
+ &dummy_data[0], 28)));
+ EXPECT_EQ(84, tsig_ctx->getTSIGLength());
+
+ // hmac-sha384: n2=13, x=48
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACSHA384_NAME(),
+ &dummy_data[0], 48)));
+ EXPECT_EQ(104, tsig_ctx->getTSIGLength());
+
+ // hmac-sha512: n2=13, x=64
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACSHA512_NAME(),
+ &dummy_data[0], 64)));
+ EXPECT_EQ(120, tsig_ctx->getTSIGLength());
+
+ // hmac-sha512-256: n2=13, x=32
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACSHA512_NAME(),
+ &dummy_data[0], 32, 256)));
+ EXPECT_EQ(88, tsig_ctx->getTSIGLength());
+
+ // bad key case: n1=len(badkey.example.com)=20, n2=26, x=0
+ tsig_ctx.reset(new TestTSIGContext(badkey_name, TSIGKey::HMACMD5_NAME(),
+ keyring));
+ EXPECT_EQ(72, tsig_ctx->getTSIGLength());
+
+ // bad sig case: n1=17, n2=26, x=0
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+ createMessageFromFile("message_toWire2.wire");
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACMD5_NAME(),
+ &dummy_data[0],
+ dummy_data.size())));
+ {
+ SCOPED_TRACE("Verify resulting in BADSIG");
+ commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST);
+ }
+ EXPECT_EQ(69, tsig_ctx->getTSIGLength());
+
+ // bad time case: n1=17, n2=26, x=16, y=6
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a - 1000>;
+ tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name,
+ TSIGKey::HMACMD5_NAME(),
+ &dummy_data[0],
+ dummy_data.size())));
+ {
+ SCOPED_TRACE("Verify resulting in BADTIME");
+ commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(),
+ &received_data[0], received_data.size(),
+ TSIGError::BAD_TIME(),
+ TSIGContext::RECEIVED_REQUEST);
+ }
+ EXPECT_EQ(91, tsig_ctx->getTSIGLength());
+}
+
+// Verify a stream of multiple messages. Some of them have a signature omitted.
+//
+// We have two contexts, one that signs, another that verifies.
+TEST_F(TSIGTest, verifyMulti) {
+ isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>;
+
+ // First, send query from the verify one to the normal one, so
+ // we initialize something like AXFR
+ {
+ SCOPED_TRACE("Query");
+ ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name,
+ tsig_verify_ctx.get());
+ commonVerifyChecks(*tsig_ctx, tsig.get(),
+ renderer.getData(), renderer.getLength(),
+ TSIGError(Rcode::NOERROR()),
+ TSIGContext::RECEIVED_REQUEST);
+ }
+
+ {
+ SCOPED_TRACE("First message");
+ ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name,
+ tsig_ctx.get());
+ commonVerifyChecks(*tsig_verify_ctx, tsig.get(),
+ renderer.getData(), renderer.getLength(),
+ TSIGError(Rcode::NOERROR()),
+ TSIGContext::VERIFIED_RESPONSE);
+ EXPECT_TRUE(tsig_verify_ctx->lastHadSignature());
+ }
+
+ {
+ SCOPED_TRACE("Second message");
+ ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name,
+ tsig_ctx.get());
+ commonVerifyChecks(*tsig_verify_ctx, tsig.get(),
+ renderer.getData(), renderer.getLength(),
+ TSIGError(Rcode::NOERROR()),
+ TSIGContext::VERIFIED_RESPONSE);
+ EXPECT_TRUE(tsig_verify_ctx->lastHadSignature());
+ }
+
+ {
+ SCOPED_TRACE("Third message. Unsigned.");
+ // Another message does not carry the TSIG on it. But it should
+ // be OK, it's in the middle of stream.
+ message.clear(Message::RENDER);
+ message.setQid(1234);
+ message.setOpcode(Opcode::QUERY());
+ message.setRcode(Rcode::NOERROR());
+ RRsetPtr answer_rrset(new RRset(test_name, test_class, RRType::A(),
+ test_ttl));
+ answer_rrset->addRdata(createRdata(RRType::A(), test_class,
+ "192.0.2.1"));
+ message.addRRset(Message::SECTION_ANSWER, answer_rrset);
+ message.toWire(renderer);
+ // Update the internal state. We abuse the knowledge of
+ // internals here a little bit to generate correct test data
+ tsig_ctx->update(renderer.getData(), renderer.getLength());
+
+ commonVerifyChecks(*tsig_verify_ctx, NULL,
+ renderer.getData(), renderer.getLength(),
+ TSIGError(Rcode::NOERROR()),
+ TSIGContext::VERIFIED_RESPONSE);
+
+ EXPECT_FALSE(tsig_verify_ctx->lastHadSignature());
+ }
+
+ {
+ SCOPED_TRACE("Fourth message. Signed again.");
+ ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name,
+ tsig_ctx.get());
+ commonVerifyChecks(*tsig_verify_ctx, tsig.get(),
+ renderer.getData(), renderer.getLength(),
+ TSIGError(Rcode::NOERROR()),
+ TSIGContext::VERIFIED_RESPONSE);
+ EXPECT_TRUE(tsig_verify_ctx->lastHadSignature());
+ }
+
+ {
+ SCOPED_TRACE("Filling in bunch of unsigned messages");
+ for (size_t i = 0; i < 100; ++i) {
+ SCOPED_TRACE(i);
+ // Another message does not carry the TSIG on it. But it should
+ // be OK, it's in the middle of stream.
+ message.clear(Message::RENDER);
+ message.setQid(1234);
+ message.setOpcode(Opcode::QUERY());
+ message.setRcode(Rcode::NOERROR());
+ RRsetPtr answer_rrset(new RRset(test_name, test_class, RRType::A(),
+ test_ttl));
+ answer_rrset->addRdata(createRdata(RRType::A(), test_class,
+ "192.0.2.1"));
+ message.addRRset(Message::SECTION_ANSWER, answer_rrset);
+ message.toWire(renderer);
+ // Update the internal state. We abuse the knowledge of
+ // internals here a little bit to generate correct test data
+ tsig_ctx->update(renderer.getData(), renderer.getLength());
+
+ // 99 unsigned messages is OK. But the 100th must be signed, according
+ // to the RFC2845, section 4.4
+ commonVerifyChecks(*tsig_verify_ctx, NULL,
+ renderer.getData(), renderer.getLength(),
+ i == 99 ? TSIGError::FORMERR() :
+ TSIGError(Rcode::NOERROR()),
+ TSIGContext::VERIFIED_RESPONSE);
+
+ EXPECT_FALSE(tsig_verify_ctx->lastHadSignature());
+ }
+ }
+}
+
+} // end namespace
diff --git a/src/lib/dns/tests/tsigerror_unittest.cc b/src/lib/dns/tests/tsigerror_unittest.cc
new file mode 100644
index 0000000..e50f076
--- /dev/null
+++ b/src/lib/dns/tests/tsigerror_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+#include <ostream>
+
+#include <gtest/gtest.h>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/rcode.h>
+#include <dns/tsigerror.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+
+namespace {
+TEST(TSIGErrorTest, constructFromErrorCode) {
+ // These are pretty trivial, and also test getCode();
+ EXPECT_EQ(0, TSIGError(0).getCode());
+ EXPECT_EQ(18, TSIGError(18).getCode());
+ EXPECT_EQ(65535, TSIGError(65535).getCode());
+}
+
+TEST(TSIGErrorTest, constructFromRcode) {
+ // We use RCODE for code values from 0-15.
+ EXPECT_EQ(0, TSIGError(Rcode::NOERROR()).getCode());
+ EXPECT_EQ(15, TSIGError(Rcode(15)).getCode());
+
+ // From error code 16 TSIG errors define a separate space, so passing
+ // corresponding RCODE for such code values should be prohibited.
+ EXPECT_THROW(TSIGError(Rcode(16)).getCode(), OutOfRange);
+}
+
+TEST(TSIGErrorTest, constants) {
+ // We'll only test arbitrarily chosen subsets of the codes.
+ // This class is quite simple, so it should be suffice.
+
+ EXPECT_EQ(TSIGError::BAD_SIG_CODE, TSIGError(16).getCode());
+ EXPECT_EQ(TSIGError::BAD_KEY_CODE, TSIGError(17).getCode());
+ EXPECT_EQ(TSIGError::BAD_TIME_CODE, TSIGError(18).getCode());
+ EXPECT_EQ(TSIGError::BAD_MODE_CODE, TSIGError(19).getCode());
+ EXPECT_EQ(TSIGError::BAD_NAME_CODE, TSIGError(20).getCode());
+ EXPECT_EQ(TSIGError::BAD_ALG_CODE, TSIGError(21).getCode());
+ EXPECT_EQ(TSIGError::BAD_TRUNC_CODE, TSIGError(22).getCode());
+
+ EXPECT_EQ(0, TSIGError::NOERROR().getCode());
+ EXPECT_EQ(9, TSIGError::NOTAUTH().getCode());
+ EXPECT_EQ(14, TSIGError::RESERVED14().getCode());
+ EXPECT_EQ(TSIGError::BAD_SIG_CODE, TSIGError::BAD_SIG().getCode());
+ EXPECT_EQ(TSIGError::BAD_KEY_CODE, TSIGError::BAD_KEY().getCode());
+ EXPECT_EQ(TSIGError::BAD_TIME_CODE, TSIGError::BAD_TIME().getCode());
+ EXPECT_EQ(TSIGError::BAD_MODE_CODE, TSIGError::BAD_MODE().getCode());
+ EXPECT_EQ(TSIGError::BAD_NAME_CODE, TSIGError::BAD_NAME().getCode());
+ EXPECT_EQ(TSIGError::BAD_ALG_CODE, TSIGError::BAD_ALG().getCode());
+ EXPECT_EQ(TSIGError::BAD_TRUNC_CODE, TSIGError::BAD_TRUNC().getCode());
+}
+
+TEST(TSIGErrorTest, equal) {
+ EXPECT_TRUE(TSIGError::NOERROR() == TSIGError(Rcode::NOERROR()));
+ EXPECT_TRUE(TSIGError(Rcode::NOERROR()) == TSIGError::NOERROR());
+ EXPECT_TRUE(TSIGError::NOERROR().equals(TSIGError(Rcode::NOERROR())));
+ EXPECT_TRUE(TSIGError::NOERROR().equals(TSIGError(Rcode::NOERROR())));
+
+ EXPECT_TRUE(TSIGError::BAD_SIG() == TSIGError(16));
+ EXPECT_TRUE(TSIGError(16) == TSIGError::BAD_SIG());
+ EXPECT_TRUE(TSIGError::BAD_SIG().equals(TSIGError(16)));
+ EXPECT_TRUE(TSIGError(16).equals(TSIGError::BAD_SIG()));
+}
+
+TEST(TSIGErrorTest, nequal) {
+ EXPECT_TRUE(TSIGError::BAD_KEY() != TSIGError(Rcode::NOERROR()));
+ EXPECT_TRUE(TSIGError(Rcode::NOERROR()) != TSIGError::BAD_KEY());
+ EXPECT_TRUE(TSIGError::BAD_KEY().nequals(TSIGError(Rcode::NOERROR())));
+ EXPECT_TRUE(TSIGError(Rcode::NOERROR()).nequals(TSIGError::BAD_KEY()));
+}
+
+TEST(TSIGErrorTest, toText) {
+ // TSIGError derived from the standard Rcode
+ EXPECT_EQ("NOERROR", TSIGError(Rcode::NOERROR()).toText());
+
+ // Well known TSIG errors
+ EXPECT_EQ("BADSIG", TSIGError::BAD_SIG().toText());
+ EXPECT_EQ("BADKEY", TSIGError::BAD_KEY().toText());
+ EXPECT_EQ("BADTIME", TSIGError::BAD_TIME().toText());
+ EXPECT_EQ("BADMODE", TSIGError::BAD_MODE().toText());
+ EXPECT_EQ("BADNAME", TSIGError::BAD_NAME().toText());
+ EXPECT_EQ("BADALG", TSIGError::BAD_ALG().toText());
+ EXPECT_EQ("BADTRUNC", TSIGError::BAD_TRUNC().toText());
+
+ // Unknown (or not yet supported) codes. Simply converted as numeric.
+ EXPECT_EQ("23", TSIGError(23).toText());
+ EXPECT_EQ("65535", TSIGError(65535).toText());
+}
+
+TEST(TSIGErrorTest, toRcode) {
+ // TSIGError derived from the standard Rcode
+ EXPECT_EQ(Rcode::NOERROR(), TSIGError(Rcode::NOERROR()).toRcode());
+
+ // Well known TSIG errors
+ EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_SIG().toRcode());
+ EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_KEY().toRcode());
+ EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_TIME().toRcode());
+ EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_MODE().toRcode());
+ EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_NAME().toRcode());
+ EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_ALG().toRcode());
+ EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_TRUNC().toRcode());
+
+ // Unknown (or not yet supported) codes are treated as SERVFAIL.
+ EXPECT_EQ(Rcode::SERVFAIL(), TSIGError(23).toRcode());
+ EXPECT_EQ(Rcode::SERVFAIL(), TSIGError(65535).toRcode());
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST(TSIGErrorTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << TSIGError::BAD_KEY();
+ EXPECT_EQ(TSIGError::BAD_KEY().toText(), oss.str());
+}
+} // end namespace
diff --git a/src/lib/dns/tests/tsigkey_unittest.cc b/src/lib/dns/tests/tsigkey_unittest.cc
new file mode 100644
index 0000000..90c59ac
--- /dev/null
+++ b/src/lib/dns/tests/tsigkey_unittest.cc
@@ -0,0 +1,350 @@
+// Copyright (C) 2021-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include <exceptions/exceptions.h>
+
+#include <cryptolink/cryptolink.h>
+
+#include <dns/tsigkey.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::dns;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class TSIGKeyTest : public ::testing::Test {
+protected:
+ TSIGKeyTest() : secret("someRandomData"), key_name("example.com") {}
+ string secret;
+ const Name key_name;
+};
+
+TEST_F(TSIGKeyTest, algorithmNames) {
+ EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), TSIGKey::HMACMD5_NAME());
+ EXPECT_EQ(Name("hmac-md5"), TSIGKey::HMACMD5_SHORT_NAME());
+ EXPECT_EQ(Name("hmac-sha1"), TSIGKey::HMACSHA1_NAME());
+ EXPECT_EQ(Name("hmac-sha256"), TSIGKey::HMACSHA256_NAME());
+ EXPECT_EQ(Name("hmac-sha224"), TSIGKey::HMACSHA224_NAME());
+ EXPECT_EQ(Name("hmac-sha384"), TSIGKey::HMACSHA384_NAME());
+ EXPECT_EQ(Name("hmac-sha512"), TSIGKey::HMACSHA512_NAME());
+ EXPECT_EQ(Name("gss-tsig"), TSIGKey::GSSTSIG_NAME());
+
+ // Also check conversion to cryptolink definitions
+ EXPECT_EQ(isc::cryptolink::MD5, TSIGKey(key_name, TSIGKey::HMACMD5_NAME(),
+ NULL, 0).getAlgorithm());
+ EXPECT_EQ(isc::cryptolink::MD5,
+ TSIGKey(key_name, TSIGKey::HMACMD5_SHORT_NAME(),
+ NULL, 0).getAlgorithm());
+ EXPECT_EQ(isc::cryptolink::SHA1, TSIGKey(key_name, TSIGKey::HMACSHA1_NAME(),
+ NULL, 0).getAlgorithm());
+ EXPECT_EQ(isc::cryptolink::SHA256, TSIGKey(key_name,
+ TSIGKey::HMACSHA256_NAME(),
+ NULL, 0).getAlgorithm());
+ EXPECT_EQ(isc::cryptolink::SHA224, TSIGKey(key_name,
+ TSIGKey::HMACSHA224_NAME(),
+ NULL, 0).getAlgorithm());
+ EXPECT_EQ(isc::cryptolink::SHA384, TSIGKey(key_name,
+ TSIGKey::HMACSHA384_NAME(),
+ NULL, 0).getAlgorithm());
+ EXPECT_EQ(isc::cryptolink::SHA512, TSIGKey(key_name,
+ TSIGKey::HMACSHA512_NAME(),
+ NULL, 0).getAlgorithm());
+}
+
+TEST_F(TSIGKeyTest, construct) {
+ TSIGKey key(key_name, TSIGKey::HMACMD5_NAME(),
+ secret.c_str(), secret.size());
+ EXPECT_EQ(key_name, key.getKeyName());
+ EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), key.getAlgorithmName());
+ matchWireData(secret.c_str(), secret.size(),
+ key.getSecret(), key.getSecretLength());
+
+ TSIGKey key_short_md5(key_name, TSIGKey::HMACMD5_SHORT_NAME(),
+ secret.c_str(), secret.size());
+ EXPECT_EQ(key_name, key_short_md5.getKeyName());
+ EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"),
+ key_short_md5.getAlgorithmName());
+ matchWireData(secret.c_str(), secret.size(),
+ key_short_md5.getSecret(), key_short_md5.getSecretLength());
+
+ // "unknown" algorithm is only accepted with empty secret.
+ EXPECT_THROW(TSIGKey(key_name, Name("unknown-alg"),
+ secret.c_str(), secret.size()),
+ isc::InvalidParameter);
+ TSIGKey key2(key_name, Name("unknown-alg"), NULL, 0);
+ EXPECT_EQ(key_name, key2.getKeyName());
+ EXPECT_EQ(Name("unknown-alg"), key2.getAlgorithmName());
+
+ // The algorithm name should be converted to the canonical form.
+ EXPECT_EQ("hmac-sha1.",
+ TSIGKey(key_name, Name("HMAC-sha1"),
+ secret.c_str(),
+ secret.size()).getAlgorithmName().toText());
+
+ // Same for key name
+ EXPECT_EQ("example.com.",
+ TSIGKey(Name("EXAMPLE.CoM."), TSIGKey::HMACSHA256_NAME(),
+ secret.c_str(),
+ secret.size()).getKeyName().toText());
+
+ // Check digestbits
+ EXPECT_EQ(key.getDigestbits(), 0);
+ TSIGKey key_trunc(key_name, TSIGKey::HMACMD5_NAME(),
+ secret.c_str(), secret.size(), 120);
+ EXPECT_EQ(key_trunc.getDigestbits(), 120);
+
+ // Invalid combinations of secret and secret_len:
+ EXPECT_THROW(TSIGKey(key_name, TSIGKey::HMACSHA1_NAME(), secret.c_str(), 0),
+ isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), NULL, 16),
+ isc::InvalidParameter);
+
+ // Empty secret
+ TSIGKey keye = TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), NULL, 0);
+ EXPECT_EQ(keye.getSecretLength(), 0);
+ EXPECT_EQ(keye.getSecret(), (const void*)0);
+}
+
+void
+compareTSIGKeys(const TSIGKey& expect, const TSIGKey& actual) {
+ EXPECT_EQ(expect.getKeyName(), actual.getKeyName());
+ EXPECT_EQ(expect.getAlgorithmName(), actual.getAlgorithmName());
+ EXPECT_EQ(expect.getDigestbits(), actual.getDigestbits());
+ matchWireData(expect.getSecret(), expect.getSecretLength(),
+ actual.getSecret(), actual.getSecretLength());
+}
+
+TEST_F(TSIGKeyTest, copyConstruct) {
+ const TSIGKey original(key_name, TSIGKey::HMACSHA256_NAME(),
+ secret.c_str(), secret.size(), 128);
+ const TSIGKey copy(original);
+ compareTSIGKeys(original, copy);
+
+ // Check the copied data is valid even after the original is deleted
+ TSIGKey* copy2 = new TSIGKey(original);
+ TSIGKey copy3(*copy2);
+ delete copy2;
+ compareTSIGKeys(original, copy3);
+}
+
+TEST_F(TSIGKeyTest, assignment) {
+ const TSIGKey original(key_name, TSIGKey::HMACSHA256_NAME(),
+ secret.c_str(), secret.size(), 200);
+ TSIGKey copy = original;
+ compareTSIGKeys(original, copy);
+
+ // Check if the copied data is valid even after the original is deleted
+ TSIGKey* copy2 = new TSIGKey(original);
+ TSIGKey copy3(original);
+ copy3 = *copy2;
+ delete copy2;
+ compareTSIGKeys(original, copy3);
+
+ // Self assignment
+ copy = *&copy;
+ compareTSIGKeys(original, copy);
+}
+
+class TSIGKeyRingTest : public ::testing::Test {
+protected:
+ TSIGKeyRingTest() :
+ key_name("example.com"),
+ md5_name("hmac-md5.sig-alg.reg.int"),
+ sha1_name("hmac-sha1"),
+ sha256_name("hmac-sha256"),
+ secretstring("anotherRandomData"),
+ secret(secretstring.c_str()),
+ secret_len(secretstring.size())
+ {}
+ TSIGKeyRing keyring;
+ const Name key_name;
+ const Name md5_name;
+ const Name sha1_name;
+ const Name sha256_name;
+private:
+ const string secretstring;
+protected:
+ const char* secret;
+ size_t secret_len;
+};
+
+TEST_F(TSIGKeyRingTest, init) {
+ EXPECT_EQ(0, keyring.size());
+}
+
+TEST_F(TSIGKeyRingTest, add) {
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(1, keyring.size());
+ EXPECT_EQ(TSIGKeyRing::EXIST, keyring.add(
+ TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(),
+ secret, secret_len)));
+ // keys are identified by their names, the same name of key with a
+ // different algorithm would be considered a duplicate.
+ EXPECT_EQ(TSIGKeyRing::EXIST, keyring.add(
+ TSIGKey(Name("example.com"), TSIGKey::HMACSHA1_NAME(),
+ secret, secret_len)));
+ // names are compared in a case insensitive manner.
+ EXPECT_EQ(TSIGKeyRing::EXIST, keyring.add(
+ TSIGKey(Name("EXAMPLE.COM"), TSIGKey::HMACSHA1_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(1, keyring.size());
+}
+
+TEST_F(TSIGKeyRingTest, addMore) {
+ // essentially the same test, but try adding more than 1
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(Name("another.example"), TSIGKey::HMACMD5_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(Name("more.example"), TSIGKey::HMACSHA1_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(3, keyring.size());
+}
+
+TEST_F(TSIGKeyRingTest, remove) {
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.remove(key_name));
+ EXPECT_EQ(TSIGKeyRing::NOTFOUND, keyring.remove(key_name));
+}
+
+TEST_F(TSIGKeyRingTest, removeFromSome) {
+ // essentially the same test, but try removing from a larger set
+
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(Name("another.example"), TSIGKey::HMACMD5_NAME(),
+ secret, secret_len)));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(
+ TSIGKey(Name("more.example"), TSIGKey::HMACSHA1_NAME(),
+ secret, secret_len)));
+
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.remove(Name("another.example")));
+ EXPECT_EQ(TSIGKeyRing::NOTFOUND, keyring.remove(Name("noexist.example")));
+ EXPECT_EQ(2, keyring.size());
+}
+
+TEST_F(TSIGKeyRingTest, find) {
+ // If the keyring is empty the search should fail.
+ EXPECT_EQ(TSIGKeyRing::NOTFOUND, keyring.find(key_name, md5_name).code);
+ EXPECT_EQ(static_cast<const TSIGKey*>(NULL),
+ keyring.find(key_name, md5_name).key);
+
+ // Add a key and try to find it. Should succeed.
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(key_name, sha256_name,
+ secret, secret_len)));
+ const TSIGKeyRing::FindResult result1(keyring.find(key_name, sha256_name));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, result1.code);
+ EXPECT_EQ(key_name, result1.key->getKeyName());
+ EXPECT_EQ(TSIGKey::HMACSHA256_NAME(), result1.key->getAlgorithmName());
+ matchWireData(secret, secret_len,
+ result1.key->getSecret(), result1.key->getSecretLength());
+
+ // If either key name or algorithm doesn't match, search should fail.
+ const TSIGKeyRing::FindResult result2 =
+ keyring.find(Name("different-key.example"), sha256_name);
+ EXPECT_EQ(TSIGKeyRing::NOTFOUND, result2.code);
+ EXPECT_EQ(static_cast<const TSIGKey*>(NULL), result2.key);
+
+ const TSIGKeyRing::FindResult result3 = keyring.find(key_name, md5_name);
+ EXPECT_EQ(TSIGKeyRing::NOTFOUND, result3.code);
+ EXPECT_EQ(static_cast<const TSIGKey*>(NULL), result3.key);
+
+ // But with just the name it should work
+ const TSIGKeyRing::FindResult result4(keyring.find(key_name));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, result4.code);
+ EXPECT_EQ(key_name, result4.key->getKeyName());
+ EXPECT_EQ(TSIGKey::HMACSHA256_NAME(), result4.key->getAlgorithmName());
+ matchWireData(secret, secret_len,
+ result4.key->getSecret(), result4.key->getSecretLength());
+}
+
+TEST_F(TSIGKeyRingTest, findFromSome) {
+ // essentially the same test, but search a larger set
+
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(key_name, sha256_name,
+ secret, secret_len)));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(Name("another.example"),
+ md5_name,
+ secret, secret_len)));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(Name("more.example"),
+ sha1_name,
+ secret, secret_len)));
+
+ const TSIGKeyRing::FindResult result(
+ keyring.find(Name("another.example"), md5_name));
+ EXPECT_EQ(TSIGKeyRing::SUCCESS, result.code);
+ EXPECT_EQ(Name("another.example"), result.key->getKeyName());
+ EXPECT_EQ(TSIGKey::HMACMD5_NAME(), result.key->getAlgorithmName());
+
+ EXPECT_EQ(TSIGKeyRing::NOTFOUND,
+ keyring.find(Name("noexist.example"), sha1_name).code);
+ EXPECT_EQ(static_cast<const TSIGKey*>(NULL),
+ keyring.find(Name("noexist.example"), sha256_name).key);
+
+ EXPECT_EQ(TSIGKeyRing::NOTFOUND,
+ keyring.find(Name("another.example"), sha1_name).code);
+ EXPECT_EQ(static_cast<const TSIGKey*>(NULL),
+ keyring.find(Name("another.example"), sha256_name).key);
+}
+
+TEST(TSIGStringTest, TSIGKeyFromToString) {
+ TSIGKey k1 = TSIGKey("test.example:MSG6Ng==:hmac-md5.sig-alg.reg.int");
+ TSIGKey k2 = TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.");
+ TSIGKey k3 = TSIGKey("test.example:MSG6Ng==");
+ TSIGKey k4 = TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:120");
+ TSIGKey k5 = TSIGKey(Name("test.example."), Name("hmac-sha1."), NULL, 0);
+ // "Unknown" key with empty secret is okay
+ TSIGKey k6 = TSIGKey("test.example.::unknown");
+
+ EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+ k1.toText());
+ EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+ k2.toText());
+ EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.",
+ k3.toText());
+ EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:120",
+ k4.toText());
+ EXPECT_EQ(120, k4.getDigestbits());
+ EXPECT_EQ("test.example.::hmac-sha1.", k5.toText());
+ EXPECT_EQ(Name("test.example."), k6.getKeyName());
+ EXPECT_EQ(Name("unknown"), k6.getAlgorithmName());
+
+ EXPECT_THROW(TSIGKey(""), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey(":"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("::"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("..:aa:"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("test.example:xxxx:"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("test.example.::"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("test.example.:"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:unknown"), isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:"),
+ isc::InvalidParameter);
+ EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:xxx"),
+ isc::InvalidParameter);
+}
+
+
+} // end namespace
diff --git a/src/lib/dns/tests/tsigrecord_unittest.cc b/src/lib/dns/tests/tsigrecord_unittest.cc
new file mode 100644
index 0000000..624f03b
--- /dev/null
+++ b/src/lib/dns/tests/tsigrecord_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright (C) 2011-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <vector>
+#include <sstream>
+
+#include <gtest/gtest.h>
+
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/tsig.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigrecord.h>
+
+#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using namespace isc::dns::rdata::any;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class TSIGRecordTest : public ::testing::Test {
+protected:
+ TSIGRecordTest() :
+ test_name("www.example.com"), test_mac(16, 0xda),
+ test_rdata(TSIG(TSIGKey::HMACMD5_NAME(), 0x4da8877a, TSIGContext::DEFAULT_FUDGE,
+ test_mac.size(), &test_mac[0], 0x2d65, 0, 0, NULL)),
+ test_record(test_name, test_rdata),
+ buffer(0) {
+ }
+
+ const Name test_name;
+
+ vector<unsigned char> test_mac;
+
+ const TSIG test_rdata;
+
+ const TSIGRecord test_record;
+
+ OutputBuffer buffer;
+
+ MessageRenderer renderer;
+
+ vector<unsigned char> data;
+};
+
+TEST_F(TSIGRecordTest, getName) {
+ EXPECT_EQ(test_name, test_record.getName());
+}
+
+TEST_F(TSIGRecordTest, getLength) {
+ // 85 = 17 + 26 + 16 + 26
+ // len(www.example.com) = 17
+ // len(hmac-md5.sig-alg.reg.int) = 26
+ // len(MAC) = 16
+ // the rest are fixed length fields (26 in total)
+ EXPECT_EQ(85, test_record.getLength());
+}
+
+TEST_F(TSIGRecordTest, fromParams) {
+ // Construct the same TSIG RR as test_record from parameters.
+ // See the getLength test for the magic number of 85 (although it
+ // actually doesn't matter)
+ const TSIGRecord record(test_name, TSIGRecord::getClass(),
+ TSIGRecord::getTTL(), test_rdata, 85);
+ // Perform straight sanity checks
+ EXPECT_EQ(test_name, record.getName());
+ EXPECT_EQ(85, record.getLength());
+ EXPECT_EQ(0, test_rdata.compare(record.getRdata()));
+
+ // The constructor doesn't check the length...
+ EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+ TSIGRecord::getTTL(), test_rdata, 82));
+ // ...even for impossibly small values...
+ EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+ TSIGRecord::getTTL(), test_rdata, 1));
+ // ...or too large values.
+ EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+ TSIGRecord::getTTL(), test_rdata, 65536));
+
+ // RDATA must indeed be TSIG
+ EXPECT_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+ TSIGRecord::getTTL(), in::A("192.0.2.1"), 85),
+ DNSMessageFORMERR);
+
+ // Unexpected class
+ EXPECT_THROW(TSIGRecord(test_name, RRClass::IN(), TSIGRecord::getTTL(),
+ test_rdata, 85), DNSMessageFORMERR);
+
+ // Unexpected TTL
+ EXPECT_THROW(TSIGRecord(test_name, TSIGRecord::getClass(),
+ RRTTL(3600), test_rdata, 85), DNSMessageFORMERR);
+}
+
+TEST_F(TSIGRecordTest, recordToWire) {
+ UnitTestUtil::readWireData("tsigrecord_toWire1.wire", data);
+ EXPECT_EQ(1, test_record.toWire(renderer));
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+
+ // Same test for a dumb buffer
+ buffer.clear();
+ EXPECT_EQ(1, test_record.toWire(buffer));
+ matchWireData(&data[0], data.size(),
+ buffer.getData(), buffer.getLength());
+}
+
+TEST_F(TSIGRecordTest, recordToOLongToWire) {
+ // By setting the limit to "record length - 1", it will fail, and the
+ // renderer will be marked as "truncated".
+ renderer.setLengthLimit(test_record.getLength() - 1);
+ EXPECT_FALSE(renderer.isTruncated()); // not marked before render attempt
+ EXPECT_EQ(0, test_record.toWire(renderer));
+ EXPECT_TRUE(renderer.isTruncated());
+}
+
+TEST_F(TSIGRecordTest, recordToWireAfterNames) {
+ // A similar test but the TSIG RR follows some domain names that could
+ // cause name compression inside TSIG. Our implementation shouldn't
+ // compress either owner (key) name or the algorithm name. This test
+ // confirms that.
+
+ UnitTestUtil::readWireData("tsigrecord_toWire2.wire", data);
+ renderer.writeName(TSIGKey::HMACMD5_NAME());
+ renderer.writeName(Name("foo.example.com"));
+ EXPECT_EQ(1, test_record.toWire(renderer));
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+}
+
+TEST_F(TSIGRecordTest, toText) {
+ EXPECT_EQ("www.example.com. 0 ANY TSIG hmac-md5.sig-alg.reg.int. "
+ "1302890362 300 16 2tra2tra2tra2tra2tra2g== 11621 NOERROR 0\n",
+ test_record.toText());
+}
+
+// test operator<<. We simply confirm it appends the result of toText().
+TEST_F(TSIGRecordTest, LeftShiftOperator) {
+ ostringstream oss;
+ oss << test_record;
+ EXPECT_EQ(test_record.toText(), oss.str());
+}
+} // end namespace
diff --git a/src/lib/dns/tests/unittest_util.cc b/src/lib/dns/tests/unittest_util.cc
new file mode 100644
index 0000000..b234c1c
--- /dev/null
+++ b/src/lib/dns/tests/unittest_util.cc
@@ -0,0 +1,176 @@
+// Copyright (C) 2009-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <stdexcept>
+#include <vector>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include <dns/rcode.h>
+#include <dns/name.h>
+#include <dns/message.h>
+#include <dns/tests/unittest_util.h>
+
+using namespace std;
+using namespace isc::dns;
+
+using isc::UnitTestUtil;
+
+namespace {
+class UnitTestUtilConfig {
+private:
+ // This is a singleton object and cannot be constructed explicitly.
+ UnitTestUtilConfig() {}
+ UnitTestUtilConfig(const UnitTestUtilConfig& source);
+ ~UnitTestUtilConfig() {}
+public:
+ /// Return a singleton unit test configuration object. On first invocation
+ /// one will be constructed.
+ static UnitTestUtilConfig& getConfig();
+
+ /// A list of paths to wire data files.
+ /// \c UnitTestUtil::readWireData() (first version)
+ /// will search the directories in this list for the specified data file.
+ std::vector<string> data_paths_;
+};
+
+UnitTestUtilConfig&
+UnitTestUtilConfig::getConfig() {
+ static UnitTestUtilConfig config;
+ return (config);
+}
+}
+
+void
+UnitTestUtil::readWireData(const char* datafile, vector<unsigned char>& data) {
+ ifstream ifs;
+
+ const UnitTestUtilConfig& config = UnitTestUtilConfig::getConfig();
+ vector<string>::const_iterator it = config.data_paths_.begin();
+ for (; it != config.data_paths_.end(); ++it) {
+ string data_path = *it;
+ if (data_path.empty() || *data_path.rbegin() != '/') {
+ data_path.push_back('/');
+ }
+ ifs.open((data_path + datafile).c_str(), ios_base::in);
+ if ((ifs.rdstate() & istream::failbit) == 0) {
+ break;
+ }
+ }
+
+ if (it == config.data_paths_.end()) {
+ throw runtime_error("failed to open data file in data paths: " +
+ string(datafile));
+ }
+
+ data.clear();
+
+ string s;
+ while (getline(ifs, s), !ifs.eof()) {
+ if (ifs.bad() || ifs.fail()) {
+ throw runtime_error("unexpected data line");
+ }
+ if (s.empty() || s[0] == '#') {
+ continue;
+ }
+
+ readWireData(s, data);
+ }
+}
+
+void
+UnitTestUtil::addDataPath(const string& directory) {
+ UnitTestUtilConfig::getConfig().data_paths_.push_back(directory);
+}
+
+void
+UnitTestUtil::readWireData(const string& datastr,
+ vector<unsigned char>& data)
+{
+ istringstream iss(datastr);
+
+ do {
+ string bytes;
+ iss >> bytes;
+ if (iss.bad() || iss.fail() || (bytes.size() % 2) != 0) {
+ ostringstream err_oss;
+ err_oss << "unexpected input or I/O error in reading " <<
+ datastr;
+ throw runtime_error(err_oss.str());
+ }
+
+ for (string::size_type pos = 0; pos < bytes.size(); pos += 2) {
+ istringstream iss_byte(bytes.substr(pos, 2));
+ unsigned int ch;
+
+ iss_byte >> hex >> ch;
+ if (iss_byte.rdstate() != istream::eofbit) {
+ ostringstream err_oss;
+ err_oss << "invalid byte representation: " << iss_byte.str();
+ throw runtime_error(err_oss.str());
+ }
+ data.push_back(static_cast<unsigned char>(ch));
+ }
+ } while (!iss.eof());
+}
+
+::testing::AssertionResult
+UnitTestUtil::matchName(const char*, const char*,
+ const isc::dns::Name& name1,
+ const isc::dns::Name& name2)
+{
+ ::testing::Message msg;
+
+ NameComparisonResult cmpresult = name1.compare(name2);
+ if (cmpresult.getOrder() != 0 ||
+ cmpresult.getRelation() != NameComparisonResult::EQUAL) {
+ msg << "Two names are expected to be equal but not:\n"
+ << " One: " << name1 << "\n"
+ << "Other: " << name2 << "\n";
+ return (::testing::AssertionFailure(msg));
+ }
+ return (::testing::AssertionSuccess());
+}
+
+void
+UnitTestUtil::createRequestMessage(Message& message,
+ const Opcode& opcode,
+ const uint16_t qid,
+ const Name& name,
+ const RRClass& rrclass,
+ const RRType& rrtype)
+{
+ message.clear(Message::RENDER);
+ message.setOpcode(opcode);
+ message.setRcode(Rcode::NOERROR());
+ message.setQid(qid);
+ message.addQuestion(Question(name, rrclass, rrtype));
+}
+
+void
+UnitTestUtil::createDNSSECRequestMessage(Message& message,
+ const Opcode& opcode,
+ const uint16_t qid,
+ const Name& name,
+ const RRClass& rrclass,
+ const RRType& rrtype)
+{
+ message.clear(Message::RENDER);
+ message.setOpcode(opcode);
+ message.setRcode(Rcode::NOERROR());
+ message.setQid(qid);
+ message.addQuestion(Question(name, rrclass, rrtype));
+ EDNSPtr edns(new EDNS());
+ edns->setUDPSize(4096);
+ edns->setDNSSECAwareness(true);
+ message.setEDNS(edns);
+}
diff --git a/src/lib/dns/tests/unittest_util.h b/src/lib/dns/tests/unittest_util.h
new file mode 100644
index 0000000..8c6b8f5
--- /dev/null
+++ b/src/lib/dns/tests/unittest_util.h
@@ -0,0 +1,88 @@
+// Copyright (C) 2009-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef UNITTEST_UTIL_H
+#define UNITTEST_UTIL_H 1
+
+#include <vector>
+#include <string>
+
+#include <dns/name.h>
+#include <dns/message.h>
+
+#include <gtest/gtest.h>
+
+namespace isc {
+
+class UnitTestUtil {
+public:
+ ///
+ /// read text format wire data from a file and put it to the given vector.
+ ///
+ static void readWireData(const char* datafile,
+ std::vector<unsigned char>& data);
+
+ ///
+ /// add a path that \c readWireData() will search for test data files.
+ ///
+ static void addDataPath(const std::string& directory);
+
+ ///
+ /// convert a sequence of hex strings into the corresponding list of
+ /// 8-bit integers, and append them to the vector.
+ ///
+ static void readWireData(const std::string& datastr,
+ std::vector<unsigned char>& data);
+
+ ///
+ /// Compare two names.
+ ///
+ /// This check method uses \c Name::compare() for comparison, which performs
+ /// deeper checks including the equality of offsets, and should be better
+ /// than EXPECT_EQ, which uses operator==. Like the \c matchWireData()
+ /// method, the usage is a bit awkward; the caller should use
+ /// \c EXPECT_PRED_FORMAT2.
+ ///
+ static ::testing::AssertionResult
+ matchName(const char* nameexp1, const char* nameexp2,
+ const isc::dns::Name& name1, const isc::dns::Name& name2);
+
+ ///
+ /// Populate a request message
+ ///
+ /// Create a request message in 'request_message' using the
+ /// opcode 'opcode' and the name/class/type query tuple specified in
+ /// 'name', 'rrclass' and 'rrtype.
+ static void
+ createRequestMessage(isc::dns::Message& request_message,
+ const isc::dns::Opcode& opcode,
+ const uint16_t qid,
+ const isc::dns::Name& name,
+ const isc::dns::RRClass& rrclass,
+ const isc::dns::RRType& rrtype);
+
+ ///
+ /// Populate a DNSSEC request message
+ ///
+ /// Create a request message in 'request_message' using the
+ /// opcode 'opcode' and the name/class/type query tuple specified in
+ /// 'name', 'rrclass' and 'rrtype.
+ /// EDNS will be added with DO=1 and bufsize 4096
+ static void
+ createDNSSECRequestMessage(isc::dns::Message& request_message,
+ const isc::dns::Opcode& opcode,
+ const uint16_t qid,
+ const isc::dns::Name& name,
+ const isc::dns::RRClass& rrclass,
+ const isc::dns::RRType& rrtype);
+
+};
+}
+#endif // UNITTEST_UTIL_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/tests/zone_checker_unittest.cc b/src/lib/dns/tests/zone_checker_unittest.cc
new file mode 100644
index 0000000..863b439
--- /dev/null
+++ b/src/lib/dns/tests/zone_checker_unittest.cc
@@ -0,0 +1,349 @@
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <dns/zone_checker.h>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/name.h>
+#include <dns/rrclass.h>
+#include <dns/rrset.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdataclass.h>
+#include <dns/rrset_collection.h>
+
+#include <gtest/gtest.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <algorithm>
+#include <functional>
+#include <string>
+#include <sstream>
+#include <vector>
+
+using isc::Unexpected;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+namespace ph = std::placeholders;
+
+namespace {
+
+const char* const soa_txt = "ns.example.com. root.example.com. 0 0 0 0 0";
+const char* const ns_txt1 = "ns.example.com.";
+const char* const ns_a_txt1 = "192.0.2.1";
+const char* const ns_txt2 = "ns2.example.com.";
+const char* const ns_a_txt2 = "192.0.2.2";
+
+class ZoneCheckerTest : public ::testing::Test {
+protected:
+ ZoneCheckerTest() :
+ zname_("example.com"), zclass_(RRClass::IN()),
+ soa_(new RRset(zname_, zclass_, RRType::SOA(), RRTTL(60))),
+ ns_(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))),
+ callbacks_(std::bind(&ZoneCheckerTest::callback, this, ph::_1, true),
+ std::bind(&ZoneCheckerTest::callback, this, ph::_1, false))
+ {
+ std::stringstream ss;
+ ss << "example.com. 60 IN SOA " << soa_txt << "\n";
+ ss << "example.com. 60 IN NS " << ns_txt1 << "\n";
+ ss << "ns.example.com. 60 IN A " << ns_a_txt1 << "\n";
+ ss << "ns2.example.com. 60 IN A " << ns_a_txt2 << "\n";
+ rrsets_.reset(new RRsetCollection(ss, zname_, zclass_));
+ }
+
+public:
+ // This one is passed to std::bind. Some compilers seem to require
+ // it be public.
+ void callback(const std::string& reason, bool is_error) {
+ if (is_error) {
+ errors_.push_back(reason);
+ } else {
+ warns_.push_back(reason);
+ }
+ }
+
+protected:
+ // Check stored issue messages with expected ones. Clear vectors so
+ // the caller can check other cases.
+ void checkIssues() {
+ EXPECT_EQ(expected_errors_.size(), errors_.size());
+ for (size_t i = 0;
+ i < std::min(expected_errors_.size(), errors_.size());
+ ++i) {
+ // The actual message should begin with the expected message.
+ EXPECT_EQ(0, errors_[0].find(expected_errors_[0]))
+ << "actual message: " << errors_[0] << " expected: " <<
+ expected_errors_[0];
+ }
+ EXPECT_EQ(expected_warns_.size(), warns_.size());
+ for (size_t i = 0;
+ i < std::min(expected_warns_.size(), warns_.size());
+ ++i) {
+ EXPECT_EQ(0, warns_[0].find(expected_warns_[0]))
+ << "actual message: " << warns_[0] << " expected: " <<
+ expected_warns_[0];
+ }
+
+ errors_.clear();
+ expected_errors_.clear();
+ warns_.clear();
+ expected_warns_.clear();
+ }
+
+ const Name zname_;
+ const RRClass zclass_;
+ boost::scoped_ptr<RRsetCollection> rrsets_;
+ RRsetPtr soa_;
+ RRsetPtr ns_;
+ std::vector<std::string> errors_;
+ std::vector<std::string> warns_;
+ std::vector<std::string> expected_errors_;
+ std::vector<std::string> expected_warns_;
+ ZoneCheckerCallbacks callbacks_;
+};
+
+TEST_F(ZoneCheckerTest, checkGood) {
+ // Checking a valid case. No errors or warnings should be reported.
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ checkIssues();
+
+ // Multiple NS RRs are okay.
+ rrsets_->removeRRset(zname_, zclass_, RRType::NS());
+ ns_->addRdata(generic::NS(ns_txt1));
+ ns_->addRdata(generic::NS(ns_txt2));
+ rrsets_->addRRset(ns_);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ checkIssues();
+}
+
+TEST_F(ZoneCheckerTest, checkSOA) {
+ // If the zone has no SOA it triggers an error.
+ rrsets_->removeRRset(zname_, zclass_, RRType::SOA());
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_errors_.push_back("zone example.com/IN: has 0 SOA records");
+ checkIssues();
+
+ // If null callback is specified, checkZone() only returns the final
+ // result.
+ ZoneCheckerCallbacks noerror_callbacks(
+ 0, std::bind(&ZoneCheckerTest::callback, this, ph::_1, false));
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, noerror_callbacks));
+ checkIssues();
+
+ // If there are more than 1 SOA RR, it's also an error.
+ errors_.clear();
+ soa_->addRdata(generic::SOA(soa_txt));
+ soa_->addRdata(generic::SOA("ns2.example.com. . 0 0 0 0 0"));
+ rrsets_->addRRset(soa_);
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_errors_.push_back("zone example.com/IN: has 2 SOA records");
+ checkIssues();
+
+ // If the SOA RRset is "empty", it's treated as an implementation
+ // (rather than operational) error and results in an exception.
+ rrsets_->removeRRset(zname_, zclass_, RRType::SOA());
+ soa_.reset(new RRset(zname_, zclass_, RRType::SOA(), RRTTL(60)));
+ rrsets_->addRRset(soa_);
+ EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected);
+ checkIssues(); // no error/warning should be reported
+
+ // Likewise, if the SOA RRset contains non SOA Rdata, it should be a bug.
+ rrsets_->removeRRset(zname_, zclass_, RRType::SOA());
+ soa_.reset(new RRset(zname_, zclass_, RRType::SOA(), RRTTL(60)));
+ soa_->addRdata(createRdata(RRType::NS(), zclass_, "ns.example.com."));
+ rrsets_->addRRset(soa_);
+ EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected);
+ checkIssues(); // no error/warning should be reported
+}
+
+TEST_F(ZoneCheckerTest, checkNS) {
+ // If the zone has no NS at origin it triggers an error.
+ rrsets_->removeRRset(zname_, zclass_, RRType::NS());
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_errors_.push_back("zone example.com/IN: has no NS records");
+ checkIssues();
+
+ // Check two buggy cases like the SOA tests
+ ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60)));
+ rrsets_->addRRset(ns_);
+ EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected);
+ checkIssues(); // no error/warning should be reported
+
+ rrsets_->removeRRset(zname_, zclass_, RRType::NS());
+ ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60)));
+ ns_->addRdata(createRdata(RRType::TXT(), zclass_, "ns.example.com"));
+ rrsets_->addRRset(ns_);
+ EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected);
+ checkIssues(); // no error/warning should be reported
+}
+
+TEST_F(ZoneCheckerTest, checkNSData) {
+ const Name ns_name("ns.example.com");
+
+ // If a ("in-bailiwick") NS name doesn't have an address record, it's
+ // reported as a warning.
+ rrsets_->removeRRset(ns_name, zclass_, RRType::A());
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_warns_.push_back("zone example.com/IN: NS has no address");
+ checkIssues();
+
+ // Same check, but disabling warning callback. Same result, but without
+ // the warning.
+ ZoneCheckerCallbacks nowarn_callbacks(
+ std::bind(&ZoneCheckerTest::callback, this, ph::_1, true), 0);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, nowarn_callbacks));
+ checkIssues();
+
+ // A tricky case: if the name matches a wildcard, it should technically
+ // be considered valid, but this checker doesn't check that far and still
+ // warns.
+ RRsetPtr wild(new RRset(Name("*.example.com"), zclass_, RRType::A(),
+ RRTTL(0)));
+ wild->addRdata(in::A("192.0.2.255"));
+ rrsets_->addRRset(wild);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_warns_.push_back("zone example.com/IN: NS has no address");
+ checkIssues();
+
+ // If there's a CNAME at the name instead, it's an error.
+ rrsets_->removeRRset(Name("*.example.com"), zclass_, RRType::A());
+ RRsetPtr cname(new RRset(ns_name, zclass_, RRType::CNAME(), RRTTL(60)));
+ cname->addRdata(generic::CNAME("cname.example.com."));
+ rrsets_->addRRset(cname);
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_errors_.push_back("zone example.com/IN: NS 'ns.example.com' is "
+ "a CNAME (illegal per RFC2181)");
+ checkIssues();
+
+ // It doesn't have to be A. An AAAA is enough.
+ rrsets_->removeRRset(ns_name, zclass_, RRType::CNAME());
+ RRsetPtr aaaa(new RRset(ns_name, zclass_, RRType::AAAA(), RRTTL(60)));
+ aaaa->addRdata(in::AAAA("2001:db8::1"));
+ rrsets_->addRRset(aaaa);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ checkIssues();
+
+ // Coexisting CNAME makes it error (CNAME with other record is itself
+ // invalid, but it's a different issue in this context)
+ rrsets_->addRRset(cname);
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_errors_.push_back("zone example.com/IN: NS 'ns.example.com' is "
+ "a CNAME (illegal per RFC2181)");
+ checkIssues();
+
+ // It doesn't matter if the NS name is "out of bailiwick".
+ rrsets_->removeRRset(ns_name, zclass_, RRType::CNAME());
+ rrsets_->removeRRset(zname_, zclass_, RRType::NS());
+ ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60)));
+ ns_->addRdata(generic::NS("ns.example.org."));
+ rrsets_->addRRset(ns_);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ checkIssues();
+
+ // Note that if the NS name is the origin name, it should be checked
+ rrsets_->removeRRset(zname_, zclass_, RRType::NS());
+ ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60)));
+ ns_->addRdata(generic::NS(zname_));
+ rrsets_->addRRset(ns_);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_warns_.push_back("zone example.com/IN: NS has no address");
+ checkIssues();
+}
+
+TEST_F(ZoneCheckerTest, checkNSWithDelegation) {
+ // Tests various cases where there's a zone cut due to delegation between
+ // the zone origin and the NS name. In each case the NS name doesn't have
+ // an address record.
+ const Name ns_name("ns.child.example.com");
+
+ // Zone cut due to delegation in the middle; the check for the address
+ // record should be skipped.
+ rrsets_->removeRRset(zname_, zclass_, RRType::NS());
+ ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60)));
+ ns_->addRdata(generic::NS(ns_name));
+ rrsets_->addRRset(ns_);
+ RRsetPtr child_ns(new RRset(Name("child.example.com"), zclass_,
+ RRType::NS(), RRTTL(60)));
+ child_ns->addRdata(generic::NS("ns.example.org."));
+ rrsets_->addRRset(child_ns);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ checkIssues();
+
+ // Zone cut at the NS name. Same result.
+ rrsets_->removeRRset(child_ns->getName(), zclass_, RRType::NS());
+ child_ns.reset(new RRset(ns_name, zclass_, RRType::NS(), RRTTL(60)));
+ child_ns->addRdata(generic::NS("ns.example.org."));
+ rrsets_->addRRset(child_ns);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ checkIssues();
+
+ // Zone cut below the NS name. The check applies.
+ rrsets_->removeRRset(child_ns->getName(), zclass_, RRType::NS());
+ child_ns.reset(new RRset(Name("another.ns.child.example.com"), zclass_,
+ RRType::NS(), RRTTL(60)));
+ child_ns->addRdata(generic::NS("ns.example.org."));
+ rrsets_->addRRset(child_ns);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_warns_.push_back("zone example.com/IN: NS has no address");
+ checkIssues();
+}
+
+TEST_F(ZoneCheckerTest, checkNSWithDNAME) {
+ // Similar to the above case, but the zone cut is due to DNAME. This is
+ // an invalid configuration.
+ const Name ns_name("ns.child.example.com");
+
+ // Zone cut due to DNAME at the zone origin. This is an invalid case.
+ rrsets_->removeRRset(zname_, zclass_, RRType::NS());
+ ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60)));
+ ns_->addRdata(generic::NS(ns_name));
+ rrsets_->addRRset(ns_);
+ RRsetPtr dname(new RRset(zname_, zclass_, RRType::DNAME(), RRTTL(60)));
+ dname->addRdata(generic::DNAME("example.org."));
+ rrsets_->addRRset(dname);
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_errors_.push_back("zone example.com/IN: NS 'ns.child.example.com'"
+ " is below a DNAME 'example.com'");
+ checkIssues();
+
+ // Zone cut due to DNAME in the middle. Same result.
+ rrsets_->removeRRset(zname_, zclass_, RRType::DNAME());
+ dname.reset(new RRset(Name("child.example.com"), zclass_, RRType::DNAME(),
+ RRTTL(60)));
+ dname->addRdata(generic::DNAME("example.org."));
+ rrsets_->addRRset(dname);
+ EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_errors_.push_back("zone example.com/IN: NS 'ns.child.example.com'"
+ " is below a DNAME 'child.example.com'");
+ checkIssues();
+
+ // A tricky case: there's also an NS at the name that has DNAME. It's
+ // prohibited per RFC6672 so we could say it's "undefined". Nevertheless,
+ // this implementation prefers the NS and skips further checks.
+ ns_.reset(new RRset(Name("child.example.com"), zclass_, RRType::NS(),
+ RRTTL(60)));
+ ns_->addRdata(generic::NS("ns.example.org."));
+ rrsets_->addRRset(ns_);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ checkIssues();
+
+ // Zone cut due to DNAME at the NS name. In this case DNAME doesn't
+ // affect the NS name, so it should result in "no address record" warning.
+ rrsets_->removeRRset(dname->getName(), zclass_, RRType::DNAME());
+ rrsets_->removeRRset(ns_->getName(), zclass_, RRType::NS());
+ dname.reset(new RRset(ns_name, zclass_, RRType::DNAME(), RRTTL(60)));
+ dname->addRdata(generic::DNAME("example.org."));
+ rrsets_->addRRset(dname);
+ EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_));
+ expected_warns_.push_back("zone example.com/IN: NS has no address");
+ checkIssues();
+}
+
+}