diff --git a/Knot.files b/Knot.files
index 552f82c4b59d30831b4ceef92837d62ffc056901..c9c1621931e06182686c16328f034f465d6911c1 100644
--- a/Knot.files
+++ b/Knot.files
@@ -216,3 +216,17 @@ src/dnslib/dname-table.h
 src/dnslib/dname-table.c
 src/common/general-tree.h
 src/common/general-tree.c
+src/dnslib/tests/dnslib/dname_table_tests.h
+src/dnslib/tests/dnslib/dname_table_tests.c
+src/dnslib/tests/dnslib/packet_tests.c
+src/dnslib/tests/dnslib/packet_tests.h
+src/dnslib/tests/realdata/dnslib/packet_tests_realdata.c
+src/dnslib/tests/realdata/dnslib/packet_tests_realdata.h
+src/dnslib/tests/dnslib/response2_tests.c
+src/dnslib/tests/dnslib/response2_tests.h
+src/dnslib/tests/realdata/dnslib/response2_tests_realdata.c
+src/dnslib/tests/realdata/dnslib/response2_tests_realdata.h
+src/dnslib/tests/dnslib/query_tests.c
+src/dnslib/tests/dnslib/query_tests.h
+src/dnslib/tests/dnslib/nsec3_tests.c
+src/dnslib/tests/dnslib/nsec3_tests.h
diff --git a/scripts/parse_dump.py b/scripts/parse_dump.py
index 7f71950d7a843dfa035b30dc565e7022e6488107..d9cc44b6998ca68fad2f8d4c2e32ae97ebac5020 100755
--- a/scripts/parse_dump.py
+++ b/scripts/parse_dump.py
@@ -106,6 +106,9 @@ def chop_and_write_packet(packet):
 	fp.write(pack('H', packet.ancount))
 	fp.write(pack('H', packet.nscount))
 	fp.write(pack('H', packet.arcount))
+	
+#write query flag
+	fp.write(pack('H', packet.qr))
 
 	chop_and_write_section_query(packet.qd)
 	chop_and_write_section_response(packet.an)
@@ -122,6 +125,7 @@ fp.write(pack('L', total_length))
 for packet in packets:
 	try:
 		data = a2b_hex(str(packet['DNS']).encode('hex'))
+		fr.write(pack('H', packet.qr))
 		fr.write(pack('H', len(data)))
 		fr.write(data)
 		chop_and_write_packet(packet['DNS'])
diff --git a/src/Makefile.am b/src/Makefile.am
index d4866d5c09a4f5734975a6d1c1c716034a42cdfe..8e7957c7e9998cf35e3f399f68771e4a9b490e11 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,15 +11,19 @@ libknotd_la_LFLAGS = # TODO: reentrant parser, prefix
 
 BUILT_SOURCES =					\
 	dnslib/tests/parsed_data.rc		\
+	dnslib/tests/realdata/parsed_data.rc	\
 	dnslib/tests/raw_data_queries.rc	\
 	dnslib/tests/raw_data.rc		\
+	dnslib/tests/realdata/raw_data.rc	\
 	dnslib/tests/parsed_data_queries.rc     \
 	tests/sample_conf.rc
 
 CLEANFILES =					\
 	dnslib/tests/parsed_data.rc		\
+	dnslib/tests/realdata/parsed_data.rc	\
 	dnslib/tests/raw_data_queries.rc	\
 	dnslib/tests/raw_data.rc		\
+	dnslib/tests/realdata/raw_data.rc	\
 	dnslib/tests/parsed_data_queries.rc     \
 	tests/sample_conf.rc                    \
 	zparser.h				\
@@ -70,9 +74,12 @@ unittests_dnslib_realdata_SOURCES =			\
 	dnslib/tests/realdata/dnslib/node_tests_realdata.c	\
 	dnslib/tests/realdata/dnslib/rdata_tests_realdata.c	\
 	dnslib/tests/realdata/dnslib/response_tests_realdata.c	\
+	dnslib/tests/realdata/dnslib/response2_tests_realdata.c	\
 	dnslib/tests/realdata/dnslib/rrset_tests_realdata.c	\
 	dnslib/tests/realdata/dnslib/zone_tests_realdata.c	\
 	dnslib/tests/realdata/dnslib/zonedb_tests_realdata.c	\
+	dnslib/tests/realdata/dnslib/packet_tests_realdata.h	\
+	dnslib/tests/realdata/dnslib/packet_tests_realdata.c	\
 	dnslib/tests/realdata/dnslib_tests_loader_realdata.h	\
 	dnslib/tests/realdata/dnslib_tests_loader_realdata.c	\
 	dnslib/tests/realdata/unittests_dnslib_realdata.c
@@ -82,6 +89,14 @@ unittests_dnslib_SOURCES =			\
 	dnslib/tests/dnslib/cuckoo_tests.h	\
 	dnslib/tests/dnslib/dname_tests.c	\
 	dnslib/tests/dnslib/dname_tests.h	\
+	dnslib/tests/dnslib/dname_table_tests.h	\
+	dnslib/tests/dnslib/dname_table_tests.c	\
+	dnslib/tests/dnslib/nsec3_tests.h	\
+	dnslib/tests/dnslib/nsec3_tests.c	\
+	dnslib/tests/dnslib/packet_tests.h	\
+	dnslib/tests/dnslib/packet_tests.c	\
+	dnslib/tests/dnslib/query_tests.h	\
+	dnslib/tests/dnslib/query_tests.c	\
 	dnslib/tests/dnslib/edns_tests.c	\
 	dnslib/tests/dnslib/edns_tests.h	\
 	dnslib/tests/dnslib/node_tests.c	\
@@ -90,6 +105,8 @@ unittests_dnslib_SOURCES =			\
 	dnslib/tests/dnslib/rdata_tests.h	\
 	dnslib/tests/dnslib/rrset_tests.c	\
 	dnslib/tests/dnslib/rrset_tests.h	\
+	dnslib/tests/dnslib/response2_tests.h	\
+	dnslib/tests/dnslib/response2_tests.c	\
 	dnslib/tests/dnslib/zone_tests.c	\
 	dnslib/tests/dnslib/zone_tests.h	\
 	dnslib/tests/dnslib/zonedb_tests.c	\
@@ -273,6 +290,9 @@ unittests_dnslib_realdata_LDADD = libknot.la libknots.la @LIBOBJS@
 dnslib/tests/parsed_data.rc: dnslib/tests/files/parsed_data
 	../resource.sh dnslib/tests/files/parsed_data >$@
 
+dnslib/tests/realdata/parsed_data.rc: dnslib/tests/realdata/files/parsed_data
+	../resource.sh dnslib/tests/realdata/files/parsed_data >$@
+
 dnslib/tests/parsed_data_queries.rc: dnslib/tests/files/parsed_data_queries
 	../resource.sh dnslib/tests/files/parsed_data_queries >$@
 
@@ -282,6 +302,9 @@ dnslib/tests/raw_data_queries.rc: dnslib/tests/files/raw_data_queries
 dnslib/tests/raw_data.rc: dnslib/tests/files/raw_data
 	../resource.sh dnslib/tests/files/raw_data >$@
 
+dnslib/tests/realdata/raw_data.rc: dnslib/tests/realdata/files/raw_data
+	../resource.sh dnslib/tests/realdata/files/raw_data >$@
+
 tests/sample_conf.rc: tests/files/sample_conf
 	../resource.sh tests/files/sample_conf >$@
 
diff --git a/src/common/evqueue.c b/src/common/evqueue.c
index 54f1f6da0e2d53e7374bab65eb53ce1eca243b9d..e70998b3953f1d6ac8a5c3171fb9a54034b145bf 100644
--- a/src/common/evqueue.c
+++ b/src/common/evqueue.c
@@ -37,6 +37,11 @@ void evqueue_free(evqueue_t **q)
 	free(eq);
 }
 
