diff --git a/lib/cache.c b/lib/cache.c
index 2ce91795c674d2be0f39cebcb5e632f7776dcf92..c735e4510f0f29fc9b84d65e5b243464eb9dad2f 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -28,12 +28,6 @@
 #include "lib/cache.h"
 #include "lib/defines.h"
 
-#ifndef NDEBUG
-#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[cache] " fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_MSG(fmt, ...)
-#endif
-
 #define db_api namedb_lmdb_api()
 
 namedb_t *kr_cache_open(const char *handle, mm_ctx_t *mm, size_t maxsize)
@@ -103,13 +97,7 @@ int kr_cache_peek(namedb_txn_t *txn, knot_rrset_t *rr, uint32_t *timestamp)
 	/* Check if the RRSet is in the cache. */
 	struct kr_cache_rrset *found_rr = cache_rr(txn, rr->owner, rr->type);
 	if (found_rr != NULL) {
-#ifndef NDEBUG
-		char name_str[KNOT_DNAME_MAXLEN];
-		knot_dname_to_str(name_str, rr->owner, sizeof(name_str));
-		char type_str[16];
-		knot_rrtype_to_string(rr->type, type_str, sizeof(type_str));
-		DEBUG_MSG("read '%s %s' => %u RRs\n", name_str, type_str, found_rr->count);
-#endif
+
 		/* Assign data and return success. */
 		rr->rrs.rr_count = found_rr->count;
 		rr->rrs.data = found_rr->data;
@@ -183,14 +171,6 @@ int kr_cache_insert(namedb_txn_t *txn, const knot_rrset_t *rr, uint32_t timestam
 	namedb_val_t key = { keybuf, key_len };
 	namedb_val_t val = { NULL, sizeof(struct kr_cache_rrset) + knot_rdataset_size(&rr->rrs) };
 
-#ifndef NDEBUG
-	char name_str[KNOT_DNAME_MAXLEN];
-	knot_dname_to_str(name_str, rr->owner, sizeof(name_str));
-	char type_str[16];
-	knot_rrtype_to_string(rr->type, type_str, sizeof(type_str));
-	DEBUG_MSG("write '%s %s' => %u RRs (key=%zuB,data=%zuB)\n", name_str, type_str, rr->rrs.rr_count, key.len, val.len);
-#endif
-
 	int ret = db_api->insert(txn, &key, &val, 0);
 	if (ret != KNOT_EOK) {
 		return ret;
@@ -211,16 +191,6 @@ int kr_cache_remove(namedb_txn_t *txn, const knot_rrset_t *rr)
 	size_t key_len = cache_key(keybuf, rr->owner, rr->type);
 	namedb_val_t key = { keybuf, key_len };
 
-#ifndef NDEBUG
-	char name_str[KNOT_DNAME_MAXLEN];
-	knot_dname_to_str(name_str, rr->owner, sizeof(name_str));
-	char type_str[16];
-	knot_rrtype_to_string(rr->type, type_str, sizeof(type_str));
-	DEBUG_MSG("del  '%s %s'\n", name_str, type_str);
-#endif
-
-	/* TODO: selective deletion by RRSet subtraction */
-
 	return db_api->del(txn, &key);
 }
 
diff --git a/lib/layer.h b/lib/layer.h
index 6a11efc1a504d2548db0ee76457d99337f42c1a0..e3fa7b7c0f7179157dcf84cad3a6acde1167286e 100644
--- a/lib/layer.h
+++ b/lib/layer.h
@@ -32,3 +32,15 @@ struct kr_layer_param {
 	struct kr_rplan *rplan;
 	knot_pkt_t *answer;
 };
+
+/*! \internal Print a debug message related to resolution. */
+#ifndef NDEBUG
+ #define QRDEBUG(query, cls, fmt, ...) do { \
+    unsigned _ind = 0; \
+    for (struct kr_query *q = (query); q; q = q->parent, _ind += 2); \
+    fprintf(stderr, "[%s] %*s" fmt, cls, _ind, "", ##  __VA_ARGS__); \
+    } while (0)
+#else
+ #define QRDEBUG(query, cls, fmt, ...)
+#endif
+
diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c
index e839a2f4b495182b353dd3052f6a17fb56ca6b26..a15c3292ecbafa977309a6a877188c8fd21239a9 100644
--- a/lib/layer/iterate.c
+++ b/lib/layer/iterate.c
@@ -26,11 +26,15 @@
 #include "lib/rplan.h"
 #include "lib/defines.h"
 
-#ifndef NDEBUG
-#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[qiter] " fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_MSG(fmt, ...)
-#endif
+#define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(param->rplan), "iter", fmt)
+
+/* Packet classification. */
+enum {
+	PKT_NOERROR   = 1 << 0, /* Positive response */
+	PKT_NODATA    = 1 << 1, /* No data response */
+	PKT_NXDOMAIN  = 1 << 2, /* Negative response */
+	PKT_ERROR     = 1 << 3  /* Refused or server failure */ 
+};
 
 /* Iterator often walks through packet section, this is an abstraction. */
 typedef int (*rr_callback_t)(const knot_rrset_t *, unsigned, struct kr_layer_param *);
@@ -72,6 +76,20 @@ static bool is_paired_to_query(const knot_pkt_t *answer, struct kr_query *query)
 	       knot_dname_is_equal(qname, knot_pkt_qname(answer));
 }
 
+/*! \brief Return response class. */
+static int response_classify(knot_pkt_t *pkt)
+{
+	const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+	switch (knot_wire_get_rcode(pkt->wire)) {
+	case KNOT_RCODE_NOERROR:
+		return (an->count == 0) ? PKT_NODATA : PKT_NOERROR;
+	case KNOT_RCODE_NXDOMAIN:
+		return PKT_NXDOMAIN;
+	default:
+		return PKT_ERROR;
+	}
+}
+
 static void follow_cname_chain(const knot_dname_t **cname, const knot_rrset_t *rr,
                                struct kr_query *cur)
 {
@@ -129,8 +147,7 @@ int rr_update_answer(const knot_rrset_t *rr, unsigned hint, struct kr_layer_para
 		return KNOT_NS_PROC_DONE;
 	}
 
-	/* Update parent query as well. */
-	return rr_update_parent(rr, hint, param);
+	return KNOT_NS_PROC_DONE;
 }
 
 int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param)
@@ -157,28 +174,18 @@ int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_
 
 static int process_authority(knot_pkt_t *pkt, struct kr_layer_param *param)
 {
-	int state = KNOT_NS_PROC_MORE;
-
-	/* Answer declares AA, can't be referral. */
-	if (knot_wire_get_aa(pkt->wire)) {
-		return state;
-	}
-
-	/* Update current zone cut from NS records. */
 	const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
 	for (unsigned i = 0; i < ns->count; ++i) {
 		const knot_rrset_t *rr = knot_pkt_rr(ns, i);
-		if (rr->type != KNOT_RRTYPE_NS) {
-			continue;
-		}
-
-		state = rr_update_nameserver(rr, 0, param);
-		if (state != KNOT_NS_PROC_MORE) {
-			break;
+		if (rr->type == KNOT_RRTYPE_NS) {
+			int state = rr_update_nameserver(rr, 0, param);
+			if (state != KNOT_NS_PROC_MORE) {
+				return state;
+			}
 		}
 	}
 
-	return state;
+	return KNOT_NS_PROC_MORE;
 }
 
 static int process_additional(knot_pkt_t *pkt, struct kr_layer_param *param)
@@ -211,27 +218,19 @@ static int process_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
 	 * NOERROR  => found zone cut, retry
 	 * NXDOMAIN => parent is zone cut, retry as a workaround for bad authoritatives
 	 */
-	const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
-	bool is_minimized = (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname));
-	bool is_nodata = (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NOERROR) && !an->count;
-	bool is_nxdomain = (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NXDOMAIN);
-	if (is_minimized && (is_nodata || is_nxdomain)) {
+	bool is_final = (query->parent == NULL);
+	int pkt_class = response_classify(pkt);
+	if (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname) && (pkt_class & (PKT_NXDOMAIN|PKT_NODATA))) {
 		query->flags |= QUERY_NO_MINIMIZE;
 		return KNOT_NS_PROC_DONE;
 	}
 