+int evqueue_pollfd(evqueue_t *q)
+{
+	return q->fds[EVQUEUE_READFD];
+}
+
 int evqueue_poll(evqueue_t *q, const struct timespec *ts,
 		 const sigset_t *sigmask)
 {
diff --git a/src/common/evqueue.h b/src/common/evqueue.h
index d5eed9d0b931384248cbbdc9107473dce0dc1cc3..c5d9205448aaeee38a1ec330b3046bead8447ff1 100644
--- a/src/common/evqueue.h
+++ b/src/common/evqueue.h
@@ -83,6 +83,16 @@ evqueue_t *evqueue_new();
  */
 void evqueue_free(evqueue_t **q);
 
+/*!
+ * \brief Return evqueue pollable fd.
+ *
+ * \param q Event queue.
+ *
+ * \retval File descriptor available for polling.
+ * \retval -1 On error.
+ */
+int evqueue_pollfd(evqueue_t *q);
+
 /*!
  * \brief Poll for new events.
  *
diff --git a/src/dnslib/dname.c b/src/dnslib/dname.c
index fb51b80d1d42914f41163ed9cdccbd1846b77eb4..e0edd8a0920313d7db40e2da5f08f2dc52dfc2a1 100644
--- a/src/dnslib/dname.c
+++ b/src/dnslib/dname.c
@@ -680,6 +680,13 @@ void dnslib_dname_update_node(dnslib_dname_t *dname)
 
 /*----------------------------------------------------------------------------*/
 
+void dnslib_dname_set_node(dnslib_dname_t *dname, dnslib_node_t *node)
+{
+	dname->node = node;
+}
+
+/*----------------------------------------------------------------------------*/
+
 int dnslib_dname_is_fqdn(const dnslib_dname_t *dname)
 {
 	return (dname->name[dname->size - 1] == '\0');
diff --git a/src/dnslib/dname.h b/src/dnslib/dname.h
index df2d6feece3f49466cade28b64c38acbf811e6ac..739142fb320d27836de39be9805f926acdbc1484 100644
--- a/src/dnslib/dname.h
+++ b/src/dnslib/dname.h
@@ -204,6 +204,8 @@ void dnslib_dname_set_node(dnslib_dname_t *dname, struct dnslib_node *node);
 
 void dnslib_dname_update_node(dnslib_dname_t *dname);
 
+void dnslib_dname_set_node(dnslib_dname_t *dname, struct dnslib_node *node);
+
 /*!
  * \brief Checks if the given domain name is a fully-qualified domain name.
  *
diff --git a/src/dnslib/edns.c b/src/dnslib/edns.c
index 6f51044c16e0bdcefed5748d44a5113568412055..e240d7e48059a5369483fb21b0acefac5ec8c0af 100644
--- a/src/dnslib/edns.c
+++ b/src/dnslib/edns.c
@@ -182,6 +182,7 @@ int dnslib_edns_new_from_rr(dnslib_opt_rr_t *opt_rr,
 
 uint16_t dnslib_edns_get_payload(const dnslib_opt_rr_t *opt_rr)
 {
+	assert(opt_rr != NULL);
 	return opt_rr->payload;
 }
 
@@ -190,6 +191,7 @@ uint16_t dnslib_edns_get_payload(const dnslib_opt_rr_t *opt_rr)
 void dnslib_edns_set_payload(dnslib_opt_rr_t *opt_rr,
                              uint16_t payload)
 {
+	assert(opt_rr != NULL);
 	opt_rr->payload = payload;
 }
 
@@ -203,8 +205,9 @@ uint8_t dnslib_edns_get_ext_rcode(const dnslib_opt_rr_t *opt_rr)
 /*----------------------------------------------------------------------------*/
 
 void dnslib_edns_set_ext_rcode(dnslib_opt_rr_t *opt_rr,
-                                             uint8_t ext_rcode)
+                               uint8_t ext_rcode)
 {
+	assert(opt_rr != NULL);
 	opt_rr->ext_rcode = ext_rcode;
 }
 
@@ -212,6 +215,7 @@ void dnslib_edns_set_ext_rcode(dnslib_opt_rr_t *opt_rr,
 
 uint8_t dnslib_edns_get_version(const dnslib_opt_rr_t *opt_rr)
 {
+	assert(opt_rr != NULL);
 	return opt_rr->version;
 }
 
@@ -220,6 +224,7 @@ uint8_t dnslib_edns_get_version(const dnslib_opt_rr_t *opt_rr)
 void dnslib_edns_set_version(dnslib_opt_rr_t *opt_rr,
                                            uint8_t version)
 {
+	assert(opt_rr != NULL);
 	opt_rr->version = version;
 }
 
@@ -227,6 +232,7 @@ void dnslib_edns_set_version(dnslib_opt_rr_t *opt_rr,
 
 uint16_t dnslib_edns_get_flags(const dnslib_opt_rr_t *opt_rr)
 {
+	assert(opt_rr != NULL);
 	return opt_rr->flags;
 }
 
@@ -234,6 +240,10 @@ uint16_t dnslib_edns_get_flags(const dnslib_opt_rr_t *opt_rr)
 
 int dnslib_edns_do(const dnslib_opt_rr_t *opt_rr)
 {
+	if (opt_rr == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	debug_dnslib_edns("Flags: %u\n", opt_rr->flags);
 	return (opt_rr->flags & DNSLIB_EDNS_DO_MASK);
 }
@@ -242,6 +252,10 @@ int dnslib_edns_do(const dnslib_opt_rr_t *opt_rr)
 
 void dnslib_edns_set_do(dnslib_opt_rr_t *opt_rr)
 {
+	if (opt_rr == NULL) {
+		return;
+	}
+
 	opt_rr->flags |= DNSLIB_EDNS_DO_MASK;
 }
 
@@ -250,6 +264,10 @@ void dnslib_edns_set_do(dnslib_opt_rr_t *opt_rr)
 int dnslib_edns_add_option(dnslib_opt_rr_t *opt_rr, uint16_t code,
                            uint16_t length, const uint8_t *data)
 {
+	if (opt_rr == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	if (opt_rr->option_count == opt_rr->options_max) {
 		dnslib_opt_option_t *options_new =
 			(dnslib_opt_option_t *)calloc(
@@ -283,6 +301,10 @@ int dnslib_edns_add_option(dnslib_opt_rr_t *opt_rr, uint16_t code,
 
 int dnslib_edns_has_option(const dnslib_opt_rr_t *opt_rr, uint16_t code)
 {
+	if (opt_rr == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	int i = 0;
 	while (i < opt_rr->option_count && opt_rr->options[i].code != code) {
 		++i;
@@ -298,6 +320,10 @@ int dnslib_edns_has_option(const dnslib_opt_rr_t *opt_rr, uint16_t code)
 short dnslib_edns_to_wire(const dnslib_opt_rr_t *opt_rr, uint8_t *wire,
                           size_t max_size)
 {
+	if (opt_rr == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	assert(DNSLIB_EDNS_MIN_SIZE <= max_size);
 
 	if (max_size < opt_rr->size) {
@@ -340,6 +366,10 @@ short dnslib_edns_to_wire(const dnslib_opt_rr_t *opt_rr, uint8_t *wire,
 
 short dnslib_edns_size(dnslib_opt_rr_t *opt_rr)
 {
+	if (opt_rr == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	return opt_rr->size;
 }
 
diff --git a/src/dnslib/edns.h b/src/dnslib/edns.h
index 491e841cad5002be0a33889909da1dbb58028f3d..0983a10082368475eca47fc0e8033c7c1ac1fee7 100644
--- a/src/dnslib/edns.h
+++ b/src/dnslib/edns.h
@@ -97,6 +97,10 @@ int dnslib_edns_new_from_rr(dnslib_opt_rr_t *opt_rr,
 /*!
  * \brief Returns the UDP payload stored in the OPT RR.
  *
+ * \warning This function does not check the parameter, so ensure to check it
+ *          before calling the function. It must not be NULL.
+ * \note There is an assert() for debug checking of the parameter.
+ *
  * \param opt_rr OPT RR structure to get the payload from.
  *
  * \return UDP payload in bytes.
@@ -106,6 +110,10 @@ uint16_t dnslib_edns_get_payload(const dnslib_opt_rr_t *opt_rr);
 /*!
  * \brief Sets the UDP payload field in the OPT RR.
  *
+ * \warning This function does not check the parameter, so ensure to check it
+ *          before calling the function. It must not be NULL.
+ * \note There is an assert() for debug checking of the parameter.
+ *
  * \param opt_rr OPT RR structure to set the payload to.
  * \param payload UDP payload in bytes.
  */
@@ -114,6 +122,10 @@ void dnslib_edns_set_payload(dnslib_opt_rr_t *opt_rr, uint16_t payload);
 /*!
  * \brief Returns the Extended RCODE stored in the OPT RR.
  *
+ * \warning This function does not check the parameter, so ensure to check it
+ *          before calling the function. It must not be NULL.
+ * \note There is an assert() for debug checking of the parameter.
+ *
  * \param opt_rr OPT RR structure to get the Extended RCODE from.
  *
  * \return Extended RCODE.
@@ -123,6 +135,10 @@ uint8_t dnslib_edns_get_ext_rcode(const dnslib_opt_rr_t *opt_rr);
 /*!
  * \brief Sets the Extended RCODE field in the OPT RR.
  *
+ * \warning This function does not check the parameter, so ensure to check it
+ *          before calling the function. It must not be NULL.
+ * \note There is an assert() for debug checking of the parameter.
+ *
  * \param opt_rr OPT RR structure to set the Extended RCODE to.
  * \param ext_rcode Extended RCODE to set.
  */
@@ -131,6 +147,10 @@ void dnslib_edns_set_ext_rcode(dnslib_opt_rr_t *opt_rr, uint8_t ext_rcode);
 /*!
  * \brief Returns the EDNS version stored in the OPT RR.
  *
+ * \warning This function does not check the parameter, so ensure to check it
+ *          before calling the function. It must not be NULL.
+ * \note There is an assert() for debug checking of the parameter.
+ *
  * \param opt_rr OPT RR structure to get the EDNS version from.
  *
  * \return EDNS version.
@@ -140,6 +160,10 @@ uint8_t dnslib_edns_get_version(const dnslib_opt_rr_t *opt_rr);
 /*!
  * \brief Sets the EDNS version field in the OPT RR.
  *
+ * \warning This function does not check the parameter, so ensure to check it
+ *          before calling the function. It must not be NULL.
+ * \note There is an assert() for debug checking of the parameter.
+ *
  * \param opt_rr OPT RR structure to set the EDNS version to.
  * \param version EDNS version to set.
  */
@@ -148,6 +172,10 @@ void dnslib_edns_set_version(dnslib_opt_rr_t *opt_rr, uint8_t version);
 /*!
  * \brief Returns the flags stored in the OPT RR.
  *
+ * \warning This function does not check the parameter, so ensure to check it
+ *          before calling the function. It must not be NULL.
+ * \note There is an assert() for debug checking of the parameter.
+ *
  * \param opt_rr OPT RR structure to get the flags from.
  *
  * \return EDNS flags.
diff --git a/src/dnslib/packet.c b/src/dnslib/packet.c
index d7b5aa45bb7863d4cf8d15a6b6c2c9397260fc21..563fd6526f118199a77513098055d00be4dc510a 100644
--- a/src/dnslib/packet.c
+++ b/src/dnslib/packet.c
@@ -815,6 +815,10 @@ int dnslib_packet_parse_from_wire(dnslib_packet_t *packet,
 
 int dnslib_packet_parse_rest(dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	if (packet->parsed >= packet->size) {
 		return DNSLIB_EOK;
 	}
@@ -829,7 +833,7 @@ int dnslib_packet_parse_rest(dnslib_packet_t *packet)
 int dnslib_packet_parse_next_rr_answer(dnslib_packet_t *packet,
                                        dnslib_rrset_t **rr)
 {
-	if (packet == NULL) {
+	if (packet == NULL || rr == NULL) {
 		return DNSLIB_EBADARG;
 	}
 
@@ -893,6 +897,7 @@ int dnslib_packet_set_max_size(dnslib_packet_t *packet, int max_size)
 
 uint16_t dnslib_packet_id(const dnslib_packet_t *packet)
 {
+	assert(packet != NULL);
 	return packet->header.id;
 }
 
@@ -900,6 +905,7 @@ uint16_t dnslib_packet_id(const dnslib_packet_t *packet)
 
 uint8_t dnslib_packet_opcode(const dnslib_packet_t *packet)
 {
+	assert(packet != NULL);
 	return dnslib_wire_flags_get_opcode(packet->header.flags1);
 }
 
@@ -907,6 +913,10 @@ uint8_t dnslib_packet_opcode(const dnslib_packet_t *packet)
 
 const dnslib_dname_t *dnslib_packet_qname(const dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return NULL;
+	}
+
 	return packet->question.qname;
 }
 
@@ -914,6 +924,7 @@ const dnslib_dname_t *dnslib_packet_qname(const dnslib_packet_t *packet)
 
 uint16_t dnslib_packet_qtype(const dnslib_packet_t *packet)
 {
+	assert(packet != NULL);
 	return packet->question.qtype;
 }
 
@@ -921,6 +932,7 @@ uint16_t dnslib_packet_qtype(const dnslib_packet_t *packet)
 
 uint16_t dnslib_packet_qclass(const dnslib_packet_t *packet)
 {
+	assert(packet != NULL);
 	return packet->question.qclass;
 }
 
@@ -928,6 +940,10 @@ uint16_t dnslib_packet_qclass(const dnslib_packet_t *packet)
 
 int dnslib_packet_is_query(const dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	return (dnslib_wire_flags_get_qr(packet->header.flags1) == 0);
 }
 
@@ -935,6 +951,10 @@ int dnslib_packet_is_query(const dnslib_packet_t *packet)
 
 const dnslib_packet_t *dnslib_packet_query(const dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return NULL;
+	}
+
 	return packet->query;
 }
 
@@ -942,6 +962,10 @@ const dnslib_packet_t *dnslib_packet_query(const dnslib_packet_t *packet)
 
 short dnslib_packet_answer_rrset_count(const dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	return packet->an_rrsets;
 }
 
@@ -949,6 +973,10 @@ short dnslib_packet_answer_rrset_count(const dnslib_packet_t *packet)
 
 short dnslib_packet_authority_rrset_count(const dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	return packet->ns_rrsets;
 }
 
@@ -956,6 +984,10 @@ short dnslib_packet_authority_rrset_count(const dnslib_packet_t *packet)
 
 short dnslib_packet_additional_rrset_count(const dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	return packet->ar_rrsets;
 }
 
@@ -964,7 +996,7 @@ short dnslib_packet_additional_rrset_count(const dnslib_packet_t *packet)
 const dnslib_rrset_t *dnslib_packet_answer_rrset(
 	const dnslib_packet_t *packet, short pos)
 {
-	if (pos > packet->an_rrsets) {
+	if (packet == NULL || pos > packet->an_rrsets) {
 		return NULL;
 	}
 
@@ -976,7 +1008,7 @@ const dnslib_rrset_t *dnslib_packet_answer_rrset(
 const dnslib_rrset_t *dnslib_packet_authority_rrset(
 	dnslib_packet_t *packet, short pos)
 {
-	if (pos > packet->ns_rrsets) {
+	if (packet == NULL || pos > packet->ns_rrsets) {
 		return NULL;
 	}
 
@@ -988,7 +1020,7 @@ const dnslib_rrset_t *dnslib_packet_authority_rrset(
 const dnslib_rrset_t *dnslib_packet_additional_rrset(
 	dnslib_packet_t *packet, short pos)
 {
-	if (pos > packet->ar_rrsets) {
+	if (packet == NULL || pos > packet->ar_rrsets) {
 		return NULL;
 	}
 
@@ -1001,6 +1033,10 @@ int dnslib_packet_contains(const dnslib_packet_t *packet,
                            const dnslib_rrset_t *rrset,
                            dnslib_rrset_compare_type_t cmp)
 {
+	if (packet == NULL || rrset == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	for (int i = 0; i < packet->header.ancount; ++i) {
 		if (dnslib_rrset_compare(packet->answer[i], rrset, cmp)) {
 			return 1;
@@ -1027,6 +1063,10 @@ int dnslib_packet_contains(const dnslib_packet_t *packet,
 int dnslib_packet_add_tmp_rrset(dnslib_packet_t *packet,
                                 dnslib_rrset_t *tmp_rrset)
 {
+	if (packet == NULL || tmp_rrset == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	if (packet->tmp_rrsets_count == packet->tmp_rrsets_max
 	    && dnslib_packet_realloc_rrsets(&packet->tmp_rrsets,
 			&packet->tmp_rrsets_max,
@@ -1050,6 +1090,10 @@ int dnslib_packet_add_tmp_rrset(dnslib_packet_t *packet,
  */
 void dnslib_packet_free_tmp_rrsets(dnslib_packet_t *pkt)
 {
+	if (pkt == NULL) {
+		return;
+	}
+
 	for (int i = 0; i < pkt->tmp_rrsets_count; ++i) {
 DEBUG_DNSLIB_PACKET(
 		char *name = dnslib_dname_to_str(
@@ -1075,6 +1119,10 @@ DEBUG_DNSLIB_PACKET(
 void dnslib_packet_header_to_wire(const dnslib_header_t *header,
                                   uint8_t **pos, size_t *size)
 {
+	if (header == NULL || pos == NULL || *pos == NULL || size == NULL) {
+		return;
+	}
+
 	dnslib_wire_set_id(*pos, header->id);
 	dnslib_wire_set_flags1(*pos, header->flags1);
 	dnslib_wire_set_flags2(*pos, header->flags2);
@@ -1091,6 +1139,10 @@ void dnslib_packet_header_to_wire(const dnslib_header_t *header,
 
 int dnslib_packet_question_to_wire(dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	if (packet->size > DNSLIB_WIRE_HEADER_SIZE) {
 		return DNSLIB_ERROR;
 	}
@@ -1126,13 +1178,19 @@ int dnslib_packet_question_to_wire(dnslib_packet_t *packet)
 
 /*----------------------------------------------------------------------------*/
 
-void dnslib_packet_edns_to_wire(dnslib_packet_t *packet)
+int dnslib_packet_edns_to_wire(dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	packet->size += dnslib_edns_to_wire(&packet->opt_rr,
 	                                  packet->wireformat + packet->size,
 	                                  packet->max_size - packet->size);
 
 	packet->header.arcount += 1;
+
+	return DNSLIB_EOK;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -1202,47 +1260,10 @@ void dnslib_packet_free(dnslib_packet_t **packet)
 static void dnslib_packet_dump_rrsets(const dnslib_rrset_t **rrsets,
                                       int count)
 {
+	assert(rrsets != NULL && *rrsets != NULL);
+
 	for (int i = 0; i < count; ++i) {
-		debug_dnslib_packet("  RRSet %d:\n", i + 1);
-		char *name = dnslib_dname_to_str(rrsets[i]->owner);
-		debug_dnslib_packet("    Owner: %s\n", name);
-		free(name);
-		debug_dnslib_packet("    Type: %s\n",
-		                      dnslib_rrtype_to_string(rrsets[i]->type));
-		debug_dnslib_packet("    Class: %s\n",
-		                   dnslib_rrclass_to_string(rrsets[i]->rclass));
-		debug_dnslib_packet("    TTL: %d\n", rrsets[i]->ttl);
-		debug_dnslib_packet("    RDATA: ");
-
-		dnslib_rrtype_descriptor_t *desc =
-			dnslib_rrtype_descriptor_by_type(rrsets[i]->type);
-
-		const dnslib_rdata_t *rdata = dnslib_rrset_rdata(rrsets[i]);
-		while (rdata != NULL) {
-			for (int j = 0; j < rdata->count; ++j) {
-				switch (desc->wireformat[j]) {
-				case DNSLIB_RDATA_WF_COMPRESSED_DNAME:
-				case DNSLIB_RDATA_WF_LITERAL_DNAME:
-				case DNSLIB_RDATA_WF_UNCOMPRESSED_DNAME:
-					name = dnslib_dname_to_str(
-						rdata->items[j].dname);
-					debug_dnslib_packet("%s \n",name);
-					free(name);
-					break;
-				case DNSLIB_RDATA_WF_BINARYWITHLENGTH:
-					debug_dnslib_packet_hex(
-					    (char *)rdata->items[j].raw_data,
-					    rdata->items[j].raw_data[0]);
-					break;
-				default:
-					debug_dnslib_packet_hex(
-					   (char *)&rdata->items[j].raw_data[1],
-					   rdata->items[j].raw_data[0]);
-					break;
-				}
-			}
-			rdata = dnslib_rrset_rdata_next(rrsets[i], rdata);
-		}
+		dnslib_rrset_dump(rrsets[i], 0);
 	}
 }
 #endif
@@ -1250,6 +1271,10 @@ static void dnslib_packet_dump_rrsets(const dnslib_rrset_t **rrsets,
 
 void dnslib_packet_dump(const dnslib_packet_t *packet)
 {
+	if (packet == NULL) {
+		return;
+	}
+
 #ifdef DNSLIB_PACKET_DEBUG
 	debug_dnslib_packet("DNS packet:\n-----------------------------\n");
 
diff --git a/src/dnslib/packet.h b/src/dnslib/packet.h
index 3d91b1849ac4515b66490dc65f61646ae342db29..1f4f439e9658e90cfbc76a427118f1db18aaa581 100644
--- a/src/dnslib/packet.h
+++ b/src/dnslib/packet.h
@@ -430,7 +430,8 @@ void dnslib_packet_free_tmp_rrsets(dnslib_packet_t *pkt);
  *       the size of the converted wire format.
  *
  * \param[in] header DNS header structure to convert.
- * \param[out] pos Position where to put the converted header.
+ * \param[out] pos Position where to put the converted header. The space has
+ *                 to be allocated before calling this function.
  * \param[out] size Size of the wire format of the header in bytes.
  */
 void dnslib_packet_header_to_wire(const dnslib_header_t *header,
@@ -444,7 +445,7 @@ int dnslib_packet_question_to_wire(dnslib_packet_t *packet);
  *
  * \param resp Response structure.
  */
-void dnslib_packet_edns_to_wire(dnslib_packet_t *packet);
+int dnslib_packet_edns_to_wire(dnslib_packet_t *packet);
 
 /*!
  * \brief Converts the packet to wire format.
diff --git a/src/dnslib/response2.c b/src/dnslib/response2.c
index cceafe1b699604c9b4cc187d02783c85010e7cdc..53448373b7c158a5484c912325d72784c8a7c979 100644
--- a/src/dnslib/response2.c
+++ b/src/dnslib/response2.c
@@ -186,7 +186,7 @@ DEBUG_DNSLIB_RESPONSE(
 	size_t parent_pos = pos;
 	int i = 0;
 
-	while (to_save != NULL) {
+	while (to_save != NULL && i < dnslib_dname_label_count(dname)) {
 		if (i == not_matched) {
 			parent_pos = unmatched_offset;
 		}
@@ -782,6 +782,10 @@ static int dnslib_response_realloc_rrsets(const dnslib_rrset_t ***rrsets,
 
 int dnslib_response2_init(dnslib_packet_t *response)
 {
+	if (response == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	if (response->max_size < DNSLIB_WIRE_HEADER_SIZE) {
 		return DNSLIB_ESPACE;
 	}
@@ -801,6 +805,10 @@ int dnslib_response2_init(dnslib_packet_t *response)
 int dnslib_response2_init_from_query(dnslib_packet_t *response,
                                     dnslib_packet_t *query)
 {
+	if (response == NULL || query == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	// copy the header from the query
 	memcpy(&response->header, &query->header, sizeof(dnslib_header_t));
 
@@ -842,6 +850,10 @@ int dnslib_response2_init_from_query(dnslib_packet_t *response,
 
 void dnslib_response2_clear(dnslib_packet_t *resp, int clear_question)
 {
+	if (resp == NULL) {
+		return;
+	}
+
 	resp->size = (clear_question) ? DNSLIB_WIRE_HEADER_SIZE
 	              : DNSLIB_WIRE_HEADER_SIZE + 4
 	                + dnslib_dname_size(resp->question.qname);
@@ -985,10 +997,13 @@ int dnslib_response2_add_rrset_additional(dnslib_packet_t *response,
 		return DNSLIB_EBADARG;
 	}
 
+	int ret;
+
 	// if this is the first additional RRSet, add EDNS OPT RR first
 	if (response->header.arcount == 0
-	    && response->opt_rr.version != EDNS_NOT_SUPPORTED) {
-		dnslib_packet_edns_to_wire(response);
+	    && response->opt_rr.version != EDNS_NOT_SUPPORTED
+	    && (ret = dnslib_packet_edns_to_wire(response)) != DNSLIB_EOK) {
+		return ret;
 	}
 
 	if (response->ar_rrsets == response->max_ar_rrsets
@@ -1023,6 +1038,10 @@ int dnslib_response2_add_rrset_additional(dnslib_packet_t *response,
 
 void dnslib_response2_set_rcode(dnslib_packet_t *response, short rcode)
 {
+	if (response == NULL) {
+		return;
+	}
+
 	dnslib_wire_flags_set_rcode(&response->header.flags2, rcode);
 	dnslib_wire_set_rcode(response->wireformat, rcode);
 }
@@ -1031,6 +1050,10 @@ void dnslib_response2_set_rcode(dnslib_packet_t *response, short rcode)
 
 void dnslib_response2_set_aa(dnslib_packet_t *response)
 {
+	if (response == NULL) {
+		return;
+	}
+
 	dnslib_wire_flags_set_aa(&response->header.flags1);
 	dnslib_wire_set_aa(response->wireformat);
 }
@@ -1039,6 +1062,10 @@ void dnslib_response2_set_aa(dnslib_packet_t *response)
 
 void dnslib_response2_set_tc(dnslib_packet_t *response)
 {
+	if (response == NULL) {
+		return;
+	}
+
 	dnslib_wire_flags_set_tc(&response->header.flags1);
 	dnslib_wire_set_tc(response->wireformat);
 }
@@ -1048,6 +1075,10 @@ void dnslib_response2_set_tc(dnslib_packet_t *response)
 int dnslib_response2_add_nsid(dnslib_packet_t *response, const uint8_t *data,
                              uint16_t length)
 {
+	if (response == NULL) {
+		return DNSLIB_EBADARG;
+	}
+
 	return dnslib_edns_add_option(&response->opt_rr,
 	                              EDNS_OPTION_NSID, length, data);
 }
diff --git a/src/dnslib/tests/dnslib/dname_table_tests.c b/src/dnslib/tests/dnslib/dname_table_tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..3c263a851383549437b2f707755e9c936381b517
--- /dev/null
+++ b/src/dnslib/tests/dnslib/dname_table_tests.c
@@ -0,0 +1,378 @@
+/* blame: jan.kadlec@nic.cz */
+
+#include <assert.h>
+
+#include "dname_table_tests.h"
+#include "dnslib/error.h"
+#include "dnslib/dname-table.h"
+/* *test_t structures */
+#include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
+
+static int dnslib_dname_table_tests_count(int argc, char *argv[]);
+static int dnslib_dname_table_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api dname_table_tests_api = {
+	"Dname table",     //! Unit name
+	&dnslib_dname_table_tests_count,  //! Count scheduled tests
+	&dnslib_dname_table_tests_run     //! Run scheduled tests
+};
+
+/* Helper functions. */
+static dnslib_dname_t *dname_from_test_dname_str(const test_dname_t *test_dname)
+{
+	assert(test_dname != NULL);
+	dnslib_dname_t *ret = dnslib_dname_new_from_str (test_dname->str,
+						strlen(test_dname->str),
+						NULL);
+	CHECK_ALLOC(ret, NULL);
+
+	return ret;
+}
+
+static int dname_compare_sort_wrapper(const void *ptr1, const void *ptr2)
+{
+	const dnslib_dname_t *dname1 =
+		dname_from_test_dname_str((const test_dname_t *)ptr1);
+	const dnslib_dname_t *dname2 =
+		dname_from_test_dname_str((const test_dname_t *)ptr2);
+	assert(dname1 && dname2);
+	return dnslib_dname_compare(dname1, dname2);
+}
+
+/* Unit implementation. */
+enum {DNAME_TABLE_DNAME_COUNT = 3};
+
+/* Strings are enough, we're not testing dname here ... */
+static test_dname_t DNAME_TABLE_DNAMES[DNAME_TABLE_DNAME_COUNT] = {
+	/* list ptr, string, wire, length, labels, label_count */
+	{NULL, NULL, ".", NULL, 1, NULL, 0},
+	{NULL, NULL, "a.ns.nic.cz.", NULL, 13, NULL, 0},
+	{NULL, NULL, "b.ns.nic.cz.", NULL, 13, NULL, 0}
+};
+
+static int test_dname_table_new()
+{
+	dnslib_dname_table_t *table = dnslib_dname_table_new();
+	if (table == NULL) {
+		return 0;
+	}
+
+	dnslib_dname_table_free(&table);
+	return 1;
+}
+
+struct test_dname_table_arg {
+	/* Times two - safety measure. */
+	dnslib_dname_t *array[DNAME_TABLE_DNAME_COUNT * 2];
+	uint count;
+};
+
+static void save_dname_to_array(struct dname_table_node *node, void *data)
+{
+	assert(data);
+	struct test_dname_table_arg *arg = (struct test_dname_table_arg *)data;
+	arg->array[arg->count] = node->dname;
+	arg->count++;
+}
+
+static int test_dname_table_adding()
+{
+	int errors = 0;
+	dnslib_dname_table_t *table = dnslib_dname_table_new();
+	CHECK_ALLOC(table, 0);
+
+	/* Add NULL */
+	if (dnslib_dname_table_add_dname(table, NULL) != DNSLIB_EBADARG) {
+		diag("Adding NULL dname did not result in an error!");
+		errors++;
+	}
+
+	/* Add to NULL table*/
+	if (dnslib_dname_table_add_dname(NULL, NULL) != DNSLIB_EBADARG) {
+		diag("Adding to NULL table did not result in an error!");
+		errors++;
+	}
+
+	/* Add NULL */
+	if (dnslib_dname_table_add_dname2(table, NULL) != DNSLIB_EBADARG) {
+		diag("Adding NULL dname did not result in an error!");
+		errors++;
+	}
+
+	/* Add to NULL table*/
+	if (dnslib_dname_table_add_dname2(NULL, NULL) != DNSLIB_EBADARG) {
+		diag("Adding to NULL table did not result in an error!");
+		errors++;
+	}
+
+
+	/* Add valid dnames. */
+	for (int i = 0; i < DNAME_TABLE_DNAME_COUNT; i++) {
+		dnslib_dname_t *dname =
+			dname_from_test_dname_str(&DNAME_TABLE_DNAMES[i]);
+		if (!dname) {
+			diag("Could not create dname from test dname!");
+			errors++;
+			continue;
+		}
+		if (dnslib_dname_table_add_dname(table, dname) != DNSLIB_EOK) {
+			diag("Could not add dname! (%s)",
+			     DNAME_TABLE_DNAMES[i].str);
+			errors++;
+		}
+	}
+
+	/*
+	 * Using inorder traversal of the table,
+	 * create array containing dnames.
+	 */
+
+	struct test_dname_table_arg arg;
+	arg.count = 0;
+
+	dnslib_dname_table_tree_inorder_apply(table, save_dname_to_array, &arg);
+
+	if (arg.count != DNAME_TABLE_DNAME_COUNT) {
+		diag("Table contains too many dnames!");
+		/* No sense in continuing. */
+		dnslib_dname_table_deep_free(&table);
+		return 0;
+	}
+
+	/*
+	 * Check that inordered array is really sorted
+	 * and contains valid dnames.
+	 */
+	for (int i = 0; i < DNAME_TABLE_DNAME_COUNT; i++) {
+		assert(arg.array[i]);
+		const char *str = dnslib_dname_to_str(arg.array[i]);
+		if (str == NULL) {
+			diag("Wrong dname in table!");
+			errors++;
+			continue;
+		}
+
+		if (arg.array[i]->size !=
+		                DNAME_TABLE_DNAMES[i].size) {
+			diag("Wrong dname size in table!");
+			diag("Is: %u should be %u.",
+			     arg.array[i]->size,
+			     DNAME_TABLE_DNAMES[i].size);
+			errors++;
+			continue;
+		}
+
+		if (strncmp(str, DNAME_TABLE_DNAMES[i].str,
+		            DNAME_TABLE_DNAMES[i].size) != 0) {
+			diag("Wrong dname wire in table!");
+			errors++;
+		}
+	}
+
+	/* Now add one dname once again. It has to be the first item! */
+
+	if (dnslib_dname_table_add_dname(table,
+		dname_from_test_dname_str(&DNAME_TABLE_DNAMES[0])) !=
+	                                 DNSLIB_EOK) {
+		diag("Could not add dname to table once it's already there!");
+		/* Next test would not make sense. */
+		dnslib_dname_table_deep_free(&table);
+		return 0;
+	}
+
+	/*
+	 * After walking the table, there should now be
+	 * DNAME_TABLE_DNAME_COUNT + 1 items, with 2 identical
+	 * items at the beginning.
+	 */
+
+	memset(arg.array, 0,
+	       sizeof(dnslib_dname_t *) * DNAME_TABLE_DNAME_COUNT * 2);
+	arg.count = 0;
+	dnslib_dname_table_tree_inorder_apply(table, save_dname_to_array, &arg);
+
+	if (arg.count != DNAME_TABLE_DNAME_COUNT + 1) {
+		diag("Identical dname was not added!");
+		/* Again, next test would not make any sense. */
+		dnslib_dname_table_deep_free(&table);
+		return 0;
+	}
+
+	if (dnslib_dname_compare(arg.array[0], arg.array[1]) != 0) {
+		diag("First two dnames in table are not identical!");
+		errors++;
+	}
+
+	/* Delete table, wipe out array. */
+	dnslib_dname_table_deep_free(&table);
+	memset(arg.array, 0,
+	       sizeof(dnslib_dname_t *) * DNAME_TABLE_DNAME_COUNT * 2);
+	arg.count = 0;
+
+	table = dnslib_dname_table_new();
+	assert(table);
+
+	/*
+	 * Add dname with same content twice using dnslib_dname_table_add2 -
+	 * table should now only contain one item.
+	 */
+
+	dnslib_dname_t *tmp_dname =
+		dname_from_test_dname_str(&DNAME_TABLE_DNAMES[0]);
+	assert(tmp_dname);
+
+	if (dnslib_dname_table_add_dname2(table, &tmp_dname) != DNSLIB_EOK) {
+		diag("Could not add dname using dname_table_add_dname2!");
+		dnslib_dname_table_deep_free(&table);
+		dnslib_dname_free(&tmp_dname);
+		return 0;
+	}
+
+	tmp_dname = dname_from_test_dname_str(&DNAME_TABLE_DNAMES[0]);
+	assert(tmp_dname);
+
+	dnslib_dname_t *dname_before_add = tmp_dname;
+
+	if (dnslib_dname_table_add_dname2(table, &tmp_dname) != 1) {
+		diag("Could not add dname again using dname_table_add_dname2!");
+		dnslib_dname_table_deep_free(&table);
+		return 0;
+	}
+
+	if (tmp_dname == dname_before_add) {
+		diag("Dname was not freed after insertion!");
+		errors++;
+	}
+
+	dnslib_dname_table_tree_inorder_apply(table, save_dname_to_array, &arg);
+
+	if (arg.count != 1) {
+		diag("Add_dname2 has added dname when it shouldn't!");
+		errors++;
+	}
+
+	if (dnslib_dname_compare(tmp_dname, arg.array[0]) != 0) {
+		diag("Add_dname2 has added wrong dname!");
+		errors++;
+	}
+
+	dnslib_dname_table_deep_free(&table);
+	return (errors == 0);
+}
+
+static int test_dname_table_find()
+{
+	int errors = 0;
+	dnslib_dname_table_t *table = dnslib_dname_table_new();
+	assert(table);
+
+	if (dnslib_dname_table_find_dname(table, NULL) != NULL) {
+		diag("Dname table did not return NULL when searching NULL!");
+		errors++;
+	}
+
+	if (dnslib_dname_table_find_dname(NULL, NULL) != NULL) {
+		diag("Passing NULL instead of dname table did not "
+		     "return NULL!");
+		errors++;
+	}
+
+	/* Add all dnames but the last one. */
+	for (int i = 0; i < DNAME_TABLE_DNAME_COUNT - 1; i++) {
+		dnslib_dname_t *dname =
+			dname_from_test_dname_str(&DNAME_TABLE_DNAMES[i]);
+		if (!dname) {
+			diag("Could not create dname from test dname!");
+			errors++;
+			continue;
+		}
+		if (dnslib_dname_table_add_dname(table, dname) != DNSLIB_EOK) {
+			diag("Could not add dname! (%s)",
+			     DNAME_TABLE_DNAMES[i].str);
+			errors++;
+		}
+	}
+
+	/* Search for added dnames. */
+	for (int i = 0; i < DNAME_TABLE_DNAME_COUNT - 1; i++) {
+		dnslib_dname_t *dname =
+			dname_from_test_dname_str(&DNAME_TABLE_DNAMES[i]);
+		if (!dname) {
+			diag("Could not create dname from test dname!");
+			errors++;
+			continue;
+		}
+
+		dnslib_dname_t *found_dname =
+			dnslib_dname_table_find_dname(table, dname);
+
+		if (found_dname == NULL) {
+			diag("Dname table did not return "
+			     "dname when it should!");
+			errors++;
+			continue;
+		}
+
+		if (dnslib_dname_compare(found_dname, dname) != 0) {
+			diag("Returned dname did not match!");
+			errors++;
+			continue;
+		}
+	}
+
+	/* Search for last dname, it should return NULL. */
+	dnslib_dname_t *dname =
+		dname_from_test_dname_str(
+			&DNAME_TABLE_DNAMES[DNAME_TABLE_DNAME_COUNT]);
+	assert(dname);
+
+	if (dnslib_dname_table_find_dname(table, dname) != NULL) {
+		diag("Dname table returned dname when it "
+		     "should not be there!");
+		errors++;
+	}
+
+	dnslib_dname_free(&dname);
+	dnslib_dname_table_deep_free(&table);
+
+	return (errors == 0);
+}
+
+static const int DNSLIB_DNAME_TABLE_TEST_COUNT = 3;
+
+/*! This helper routine should report number of
+ *  scheduled tests for given parameters.
+ */
+static int dnslib_dname_table_tests_count(int argc, char *argv[])
+{
+	return DNSLIB_DNAME_TABLE_TEST_COUNT;
+}
+
+/*! Run all scheduled tests for given parameters.
+ */
+static int dnslib_dname_table_tests_run(int argc, char *argv[])
+{
+	int final_res = 1;
+	int res = 0;
+
+	/* Sort array containing test dnames. */
+	qsort(DNAME_TABLE_DNAMES, DNAME_TABLE_DNAME_COUNT,
+	      sizeof(test_dname_t), dname_compare_sort_wrapper);
+
+	ok((res = test_dname_table_new()), "dname table: new");
+	final_res *= res;
+
+	skip(!res, 2);
+
+	ok((res = test_dname_table_adding()), "dname table: adding");
+	final_res *= res;
+
+	ok((res = test_dname_table_find()), "dname table: searching");
+	final_res *= res;
+
+	endskip;
+
+	return final_res;
+}
diff --git a/src/dnslib/tests/dnslib/dname_table_tests.h b/src/dnslib/tests/dnslib/dname_table_tests.h
new file mode 100644
index 0000000000000000000000000000000000000000..52ae3998c7c03db886b2ecc339ad10a28bf044d9
--- /dev/null
+++ b/src/dnslib/tests/dnslib/dname_table_tests.h
@@ -0,0 +1,9 @@
+#ifndef _KNOT_DNAME_TABLE_TESTS_H_
+#define _KNOT_DNAME_TABLE_TESTS_H_
+
+#include "common/libtap/tap_unit.h"
+
+/* Unit API. */
+unit_api dname_table_tests_api;
+
+#endif /* _KNOT_DNAME_TABLE_TESTS_H_ */
diff --git a/src/dnslib/tests/dnslib/nsec3_tests.c b/src/dnslib/tests/dnslib/nsec3_tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..f76c1d1240a12c7599e53d33914f1ec0fb0c0fa2
--- /dev/null
+++ b/src/dnslib/tests/dnslib/nsec3_tests.c
@@ -0,0 +1,235 @@
+/* blame: jan.kadlec@nic.cz */
+
+#include <assert.h>
+
+#include "dnslib/dnslib-common.h"
+#include "dnslib/error.h"
+#include "dnslib/nsec3.h"
+#include "dnslib/utils.h"
+#include "common/base32hex.h"
+#include "nsec3_tests.h"
+
+#ifdef TEST_WITH_LDNS
+#include "ldns/ldns.h"
+#endif
+
+static int dnslib_nsec3_tests_count(int argc, char *argv[]);
+static int dnslib_nsec3_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api nsec3_tests_api = {
+	"NSEC3",      //! Unit name
+	&dnslib_nsec3_tests_count,  //! Count scheduled tests
+	&dnslib_nsec3_tests_run     //! Run scheduled tests
+};
+
+extern int compare_wires_simple(uint8_t *w1, uint8_t *w2, uint count);
+
+static dnslib_nsec3_params_t nsec3_test_params;
+
+static int test_nsec3_params_from_wire()
+{
+	/* Create sample NSEC3PARAM rdata */
+	dnslib_rdata_item_t items[4];
+	dnslib_rdata_t *rdata = dnslib_rdata_new();
+	rdata->items = items;
+	rdata->count = 4;
+	dnslib_rdata_item_set_raw_data(rdata, 0, (uint16_t *)"\x1\x0\x1");
+	dnslib_rdata_item_set_raw_data(rdata, 1, (uint16_t *)"\x1\x0\x0");
+	dnslib_rdata_item_set_raw_data(rdata, 2, (uint16_t *)"\x2\x0\x0\x64");
+	dnslib_rdata_item_set_raw_data(rdata, 3,
+		(uint16_t *)"\xF\x0\xE\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF");
+
+	dnslib_rrset_t *rrset =
+		dnslib_rrset_new(dnslib_dname_new_from_str("cz.",
+		                 strlen("cz."), NULL),
+	                         DNSLIB_RRTYPE_NSEC3PARAM,
+	                         DNSLIB_CLASS_IN,
+	                         3600);
+	assert(rrset);
+	assert(dnslib_rrset_add_rdata(rrset, rdata) == DNSLIB_EOK);
+
+	dnslib_nsec3_params_t nsec3_tests_params;
+	UNUSED(nsec3_tests_params);
+
+	int errors = 0;
+	int lived = 0;
+	lives_ok({
+		if (dnslib_nsec3_params_from_wire(NULL, NULL) !=
+		    DNSLIB_EBADARG) {
+			errors++;
+		}
+		lived = 1;
+
+		lived = 0;
+		if (dnslib_nsec3_params_from_wire(&nsec3_test_params, NULL) !=
+		    DNSLIB_EBADARG) {
+			errors++;
+		}
+		lived = 1;
+
+		lived = 0;
+		if (dnslib_nsec3_params_from_wire(NULL, rrset) !=
+		    DNSLIB_EBADARG) {
+			errors++;
+		}
+		lived = 1;
+
+	}, "nsec3 params from wire NULL tests");
+	errors += lived != 1;
+
+	if (dnslib_nsec3_params_from_wire(&nsec3_test_params,
+rrset) != DNSLIB_EOK) {
+		diag("Could not convert nsec3 params to wire!");
+		return 0;
+	}
+
+	if (nsec3_test_params.algorithm != 1) {
+		diag("Algorithm error");
+		errors++;
+	}
+
+	if (nsec3_test_params.flags != 2) {
+		diag("Flags error");
+		errors++;
+	}
+
+	if (nsec3_test_params.iterations != 15) {
+		diag("Iterations error");
+		errors++;
+	}
+
+	if (nsec3_test_params.salt_length != 8) {
+		diag("Salt length error");
+		return 0;
+	}
+
+	if (compare_wires_simple((uint8_t *)nsec3_test_params.salt,
+		(uint8_t *)"\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF",
+		15) != 0) {
+		diag("Salt wire error");
+		errors++;
+	}
+
+	dnslib_rrset_free(&rrset);
+	return (errors == 0);
+}
+
+static int test_nsec3_sha1()
+{
+	int errors = 0;
+	int lived = 0;
+
+	lives_ok({
+		if (dnslib_nsec3_sha1(NULL, NULL, 1, NULL, NULL) !=
+	            DNSLIB_EBADARG) {
+			errors++;
+		}
+		lived = 1;
+		lived = 0;
+		if (dnslib_nsec3_sha1(&nsec3_test_params,
+	                              NULL, 1, NULL, NULL) !=
+	            DNSLIB_EBADARG) {
+			errors++;
+		}
+		uint8_t data[20];
+		lived = 1;
+		lived = 0;
+		if (dnslib_nsec3_sha1(&nsec3_test_params,
+	                              data, 20, NULL, NULL) !=
+	            DNSLIB_EBADARG) {
+			errors++;
+		}
+		uint8_t *digest = NULL;
+		lived = 1;
+		lived = 0;
+		if (dnslib_nsec3_sha1(&nsec3_test_params,
+	                              data, 20, &digest, NULL) !=
+	            DNSLIB_EBADARG) {
+			errors++;
+		}
+		size_t size = 0;
+		lived = 1;
+		lived = 0;
+		if (dnslib_nsec3_sha1(&nsec3_test_params,
+	                              data, 20, &digest, &size) !=
+	            DNSLIB_EBADARG) {
+			errors++;
+		}
+		lived = 1;
+	}, "NSEC3: nsec3 sha1 NULL tests");
+	if (errors) {
+		diag("Does not return DNSLIB_EBADARG after "
+		     "execution with wrong arguments!");
+	}
+
+	errors += lived != 1;
+
+	uint8_t *digest = NULL;
+	size_t digest_size = 0;
+	if (dnslib_nsec3_sha1(&nsec3_test_params,
+	                      (uint8_t *)"\2ns\3nic\2cz",
+	                      strlen("\2ns\3nic\2cz"), &digest,
+	                      &digest_size) != DNSLIB_EOK) {
+		diag("Could not hash name!");
+		return 0;
+	}
+
+#ifdef TEST_WITH_LDNS
+	ldns_rdf *name = ldns_dname_new_frm_str("ns.nic.cz.");
+	assert(name);
+	ldns_rdf *hashed_name = ldns_nsec3_hash_name(name,
+	                                          nsec3_test_params.algorithm,
+	                                          nsec3_test_params.iterations,
+	                                          nsec3_test_params.salt_length,
+	                                          nsec3_test_params.salt);
+	assert(hashed_name);
+//	dnslib_dname_t *dname_from_ldns =
+//		dnslib_dname_new_from_wire(ldns_rdf_data(hashed_name),
+//	                                   ldns_rdf_size(hashed_name),
+//	                                   NULL);
+
+	char *name_b32 = NULL;
+	size_t size_b32 = base32hex_encode_alloc((char *)digest, digest_size,
+	                                     &name_b32);
+
+//	hex_print(name_b32, size_b32);
+//	hex_print(ldns_rdf_data(hashed_name), ldns_rdf_size(hashed_name));
+	if (ldns_rdf_size(hashed_name) != size_b32) {
+		diag("Wrong hashed name length! Should be: %d is: %d",
+		     ldns_rdf_size(hashed_name), size_b32);
+		return 0;
+	}
+
+	if (compare_wires_simple(ldns_rdf_data(hashed_name),
+	                         (uint8_t *)name_b32, size_b32) != 0) {
+		diag("Wrong hashed name wire!");
+		errors++;
+	}
+#endif
+
+#ifndef TEST_WITH_LDNS
+	diag("Warning: without ldns this test is only partial!");
+#endif
+	return (errors == 0);
+}
+
+static const int DNSLIB_NSEC3_TESTS_COUNT = 2;
+
+/*! This helper routine should report number of
+ *  scheduled tests for given parameters.
+ */
+static int dnslib_nsec3_tests_count(int argc, char *argv[])
+{
+	return DNSLIB_NSEC3_TESTS_COUNT;
+}
+
+/*! Run all scheduled tests for given parameters.
+ */
+static int dnslib_nsec3_tests_run(int argc, char *argv[])
+{
+	ok(test_nsec3_params_from_wire(), "nsec3: params from wire");
+	ok(test_nsec3_sha1(), "nsec3: sha1");
+	return 1;
+}
diff --git a/src/dnslib/tests/dnslib/nsec3_tests.h b/src/dnslib/tests/dnslib/nsec3_tests.h
new file mode 100644
index 0000000000000000000000000000000000000000..90d377d71fbda9a81550a2eb554411681663b704
--- /dev/null
+++ b/src/dnslib/tests/dnslib/nsec3_tests.h
@@ -0,0 +1,9 @@
+#ifndef _KNOT_NSEC3_TESTS_H_
+#define _KNOT_NSEC3_TESTS_H_
+
+#include "common/libtap/tap_unit.h"
+
+/* Unit API. */
+unit_api nsec3_tests_api;
+
+#endif /* _KNOT_NSEC3_TESTS_H_ */
diff --git a/src/dnslib/tests/dnslib/packet_tests.c b/src/dnslib/tests/dnslib/packet_tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..6b7643b507cd5353f7338d5461e6901399c69aee
--- /dev/null
+++ b/src/dnslib/tests/dnslib/packet_tests.c
@@ -0,0 +1,408 @@
+/* blame: jan.kadlec@nic.cz */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "packet_tests.h"
+#include "dnslib/error.h"
+#include "dnslib/packet.h"
+#include "dnslib/wire.h"
+/* *test_t structures */
+#include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
+
+static int packet_tests_count(int argc, char *argv[]);
+static int packet_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api packet_tests_api = {
+	"packet",     //! Unit name
+	&packet_tests_count,  //! Count scheduled tests
+	&packet_tests_run     //! Run scheduled tests
+};
+
+static int test_packet_new()
+{
+	int errors = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_NONE);
+	if (packet == NULL) {
+		diag("Could not create packet using prealloc_node constant!");
+		errors++;
+	}
+	dnslib_packet_free(&packet);
+
+	packet = dnslib_packet_new(DNSLIB_PACKET_PREALLOC_QUERY);
+	if (packet == NULL) {
+		diag("Could not create packet using prealloc_query constant!");
+		errors++;
+	}
+	dnslib_packet_free(&packet);
+
+	packet = dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	if (packet == NULL) {
+		diag("Could not create packet using prealloc_resp constant!");
+		errors++;
+	}
+	dnslib_packet_free(&packet);
+
+	/*!< \todo Should it create packet using any size? */
+
+	return (errors == 0);
+}
+
+static int test_packet_parse_from_wire()
+{
+	int errors = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_QUERY);
+
+	int tmp = 0;
+	lives_ok({
+		if (dnslib_packet_parse_from_wire(NULL, NULL, 0, 0) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to parse NULL packet with NULL wire "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		tmp = 1;
+		tmp = 0;
+		if (dnslib_packet_parse_from_wire(packet, NULL, 0, 0) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to parse with NULL wire "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		tmp = 1;
+		tmp = 0;
+		if (dnslib_packet_parse_from_wire(packet, (uint8_t *)0xbeef,
+		                                  0, 0) !=
+		    DNSLIB_EFEWDATA) {
+			diag("Trying to parse 0 lengt"
+			     "did not return DNSLIB_EOK!");
+			errors++;
+		}
+		tmp = 1;
+	}, "packet: parse from wire NULL tests.");
+	errors += tmp != 1;
+
+	dnslib_packet_free(&packet);
+
+	return (errors == 0);
+}
+
+static int test_packet_parse_next_rr_answer()
+{
+	int errors = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(packet);
+
+	int tmp = 0;
+	lives_ok({
+		int ret = 0;
+		if (dnslib_packet_parse_next_rr_answer(NULL, NULL) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to parse next RR answer with "
+			     "NULL packet with and NULL RRSet "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		tmp = 1;
+		tmp = 0;
+		if ((ret = dnslib_packet_parse_next_rr_answer(packet,
+		                                              NULL)) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to parse next RR with NULL RRSet pointer "
+			     "did not return DNSLIB_EBADARG! Got %d.",
+			     ret);
+			errors++;
+		}
+		tmp = 1;
+		dnslib_rrset_t *rrset = (dnslib_rrset_t *)0xaaaa;
+		tmp = 0;
+		if (dnslib_packet_parse_next_rr_answer(packet,
+		                                       &rrset) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to parse next RR answer with rrset pointer"
+			     " not pointing to NULL did not "
+			     "return DNSLIB_EBADARG!");
+			errors++;
+		}
+		tmp = 1;
+	}, "packet: parse next rr answer NULL tests.");
+	errors += tmp != 1;
+
+	dnslib_packet_free(&packet);
+
+	return (errors == 0);
+}
+
+static int test_packet_parse_rest()
+{
+	int res = 0;
+	lives_ok({res *= dnslib_packet_parse_rest(NULL);},
+	"packet: parse rest NULL test");
+
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_NONE);
+	assert(packet);
+
+	lives_ok({res *= dnslib_packet_parse_rest(packet);},
+	"packet: parser rest empty packet");
+
+	dnslib_packet_free(&packet);
+
+	return res;
+}
+
+
+static int test_packet_set_max_size()
+{
+	int errors = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_NONE);
+	assert(packet);
+
+	int lived = 0;
+
+	lives_ok({
+		lived = 0;
+		if (dnslib_packet_set_max_size(NULL, 1) != DNSLIB_EBADARG) {
+			diag("Calling packet_set_max() with NULL packet "
+			     "did not return DNSLIB_EBADARG");
+			errors++;
+		}
+		lived = 1;
+	}, "packet: set max size NULL test");
+
+	errors += lived != 1;
+
+	if (dnslib_packet_set_max_size(packet, 0) != DNSLIB_EBADARG) {
+		diag("Calling packet_set_max() with size eqeal to 0 did not "
+		     "return DNSLIB_EBADARG");
+		errors++;
+	}
+
+	if (dnslib_packet_set_max_size(packet, 10) != DNSLIB_EOK) {
+		diag("Calling packet_set_max() with valid arguments did not "
+		     "return DNSLIB_EOK");
+		errors++;
+	}
+
+	dnslib_packet_free(&packet);
+
+	return (errors == 0);
+}
+
+static int test_packet_add_tmp_rrset()
+{
+	int errors = 0;
+	int lived = 0;
+
+	/* dnslib_packet_add_tmp_rrset only works with pointers. */
+	dnslib_rrset_t *rrset = (dnslib_rrset_t *)0xabcdef;
+
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(packet);
+
+	lives_ok({
+		if (dnslib_packet_add_tmp_rrset(NULL, rrset) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to add to NULL packet did not return "
+			     "DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+
+		lived = 0;
+		if (dnslib_packet_add_tmp_rrset(packet, NULL) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to add NULL rrset did not return "
+			     "DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+
+		lived = 0;
+		if (dnslib_packet_add_tmp_rrset(NULL, NULL) !=
+		    DNSLIB_EBADARG) {
+			diag("Trying to add NULL rrset to NULL packet "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+	}, "packet: add tmp rrset NULL test");
+	errors += lived != 1;
+
+	if (dnslib_packet_add_tmp_rrset(packet, rrset) != DNSLIB_EOK) {
+		diag("Could not add valid RRSet to packet!");
+		errors++;
+	}
+
+	/* Not freeing because RRSet is fake. */
+//	dnslib_packet_free(&packet);
+
+	free(packet->wireformat);
+	free(packet);
+
+	return (errors == 0);
+}
+
+//static int test_packet_contains()
+//{
+//	int errors = 0;
+//	int lives = 0;
+
+//	dnslib_packet_t *packet =
+//		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+//	assert(packet);
+
+//	lives_ok({
+//		if (dnslib_packet_contains(packet, NULL,
+//		                           DNSLIB_RRSET_COMPARE_PTR) !=
+//		    DNSLIB_EBADARG{
+//			diag();
+//		}
+//	}, "packet: contains NULL tests);
+
+//	dnslib_packet_contains()
+
+//}
+
+static int test_packet_header_to_wire()
+{
+	int errors = 0;
+	int lived = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(packet);
+	size_t size;
+
+	lives_ok({
+		dnslib_packet_header_to_wire(NULL, NULL, NULL);
+		lived = 1;
+		lived = 0;
+		dnslib_packet_header_to_wire(&packet->header, NULL, &size);
+		lived = 1;
+	}, "packet: header to wire NULL tests");
+	errors += lived != 1;
+
+	dnslib_packet_free(&packet);
+	return (errors == 0);
+}
+
+static int test_packet_question_to_wire()
+{
+	int errors = 0 ;
+	int lived = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(packet);
+
+	lives_ok({
+		if (dnslib_packet_question_to_wire(NULL) != DNSLIB_EBADARG) {
+			diag("Calling packet_question_to_wire with "
+			     "NULL pointer did not result to DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+	}, "packet: question to wire NULL tests");
+	errors += lived != 1;
+
+	packet->size = DNSLIB_WIRE_HEADER_SIZE + 1;
+	if (dnslib_packet_question_to_wire(packet) != DNSLIB_ERROR) {
+		diag("Calling packet_question_to_wire with oversized packet "
+		     "did not return DNSLIB_ERROR!");
+		errors++;
+	}
+
+	dnslib_packet_free(&packet);
+	return (errors == 0);
+}
+
+static int test_packet_edns_to_wire()
+{
+	int errors = 0 ;
+	int lived = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(packet);
+
+	lives_ok({
+		dnslib_packet_edns_to_wire(NULL);
+		lived = 1;
+	}, "packet: question to wire NULL tests");
+	errors += lived != 1;
+
+	dnslib_packet_free(&packet);
+	return (errors == 0);
+}
+
+static int test_packet_to_wire()
+{
+	int errors = 0 ;
+	int lived = 0;
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(packet);
+
+	lives_ok({
+		if (dnslib_packet_to_wire(NULL, NULL, NULL) != DNSLIB_EBADARG) {
+			diag("Calling packet_to_wire with "
+			     "NULL pointers did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		size_t size;
+		lived = 0;
+		if (dnslib_packet_to_wire(packet, NULL, &size) !=
+		    DNSLIB_EBADARG) {
+			diag("Calling packet_to_wire with "
+			     "NULL wire did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		uint8_t *wire = (uint8_t *)0xabcdef;
+		lived = 0;
+		if (dnslib_packet_to_wire(packet, &wire, &size) !=
+		    DNSLIB_EBADARG) {
+			diag("Calling packet_to_wire with "
+			     "wire not pointing to NULL did not return"
+			     " DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+	}, "packet: to wire NULL tests");
+	errors += lived != 1;
+
+	dnslib_packet_free(&packet);
+	return (errors == 0);
+}
+
+static const uint DNSLIB_PACKET_TEST_COUNT = 21;
+
+static int packet_tests_count(int argc, char *argv[])
+{
+	return DNSLIB_PACKET_TEST_COUNT;
+}
+
+static int packet_tests_run(int argc, char *argv[])
+{
+	int res = 0;
+	ok(res = test_packet_new(), "packet: new");
+	skip(!res, 20);
+	ok(test_packet_parse_rest(), "packet: parse rest");
+	ok(test_packet_parse_from_wire(), "packet: parse from wire");
+	ok(test_packet_parse_next_rr_answer(), "packet: parse next rr answer");
+	ok(test_packet_set_max_size(), "packet: set max size");
+	ok(test_packet_add_tmp_rrset(), "packet: add tmp rrset");
+	ok(test_packet_header_to_wire(), "packet: header to wire");
+	ok(test_packet_question_to_wire(), "packet: header to wire");
+	ok(test_packet_edns_to_wire(), "packet: header to wire");
+	ok(test_packet_to_wire(), "packet: to wire");
+//	ok(res = test_packet_contains(), "Packet: contains");
+	endskip;
+	return 1;
+}
diff --git a/src/dnslib/tests/dnslib/packet_tests.h b/src/dnslib/tests/dnslib/packet_tests.h
new file mode 100644
index 0000000000000000000000000000000000000000..6189dc038f79f37b32aacb7b08403c29d0bc4477
--- /dev/null
+++ b/src/dnslib/tests/dnslib/packet_tests.h
@@ -0,0 +1,9 @@
+#ifndef _KNOT_PACKET_TESTS_H_
+#define _KNOT_PACKET_TESTS_H_
+
+#include "common/libtap/tap_unit.h"
+
+/* Unit API. */
+unit_api packet_tests_api;
+
+#endif /* _KNOT_PACKET_TESTS_H_ */
diff --git a/src/dnslib/tests/dnslib/query_tests.c b/src/dnslib/tests/dnslib/query_tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..1d433a8a020c40074dc1a527af66eb34d5e5d442
--- /dev/null
+++ b/src/dnslib/tests/dnslib/query_tests.c
@@ -0,0 +1,145 @@
+/* blame: jan.kadlec@nic.cz */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "packet_tests.h"
+#include "dnslib/error.h"
+#include "dnslib/packet.h"
+#include "dnslib/wire.h"
+#include "dnslib/query.h"
+/* *test_t structures */
+#include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
+
+static int query_tests_count(int argc, char *argv[]);
+static int query_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api query_tests_api = {
+	"query",     //! Unit name
+	&query_tests_count,  //! Count scheduled tests
+	&query_tests_run     //! Run scheduled tests
+};
+
+static const uint DNSLIB_QUERY_TEST_COUNT = 1;
+
+static int query_tests_count(int argc, char *argv[])
+{
+	return DNSLIB_QUERY_TEST_COUNT;
+}
+
+static int test_query_init()
+{
+	int errors = 0;
+	int lived = 0;
+	dnslib_packet_t *query =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_QUERY);
+	assert(query);
+	lives_ok({
+		if (dnslib_query_init(NULL) != DNSLIB_EBADARG) {
+			diag("Calling query_init with NULL query did "
+			     "not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+	}, "query: init NULL tests");
+	errors += lived != 1;
+
+	assert(dnslib_packet_set_max_size(query, 1024 * 10) == DNSLIB_EOK);
+	if (dnslib_query_init(query) != DNSLIB_EOK) {
+		diag("Calling query_init with valid query did not return "
+		     "DNSLIB_EOK!");
+		errors++;
+	}
+
+	if (!dnslib_packet_is_query(query)) {
+		diag("QR flag was not set!");
+		errors++;
+	}
+
+	return (errors == 0);
+}
+
+static int test_query_set_question()
+{
+	int errors = 0;
+	int lived = 0;
+
+	dnslib_packet_t *query =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_QUERY);
+	assert(query);
+	assert(dnslib_packet_set_max_size(query, 1024 * 10) == DNSLIB_EOK);
+	dnslib_query_init(query);
+
+	dnslib_rrset_t *rrset =
+		dnslib_rrset_new(dnslib_dname_new_from_str("a.ns.cz.",
+	                                                   strlen("a.ns.cz."),
+	                                                   NULL),
+	                         DNSLIB_RRTYPE_A, DNSLIB_CLASS_IN, 3600);
+	assert(rrset);
+
+	dnslib_question_t *question = malloc(sizeof(dnslib_question_t));
+	assert(question);
+	question->qname = rrset->owner;
+	question->qtype = rrset->type;
+	question->qclass = rrset->rclass;
+
+	lives_ok({
+		if (dnslib_query_set_question(NULL, NULL) != DNSLIB_EBADARG) {
+			diag("Calling query_set_question with NULL");
+			errors++;
+		}
+		lived = 1;
+		lived = 0;
+		if (dnslib_query_set_question(query, NULL) != DNSLIB_EBADARG) {
+			diag("Calling query_set_question with NULL");
+			errors++;
+		}
+		lived = 1;
+		lived = 0;
+		if (dnslib_query_set_question(NULL, question) != DNSLIB_EBADARG) {
+			diag("Calling query_set_question with NULL");
+			errors++;
+		}
+		lived = 1;
+	}, "query: set question NULL tests");
+	errors += lived != 1;
+
+	if (dnslib_query_set_question(query, question) != DNSLIB_EOK) {
+		diag("Calling query_set_question with valid arguments ");
+		errors++;
+	}
+
+	if (query->question.qname != rrset->owner) {
+		diag("Qname was not set right!");
+		errors++;
+	}
+
+	if (query->question.qtype != rrset->type) {
+		diag("Qtype was not set right!");
+		errors++;
+	}
+
+	if (query->question.qclass != rrset->rclass) {
+		diag("Qclass was not set right!");
+		errors++;
+	}
+
+	if (query->header.qdcount != 1) {
+		diag("Qdcount was not set right!");
+		errors++;
+	}
+
+	dnslib_packet_free(&query);
+	dnslib_rrset_deep_free(&rrset, 1, 0, 0);
+
+	return (errors == 0);
+}
+
+static int query_tests_run(int argc, char *argv[])
+{
+	ok(test_query_init(), "query: init");
+	ok(test_query_set_question(), "query: set question");
+	return 1;
+}
diff --git a/src/dnslib/tests/dnslib/query_tests.h b/src/dnslib/tests/dnslib/query_tests.h
new file mode 100644
index 0000000000000000000000000000000000000000..590259659ec018e13dabf1eb89c60a2da323ee09
--- /dev/null
+++ b/src/dnslib/tests/dnslib/query_tests.h
@@ -0,0 +1,9 @@
+#ifndef _KNOT_QUERY_TESTS_H_
+#define _KNOT_QUERY_TESTS_H_
+
+#include "common/libtap/tap_unit.h"
+
+/* Unit API. */
+unit_api query_tests_api;
+
+#endif /* _KNOT_QUERY_TESTS_H_ */
diff --git a/src/dnslib/tests/dnslib/response2_tests.c b/src/dnslib/tests/dnslib/response2_tests.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a2e8b3a43c12e71406614d38a43c3c77bac223f
--- /dev/null
+++ b/src/dnslib/tests/dnslib/response2_tests.c
@@ -0,0 +1,433 @@
+#include <assert.h>
+#include <inttypes.h>
+
+//#define RESP_TEST_DEBUG
+#include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
+#include "dnslib/tests/dnslib/response2_tests.h"
+#include "common/lists.h"
+#include "dnslib/dnslib-common.h"
+#include "dnslib/error.h"
+#include "dnslib/response2.h"
+#include "dnslib/rdata.h"
+#include "dnslib/rrset.h"
+#include "dnslib/dname.h"
+#include "dnslib/wire.h"
+#include "dnslib/descriptor.h"
+#include "dnslib/edns.h"
+
+#ifdef TEST_WITH_LDNS
+#include "ldns/ldns.h"
+#endif
+
+static int dnslib_response2_tests_count(int argc, char *argv[]);
+static int dnslib_response2_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api response2_tests_api = {
+	"DNS library - response",      //! Unit name
+	&dnslib_response2_tests_count,  //! Count scheduled tests
+	&dnslib_response2_tests_run     //! Run scheduled tests
+};
+
+static int test_response_init()
+{
+	int errors = 0;
+	int lived = 0;
+	lives_ok({
+		if (dnslib_response2_init(NULL) != DNSLIB_EBADARG) {
+			diag("Calling response_init with NULL packet did "
+			     "not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+	}, "response2: init NULL tests");
+	errors += lived != 1;
+
+	dnslib_packet_t *response =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_QUERY);
+	response->max_size = DNSLIB_WIRE_HEADER_SIZE - 1;
+	if (dnslib_response2_init(response) != DNSLIB_ESPACE) {
+		diag("Calling response_init too small packet did "
+		     "not return DNSLIB_ESPACE!");
+		errors++;
+	}
+
+	return (errors == 0);
+}
+
+static int test_response_init_query()
+{
+	int errors = 0;
+	int lived = 0;
+	lives_ok({
+		if (dnslib_response2_init_from_query(NULL, NULL) !=
+		    DNSLIB_EBADARG) {
+			diag("Calling response_init_query with NULL packet and "
+			     "NULL query did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		dnslib_packet_t *response =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+		assert(response);
+		dnslib_packet_set_max_size(response,
+		                           DNSLIB_PACKET_PREALLOC_RESPONSE);
+		dnslib_response2_init(response);
+		lived = 0;
+		if (dnslib_response2_init_from_query(response, NULL) !=
+		    DNSLIB_EBADARG) {
+			diag("Calling response_init_query with NULL query "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		dnslib_packet_t *query =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_QUERY);
+		if (dnslib_response2_init_from_query(NULL, query) !=
+		    DNSLIB_EBADARG) {
+			diag("Calling response_init_query with NULL response "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+	}, "response2: init from query NULL tests");
+	errors += lived != 1;
+
+	/* Cannot test the rest of return values, since there is now constant
+	 * controlling value that could return DNSLIB_EDNAMEPTR */
+
+	return (errors == 0);
+}
+
+int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count)
+{
+	int i = 0;
+	while (i < count &&
+	       wire1[i] == wire2[i]) {
+		i++;
+	}
+	return (!(count == i));
+}
+
+
+//static int test_response_clear()
+//{
+//	int errors = 0;
+//	int lived = 0;
+//	lives_ok({
+//		dnslib_response2_clear(NULL, 1);
+//		lived = 1;
+//	}, "response2: clear NULL tests");
+//	errors += lived != 1;
+
+//	/*
+//	 * Create new response, convert to wire, then add something, clear
+//	 * the response, convert to wire again and compare wires.
+//	 */
+
+//	dnslib_packet_t *response =
+//		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+//	dnslib_packet_set_max_size(response, DNSLIB_WIRE_HEADER_SIZE * 100);
+//	assert(dnslib_response2_init(response) == DNSLIB_EOK);
+
+//	uint8_t *original_wire = NULL;
+//	size_t original_size = 0;
+//	assert(dnslib_packet_to_wire(response, &original_wire,
+//	                             &original_size) ==
+//	       DNSLIB_EOK);
+//	/* Do something in question section. */
+////	test_dname_t test_dname;
+////	test_dname.str = "ns8.nic.cz.";
+////	dnslib_dname_t *dname = dname_from_test_dname_str(&test_dname);
+////	assert(dname);
+
+//	response->question.qtype = DNSLIB_RRTYPE_HINFO;
+//	response->question.qclass = DNSLIB_CLASS_CH;
+
+//	uint8_t *question_changed_wire = NULL;
+//	size_t question_changed_size = 0;
+//	assert(dnslib_packet_to_wire(response,
+//	                             &question_changed_wire,
+//	                             &question_changed_size) ==
+//	       DNSLIB_EOK);
+
+//	dnslib_response2_set_aa(response);
+//	dnslib_response2_set_tc(response);
+//	dnslib_response2_set_rcode(response, dnslib_quick_rand());
+
+//	dnslib_response2_clear(response, 0);
+//	uint8_t *new_wire = NULL;
+//	size_t new_size = 0;
+//	assert(dnslib_packet_to_wire(response, &new_wire, &new_size) ==
+//	       DNSLIB_EOK);
+//	if (question_changed_size != new_size) {
+//		diag("Wrong wire size after calling response_clear! "
+//		     "got %d should be %d", new_size, question_changed_size);
+//		errors++;
+//	} else {
+//		if (compare_wires_simple(question_changed_wire,
+//		                         new_wire, new_size)) {
+//			diag("Wrong wire after calling response_clear! ");
+//			errors++;
+//		}
+//	}
+//	free(new_wire);
+
+//	new_wire = NULL;
+//	new_size = 0;
+
+//	/*!< \todo figure out this segfault! */
+
+////	dnslib_response2_clear(response, 1);
+////	assert(dnslib_packet_to_wire(response, &new_wire, &new_size) ==
+////	       DNSLIB_EOK);
+
+////	if (original_size != new_size) {
+////		diag("Wrong wire size after calling response_clear!");
+////		errors++;
+////	} else {
+////		if (compare_wires_simple(original_wire,
+////		                         new_wire, new_size)) {
+////			diag("Wrong wire after calling response_clear!");
+////			errors++;
+////		}
+////	}
+
+////	free(new_wire);
+////	free(original_wire);
+////	free(question_changed_wire);
+////	dnslib_packet_free(&response);
+
+//	return (errors == 0);
+//}
+
+static int test_response_add_opt()
+{
+	int errors = 0;
+	int lived = 0;
+
+	dnslib_opt_rr_t opt;
+	opt.payload = 512;
+	opt.ext_rcode = 0;
+	opt.version = EDNS_VERSION_0;
+	opt.flags = 0;
+	opt.options = NULL;
+	opt.option_count = 0;
+	opt.options_max = 0;
+	opt.size = 25; // does it matter?
+
+	lives_ok({
+		if (dnslib_response2_add_opt(NULL, NULL, 0) != DNSLIB_EBADARG) {
+			diag("Calling response add opt with NULL arguments "
+			     "did not result to DNSLIB_EBADARG");
+			errors++;
+		}
+		lived = 1;
+		dnslib_packet_t *response =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+		assert(response);
+		lived = 0;
+		if (dnslib_response2_add_opt(response,
+		                             NULL, 0) != DNSLIB_EBADARG) {
+			diag("Calling response add opt with NULL OPT RR "
+			     "did not result to DNSLIB_EBADARG");
+			errors++;
+		}
+		lived = 1;
+
+		lived = 0;
+		if (dnslib_response2_add_opt(NULL,
+		                             &opt, 0) != DNSLIB_EBADARG) {
+			diag("Calling response add opt with NULL response "
+			     "did not result to DNSLIB_EBADARG");
+			errors++;
+		}
+		lived = 1;
+		dnslib_packet_free(&response);
+	}, "response2: add opt NULL tests");
+	errors += lived != 1;
+
+	dnslib_packet_t *response =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(response);
+	dnslib_packet_set_max_size(response, DNSLIB_PACKET_PREALLOC_RESPONSE * 100);
+	assert(dnslib_response2_init(response) == DNSLIB_EOK);;
+
+	if (dnslib_response2_add_opt(response, &opt, 0) != DNSLIB_EOK) {
+		diag("Adding valid OPT RR to response "
+		     "did not return DNSLIB_EOK");
+		errors++;
+	}
+
+	opt.payload = response->max_size + 1;
+	if (dnslib_response2_add_opt(response, &opt, 1) != DNSLIB_EPAYLOAD) {
+		diag("If OPT RR payload is bigger than response max size "
+		     "response_add_opt does not return DNSLIB_EPAYLOAD!");
+		errors++;
+	}
+
+	opt.payload = 0;
+	if (dnslib_response2_add_opt(response, &opt, 1) != DNSLIB_EBADARG) {
+		diag("Calling response_add_opt with OPT RR payload set to 0 "
+		     "did not return DNSLIB_EBADARG");
+	}
+
+	dnslib_packet_free(&response);
+	return (errors == 0);
+}
+
+static int test_response_add_generic(int (*func)(dnslib_packet_t *,
+                                                 const dnslib_rrset_t *,
+                                                 int, int, int))
+{
+	int errors = 0;
+	int lived = 0;
+
+	lives_ok({
+		if (func(NULL, NULL, 0, 0, 0) != DNSLIB_EBADARG) {
+			diag("Calling response add rrset with NULL "
+			     "arguments did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		dnslib_packet_t *response =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+		assert(response);
+		lived = 0;
+		if (func(response, NULL, 0, 0, 0) != DNSLIB_EBADARG) {
+			diag("Calling response add rrset with NULL rrset "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		dnslib_dname_t *owner =
+			dnslib_dname_new_from_str("ns.nic.cz.",
+			                          strlen("ns.nic.cz."),
+			                          NULL);
+		assert(owner);
+		dnslib_rrset_t *rrset =
+			dnslib_rrset_new(owner, DNSLIB_RRTYPE_A,
+			                 DNSLIB_CLASS_IN, 3600);
+		assert(rrset);
+		lived = 0;
+		if (func(NULL, rrset, 0, 0, 0) != DNSLIB_EBADARG) {
+			diag("Calling response add rrset with NULL response "
+			     "did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		dnslib_rrset_deep_free(&rrset, 1, 0, 0);
+		dnslib_packet_free(&response);
+	}, "response2: rrset adding NULL tests");
+	errors += lived != 1;
+
+	/*!< \todo Test case when DNSLIB_ESPACE should be returned. */
+	/*!< \todo Compression and so on - should it be tested here? */
+
+	dnslib_packet_t *response =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(response);
+
+	dnslib_dname_t *owner =
+		dnslib_dname_new_from_str("ns12.nic.cz.",
+		                          strlen("ns12.nic.cz."),
+		                          NULL);
+	assert(owner);
+	dnslib_rrset_t *rrset =
+		dnslib_rrset_new(owner, DNSLIB_RRTYPE_NS,
+		                 DNSLIB_CLASS_IN, 3600);
+	assert(rrset);
+	if (func(response, rrset, 0, 0, 0) != DNSLIB_EOK) {
+		diag("Adding valid RRSet to response did not result to "
+		     "DNSLIB_EOK");
+		errors++;
+	}
+
+	dnslib_rrset_deep_free(&rrset, 1, 0, 0);
+	dnslib_packet_free(&response);
+
+	return (errors == 0);
+}
+
+static void test_response_add_rrset()
+{
+	ok(test_response_add_generic(dnslib_response2_add_rrset_answer),
+	   "response: add answer rrset");
+	ok(test_response_add_generic(dnslib_response2_add_rrset_authority),
+	   "response: add answer authority");
+	ok(test_response_add_generic(dnslib_response2_add_rrset_additional),
+	   "response: add answer additional");
+}
+
+static int test_response_add_nsid()
+{
+	int errors = 0;
+	int lived = 0;
+
+	dnslib_packet_t *response =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(response);
+
+	uint8_t *nsid = (uint8_t *)"knotDNS";
+	uint16_t nsid_size = strlen((char *)nsid);
+	lives_ok({
+		if (dnslib_response2_add_nsid(NULL,
+		                              NULL, 1) != DNSLIB_EBADARG) {
+			diag("Calling response add nsid with NULL arguments "
+			     "did not return DNSLIB_EBADARG");
+			errors++;
+		}
+		lived = 1;
+
+		lived = 0;
+		if (dnslib_response2_add_nsid(NULL, nsid,
+		                              nsid_size) != DNSLIB_EBADARG) {
+			diag("Calling response add nsid with NULL response "
+			     "did not return DNSLIB_EBADARG");
+			errors++;
+		}
+		lived = 1;
+		lived = 0;
+		if (dnslib_response2_add_nsid(response, nsid,
+		                              0) != DNSLIB_EBADARG) {
+			diag("Calling response add nsid with zero size "
+			     "did not return DNSLIB_EBADARG");
+			errors++;
+		}
+		lived = 1;
+	}, "response: add nsid NULL tests");
+	errors += lived != 1;
+
+	if (dnslib_response2_add_nsid(response, nsid,
+	                              nsid_size) != DNSLIB_EOK) {
+		diag("Adding valid nsid to response did not return DNSLIB_EOK");
+		errors++;
+	}
+
+	dnslib_packet_free(&response);
+	return (errors == 0);
+}
+
+static const int DNSLIB_RESPONSE2_TEST_COUNT = 14;
+
+/*! This helper routine should report number of
+ *  scheduled tests for given parameters.
+ */
+static int dnslib_response2_tests_count(int argc, char *argv[])
+{
+	return DNSLIB_RESPONSE2_TEST_COUNT;
+}
+
+
+/*! Run all scheduled tests for given parameters.
+ */
+static int dnslib_response2_tests_run(int argc, char *argv[])
+{
+	ok(test_response_init(), "response: init");
+	ok(test_response_init_query(), "response: init from query");
+//	ok(test_response_clear(), "response: clear");
+	ok(test_response_add_opt(), "response: add opt");
+	test_response_add_rrset();
+	ok(test_response_add_nsid(), "response: add nsid");
+	return 1;
+}
diff --git a/src/dnslib/tests/dnslib/response2_tests.h b/src/dnslib/tests/dnslib/response2_tests.h
new file mode 100644
index 0000000000000000000000000000000000000000..d9dbdfc97667ac1c05b1ba3093b8c54e6e8d1cb6
--- /dev/null
+++ b/src/dnslib/tests/dnslib/response2_tests.h
@@ -0,0 +1,9 @@
+#ifndef _KNOT_RESPONSE2_TESTS_H_
+#define _KNOT_RESPONSE2_TESTS_H_
+
+#include "common/libtap/tap_unit.h"
+
+/* Unit API. */
+unit_api response2_tests_api;
+
+#endif /* _KNOT_RESPONSE2_TESTS_H_ */
diff --git a/src/dnslib/tests/dnslib/response_tests.c b/src/dnslib/tests/dnslib/response_tests.c
index 1c45a4f1299cb8a66fb637b58c9ad79b81875434..55f04df368e4968db7754ad98e9973d6b8d808be 100644
--- a/src/dnslib/tests/dnslib/response_tests.c
+++ b/src/dnslib/tests/dnslib/response_tests.c
@@ -1092,7 +1092,7 @@ static int test_response_parse_query(test_response_t **responses,
 
 #ifdef TEST_WITH_LDNS
 /* count1 == count2 */
-static int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count)
+int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count)
 {
 	int i = 0;
 	while (i < count &&
@@ -1106,7 +1106,7 @@ static int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count)
  * Comparison is done through comparing wireformats.
  * Returns 0 if rdata are the same, 1 otherwise
  */
-static int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr,
+int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr,
 			    uint16_t type)
 {
 	dnslib_rrtype_descriptor_t *desc =
@@ -1174,7 +1174,7 @@ static int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr,
 	return 0;
 }
 
-static int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
+int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
 				      ldns_rr *rr, char check_rdata)
 {
 	/* We should have only one rrset from ldns, although it is
@@ -1271,7 +1271,7 @@ static int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
 	return 0;
 }
 
-static int compare_rrsets_w_ldns_rrlist(const dnslib_rrset_t **rrsets,
+int compare_rrsets_w_ldns_rrlist(const dnslib_rrset_t **rrsets,
 					ldns_rr_list *rrlist, int count)
 {
 	int errors = 0;
@@ -1309,7 +1309,7 @@ static int compare_rrsets_w_ldns_rrlist(const dnslib_rrset_t **rrsets,
  * different.
  * TODO well, call it "check" then
  */
-static int compare_response_w_ldns_packet(dnslib_response_t *response,
+int compare_response_w_ldns_packet(dnslib_response_t *response,
 					  ldns_pkt *packet)
 {
 	if (response->header.id != ldns_pkt_id(packet)) {
diff --git a/src/dnslib/tests/dnslib/zone_tests.c b/src/dnslib/tests/dnslib/zone_tests.c
index db8c982ee5325ff917a488ab98058c1d1060109f..8c04567eebe0c26c9ce6de279540245489d8c6f8 100644
--- a/src/dnslib/tests/dnslib/zone_tests.c
+++ b/src/dnslib/tests/dnslib/zone_tests.c
@@ -2,6 +2,7 @@
 
 #include "dnslib/tests/dnslib/zone_tests.h"
 #include "dnslib/dnslib-common.h"
+#include "dnslib/dname-table.h"
 #include "dnslib/zone.h"
 #include "dnslib/error.h"
 #include "dnslib/node.h"
@@ -338,12 +339,12 @@ static int test_zone_find_node(dnslib_zone_t *zone, int nsec3)
 	return (errors == 0);
 }
 
-static void test_zone_destroy_node_from_tree(dnslib_node_t *node,
-                                             void *data)
-{
-	UNUSED(data);
-	dnslib_node_free(&node, 0, 0);
-}
+//static void test_zone_destroy_node_from_tree(dnslib_node_t *node,
+//                                             void *data)
+//{
+//	UNUSED(data);
+//	dnslib_node_free(&node, 0);
+//}
 
 /* explained below */
 static size_t node_index = 0;
@@ -471,19 +472,283 @@ static int test_zone_traversals(dnslib_zone_t *zone)
 	return 1;
 }
 
-static int test_zone_free(dnslib_zone_t **zone)
+struct zone_test_param {
+	/* Times 2 so that we don't have to mess with mallocs. */
+	dnslib_node_t *dnslib_node_array[TEST_NODES_GOOD * 2];
+	dnslib_dname_t *table_node_array[TEST_NODES_GOOD * 2];
+	int count;
+};
+
+static void tree_node_to_array(dnslib_node_t *node, void *data)
+{
+	struct zone_test_param *param = (struct zone_test_param *)data;
+	param->dnslib_node_array[param->count++] = node;
+}
+
+static void tree_dname_node_to_array(struct dname_table_node *node,
+                                     void *data)
+{
+	struct zone_test_param *param = (struct zone_test_param *)data;
+	param->table_node_array[param->count++] = node->dname;
+}
+
+extern int compare_wires_simple(uint8_t *w1, uint8_t *w2, uint count);
+static int test_zone_shallow_copy()
 {
-	dnslib_zone_tree_apply_postorder(*zone,
-	                                 test_zone_destroy_node_from_tree,
-	                                 NULL);
-	dnslib_zone_nsec3_apply_postorder(*zone,
-	                                 test_zone_destroy_node_from_tree,
-	                                 NULL);
-	dnslib_zone_free(zone);
-	return (*zone == NULL);
+	int errors = 0;
+	int lived = 0;
+	dnslib_dname_t *apex_dname =
+		dnslib_dname_new_from_str("a.ns.nic.cz.",
+	                                  strlen("a.ns.nic.cz"), NULL);
+	assert(apex_dname);
+	dnslib_node_t *apex_node =
+		dnslib_node_new(apex_dname, NULL);
+	assert(apex_node);
+	lives_ok({
+		if (dnslib_zone_shallow_copy(NULL, NULL) != DNSLIB_EBADARG) {
+			diag("Calling zone_shallow_copy with NULL "
+			     "arguments did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		lived = 0;
+		dnslib_zone_t *zone = dnslib_zone_new(apex_node, 0, 1);
+		if (dnslib_zone_shallow_copy(zone, NULL) != DNSLIB_EBADARG) {
+			diag("Calling zone_shallow_copy with NULL destination "
+			     "zone argument did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		lived = 0;
+		if (dnslib_zone_shallow_copy(NULL, &zone) != DNSLIB_EBADARG) {
+			diag("Calling zone_shallow_copy with NULL source "
+			     "zone argument did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		lived = 0;
+		if (dnslib_zone_shallow_copy(zone, &zone) != DNSLIB_EBADARG) {
+			diag("Calling zone_shallow_copy with identical source "
+			 "and destination zone did not return DNSLIB_EBADARG!");
+			errors++;
+		}
+		lived = 1;
+		dnslib_zone_free(&zone);
+	}, "zone: shallow copy NULL tests");
+	errors += lived != 1;
+
+	/* example.com. */
+	dnslib_zone_t *from =
+		dnslib_zone_new(dnslib_node_new(&test_nodes_good[0].owner,
+		                test_nodes_good[0].parent), 10, 1);
+
+	/* Add nodes to zone. */
+	for (int i = 1; i < TEST_NODES_GOOD; ++i) {
+		dnslib_node_t *node = dnslib_node_new(&test_nodes_good[i].owner,
+		                                     test_nodes_good[i].parent);
+		if (node == NULL) {
+			diag("zone: Could not create node.");
+			return 0;
+		}
+
+		if (dnslib_zone_add_node(from, node, 1, 1) != DNSLIB_EOK) {
+			diag("zone: Could not add node. %s",
+			     dnslib_dname_to_str(node->owner));
+//			return 0;
+		}
+	}
+
+	/* Make a copy of zone */
+	dnslib_zone_t *to = NULL;
+	int ret = 0;
+	if ((ret = dnslib_zone_shallow_copy(from, &to) != DNSLIB_EOK)) {
+		diag("Could not copy zone! %s", dnslib_strerror(ret));
+		return 0;
+	}
+
+	assert(to);
+
+	/* Compare non-tree parts of the zone. */
+	if (from->data != to->data) {
+		diag("Zone data field wrong after shallow copy!");
+		errors++;
+	}
+
+	if (from->dtor != to->dtor) {
+		diag("Zone data destructor field wrong after shallow copy!");
+		errors++;
+	}
+
+	if (from->node_count != to->node_count) {
+		diag("Zone node count data field wrong after shallow copy!");
+		errors++;
+	}
+
+	if (from->version != to->version) {
+		diag("Zone version data field wrong after shallow copy!");
+		errors++;
+	}
+
+	if (from->apex != to->apex) {
+		diag("Zone apex differ after shallow copy!");
+	}
+
+	if (compare_wires_simple((uint8_t *)(&from->nsec3_params),
+	                         (uint8_t *)(&to->nsec3_params),
+	                         sizeof(from->nsec3_params)) != 0) {
+		diag("Nsec3_params data field wrong after shallow copy!");
+		errors++;
+	}
+
+	if (from->nodes == to->nodes) {
+		diag("Copied zones have identical trees!");
+		errors++;
+	}
+
+	if (from->nsec3_nodes == to->nsec3_nodes) {
+		diag("Copied zones have identical trees!");
+		errors++;
+	}
+
+	/* Compare nodes, convert tree to array then compare those arrays. */
+	struct zone_test_param param1;
+	param1.count = 0;
+	dnslib_zone_tree_apply_inorder(from, tree_node_to_array,
+	                               (void *)&param1);
+
+	struct zone_test_param param2;
+	param2.count = 0;
+	dnslib_zone_tree_apply_inorder(to, tree_node_to_array,
+	                               (void *)&param2);
+
+	if (param1.count != param2.count) {
+		diag("wrong tree");
+		return 0;
+	}
+
+	for (int i = 0; i < param1.count; i++) {
+		if (param1.dnslib_node_array[i] !=
+		    param2.dnslib_node_array[i]) {
+			diag("wrong tree");
+			return 0;
+		}
+	}
+
+	param1.count = 0;
+	dnslib_dname_table_tree_inorder_apply(from->dname_table,
+	                                       tree_dname_node_to_array,
+	                                       (void *)&param1);
+
+	param2.count = 0;
+	dnslib_dname_table_tree_inorder_apply(to->dname_table,
+	                                      tree_dname_node_to_array,
+	                                      (void *)&param2);
+
+	if (param1.count != param2.count) {
+		diag("wrong table count");
+		return 0;
+	}
+
+	for (int i = 0; i < param1.count; i++) {
+		if (param1.table_node_array[i] != param2.table_node_array[i]) {
+			diag("wrong table nodes");
+			errors++;
+		}
+	}
+
+#ifdef USE_HASH_TABLE
+	if (from->table) {
+		if (from->table == to->table) {
+			diag("hash tables after shallow copy are identical!");
+			return 0;
+		}
+		uint i;
+		if (hashsize(from->table->table_size_exp) !=
+		                hashsize(to->table->table_size_exp)) {
+			diag("hash tables after shallow copy error!");
+			return 0;
+		}
+
+		if (from->table->table_count != to->table->table_count) {
+			diag("hash tables after shallow copy error!");
+			return 0;
+		}
+
+		for (uint t = 0; t < from->table->table_count; ++t) {
+			for (i = 0; i <
+			     hashsize(from->table->table_size_exp); i++) {
+				if (from->table->tables[t][i] == NULL) {
+					if (to->table->tables[t][i] != NULL) {
+						diag("hash table item error");
+					}
+					continue;
+				}
+				if ((from->table->tables[t])[i]->key_length !=
+				    (to->table->tables[t])[i]->key_length) {
+					diag("hash table key lengths error!");
+					return 0;
+				}
+				if ((from->table->tables[t])[i]->key !=
+				    (to->table->tables[t])[i]->key) {
+					diag("hash table key error!");
+					return 0;
+				}
+				if ((from->table->tables[t])[i]->value !=
+				    (to->table->tables[t])[i]->value) {
+					diag("hash table value error!");
+					return 0;
+				}
+			}
+		}
+
+		ck_stash_item_t *item1 = from->table->stash2;
+		ck_stash_item_t *item2 = to->table->stash2;
+		while (item1 != NULL && item2 != NULL) {
+			if (item1->item->key_length !=
+			    item2->item->key_length) {
+				diag("hash stash key length error!");
+				return 0;
+			}
+			if (item1->item->key != item2->item->key) {
+				diag("hash stash key error!");
+				return 0;
+			}
+			if (item1->item->value != item2->item->value) {
+				diag("hash stash value error!");
+				return 0;
+			}
+
+			item1 = item1->next;
+			item2 = item2->next;
+		}
+	} else {
+		if (to->table) {
+			diag("Hash table is not set to NULL "
+			     "after shallow copy!");
+			errors++;
+		}
+	}
+#endif
+
+	dnslib_zone_free(&from);
+	dnslib_zone_free(&to);
+	return (errors == 0);
+
 }
 
-static const int DNSLIB_ZONE_TEST_COUNT = 9;
+//static int test_zone_free(dnslib_zone_t **zone)
+//{
+//	dnslib_zone_tree_apply_postorder(*zone,
+//	                                 test_zone_destroy_node_from_tree,
+//	                                 NULL);
+//	dnslib_zone_nsec3_apply_postorder(*zone,
+//	                                 test_zone_destroy_node_from_tree,
+//	                                 NULL);
+//	dnslib_zone_free(zone);
+//	return (*zone == NULL);
+//}
+
+static const int DNSLIB_ZONE_TEST_COUNT = 10;
 
 /*! This helper routine should report number of
  *  scheduled tests for given parameters.
@@ -544,9 +809,12 @@ static int dnslib_zone_tests_run(int argc, char *argv[])
 	ok(res = test_zone_traversals(zone), "zone: traversals");
 	res_final *= res;
 
-	ok((res = test_zone_free(&zone)), "zone: free");
+	ok((res = test_zone_shallow_copy()), "zone: shallow copy");
 	res_final *= res;
 
+//	ok((res = test_zone_free(&zone)), "zone: free");
+//	res_final *= res;
+
 	endskip; // create failed
 
 	return res_final;
diff --git a/src/dnslib/tests/realdata/dnslib/packet_tests_realdata.c b/src/dnslib/tests/realdata/dnslib/packet_tests_realdata.c
new file mode 100644
index 0000000000000000000000000000000000000000..1045990ae5e3d8b52c0b201eb6e1f8491012988d
--- /dev/null
+++ b/src/dnslib/tests/realdata/dnslib/packet_tests_realdata.c
@@ -0,0 +1,435 @@
+/* blame: jan.kadlec@nic.cz */
+
+#include <assert.h>
+
+#include "packet_tests_realdata.h"
+#include "dnslib/error.h"
+#include "dnslib/packet.h"
+#include "dnslib/response2.h"
+/* *test_t structures */
+#include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
+#ifdef TEST_WITH_LDNS
+#include "ldns/ldns.h"
+#endif
+
+static int packet_tests_count(int argc, char *argv[]);
+static int packet_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api packet_tests_api = {
+	"DNS library - packet",     //! Unit name
+	&packet_tests_count,  //! Count scheduled tests
+	&packet_tests_run     //! Run scheduled tests
+};
+
+#ifdef TEST_WITH_LDNS
+extern int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count);
+extern int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr, uint16_t type);
+extern int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
+                                   ldns_rr *rr, char check_rdata);
+extern int compare_rrsets_w_ldns_rrlist(const dnslib_rrset_t **rrsets,
+					ldns_rr_list *rrlist, int count);
+
+int check_packet_w_ldns_packet(dnslib_packet_t *packet,
+                                      ldns_pkt *ldns_packet,
+                                      int check_header,
+                                      int check_question,
+                                      int check_body,
+                                      int check_edns)
+{
+	int errors = 0;
+	if (check_header) {
+		if (packet->header.id != ldns_pkt_id(ldns_packet)) {
+			diag("response ID does not match");
+			errors++;
+		}
+
+		/* qdcount is always 1 in dnslib's case */
+
+		/* TODO check flags1 and flags2 - no API for that,
+		 * write my own */
+
+		if (packet->header.ancount !=
+		                ldns_pkt_ancount(ldns_packet)) {
+			diag("Answer RRSet count wrongly converted");
+			errors++;
+		}
+
+		if (packet->header.nscount !=
+		                ldns_pkt_nscount(ldns_packet)) {
+			diag("Authority RRSet count wrongly converted.\n"
+			     "got %d should be %d",
+			     dnslib_packet_authority_rrset_count(packet),
+			     ldns_pkt_nscount(ldns_packet));
+			errors++;
+		}
+
+		/* - 1 because ldns does not include OPT_RR to additional "
+		 "section */
+		int minus = (packet->opt_rr.version == 0) ? 1 : 0;
+
+		if ((packet->header.arcount - minus) !=
+		                ldns_pkt_arcount(ldns_packet)) {
+			diag("Additional RRSet count wrongly converted.\n"
+			     "got %d should be %d",
+			     dnslib_packet_additional_rrset_count(packet) -
+			     minus,
+			     ldns_pkt_arcount(ldns_packet));
+			errors++;
+		}
+
+		if (errors) {
+			return errors;
+		}
+	}
+	/* Header checked */
+
+	/* Question section */
+
+	int ret = 0;
+	if (check_question) {
+		dnslib_rrset_t *question_rrset =
+		                dnslib_rrset_new(packet->
+		                                 question.qname,
+		                                 packet->
+		                                 question.qtype,
+		                                 packet->
+		                                 question.qclass,
+		                                 3600);
+
+		if ((ret = compare_rrset_w_ldns_rr(question_rrset,
+			ldns_rr_list_rr(ldns_pkt_question(ldns_packet),
+			0), 0)) != 0) {
+			diag("Question rrsets wrongly converted");
+			errors++;
+		}
+		dnslib_rrset_free(&question_rrset);
+	}
+
+	if (check_body) {
+
+		/* other RRSets */
+
+		if ((ret =
+		     compare_rrsets_w_ldns_rrlist(packet->answer,
+		                         ldns_pkt_answer(ldns_packet),
+                        dnslib_packet_answer_rrset_count(packet))) != 0) {
+			diag("Answer rrsets wrongly converted");
+			errors++;
+		}
+
+
+
+		if ((ret = compare_rrsets_w_ldns_rrlist(packet->authority,
+		                             ldns_pkt_authority(ldns_packet),
+			dnslib_packet_authority_rrset_count(packet))) != 0) {
+			diag("Authority rrsets wrongly converted - %d", ret);
+			errors++;
+		}
+
+		/* We don't want to test OPT RR, which is the last rrset
+		 * in the additional section */
+
+		if ((ret = compare_rrsets_w_ldns_rrlist(packet->additional,
+		                           ldns_pkt_additional(ldns_packet),
+			dnslib_packet_additional_rrset_count(packet) - 1)) != 0) {
+			diag("Additional rrsets wrongly converted");
+			errors++;
+		}
+
+	}
+
+	if (check_edns) {
+
+		/* OPT RR */
+
+		if (ldns_pkt_edns(ldns_packet)) {
+			/* if (packet->edns_packet == NULL) {
+   diag("ldns has edns section, dnslib has not");
+   return 1;
+  } */
+
+			dnslib_opt_rr_t *opt = &(packet->opt_rr);
+
+			if (ldns_pkt_edns_udp_size(ldns_packet) !=
+			                dnslib_edns_get_payload(opt)) {
+				diag("Payloads in EDNS are different");
+				errors++;
+			}
+
+			if (ldns_pkt_edns_version(ldns_packet) !=
+			                dnslib_edns_get_version(opt)) {
+				diag("Versions in EDNS are different");
+				errors++;
+			}
+
+			if (ldns_pkt_edns_extended_rcode(ldns_packet) !=
+			                dnslib_edns_get_ext_rcode(opt)) {
+				diag("Extended rcodes in EDNS are different");
+				errors++;
+			}
+
+			/* TODO parse flags do bit, z value ... */
+		}
+	}
+
+	return errors;
+}
+#endif
+
+extern dnslib_rrset_t *rrset_from_test_rrset(const test_rrset_t *test_rrset);
+extern dnslib_dname_t *dname_from_test_dname(const test_dname_t *test_dname);
+
+/* Converts dnslib_rrset_t to dnslib_opt_rr */
+static dnslib_opt_rr_t *opt_rrset_to_opt_rr(dnslib_rrset_t *rrset)
+{
+	if (rrset == NULL) {
+		return NULL;
+	}
+
+	dnslib_opt_rr_t *opt_rr = dnslib_edns_new();
+	assert(opt_rr);
+
+	dnslib_edns_set_payload(opt_rr, rrset->rclass);
+
+	dnslib_edns_set_ext_rcode(opt_rr, rrset->ttl);
+
+	/* TODO rdata? mostly empty, I guess, but should be done */
+
+	return opt_rr;
+}
+
+dnslib_packet_t *packet_from_test_response(test_response_t *test_packet)
+{
+	dnslib_rrset_t *parsed_opt = NULL;
+
+	for (int j = 0; j < test_packet->arcount; j++) {
+		if (test_packet->additional[j]->type ==
+		    DNSLIB_RRTYPE_OPT) {
+			parsed_opt =
+				rrset_from_test_rrset(
+				test_packet->additional[j]);
+			assert(parsed_opt);
+			break;
+		}
+	}
+
+	dnslib_opt_rr_t *opt_rr = NULL;
+	if (parsed_opt != NULL) {
+		opt_rr =
+			opt_rrset_to_opt_rr(parsed_opt);
+		assert(opt_rr);
+	} else {
+		opt_rr = NULL;
+	}
+
+	dnslib_packet_t *packet =
+		dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+	assert(packet);
+	dnslib_packet_set_max_size(packet, 1024 * 10);
+
+	if (opt_rr != NULL) {
+		packet->opt_rr = *opt_rr;
+	}
+
+	packet->header.id = test_packet->id;
+	packet->header.qdcount = test_packet->qdcount;
+
+	packet->question.qname = dname_from_test_dname(test_packet->qname);
+	packet->size += test_packet->qname->size;
+	packet->question.qtype = test_packet->qtype;
+	packet->question.qclass = test_packet->qclass;
+
+	packet->size += 4;
+
+	packet->answer =
+		malloc(sizeof(dnslib_rrset_t *) * test_packet->ancount);
+	assert(packet->answer);
+
+	for (int j = 0; j < test_packet->ancount; j++) {
+		if (&(test_packet->answer[j])) {
+			packet->answer[packet->an_rrsets++] =
+			  rrset_from_test_rrset(test_packet->answer[j]);
+		}
+	}
+
+	packet->authority =
+		malloc(sizeof(dnslib_rrset_t *) * test_packet->nscount);
+	assert(packet->answer);
+
+	for (int j = 0; j < test_packet->nscount; j++) {
+		if (&(test_packet->authority[j])) {
+			packet->authority[packet->ns_rrsets++] =
+			  rrset_from_test_rrset(test_packet->authority[j]);
+		}
+	}
+
+	packet->authority =
+		malloc(sizeof(dnslib_rrset_t *) * test_packet->arcount);
+	assert(packet->answer);
+
+	for (int j = 0; j < test_packet->arcount; j++) {
+		if (&(test_packet->additional[j])) {
+			if (test_packet->additional[j]->type ==
+			    DNSLIB_RRTYPE_OPT) {
+				continue;
+			}
+			packet->additional[packet->ar_rrsets++] =
+			  rrset_from_test_rrset(test_packet->additional[j]);
+		}
+	}
+
+	return packet;
+}
+
+static int test_packet_parse_from_wire(list raw_response_list)
+{
+	int errors = 0;
+
+	node *n = NULL;
+	WALK_LIST(n ,raw_response_list) {
+		test_raw_packet_t *raw_packet = (test_raw_packet_t *)n;
+		dnslib_packet_t *packet =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+		int ret = 0;
+		if ((ret =
+		     dnslib_packet_parse_from_wire(packet, raw_packet->data,
+		                                   raw_packet->size, 0)) !=
+		    DNSLIB_EOK) {
+			diag("Warning: could not parse wire! "
+			     "(might be caused by malformed dump) - "
+			     "dnslib error: %s", dnslib_strerror(ret));
+//			hex_print(raw_packet->data,
+//			          raw_packet->size);
+			continue;
+		}
+
+		ldns_pkt *ldns_packet = NULL;
+
+		if (ldns_wire2pkt(&ldns_packet, raw_packet->data,
+				  raw_packet->size) != LDNS_STATUS_OK) {
+			diag("Could not parse wire using ldns");
+			diag("%s",
+			     ldns_get_errorstr_by_id(ldns_wire2pkt(&ldns_packet,
+							raw_packet->data,
+							raw_packet->size)));
+			return 0;
+		}
+
+		if (check_packet_w_ldns_packet(packet, ldns_packet, 1,
+		                               1, 1, 1) != 0) {
+			diag("Wrongly created packet");
+			errors++;
+		}
+
+		ldns_pkt_free(ldns_packet);
+		dnslib_packet_free(&packet);
+	}
+
+	return (errors == 0);
+}
+
+static int test_packet_to_wire(list raw_response_list)
+{
+	int errors = 0;
+	/*!< \todo test queries too! */
+//	/* We'll need data from both lists. */
+//	test_packet_t **test_packets = NULL;
+//	uint test_packet_count = 0;
+//	node *n = NULL;
+//	WALK_LIST(n, response_list) {
+//		test_packet_count++;
+//	}
+
+//	test_packets =
+//		malloc(sizeof(test_packet_t *) * test_packet_count);
+//	assert(test_packets);
+//	int i = 0;
+//	WALK_LIST(n, response_list) {
+//		test_packets[i++] = (test_response_t *)n;
+//	}
+
+//	test_raw_packet_t **test_packets = NULL;
+//	uint test_packet_count = 0;
+//	n = NULL;
+//	WALK_LIST(n, raw_response_list) {
+//		test_packet_count++;
+//	}
+
+//	test_packets =
+//		malloc(sizeof(test_raw_packet_t *) * test_packet_count);
+//	assert(test_packets);
+//	i = 0;
+//	WALK_LIST(n, raw_response_list) {
+//		test_packets[i++] = (test_raw_packet_t *)n;
+//	}
+
+//	assert(test_response_count == test_packet_count);
+	node *n = NULL;
+	WALK_LIST(n, raw_response_list) {
+		/* Create packet from raw response. */
+		dnslib_packet_t *packet =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+		assert(packet);
+		test_raw_packet_t *raw_packet = (test_raw_packet_t *)n;
+		if (dnslib_packet_parse_from_wire(packet, raw_packet->data,
+		                                  raw_packet->size, 0) !=
+		    DNSLIB_EOK) {
+			diag("Warning: could not parse wire! "
+			     "(might be caused be malformed dump)");
+			continue;
+		}
+		/* Use this packet to create wire */
+		uint8_t *wire = NULL;
+		size_t size = 0;
+		if (dnslib_packet_to_wire(packet, &wire ,&size) != DNSLIB_EOK) {
+			diag("Could not convert packet to wire");
+		}
+		/* Create ldns packet from created wire */
+		ldns_pkt *ldns_packet = NULL;
+
+		if (ldns_wire2pkt(&ldns_packet, wire,
+		                  size) != LDNS_STATUS_OK) {
+			diag("Could not parse wire using ldns");
+			/*!< \todo get rid of this */
+			diag("%s",
+			     ldns_get_errorstr_by_id(ldns_wire2pkt(&ldns_packet,
+			                             wire,
+			                             size)));
+			return 0;
+		}
+
+		if (check_packet_w_ldns_packet(packet, ldns_packet, 1, 1, 1,
+		                               1) != 0) {
+			diag("Packet wrongly converted to wire!");
+			errors++;
+		}
+		dnslib_packet_free(&packet);
+		ldns_pkt_free(ldns_packet);
+	}
+
+	return (errors == 0);
+}
+
+static const uint DNSLIB_PACKET_TEST_COUNT = 2;
+
+static int packet_tests_count(int argc, char *argv[])
+{
+	return DNSLIB_PACKET_TEST_COUNT;
+}
+
+static int packet_tests_run(int argc, char *argv[])
+{
+	const test_data_t *data = data_for_dnslib_tests;
+
+	int res = 0;
+	ok(res = test_packet_parse_from_wire(data->raw_packet_list),
+	   "packet: from wire");
+	skip(!res, 1);
+	ok(test_packet_to_wire(data->raw_packet_list), "packet: to wire");
+	endskip;
+
+	return 1;
+}
+
diff --git a/src/dnslib/tests/realdata/dnslib/packet_tests_realdata.h b/src/dnslib/tests/realdata/dnslib/packet_tests_realdata.h
new file mode 100644
index 0000000000000000000000000000000000000000..91b9116d3dda7fb7b5b64a7d913f134ac69cdc47
--- /dev/null
+++ b/src/dnslib/tests/realdata/dnslib/packet_tests_realdata.h
@@ -0,0 +1,9 @@
+#ifndef _KNOT_PACKET_REALDATA_TESTS_H_
+#define _KNOT_PACKET_REALDATA_TESTS_H_
+
+#include "common/libtap/tap_unit.h"
+
+/* Unit API. */
+unit_api packet_tests_api;
+
+#endif /* _KNOT_PACKET_REALDATA_TESTS_H_ */
diff --git a/src/dnslib/tests/realdata/dnslib/response2_tests_realdata.c b/src/dnslib/tests/realdata/dnslib/response2_tests_realdata.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e92bd7c38818f61ab0ba19aeae4e4849ef6667c
--- /dev/null
+++ b/src/dnslib/tests/realdata/dnslib/response2_tests_realdata.c
@@ -0,0 +1,157 @@
+/* blame: jan.kadlec@nic.cz */
+
+#include <assert.h>
+
+#include "packet_tests_realdata.h"
+#include "dnslib/error.h"
+#include "dnslib/packet.h"
+#include "dnslib/response2.h"
+/* *test_t structures */
+#include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
+#ifdef TEST_WITH_LDNS
+#include "ldns/packet.h"
+#endif
+
+static int response2_tests_count(int argc, char *argv[]);
+static int response2_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api response2_tests_api = {
+	"DNS library - response2",     //! Unit name
+	&response2_tests_count,  //! Count scheduled tests
+	&response2_tests_run     //! Run scheduled tests
+};
+
+#ifdef TEST_WITH_LDNS
+extern int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count);
+extern int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr, uint16_t type);
+extern int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
+                                   ldns_rr *rr, char check_rdata);
+extern int compare_rrsets_w_ldns_rrlist(const dnslib_rrset_t **rrsets,
+					ldns_rr_list *rrlist, int count);
+
+extern int check_packet_w_ldns_packet(dnslib_packet_t *packet,
+                                      ldns_pkt *ldns_packet,
+                                      int check_header,
+                                      int check_question,
+                                      int check_body,
+                                      int check_edns);
+#endif
+
+extern dnslib_packet_t *packet_from_test_response(test_response_t *response);
+
+static int test_response_init_from_query(list query_list)
+{
+	int errors = 0;
+	node *n = NULL;
+	WALK_LIST(n, query_list) {
+		dnslib_packet_t *response =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+		assert(response);
+		dnslib_packet_t *query =
+			packet_from_test_response((test_response_t *)n);
+		assert(query);
+		dnslib_packet_set_max_size(response, 1024 * 10);
+		if (dnslib_response2_init_from_query(response,
+		                                     query) != DNSLIB_EOK) {
+			diag("Could not init response from query!");
+			errors++;
+		}
+		dnslib_packet_free(&response);
+		dnslib_packet_free(&query);
+	}
+	return (errors == 0);
+}
+
+//static int test_response_add_opt(list opt_list)
+//{
+//	int errors = 0;
+//	node *n = NULL;
+//	WALK_LIST(n, query_list) {
+//		dnslib_packet_t *response =
+//			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+//		assert(response);
+//		dnslib_opt_rr_t *opt =
+//			opt_from_test_opt((test_opt_t *)n);
+//		assert(query);
+//		if (dnslib_response2_add_opt(response,
+//		                             opt, 1)!= DNSLIB_EOK) {
+//			diag("Could not add OPT RR to response!");
+//			errors++;
+//		}
+//		dnslib_packet_free(&response);
+//		dnslib_opt_rr_free(&opt);
+//	}
+//	return (errors == 0);
+//}
+
+extern dnslib_rrset_t *rrset_from_test_rrset(test_rrset_t *test_rrset);
+
+static int test_response_add_generic(int (*func)(dnslib_packet_t *,
+                                                 const dnslib_rrset_t *,
+                                                 int, int, int),
+                                     list rrset_list)
+{
+	/*!< \todo Now adding only one RRSet at the time, try more, use nodes */
+	int errors = 0;
+	node *n = NULL;
+	WALK_LIST(n, rrset_list) {
+		dnslib_packet_t *response =
+			dnslib_packet_new(DNSLIB_PACKET_PREALLOC_RESPONSE);
+		assert(response);
+		dnslib_packet_set_max_size(response,
+		                           DNSLIB_PACKET_PREALLOC_RESPONSE * 100);
+		assert(dnslib_response2_init(response) == DNSLIB_EOK);
+
+		dnslib_rrset_t *rrset =
+			rrset_from_test_rrset((test_rrset_t *)n);
+		assert(rrset);
+
+		int ret = 0;
+		if ((ret = func(response, rrset, 0, 1, 0)) != DNSLIB_EOK) {
+			diag("Could not add RRSet to response! Returned: %d",
+			     ret);
+			diag("(owner: %s type %s)",
+			     ((test_rrset_t *)n)->owner->str,
+			     dnslib_rrtype_to_string((
+			     (test_rrset_t *)n)->type));
+			errors++;
+		}
+		dnslib_packet_free(&response);
+		dnslib_rrset_deep_free(&rrset, 1, 1, 1);
+	}
+
+	return (errors == 0);
+}
+
+static void test_response_add_rrset(list rrset_list)
+{
+	ok(test_response_add_generic(dnslib_response2_add_rrset_answer,
+	                             rrset_list),
+	   "response: add answer rrset");
+	ok(test_response_add_generic(dnslib_response2_add_rrset_authority,
+	                             rrset_list),
+	   "response: add authority rrset");
+	ok(test_response_add_generic(dnslib_response2_add_rrset_additional,
+	                             rrset_list),
+	   "response: add additional rrset");
+}
+
+static const uint DNSLIB_RESPONSE2_TEST_COUNT = 4;
+
+static int response2_tests_count(int argc, char *argv[])
+{
+	return DNSLIB_RESPONSE2_TEST_COUNT;
+}
+
+static int response2_tests_run(int argc, char *argv[])
+{
+	const test_data_t *data = data_for_dnslib_tests;
+
+//	int res = 0;
+	ok(test_response_init_from_query(data->query_list),
+	   "response: init from query");
+	test_response_add_rrset(data->rrset_list);
+	return 1;
+}
diff --git a/src/dnslib/tests/realdata/dnslib/response2_tests_realdata.h b/src/dnslib/tests/realdata/dnslib/response2_tests_realdata.h
new file mode 100644
index 0000000000000000000000000000000000000000..d693e26a7ad57a92048e4208c2767730b3b60fe3
--- /dev/null
+++ b/src/dnslib/tests/realdata/dnslib/response2_tests_realdata.h
@@ -0,0 +1,9 @@
+#ifndef _KNOT_PACKET_RESPONSE2_TESTS_H_
+#define _KNOT_PACKET_RESPONSE2_TESTS_H_
+
+#include "common/libtap/tap_unit.h"
+
+/* Unit API. */
+unit_api response2_tests_api;
+
+#endif /* _KNOT_PACKET_RESPONSE2_TESTS_H_ */
diff --git a/src/dnslib/tests/realdata/dnslib/response_tests_realdata.c b/src/dnslib/tests/realdata/dnslib/response_tests_realdata.c
index dfc982db1c8d339f68b9239c1d231c2a2f469f9f..fcd6038aba8f1298f57f562c4c93049c31dbbcdb 100644
--- a/src/dnslib/tests/realdata/dnslib/response_tests_realdata.c
+++ b/src/dnslib/tests/realdata/dnslib/response_tests_realdata.c
@@ -58,14 +58,6 @@ static int mem_read(void *dst, size_t n, const char **src,
  *  Unit implementation.
  */
 
-/* Parsed raw packet*/
-struct test_raw_packet {
-	uint size;
-	uint8_t *data;
-};
-
-typedef struct test_raw_packet test_raw_packet_t;
-
 enum { DNAME_MAX_WIRE_LENGTH = 256 };
 
 static int load_raw_packets(test_raw_packet_t ***raw_packets, uint32_t *count,
@@ -198,164 +190,164 @@ static dnslib_dname_t *dname_from_test_dname(const test_dname_t *test_dname)
 	                                  NULL);
 }
 
-static int check_response(dnslib_response_t *resp, test_response_t *test_resp,
-			  int check_header, int check_question,
-			  int check_answer, int check_additional,
-			  int check_authority)
-{
-	int errors = 0; /* TODO maybe use it everywhere, or not use it at all */
-
-	if (check_question) {
-		/* again, in case of dnames, pointer would probably suffice */
-		if (dnslib_dname_compare(resp->question.qname,
-		                dname_from_test_dname(test_resp->qname)) != 0) {
-			char *tmp_dname;
-			tmp_dname = dnslib_dname_to_str(resp->question.qname);
-			diag("Qname in response is wrong:\
-			      should be: %s is: %s\n",
-			     tmp_dname, test_resp->qname->str);
-			free(tmp_dname);
-			return 0;
-		}
-
-		if (resp->question.qtype != test_resp->qtype) {
-			diag("Qtype value is wrong: is %u should be %u\n",
-			     resp->question.qtype, test_resp->qtype);
-			return 0;
-		}
-		if (resp->question.qclass != test_resp->qclass) {
-			diag("Qclass value is wrong: is %u should be %u\n",
-			     resp->question.qclass, test_resp->qclass);
-			return 0;
-		}
-	}
-
-	if (check_header) {
-		/* Disabled, since these check make no sense
-		 * if we have parsed the query, flags are now set to
-		 * the ones response should have */
-
-		/*
-		if (resp->header.flags1 != test_resp->flags1) {
-			diag("Flags1 value is wrong: is %u should be %u\n",
-			     resp->header.flags1, test_resp->flags1);
-			//return 0;
-		}
-		if (resp->header.flags2 != test_resp->flags2) {
-			diag("Flags2 value is wrong: is %u should be %u\n",
-			     resp->header.flags2, test_resp->flags2);
-			return 0;
-		}
-		*/
-
-		if (resp->header.qdcount != test_resp->qdcount) {
-			diag("Qdcount value is wrong: is %u should be %u\n",
-			     resp->header.qdcount, test_resp->qdcount);
-			return 0;
-		}
-		if (resp->header.ancount != test_resp->ancount) {
-			diag("Ancount value is wrong: is %u should be %u\n",
-			     resp->header.ancount, test_resp->ancount);
-			return 0;
-		}
-		if (resp->header.nscount != test_resp->nscount) {
-			diag("Nscount value is wrong: is %u should be %u\n",
-			     resp->header.nscount, test_resp->nscount);
-			return 0;
-		}
-		if (resp->header.arcount != test_resp->arcount) {
-			diag("Arcount value is different: is %u should be %u\n",
-			     resp->header.arcount, test_resp->arcount);
+//static int check_response(dnslib_response_t *resp, test_response_t *test_resp,
+//			  int check_header, int check_question,
+//			  int check_answer, int check_additional,
+//			  int check_authority)
+//{
+//	int errors = 0; /* TODO maybe use it everywhere, or not use it at all */
+
+//	if (check_question) {
+//		/* again, in case of dnames, pointer would probably suffice */
+//		if (dnslib_dname_compare(resp->question.qname,
+//		                dname_from_test_dname(test_resp->qname)) != 0) {
+//			char *tmp_dname;
+//			tmp_dname = dnslib_dname_to_str(resp->question.qname);
+//			diag("Qname in response is wrong: "
+//			      "should be: %s is: %s\n",
+//			     tmp_dname, test_resp->qname->str);
+//			free(tmp_dname);
 //			return 0;
-		}
-	}
-
-	if (check_question) {
-		/* Currently just one question RRSET allowed */
-		if (dnslib_dname_compare(resp->question.qname,
-		    dname_from_test_dname(test_resp->qname)) != 0) {
-			diag("Qname is wrongly set");
-			errors++;
-		}
-
-		if (resp->question.qtype != test_resp->qtype) {
-			diag("Qtype is wrongly set");
-			errors++;
-		}
+//		}
 
-		if (resp->question.qclass != test_resp->qclass) {
-			diag("Qclass is wrongly set");
-			errors++;
-		}
+//		if (resp->question.qtype != test_resp->qtype) {
+//			diag("Qtype value is wrong: is %u should be %u\n",
+//			     resp->question.qtype, test_resp->qtype);
+//			return 0;
+//		}
+//		if (resp->question.qclass != test_resp->qclass) {
+//			diag("Qclass value is wrong: is %u should be %u\n",
+//			     resp->question.qclass, test_resp->qclass);
+//			return 0;
+//		}
+//	}
 
-	}
+//	if (check_header) {
+//		/* Disabled, since these check make no sense
+//		 * if we have parsed the query, flags are now set to
+//		 * the ones response should have */
 
-	/* Following code is not used anywhere currently. */
+//		/*
+//		if (resp->header.flags1 != test_resp->flags1) {
+//			diag("Flags1 value is wrong: is %u should be %u\n",
+//			     resp->header.flags1, test_resp->flags1);
+//			//return 0;
+//		}
+//		if (resp->header.flags2 != test_resp->flags2) {
+//			diag("Flags2 value is wrong: is %u should be %u\n",
+//			     resp->header.flags2, test_resp->flags2);
+//			return 0;
+//		}
+//		*/
 
-//	if (check_authority) {
-//		for (int i = 0; (i < resp->header.arcount) && !errors; i++) {
-//			if (resp->authority[i] != (test_resp->authority[i])) {
-//				diag("Authority rrset #%d is wrongly set.\n",
-//				     i);
-//				errors++;
-//			}
+//		if (resp->header.qdcount != test_resp->qdcount) {
+//			diag("Qdcount value is wrong: is %u should be %u\n",
+//			     resp->header.qdcount, test_resp->qdcount);
+//			return 0;
+//		}
+//		if (resp->header.ancount != test_resp->ancount) {
+//			diag("Ancount value is wrong: is %u should be %u\n",
+//			     resp->header.ancount, test_resp->ancount);
+//			return 0;
+//		}
+//		if (resp->header.nscount != test_resp->nscount) {
+//			diag("Nscount value is wrong: is %u should be %u\n",
+//			     resp->header.nscount, test_resp->nscount);
+//			return 0;
+//		}
+//		if (resp->header.arcount != test_resp->arcount) {
+//			diag("Arcount value is different: is %u should be %u\n",
+//			     resp->header.arcount, test_resp->arcount);
+////			return 0;
 //		}
 //	}
 
-//	if (check_answer) {
-//		for (int i = 0; (i < resp->header.arcount) && !errors; i++) {
-//			if (resp->authority[i] != (test_resp->authority[i])) {
-//				diag("Authority rrset #%d is wrongly set.\n",
-//				     i);
-//				errors++;
-//			}
+//	if (check_question) {
+//		/* Currently just one question RRSET allowed */
+//		if (dnslib_dname_compare(resp->question.qname,
+//		    dname_from_test_dname(test_resp->qname)) != 0) {
+//			diag("Qname is wrongly set");
+//			errors++;
 //		}
-//	}
 
-//	if (check_additional) {
-//		for (int i = 0; (i < resp->header.arcount) && !errors; i++) {
-//			if (resp->authority[i] != (test_resp->authority[i])) {
-//				diag("Authority rrset #%d is wrongly set.\n",
-//				     i);
-//				errors++;
-//			}
+//		if (resp->question.qtype != test_resp->qtype) {
+//			diag("Qtype is wrongly set");
+//			errors++;
 //		}
-//	}
 
-	return (errors == 0);
-}
+//		if (resp->question.qclass != test_resp->qclass) {
+//			diag("Qclass is wrongly set");
+//			errors++;
+//		}
 
-static int test_response_parse_query(list response_list,
-				     test_raw_packet_t **raw_queries,
-				     uint count)
-{
-	assert(raw_queries);
+//	}
 
-	int errors = 0;
-	dnslib_response_t *resp = NULL;
-	node *n = NULL;
-	int i = 0;
-	WALK_LIST(n, response_list) {
-		assert(i < count);
-		test_response_t *test_response = (test_response_t *)n;
-		resp = dnslib_response_new_empty(NULL);
-		assert(resp);
+//	/* Following code is not used anywhere currently. */
+
+////	if (check_authority) {
+////		for (int i = 0; (i < resp->header.arcount) && !errors; i++) {
+////			if (resp->authority[i] != (test_resp->authority[i])) {
+////				diag("Authority rrset #%d is wrongly set.\n",
+////				     i);
+////				errors++;
+////			}
+////		}
+////	}
+
+////	if (check_answer) {
+////		for (int i = 0; (i < resp->header.arcount) && !errors; i++) {
+////			if (resp->authority[i] != (test_resp->authority[i])) {
+////				diag("Authority rrset #%d is wrongly set.\n",
+////				     i);
+////				errors++;
+////			}
+////		}
+////	}
+
+////	if (check_additional) {
+////		for (int i = 0; (i < resp->header.arcount) && !errors; i++) {
+////			if (resp->authority[i] != (test_resp->authority[i])) {
+////				diag("Authority rrset #%d is wrongly set.\n",
+////				     i);
+////				errors++;
+////			}
+////		}
+////	}
+
+//	return (errors == 0);
+//}
 
-//		hex_print(raw_queries[i]->data, raw_queries[i]->size);
+//static int test_response_parse_query(list response_list,
+//				     test_raw_packet_t **raw_queries,
+//				     uint count)
+//{
+//	assert(raw_queries);
 
-		if (dnslib_response_parse_query(resp,
-						raw_queries[i]->data,
-						raw_queries[i]->size) != 0) {
-			diag("Could not parse query\n");
-			errors++;
-		}
-		errors += !check_response(resp, test_response, 1, 1, 0, 0, 0);
-		dnslib_response_free(&resp);
-		i++;
-	}
+//	int errors = 0;
+//	dnslib_response_t *resp = NULL;
+//	node *n = NULL;
+//	int i = 0;
+//	WALK_LIST(n, response_list) {
+//		assert(i < count);
+//		test_response_t *test_response = (test_response_t *)n;
+//		resp = dnslib_response_new_empty(NULL);
+//		assert(resp);
+
+////		hex_print(raw_queries[i]->data, raw_queries[i]->size);
+
+//		if (dnslib_response_parse_query(resp,
+//						raw_queries[i]->data,
+//						raw_queries[i]->size) != 0) {
+//			diag("Could not parse query\n");
+//			errors++;
+//		}
+//		errors += !check_response(resp, test_response, 1, 1, 0, 0, 0);
+//		dnslib_response_free(&resp);
+//		i++;
+//	}
 
-	return (errors == 0);
-}
+//	return (errors == 0);
+//}
 
 #ifndef TEST_WITH_LDNS
 /*! \note disabled */
@@ -398,7 +390,7 @@ int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count)
  * Comparison is done through comparing wireformats.
  * Returns 0 if rdata are the same, 1 otherwise
  */
-static int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr,
+int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr,
 			    uint16_t type)
 {
 	dnslib_rrtype_descriptor_t *desc =
@@ -449,12 +441,12 @@ static int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr,
 				(rdata->items[i].raw_data + 1),
 				ldns_rdf_data(ldns_rr_rdf(rr, i)),
 				rdata->items[i].raw_data[0]) != 0) {
-				hex_print((char *)
-					  (rdata->items[i].raw_data + 1),
-					  rdata->items[i].raw_data[0]);
-				hex_print((char *)
-					  ldns_rdf_data(ldns_rr_rdf(rr, i)),
-					  rdata->items[i].raw_data[0]);
+//				hex_print((char *)
+//					  (rdata->items[i].raw_data + 1),
+//					  rdata->items[i].raw_data[0]);
+//				hex_print((char *)
+//					  ldns_rdf_data(ldns_rr_rdf(rr, i)),
+//					  rdata->items[i].raw_data[0]);
 				diag("Raw data wires in rdata differ in item "
 				     "%d", i);
 
@@ -466,12 +458,14 @@ static int compare_rr_rdata(dnslib_rdata_t *rdata, ldns_rr *rr,
 	return 0;
 }
 
-static int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
+int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
 				      ldns_rr *rr, char check_rdata)
 {
 	/* We should have only one rrset from ldns, although it is
 	 * represented as rr_list ... */
 
+	int errors = 0;
+
 	assert(rr);
 	assert(rrset);
 
@@ -485,32 +479,32 @@ static int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
 		diag("%s", tmp_dname);
 		diag("%s", ldns_rdf_data(ldns_rr_owner(rr)));
 		free(tmp_dname);
-		return 1;
+		errors++;
 	}
 
 	if (compare_wires_simple(rrset->owner->name,
 				 ldns_rdf_data(ldns_rr_owner(rr)),
 				 rrset->owner->size) != 0) {
 		diag("RRSet owner wireformats differ");
-		return 1;
+		errors++;
 	}
 
 	if (rrset->type != ldns_rr_get_type(rr)) {
 		diag("RRset types differ");
 		diag("Dnslib type: %d Ldns type: %d", rrset->type,
 		     ldns_rr_get_type(rr));
-		return 1;
+		errors++;
 	}
 
 	if (rrset->rclass != ldns_rr_get_class(rr)) {
 		diag("RRset classes differ");
-		return 1;
+		errors++;
 	}
 
 	if (rrset->ttl != ldns_rr_ttl(rr)) {
 		diag("RRset TTLs differ");
 		diag("dnslib: %d ldns: %d", rrset->ttl, ldns_rr_ttl(rr));
-		return 1;
+		errors++;
 	}
 
 	/* compare rdatas */
@@ -556,14 +550,14 @@ static int compare_rrset_w_ldns_rr(const dnslib_rrset_t *rrset,
 	if (check_rdata) {
 		if (compare_rr_rdata(rrset->rdata, rr, rrset->type) != 0) {
 			diag("Rdata differ");
-			return 1;
+			errors++;
 		}
 	}
 
-	return 0;
+	return errors;
 }
 
-static int compare_rrsets_w_ldns_rrlist(const dnslib_rrset_t **rrsets,
+int compare_rrsets_w_ldns_rrlist(const dnslib_rrset_t **rrsets,
 					ldns_rr_list *rrlist, int count)
 {
 	int errors = 0;
diff --git a/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.c b/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.c
index 5e50ae9338d3552dd99db1168181a42d934b4fae..fbda077ff330f0e56e36427d3cd6b85e98fe5b1f 100644
--- a/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.c
+++ b/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.c
@@ -6,7 +6,8 @@
 #include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
 #include "dnslib/descriptor.h"
 
-#include "dnslib/tests/parsed_data.rc"
+#include "dnslib/tests/realdata/parsed_data.rc"
+#include "dnslib/tests/realdata/raw_data.rc"
 TREE_DEFINE(test_node, avl);
 
 /* Virtual I/O over memory. */
@@ -26,6 +27,56 @@ static int mem_read(void *dst, size_t n, const char **src,
 	return 1;
 }
 
+static int load_raw_packets(test_data_t *data, uint32_t *count,
+			    const char *src, unsigned src_size)
+{
+
+	uint16_t tmp_size = 0;
+
+	/* Packets are stored like this: [size][packet_data]+ */
+
+	if(!mem_read(count, sizeof(uint32_t), &src, &src_size)) {
+		return -1;
+	}
+
+	for (int i = 0; i < *count; i++) {
+		uint16_t query = 0;
+		if (!mem_read(&query, sizeof(query), &src, &src_size)) {
+			return -1;
+		}
+
+		if(!mem_read(&tmp_size, sizeof(uint16_t), &src, &src_size)) {
+			return -1;
+		}
+
+		test_raw_packet_t *packet = malloc(sizeof(test_raw_packet_t));
+
+
+		packet->size = tmp_size;
+		packet->data = malloc(sizeof(uint8_t) * (tmp_size));
+		if(!mem_read(packet->data,
+			     sizeof(uint8_t) * tmp_size, &src, &src_size)) {
+			return -1;
+		}
+
+		if (query) {
+			add_tail(&data->raw_query_list, (void *)packet);
+		} else {
+			add_tail(&data->raw_response_list, (void *)packet);
+		}
+
+		test_raw_packet_t *new_packet =
+			malloc(sizeof(test_raw_packet_t));
+		assert(new_packet);
+		new_packet->data = packet->data;
+		new_packet->size = packet->size;
+
+		add_tail(&data->raw_packet_list, (void *)new_packet);
+	}
+
+	return 0;
+}
+
 /* Returns size of type where avalailable */
 size_t wireformat_size_load(uint wire_type)
 {
@@ -368,7 +419,7 @@ static test_rdata_t *load_response_rdata(uint16_t type,
 				    items[i].raw_data) + 3,
 				    sizeof(uint8_t) * (raw_data_length),
 				    src, src_size)) {
-					diag("Wrong read 3!");
+					fprintf(stderr, "Wrong read!\n");
 					return NULL;
 				}
 
@@ -444,7 +495,7 @@ static test_rdata_t *load_response_rdata(uint16_t type,
 				if (!mem_read(items[i].raw_data + 1,
 					      size_fr_desc,
 					      src, src_size)) {
-					diag("Wrong read 4!");
+					fprintf(stderr, "Wrong read\n!");
 					return NULL;
 				}
 
@@ -572,7 +623,8 @@ static test_rrset_t *load_response_rrset(const char **src, unsigned *src_size,
 		tmp_rdata = load_response_rdata(rrset->type, src, src_size);
 
 		if (tmp_rdata == NULL) {
-			diag("Could not load rrset rdata - type: %d",
+			fprintf(stderr,
+			        "Could not load rrset rdata - type: %d",
 			     rrset->type);
 			free(rrset);
 			return NULL;
@@ -645,6 +697,11 @@ static test_response_t *load_parsed_response(const char **src,
 	fprintf(stderr, "arcount: %d\n", resp->arcount);
 #endif
 
+	if (!mem_read(&resp->query, sizeof(resp->query), src, src_size)) {
+		free(resp);
+		return NULL;
+	}
+
 	test_rrset_t **question_rrsets;
 
 	question_rrsets = malloc(sizeof(test_rrset_t *) * resp->qdcount);
@@ -995,7 +1052,6 @@ static void get_and_save_data_from_response(const test_response_t *response,
 static int load_parsed_responses(test_data_t *data, uint32_t *count,
 				 const char* src, unsigned src_size)
 {
-
 	if (!mem_read(count, sizeof(*count), &src, &src_size)) {
 		fprintf(stderr, "Wrong read\n");
 		return -1;
@@ -1014,8 +1070,18 @@ static int load_parsed_responses(test_data_t *data, uint32_t *count,
 			return -1;
 		}
 
-		add_tail(&data->response_list,
-		         (node *)tmp_response);
+		if (tmp_response->query) {
+			add_tail(&data->query_list, (node *)tmp_response);
+		} else {
+			add_tail(&data->response_list, (node *)tmp_response);
+		}
+
+		/* Create new node */
+		test_response_t *resp = malloc(sizeof(test_response_t));
+		assert(resp);
+		memcpy(resp, tmp_response, sizeof(test_response_t));
+		add_tail(&data->packet_list,
+		         (node *)resp);
 	}
 
 	return 0;
@@ -1052,6 +1118,11 @@ static int init_data(test_data_t *data)
 	init_list(&data->rdata_list);
 	init_list(&data->rrset_list);
 	init_list(&data->item_list);
+	init_list(&data->raw_response_list);
+	init_list(&data->raw_query_list);
+	init_list(&data->raw_packet_list);
+	init_list(&data->query_list);
+	init_list(&data->packet_list);
 
 	data->node_tree = malloc(sizeof(avl_tree_test_t));
 	CHECK_ALLOC_LOG(data->node_tree, 0);
@@ -1063,8 +1134,10 @@ static int init_data(test_data_t *data)
 
 static void print_stats(test_data_t *data)
 {
-	uint resp_count = 0, dname_count = 0, edns_count = 0, node_count = 0,
-	     rdata_count = 0, rrset_count = 0, item_count = 0;
+	uint resp_count = 0, dname_count = 0, node_count = 0,
+	     rdata_count = 0, rrset_count = 0, item_count = 0, query_count = 0,
+	     raw_query_count = 0, response_count = 0, packet_count = 0,
+	     raw_packet_count = 0, raw_response_count = 0;
 
 	node *n = NULL; /* Will not be used */
 
@@ -1073,12 +1146,12 @@ static void print_stats(test_data_t *data)
 	}
 
 	WALK_LIST(n, data->rrset_list) {
-		node *tmp = NULL;
-		assert(((test_rrset_t *)n)->owner);
-		WALK_LIST(tmp, ((test_rrset_t *)n)->rdata_list) {
-			test_rdata_t *rdata = (test_rdata_t *)tmp;
-			assert(rdata->type == ((test_rrset_t *)n)->type);
-		}
+//		node *tmp = NULL;
+//		assert(((test_rrset_t *)n)->owner);
+//		WALK_LIST(tmp, ((test_rrset_t *)n)->rdata_list) {
+//			test_rdata_t *rdata = (test_rdata_t *)tmp;
+//			assert(rdata->type == ((test_rrset_t *)n)->type);
+//		}
 		rrset_count++;
 	}
 
@@ -1098,8 +1171,36 @@ static void print_stats(test_data_t *data)
 		item_count++;
 	}
 
-	printf("Loaded: Responses: %d RRSets: %d RDATAs: %d Dnames: %d Nodes: %d Items: %d\n", resp_count, rrset_count,
-	       rdata_count, dname_count, node_count, item_count);
+	WALK_LIST(n, data->raw_response_list) {
+		raw_response_count++;
+	}
+
+	WALK_LIST(n, data->query_list) {
+		query_count++;
+	}
+
+	WALK_LIST(n, data->response_list) {
+		response_count++;
+	}
+
+	WALK_LIST(n, data->raw_query_list) {
+		raw_query_count++;
+	}
+
+	WALK_LIST(n, data->packet_list) {
+		packet_count++;
+	}
+
+	WALK_LIST(n, data->raw_packet_list) {
+		raw_packet_count++;
+	}
+
+	printf("Loaded: Responses: %d RRSets: %d RDATAs: %d Dnames: %d "
+	       "Nodes: %d Items: %d Raw_responses: %d Queries: %d \n"
+	       "Raw_queries; %d Total packets: %d Total_raw_packets: %d\n", resp_count, rrset_count,
+	       rdata_count, dname_count, node_count, item_count,
+	       raw_response_count, query_count, raw_query_count, packet_count,
+	       raw_packet_count);
 }
 
 static void save_node_to_list(test_node_t *n, void *p)
@@ -1111,7 +1212,7 @@ static void save_node_to_list(test_node_t *n, void *p)
 
 static void del_node(test_node_t *n, void *p)
 {
-	test_data_t *data = (test_data_t *)p;
+//	test_data_t *data = (test_data_t *)p;
 	free(n);
 }
 
@@ -1148,7 +1249,17 @@ test_data_t *create_test_data_from_dump()
 		return NULL;
 	}
 
-	uint response_count;
+	uint32_t raw_packet_count = 0;
+
+	if (load_raw_packets(ret, &raw_packet_count, raw_data_rc,
+	                     raw_data_rc_size) != 0) {
+		fprintf(stderr, "Could not load raw_data, quitting");
+		/* TODO walk the lists*/
+		free(ret);
+		return NULL;
+	}
+
+	uint32_t response_count = 0;
 
 	if (load_parsed_responses(ret, &response_count, parsed_data_rc,
 	                          parsed_data_rc_size) != 0) {
diff --git a/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.h b/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.h
index 69c9be591de47a422eb1900562a3805d3493ecc8..0fa0a555840734a12e28e8dcea5fd57f1cf96c79 100644
--- a/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.h
+++ b/src/dnslib/tests/realdata/dnslib_tests_loader_realdata.h
@@ -9,12 +9,13 @@
 
 
 /* Parsed raw packet*/
-//struct test_raw_packet {
-//	uint size;
-//	uint8_t *data;
-//};
+struct test_raw_packet {
+	struct node *next, *prev;
+	uint size;
+	uint8_t *data;
+};
 
-/*typedef struct test_raw_packet test_raw_packet_t*/;
+typedef struct test_raw_packet test_raw_packet_t;
 
 /* Test type definitions */
 
@@ -105,6 +106,7 @@ typedef struct test_rrset test_rrset_t;
 struct test_response {
 	struct node *next, *prev;
 	/* This is basically same thing as actual response structure */
+	uint16_t query;
 	test_dname_t *qname;
 	uint16_t qclass;
 	uint16_t qtype;
@@ -140,7 +142,13 @@ struct test_data {
 	list node_list;
 	list rrset_list;
 	list response_list;
+	list raw_response_list;
+	list query_list;
+	list raw_query_list;
 	list item_list;
+	/* responses and queries together */
+	list packet_list;
+	list raw_packet_list;
 
 	avl_tree_test_t *node_tree;
 };
diff --git a/src/dnslib/tests/realdata/files/parsed_data b/src/dnslib/tests/realdata/files/parsed_data
index 4027c920d2d6372d570efbb2798f40ec194c8135..fe22b9017fc6ee4e1dca6a23bf5bd4e1e639d54b 100644
Binary files a/src/dnslib/tests/realdata/files/parsed_data and b/src/dnslib/tests/realdata/files/parsed_data differ
diff --git a/src/dnslib/tests/realdata/files/raw_data b/src/dnslib/tests/realdata/files/raw_data
index f94236b9fc5d70073b843252366d7436bea4c503..502005e96b582b149f611e1a1e1feab1d7a696cc 100644
Binary files a/src/dnslib/tests/realdata/files/raw_data and b/src/dnslib/tests/realdata/files/raw_data differ
diff --git a/src/dnslib/tests/realdata/unittests_dnslib_realdata.c b/src/dnslib/tests/realdata/unittests_dnslib_realdata.c
index e5f81825451d36c7b3849434b35977364cac17be..d48eee05f3e19eeaa78f10e9da375925a491e15f 100644
--- a/src/dnslib/tests/realdata/unittests_dnslib_realdata.c
+++ b/src/dnslib/tests/realdata/unittests_dnslib_realdata.c
@@ -9,10 +9,12 @@
 //#include "dnslib/edns_tests.h"
 #include "dnslib/node_tests_realdata.h"
 #include "dnslib/rdata_tests_realdata.h"
-#include "dnslib/response_tests_realdata.h"
+//#include "dnslib/response_tests_realdata.h"
+#include "dnslib/response2_tests_realdata.h"
 #include "dnslib/rrset_tests_realdata.h"
 //#include "dnslib/zone_tests_realdata.h"
 #include "dnslib/zonedb_tests_realdata.h"
+#include "dnslib/packet_tests_realdata.h"
 
 #include "common/lists.h"
 // Run all loaded units
@@ -37,7 +39,9 @@ int main(int argc, char *argv[])
 //		&edns_tests_api,     //! DNS library (EDNS0) unit
 		&node_tests_api,     //! DNS library (node) unit
 		&rdata_tests_api,    //! DNS library (rdata) unit
-		&response_tests_api, //! DNS library (response) unit
+		&packet_tests_api,
+//		&response_tests_api, //! DNS library (response) unit
+		&response2_tests_api, //! DNS library (response) unit
 		&rrset_tests_api,    //! DNS library (rrset) unit
 //		&zone_tests_api,     //! DNS library (zone) unit
 //		&zonedb_tests_api,   //! DNS library (zonedb) unit
diff --git a/src/dnslib/tests/unittests_dnslib.c b/src/dnslib/tests/unittests_dnslib.c
index 860fd2e265b956410948dc6e9fa7f221a7394d57..3b6a496a7b9dd8ad228a037c4f2959c82935b544 100644
--- a/src/dnslib/tests/unittests_dnslib.c
+++ b/src/dnslib/tests/unittests_dnslib.c
@@ -8,9 +8,13 @@
 #include "dnslib/edns_tests.h"
 #include "dnslib/node_tests.h"
 #include "dnslib/rdata_tests.h"
-//#include "dnslib/response_tests.h"
+#include "dnslib/response2_tests.h"
 #include "dnslib/rrset_tests.h"
 #include "dnslib/zone_tests.h"
+#include "dnslib/dname_table_tests.h"
+#include "dnslib/nsec3_tests.h"
+#include "dnslib/packet_tests.h"
+#include "dnslib/query_tests.h"
 #include "dnslib/zonedb_tests.h"
 
 // Run all loaded units
@@ -26,12 +30,16 @@ int main(int argc, char *argv[])
 		&cuckoo_tests_api,   //! Cuckoo hashing unit
 		&dname_tests_api,    //! DNS library (dname) unit
 		&edns_tests_api,     //! DNS library (EDNS0) unit
-		&node_tests_api,     //! DNS library (node) unit
+//		&node_tests_api,     //! DNS library (node) unit
 		&rdata_tests_api,    //! DNS library (rdata) unit
-//		&response_tests_api, //! DNS library (response) unit
+		&response2_tests_api, //! DNS library (response) unit
 		&rrset_tests_api,    //! DNS library (rrset) unit
-		&zone_tests_api,     //! DNS library (zone) unit
+		&dname_table_tests_api,
+		&nsec3_tests_api,
+		&packet_tests_api,
+		&query_tests_api,
 		&zonedb_tests_api,   //! DNS library (zonedb) unit
+		&zone_tests_api,     //! DNS library (zone) unit
 		NULL
 	};
 
diff --git a/src/dnslib/zone-dump.h b/src/dnslib/zone-dump.h
index 11b7014f2b3e37cfd4c39d99243c95319b941df0..4f24f59f296eba1238f47d0137f20779f6cf2596 100644
--- a/src/dnslib/zone-dump.h
+++ b/src/dnslib/zone-dump.h
@@ -53,6 +53,21 @@ int dnslib_zdump_binary(dnslib_zone_contents_t *zone, const char *filename,
 int dnslib_zdump_rrset_serialize(const dnslib_rrset_t *rrset, uint8_t **stream,
                                  size_t *size);
 
+/*!
+ * \brief Serializes RRSet into binary stream. Expects NULL pointer, memory
+ *        is handled inside function.
+ *
+ * \param rrset RRSet to be serialized.
+ * \param stream Stream containing serialized RRSet.
+ * \param size Length of created stream.
+ *
+ * \retval DNSLIB_EOK on success.
+ * \retval DNSLIB_EBADARG if wrong arguments are supplied.
+ * \retval DNSLIB_ENOMEM on memory error.
+ */
+int dnslib_zdump_rrset_serialize(const dnslib_rrset_t *rrset, uint8_t **stream,
+                                 size_t *size);
+
 #endif /* _DNSLIB_ZONEDUMP_H_ */
 
 /*! @} */