-	/* Does this answer update the final response? */
-	rr_callback_t callback = &rr_update_parent;
-	if (query->parent == NULL) {
-		knot_wire_set_rcode(param->answer->wire, knot_wire_get_rcode(pkt->wire));
-		callback = &rr_update_answer;
-	}
-
-	/* Process answer section records. */
+	/* Process answer type */
+	const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
 	const knot_dname_t *cname = query->sname;
 	for (unsigned i = 0; i < an->count; ++i) {
 		const knot_rrset_t *rr = knot_pkt_rr(an, i);
-		int state = callback(rr, 0, param);
+		int state = is_final ?  rr_update_answer(rr, 0, param) : rr_update_parent(rr, 0, param);
 		if (state == KNOT_NS_PROC_FAIL) {
 			return state;
 		}
@@ -243,16 +242,39 @@ static int process_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
 		(void) kr_rplan_push(param->rplan, query->parent, cname, query->sclass, query->stype);
 	}
 
-	/* This is either declares AA or not, either way it resolves current query. */
+	/* Either way it resolves current query. */
 	kr_rplan_pop(param->rplan, query);
 
 	return KNOT_NS_PROC_DONE;
 }
 
+static void finalize_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
+{
+	knot_pkt_t *answer = param->answer;
+
+	/* Finalize header */
+	knot_wire_set_rcode(answer->wire, knot_wire_get_rcode(pkt->wire));
+
+	/* Finalize authority */
+	knot_pkt_begin(answer, KNOT_AUTHORITY);
+
+	/* Fill in SOA if negative response */
+	int pkt_class = response_classify(pkt);
+	if (pkt_class & (PKT_NXDOMAIN|PKT_NODATA)) {
+		const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
+		for (unsigned i = 0; i < ns->count; ++i) {
+			const knot_rrset_t *rr = knot_pkt_rr(ns, i);
+			if (rr->type == KNOT_RRTYPE_SOA) {
+				rr_update_answer(rr, 0, param);
+				break;
+			}
+		}
+	}
+}
+
 /*! \brief Error handling, RFC1034 5.3.3, 4d. */
-static int resolve_error(knot_pkt_t *pkt, struct kr_layer_param *param, int errcode)
+static int resolve_error(knot_pkt_t *pkt, struct kr_layer_param *param)
 {
-	DEBUG_MSG("resolution error => %s\n", knot_strerror(errcode));
 	return KNOT_NS_PROC_FAIL;
 }
 
@@ -305,12 +327,10 @@ static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
 	}
 
 #ifndef NDEBUG
-	char name_str[KNOT_DNAME_MAXLEN], zonecut_str[KNOT_DNAME_MAXLEN], ns_str[KNOT_DNAME_MAXLEN], type_str[16];
+	char zonecut_str[KNOT_DNAME_MAXLEN], ns_str[KNOT_DNAME_MAXLEN];
 	knot_dname_to_str(ns_str, query->zone_cut.ns, sizeof(ns_str));
 	knot_dname_to_str(zonecut_str, query->zone_cut.name, sizeof(zonecut_str));
-	knot_dname_to_str(name_str, qname, sizeof(name_str));
-	knot_rrtype_to_string(qtype, type_str, sizeof(type_str));
-	DEBUG_MSG("query '%s %s' zone cut '%s' nameserver '%s'\n", name_str, type_str, zonecut_str, ns_str);
+	DEBUG_MSG("=> querying nameserver '%s' zone cut '%s'\n", ns_str, zonecut_str);
 #endif
 
 	/* Query built, expect answer. */
@@ -332,17 +352,19 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
 
 	/* Check for packet processing errors first. */
 	if (pkt->parsed < pkt->size) {
-		return resolve_error(pkt, param, KNOT_EMALF);
+		DEBUG_MSG("=> malformed response\n");
+		return resolve_error(pkt, param);
 	} else if (!is_paired_to_query(pkt, query)) {
-		DEBUG_MSG("ignoring mismatching response\n");
+		DEBUG_MSG("=> ignoring mismatching response\n");
 		return KNOT_NS_PROC_MORE;
 	} else if (knot_wire_get_tc(pkt->wire)) {
-		DEBUG_MSG("truncated response, failover to TCP\n");
+		DEBUG_MSG("=> truncated response, failover to TCP\n");
 		struct kr_query *cur = kr_rplan_current(param->rplan);
 		if (cur) {
 			/* Fail if already on TCP. */
 			if (cur->flags & QUERY_TCP) {
-				return resolve_error(pkt, param, KNOT_EMALF);
+				DEBUG_MSG("=> TC=1 with TCP, bailing out\n");
+				return resolve_error(pkt, param);
 			}
 			cur->flags |= QUERY_TCP;
 		}
@@ -355,7 +377,8 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
 	case KNOT_RCODE_NXDOMAIN:
 		break; /* OK */
 	default:
-		return resolve_error(pkt, param, KNOT_ERROR);
+		DEBUG_MSG("=> rcode: %d\n", knot_wire_get_rcode(pkt->wire));
+		return resolve_error(pkt, param);
 	}
 
 	/* Resolve authority to see if it's referral or authoritative. */
@@ -363,15 +386,22 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
 	state = process_authority(pkt, param);
 	switch(state) {
 	case KNOT_NS_PROC_MORE: /* Not referral, process answer. */
+		DEBUG_MSG("=> rcode: %d\n", knot_wire_get_rcode(pkt->wire));
 		state = process_answer(pkt, param);
 		break;
 	case KNOT_NS_PROC_DONE: /* Referral, try to find glue. */
+		DEBUG_MSG("=> referral response, follow\n");
 		state = process_additional(pkt, param);
 		break;
 	default:
 		break;
 	}
 
+	/* If resolved, finalize answer. */
+	if (kr_rplan_empty(param->rplan)) {
+		finalize_answer(pkt, param);
+	}
+
 	return state;
 }
 
diff --git a/lib/layer/itercache.c b/lib/layer/itercache.c
index 6258b0efcb5b6a17e52fb97b4e547b62b913ed69..a35a80791cfa7d876a4d695ad17de9afe6da1a90 100644
--- a/lib/layer/itercache.c
+++ b/lib/layer/itercache.c
@@ -23,11 +23,7 @@
 #include "lib/layer/static.h"
 #include "lib/layer/iterate.h"
 
-#ifndef NDEBUG
-#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[cache] " fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_MSG(fmt, ...)
-#endif
+#define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(param->rplan), " cc ",  fmt)
 
 typedef int (*rr_callback_t)(const knot_rrset_t *, unsigned, struct kr_layer_param *);
 
@@ -98,6 +94,7 @@ static int read_cache(knot_layer_t *ctx, knot_pkt_t *pkt)
 	/* Try to find expected record first. */
 	int state = read_cache_rr(txn, &cache_rr, timestamp, callback, param);
 	if (state == KNOT_NS_PROC_DONE) {
+		DEBUG_MSG("=> satisfied from cache\n");
 		kr_rplan_pop(param->rplan, cur);
 		return state;
 	}
@@ -250,6 +247,7 @@ static int write_cache(knot_layer_t *ctx, knot_pkt_t *pkt)
 	/* Cache only positive answers. */
 	/*! \todo Negative answers cache support */
 	if (knot_wire_get_rcode(pkt->wire) != KNOT_RCODE_NOERROR) {
+		DEBUG_MSG("write NCACHE (NOTIMPL)\n");
 		return ctx->state;
 	}
 
@@ -257,10 +255,10 @@ static int write_cache(knot_layer_t *ctx, knot_pkt_t *pkt)
 	int ret = KNOT_EOK;
 	if (knot_wire_get_aa(pkt->wire)) {
 		ret = write_cache_answer(pkt, txn, pool, timestamp);
-	} else {
-		ret = write_cache_authority(pkt, txn, pool, timestamp);
 	}
 
+	ret = write_cache_authority(pkt, txn, pool, timestamp);
+
 	/* Cache full, do what we must. */
 	if (ret == KNOT_ESPACE) {
 		kr_cache_clear(txn);
diff --git a/lib/layer/static.c b/lib/layer/static.c
index e4505fca62091e85cfe0aa9fae1dbe30cbb312e7..d8fa56db81a031143a21454184357254ec883d00 100644
--- a/lib/layer/static.c
+++ b/lib/layer/static.c
@@ -16,6 +16,8 @@
 
 #include "lib/layer/static.h"
 
+#define DEBUG_MSG(fmt...) QRDEBUG(NULL, "hint",  fmt)
+
 static int reset(knot_layer_t *ctx)
 {
 	/* TODO: sync, cleanup after resolution */
@@ -26,9 +28,6 @@ static int begin(knot_layer_t *ctx, void *param)
 {
 	ctx->data = param;
 
-	struct kr_context *resolve = ((struct kr_layer_param *)param)->ctx;
-	assert(resolve);
-
 	/* TODO: read static hosts file */
 
 	return ctx->state;
diff --git a/lib/layer/stats.c b/lib/layer/stats.c
index bb25b22812a3f39cc813294e4fd59b1f912280ba..610f84c15107767a433afebf22457539102ec8e5 100644
--- a/lib/layer/stats.c
+++ b/lib/layer/stats.c
@@ -19,11 +19,7 @@
 #include "lib/layer/stats.h"
 #include "lib/rplan.h"
 
-#ifndef NDEBUG
-#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[stats] " fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_MSG(fmt, ...)
-#endif
+#define DEBUG_MSG(fmt...) QRDEBUG(NULL, "stat",  fmt)
 
 //static void update_stats(struct kr_ns *ns, double rtt)
 //{
diff --git a/lib/resolve.c b/lib/resolve.c
index a81171f10c34b0add705b4effb284530e61d33d3..1ba465a50dea2579e6f549e555d30bd49078171c 100755
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -28,11 +28,7 @@
 #include "lib/layer/static.h"
 #include "lib/layer/stats.h"
 
-#ifndef NDEBUG
-#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[reslv] " fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_MSG(fmt, ...)
-#endif
+#define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(param->rplan), "resl",  fmt)
 
 /* Defines */
 #define ITER_LIMIT 50
@@ -86,8 +82,16 @@ static int iterate(struct knot_requestor *requestor, struct kr_layer_param *para
 	struct kr_rplan *rplan = param->rplan;
 	struct kr_query *cur = kr_rplan_current(rplan);
 
+#ifndef NDEBUG
+	char name_str[KNOT_DNAME_MAXLEN], type_str[16];
+	knot_dname_to_str(name_str, cur->sname, sizeof(name_str));
+	knot_rrtype_to_string(cur->stype, type_str, sizeof(type_str));
+	DEBUG_MSG("query '%s %s'\n", name_str, type_str);
+#endif
+
 	/* Invalid address for current zone cut. */
 	if (sockaddr_len((struct sockaddr *)&cur->zone_cut.addr) < 1) {
+		DEBUG_MSG("=> ns missing A/AAAA, invalidating\n");
 		return invalidate_ns(rplan, cur);
 	}
 
@@ -108,10 +112,12 @@ static int iterate(struct knot_requestor *requestor, struct kr_layer_param *para
 		}
 		/* Network error, retry over TCP. */
 		if (ret != KNOT_LAYER_ERROR && !(cur->flags & QUERY_TCP)) {
+			DEBUG_MSG("=> ns unreachable, retrying over TCP\n");
 			cur->flags |= QUERY_TCP;
 			return iterate(requestor, param);
 		}
 		/* Resolution failed, invalidate current NS and reset to UDP. */
+		DEBUG_MSG("=> resolution failed: '%s', invalidating\n", knot_strerror(ret));
 		ret = invalidate_ns(rplan, cur);
 		cur->flags &= ~QUERY_TCP;
 	}
@@ -135,7 +141,7 @@ static int resolve_iterative(struct kr_layer_param *param, mm_ctx_t *pool)
 	while((ret == KNOT_EOK) && !kr_rplan_empty(param->rplan)) {
 		ret = iterate(&requestor, param);
 		if (++iter_count > ITER_LIMIT) {
-			DEBUG_MSG("iteration limit %d reached => SERVFAIL\n", ITER_LIMIT);
+			DEBUG_MSG("iteration limit %d reached\n", ITER_LIMIT);
 			ret = KNOT_ELIMIT;
 		}
 	}
diff --git a/lib/rplan.c b/lib/rplan.c
index f25d4cb3eba5d72b4a07abec24fdc0ab2c480d66..d0cb9bba02b8f17d77360a2918db72c0953727fb 100644
--- a/lib/rplan.c
+++ b/lib/rplan.c
@@ -22,12 +22,9 @@
 #include "lib/context.h"
 #include "lib/cache.h"
 #include "lib/defines.h"
+#include "lib/layer.h"
 
-#ifndef NDEBUG
-#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[rplan] " fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_MSG(fmt, ...)
-#endif
+#define DEBUG_MSG(qry, fmt...) QRDEBUG(qry, "plan",  fmt)
 
 static struct kr_query *query_create(mm_ctx_t *pool, const knot_dname_t *name)
 {
@@ -108,6 +105,7 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
 	if (rplan == NULL) {
 		return NULL;
 	}
+
 	struct kr_query *qry =  query_create(rplan->pool, name);
 	if (qry == NULL) {
 		return NULL;
@@ -129,7 +127,7 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
 	char name_str[KNOT_DNAME_MAXLEN], type_str[16];
 	knot_dname_to_str(name_str, name, sizeof(name_str));
 	knot_rrtype_to_string(type, type_str, sizeof(type_str));
-	DEBUG_MSG("plan '%s' type '%s'\n", name_str, type_str);
+	DEBUG_MSG(parent, "plan '%s' type '%s'\n", name_str, type_str);
 #endif
 
 	return qry;
diff --git a/lib/zonecut.c b/lib/zonecut.c
index 0b0befa456ab3fc65708ecf638cd1795532b1099..df1b76feec10e70ea0cdc2f5b3e6c17a83cfa75d 100644
--- a/lib/zonecut.c
+++ b/lib/zonecut.c
@@ -24,12 +24,7 @@
 #include "lib/zonecut.h"
 #include "lib/rplan.h"
 #include "lib/defines.h"
-
-#ifndef NDEBUG
-#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[z-cut] " fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_MSG(fmt, ...)
-#endif
+#include "lib/layer.h"
 
 /* \brief Root hint descriptor. */
 struct hint_info {
@@ -84,11 +79,6 @@ int kr_set_zone_cut(struct kr_zonecut *cut, const knot_dname_t *name, const knot
 	/* Invalidate address. */
 	cut->addr.ss_family = AF_UNSPEC;
 
-	char zonecut_str[KNOT_DNAME_MAXLEN], ns_str[KNOT_DNAME_MAXLEN];
-	knot_dname_to_str(ns_str, cut->ns, sizeof(ns_str));
-	knot_dname_to_str(zonecut_str, cut->name, sizeof(zonecut_str));
-	DEBUG_MSG("zone cut set '%s' ns '%s'\n", zonecut_str, ns_str);
-
 	return KNOT_EOK;
 }
 
diff --git a/tests/pydnstest/scenario.py b/tests/pydnstest/scenario.py
index b3b71e68603213be64d651e9125ba2df2ededb06..5d1d89f95ce0d42f739e8d01367a4c7221515e54 100644
--- a/tests/pydnstest/scenario.py
+++ b/tests/pydnstest/scenario.py
@@ -14,8 +14,8 @@ class Entry:
 
     def __init__(self):
         """ Initialize data entry. """
-        self.match_fields = None
-        self.adjust_fields = None
+        self.match_fields = ['opcode', 'qtype', 'qname']
+        self.adjust_fields = ['copy_id']
         self.origin = '.'
         self.message = dns.message.Message()
         self.sections = []
diff --git a/tests/testdata/iter_cname_cache.rpl b/tests/testdata/iter_cname_cache.rpl
index 6397553ccf3889c5b380e3fa12e2a22250aa6c13..135fe39f8444b8a2b3bed680e2c17007fcd43902 100644
--- a/tests/testdata/iter_cname_cache.rpl
+++ b/tests/testdata/iter_cname_cache.rpl
@@ -290,8 +290,8 @@ REPLY QR RD RA NOERROR
 SECTION QUESTION
 ns.bla.nl. IN AAAA
 SECTION ANSWER
-;SECTION AUTHORITY
-;bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5
+SECTION AUTHORITY
+bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5
 ;SECTION ADDITIONAL
 ENTRY_END
 
diff --git a/tests/testdata/iter_cname_qnamecopy.rpl b/tests/testdata/iter_cname_qnamecopy.rpl
index d3484e6b382e7519ab82b22269b8148afa272445..12019816ac16d2e2095b586cd9e3e40c2bf620bb 100644
--- a/tests/testdata/iter_cname_qnamecopy.rpl
+++ b/tests/testdata/iter_cname_qnamecopy.rpl
@@ -149,8 +149,8 @@ SECTION QUESTION
 www.example.com. IN A
 SECTION ANSWER
 www.example.com. IN CNAME	www.next.com.
-;SECTION AUTHORITY
-;next.com. 	IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+SECTION AUTHORITY
+next.com. 	IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
 SECTION ADDITIONAL
 ENTRY_END
 
@@ -170,8 +170,8 @@ SECTION QUESTION
 www.example.com. IN A
 SECTION ANSWER
 www.example.com. IN CNAME	www.next.com.
-;SECTION AUTHORITY
-;next.com. 	IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+SECTION AUTHORITY
+next.com. 	IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
 SECTION ADDITIONAL
 ENTRY_END
 
@@ -190,8 +190,8 @@ REPLY QR RD RA NOERROR
 SECTION QUESTION
 www.next.com. IN A
 SECTION ANSWER
-;SECTION AUTHORITY
-;next.com. 	IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+SECTION AUTHORITY
+next.com. 	IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
 SECTION ADDITIONAL
 ENTRY_END
 
diff --git a/tests/testdata_notimpl/iter_ns_badip.rpl b/tests/testdata/iter_ns_badip.rpl
similarity index 99%
rename from tests/testdata_notimpl/iter_ns_badip.rpl
rename to tests/testdata/iter_ns_badip.rpl
index 28ccbb7b4d8c2677c052bbd82592716a848b8af0..b2152a7743b8c82859354f4ec0f0ae17dfd09f3d 100644
--- a/tests/testdata_notimpl/iter_ns_badip.rpl
+++ b/tests/testdata/iter_ns_badip.rpl
@@ -205,8 +205,6 @@ www.foo.com. 10 IN A	10.20.30.40
 ;foo.com.	3600 IN NS	ns2.example.com.
 ENTRY_END
 
-STEP 15 TRAFFIC
-
 ; Now move the time so good server times out and bad remains.
 STEP 20 TIME_PASSES ELAPSE 20
 
@@ -218,8 +216,6 @@ SECTION QUESTION
 www.foo.com. IN A
 ENTRY_END
 
-STEP 35 TRAFFIC
-
 ; recursion happens here.
 STEP 40 CHECK_ANSWER
 ENTRY_BEGIN
diff --git a/tests/testdata_notimpl/iter_ns_spoof.rpl b/tests/testdata/iter_ns_spoof.rpl
similarity index 100%
rename from tests/testdata_notimpl/iter_ns_spoof.rpl
rename to tests/testdata/iter_ns_spoof.rpl