From 2a26973165dc0a84d27a78412495388a5eb01436 Mon Sep 17 00:00:00 2001
From: Evgeny Voropaev <evorop@gmail.com>
Date: Fri, 20 Mar 2026 17:30:22 +0800
Subject: [PATCH v08 1/3] Implement vect and uniqsortvect containers and
 bitpack algorithms.

The vect container stores arrays of integers and provides a set of
algorithms implementing essential operations on the contained array,
such as initialization, appending, inserting, and clearing.

The uniqsortvect container is based on the vect type but assumes that
its elements are sorted and unique. In addition to the algorithms
provided by vect, uniqsortvect implements binary search and the
specialized insertion routine.

The containers support both external memory provided by a caller and
automatically managed memory using malloc, Postgres's palloc, or similar
allocation functions. A container's strategy regarding memory management
must be set at container initialization, and all subsequent operations
honor this configuration. For example, a caller can place a buffer on
the stack to avoid heap allocation and pass the buffer to a vector
instance, which results in the vector performs no dynamic allocation.

This commit also introduces the bitpack unit, which provides algorithms
for dense bit-level packing and unpacking. The bitpack unit does not
use dynamic memory.

Each unit (vect, bitpack) is implemented as a set of templates that
allow developers to generate specialized solutions for any integer type
(uint8, int8, uint16, int16, and so on). The units bitpack_u16 and
vect_u16 supporting the uint16_t type are also provided by this commit.

Unit tests for the provided implementations are included. Unit tests are
implemented as binary applications written in C language
(ELF executables) that support the TAP protocol and are run using the
Prove utility.

The new Makefile target, check-unit, is integrated into the PostgreSQL
build system and allows running the unit tests using the command 'make
check-unit'.

Author: Evgeny Voropaev <evgeny.voropaev@tantorlabs.com> <evorop@gmail.com>
Reviewed by: Andrey Borodin <x4mmm@yandex-team.ru>
---
 GNUmakefile.in                         |   1 +
 src/Makefile.global.in                 |   2 +-
 src/backend/lib/Makefile               |   5 +
 src/backend/lib/Makefile.dfor          |   5 +
 src/backend/lib/bitpack_templ.c        | 156 +++++++++
 src/backend/lib/bitpack_u16.c          |   8 +
 src/backend/lib/meson.build            |   7 +
 src/backend/lib/vect_templ.c           | 301 ++++++++++++++++++
 src/backend/lib/vect_u16.c             |   8 +
 src/include/c.h                        |   4 +
 src/include/lib/bitpack_staple_templ.h |  57 ++++
 src/include/lib/bitpack_templ.h        |  14 +
 src/include/lib/bitpack_templ_undef.h  |   5 +
 src/include/lib/bitpack_u16.h          |  12 +
 src/include/lib/bitpack_u16_config.h   |   6 +
 src/include/lib/vect_templ.h           |  27 ++
 src/include/lib/vect_templ_staple.h    | 140 ++++++++
 src/include/lib/vect_templ_undef.h     |  25 ++
 src/include/lib/vect_u16.h             |  34 ++
 src/include/lib/vect_u16_config.h      |  10 +
 src/test/Makefile                      |   1 +
 src/test/dfor/.gitignore               |   3 +
 src/test/dfor/Makefile                 |  53 ++++
 src/test/dfor/meson.build              |  62 ++++
 src/test/dfor/test.h                   |  31 ++
 src/test/dfor/test_bitpack_u16.c       | 357 +++++++++++++++++++++
 src/test/dfor/test_uniqsortvect_u16.c  | 263 +++++++++++++++
 src/test/dfor/test_vect_u16.c          | 168 ++++++++++
 src/test/libtap/.gitignore             |  13 +
 src/test/libtap/.travis.yml            |  13 +
 src/test/libtap/COPYING                | 165 ++++++++++
 src/test/libtap/INSTALL                |  41 +++
 src/test/libtap/Makefile               |  73 +++++
 src/test/libtap/Makefile.win           |  37 +++
 src/test/libtap/README.md              | 268 ++++++++++++++++
 src/test/libtap/tap.c                  | 421 +++++++++++++++++++++++++
 src/test/libtap/tap.h                  | 115 +++++++
 src/test/meson.build                   |   1 +
 38 files changed, 2911 insertions(+), 1 deletion(-)
 create mode 100644 src/backend/lib/Makefile.dfor
 create mode 100644 src/backend/lib/bitpack_templ.c
 create mode 100644 src/backend/lib/bitpack_u16.c
 create mode 100644 src/backend/lib/vect_templ.c
 create mode 100644 src/backend/lib/vect_u16.c
 create mode 100644 src/include/lib/bitpack_staple_templ.h
 create mode 100644 src/include/lib/bitpack_templ.h
 create mode 100644 src/include/lib/bitpack_templ_undef.h
 create mode 100644 src/include/lib/bitpack_u16.h
 create mode 100644 src/include/lib/bitpack_u16_config.h
 create mode 100644 src/include/lib/vect_templ.h
 create mode 100644 src/include/lib/vect_templ_staple.h
 create mode 100644 src/include/lib/vect_templ_undef.h
 create mode 100644 src/include/lib/vect_u16.h
 create mode 100644 src/include/lib/vect_u16_config.h
 create mode 100644 src/test/dfor/.gitignore
 create mode 100644 src/test/dfor/Makefile
 create mode 100644 src/test/dfor/meson.build
 create mode 100644 src/test/dfor/test.h
 create mode 100644 src/test/dfor/test_bitpack_u16.c
 create mode 100644 src/test/dfor/test_uniqsortvect_u16.c
 create mode 100644 src/test/dfor/test_vect_u16.c
 create mode 100644 src/test/libtap/.gitignore
 create mode 100644 src/test/libtap/.travis.yml
 create mode 100644 src/test/libtap/COPYING
 create mode 100644 src/test/libtap/INSTALL
 create mode 100644 src/test/libtap/Makefile
 create mode 100644 src/test/libtap/Makefile.win
 create mode 100644 src/test/libtap/README.md
 create mode 100644 src/test/libtap/tap.c
 create mode 100644 src/test/libtap/tap.h

diff --git a/GNUmakefile.in b/GNUmakefile.in
index cf6e759486e..3d9a42d6ad4 100644
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -69,6 +69,7 @@ check check-tests installcheck installcheck-parallel installcheck-tests: submake
 	$(MAKE) -C src/test/regress $@
 
 $(call recurse,check-world,src/test src/pl src/interfaces contrib src/bin src/tools/pg_bsd_indent,check)
+$(call recurse,check-unit,src/test,check-unit)
 $(call recurse,checkprep,  src/test src/pl src/interfaces contrib src/bin)
 
 $(call recurse,installcheck-world,src/test src/pl src/interfaces contrib src/bin,installcheck)
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index a7699b026bb..a37142f8160 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -19,7 +19,7 @@
 #
 # Meta configuration
 
-standard_targets = all install installdirs uninstall clean distclean coverage check checkprep installcheck init-po update-po
+standard_targets = all install installdirs uninstall clean distclean coverage check checkprep installcheck check-unit init-po update-po
 # these targets should recurse even into subdirectories not being built:
 standard_always_targets = clean distclean
 
diff --git a/src/backend/lib/Makefile b/src/backend/lib/Makefile
index b6cefd9cca0..74167bc9e4c 100644
--- a/src/backend/lib/Makefile
+++ b/src/backend/lib/Makefile
@@ -12,6 +12,8 @@ subdir = src/backend/lib
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
+include Makefile.dfor
+
 OBJS = \
 	bipartite_match.o \
 	bloomfilter.o \
@@ -22,5 +24,8 @@ OBJS = \
 	knapsack.o \
 	pairingheap.o \
 	rbtree.o \
+	$(OBJS_DFOR) \
+
+CPPFLAGS := -I$(top_srcdir)/src/backend/lib $(CPPFLAGS)
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/lib/Makefile.dfor b/src/backend/lib/Makefile.dfor
new file mode 100644
index 00000000000..b93c6e78644
--- /dev/null
+++ b/src/backend/lib/Makefile.dfor
@@ -0,0 +1,5 @@
+# Makefile.dfor
+
+OBJS_DFOR := \
+	bitpack_u16.o \
+	vect_u16.o
diff --git a/src/backend/lib/bitpack_templ.c b/src/backend/lib/bitpack_templ.c
new file mode 100644
index 00000000000..5f721ea1ebc
--- /dev/null
+++ b/src/backend/lib/bitpack_templ.c
@@ -0,0 +1,156 @@
+/*
+ * bitpack_templ.c
+ *
+ * The BITPACK unit implements routines pertaining to bit-packing. The bitpack
+ * unit allow higher-level functions to create high-density arrays packed
+ * bit-by-bit. In general, width of each item in a bitpacked array can vary and
+ * have not to be of fixed size, items can have different length.
+ */
+
+#include "lib/bitpack_staple_templ.h"
+
+item_t width_from_val(item_t val);
+item_t width_to_mask(size_t width);
+size_t bitpack_pack(uint8_t *pack, size_t caret, item_t item,
+					size_t szItemWidth);
+item_t bitpack_unpack(const uint8_t *pack, size_t *caret, size_t szItemWidth);
+
+/*
+ * Since width of item_t cannot be more than length of item_t
+ * lg(MAX(item_t))+1, we use the item_t type for returned value
+ */
+item_t
+width_from_val(item_t val)
+{
+	item_t width = 0;
+
+	while (val) {
+		width++;
+		val = val >> 1;
+	}
+
+	return width == 0 ? 1 : width;
+}
+
+item_t
+width_to_mask(size_t width)
+{
+	size_t mask = 0;
+
+	Assert(width != 0);
+	Assert(width <= sizeof(item_t) * 8);
+
+	if (likely(width < sizeof(size_t)))
+		mask = (1 << width) - 1;
+	else
+		while (width--)
+			mask = (mask << 1) | 1;
+
+	return (item_t)mask;
+}
+
+size_t
+bitpack_pack(uint8_t *pack, size_t caret, item_t item, size_t szItemWidth)
+{
+	size_t szItemWidthToGo = szItemWidth;
+	item_t itmMaskToGo = width_to_mask(szItemWidth);
+
+	while (szItemWidthToGo > 0) {
+		size_t cntSavedBits;
+		size_t byte = caret / 8;
+		size_t off = caret % 8;
+		uint8_t ubChunk = (uint8_t)item << off;
+		item_t itmChunkMask = itmMaskToGo << off;
+		/*
+		 * Applying chunk using the mask. Setting bits to one and resetting bits
+		 * to zero is only in scopes defined by the mask. Zeroing of bits
+		 * according to a mask, we can use even a pack not been nulled in
+		 * advance.
+		 */
+		pack[byte] |= (ubChunk & itmChunkMask);
+		pack[byte] &= (ubChunk | ~itmChunkMask);
+		cntSavedBits = (8 - off > szItemWidthToGo) ?
+			szItemWidthToGo :
+			8 - off; // number of saved bits
+		szItemWidthToGo -= cntSavedBits;
+		caret += cntSavedBits;
+		item = item >> cntSavedBits;
+		itmMaskToGo = itmMaskToGo >> cntSavedBits;
+	}
+	return caret;
+}
+
+item_t
+bitpack_unpack(const uint8_t *pack, size_t *caret, size_t widItem)
+{
+	size_t szItemCaret;
+	size_t szItemWidthToGo;
+	uint8_t item[sizeof(item_t)]; /* size of item array */
+
+	size_t szPackByte;
+	size_t szPackOff;
+	size_t szItemByte;
+	size_t szItemOff;
+	uint8_t ubChunk;
+
+	szItemCaret = 0;
+	szItemWidthToGo = widItem;
+	memset(item, 0, sizeof(item_t));
+
+	while (szItemWidthToGo > 0) {
+		size_t szChunkSize;
+		size_t szChunkLowSize, szChunkHighSize;
+
+		szPackByte = *caret / 8;
+		szPackOff = *caret % 8;
+		szItemByte = szItemCaret / 8;
+		szItemOff = szItemCaret % 8;
+
+		ubChunk = pack[szPackByte] >> szPackOff;
+
+		szChunkSize = 8 - szPackOff;
+		if (szItemWidthToGo < szChunkSize) {
+			szChunkSize = szItemWidthToGo;
+			ubChunk = ubChunk & (uint8_t)width_to_mask(szItemWidthToGo);
+		}
+
+		if (szChunkSize > (8 - szItemOff)) /* Free space of item[szItemByte] */
+		{
+			szChunkLowSize = 8 - szItemOff;
+			szChunkHighSize = szChunkSize - szChunkLowSize;
+		} else {
+			szChunkLowSize = szChunkSize;
+			szChunkHighSize = 0;
+		}
+
+		item[szItemByte] |= ubChunk << szItemOff; /* chunk_low */
+
+		if (szChunkHighSize != 0) {
+			Assert((szItemByte + 1) < sizeof(item_t)); /* size of item array */
+			item[szItemByte + 1] |= ubChunk >> szChunkLowSize; /* chunk_high */
+		}
+
+		*caret += szChunkSize;
+		szItemCaret += szChunkSize;
+		szItemWidthToGo -= szChunkSize;
+	}
+
+	/*
+	 * Reordering bytes in accordance with endianness of the system.
+	 *
+	 * Here for a Little-endian system we can avoid reordering, but in such a
+	 * case we need to keep the item array aligned with item_t type, but we do
+	 * not keep.
+	 */
+	{
+		size_t j = 1;
+		item_t val = item[sizeof(item_t) - j];
+		while (++j <= sizeof(item_t)) {
+			val = val << 8;
+			val |= item[sizeof(item_t) - j];
+		}
+		return val;
+	}
+}
+
+#include "lib/bitpack_templ_undef.h"
diff --git a/src/backend/lib/bitpack_u16.c b/src/backend/lib/bitpack_u16.c
new file mode 100644
index 00000000000..ae2ee6d6bb2
--- /dev/null
+++ b/src/backend/lib/bitpack_u16.c
@@ -0,0 +1,8 @@
+/*
+ * File: bitpack_u16.c
+ */
+
+/* clang-format off */
+#include "lib/bitpack_u16_config.h"
+#include "bitpack_templ.c"
+/* clang-format on */
diff --git a/src/backend/lib/meson.build b/src/backend/lib/meson.build
index 8e38fb20f17..0984bd0e3f6 100644
--- a/src/backend/lib/meson.build
+++ b/src/backend/lib/meson.build
@@ -1,5 +1,10 @@
 # Copyright (c) 2022-2026, PostgreSQL Global Development Group
 
+dfor_sources = files(
+  'bitpack_u16.c',
+  'vect_u16.c'
+)
+
 backend_sources += files(
   'bipartite_match.c',
   'bloomfilter.c',
@@ -11,3 +16,5 @@ backend_sources += files(
   'pairingheap.c',
   'rbtree.c',
 )
+
+backend_sources += dfor_sources
diff --git a/src/backend/lib/vect_templ.c b/src/backend/lib/vect_templ.c
new file mode 100644
index 00000000000..52713c39d3b
--- /dev/null
+++ b/src/backend/lib/vect_templ.c
@@ -0,0 +1,301 @@
+/*
+ * File: vect_templ.c
+ */
+
+#include "lib/vect_templ_staple.h"
+
+/*
+ * Vector's functions
+ * Keep this section equal to the same section in vect_templ.h
+ */
+/*
+ * Caller has to control whether vector use outer memory provided by caller or
+ * manage memory allocation automatically, which defines whether vect_insert,
+ * vect_append and other functions of the vector container automatically mange
+ * dynamic memory allocation or not.
+ */
+
+int vect_init(vect_t *v, size_t cap, item_t outer_mem[]);
+int vect_fill(vect_t *v, size_t cnt, const item_t in[]);
+int vect_reserve(vect_t *v, size_t szNewCap);
+int vect_append(vect_t *vect, item_t val);
+void vect_print(const vect_t *a);
+int vect_compare(const vect_t *a, const vect_t *b);
+int vect_insert(vect_t *v, size_t pos, item_t val);
+void vect_clear(vect_t *v);
+
+/*
+ * Unique sorted vector's functions
+ * Keep this section equal to the same section in vect_templ.h
+ */
+usv_ins_res_t usv_insert(uniqsortvect_t *a, item_t val);
+usv_srch_res_t usv_search(const uniqsortvect_t *usv, item_t val);
+
+int
+vect_init(vect_t *v, size_t cap, item_t outer_mem[])
+{
+	if (v == NULL)
+		goto vect_init_error;
+
+	v->cap = cap;
+	v->cnt = 0;
+
+	if (outer_mem != NULL)
+	{
+		v->mem_is_outer = true;
+		v->m = outer_mem;
+	}
+	else
+	{
+		v->mem_is_outer = false;
+		if (cap == 0)
+			v->m = NULL;
+		else
+		{
+			v->m = (item_t *)VECT_MALLOC(cap * sizeof(item_t));
+			if (v->m == NULL)
+				goto vect_init_error;
+		}
+	}
+
+	/* vect_init_ok: */
+	return 0;
+vect_init_error:
+	memset(v, 0, sizeof(vect_t));
+	return -1;
+}
+
+int
+vect_fill(vect_t *v, size_t cnt, const item_t in[])
+{
+	if (v == NULL)
+		return -1;
+
+	if (cnt == 0)
+	{
+		vect_clear(v);
+		return 0;
+	}
+
+	for (size_t j = 0; j < cnt; j++)
+	{
+		if (vect_append(v, in[j]) != 0)
+		{
+			vect_clear(v);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+int
+vect_reserve(vect_t *v, size_t szNewCap)
+{
+	item_t *mNew;
+
+	if (v == NULL)
+		return -1;
+
+	if (v->mem_is_outer)
+		return -1;
+
+	if (szNewCap <= v->cap)
+		return 0;
+
+	mNew = (item_t *) VECT_MALLOC(sizeof(item_t) * szNewCap);
+
+	if (mNew == NULL)
+		return -1;
+
+	if(v->m == NULL && v->cnt != 0)
+		return -1;
+
+	if(v->m != NULL && v->cnt != 0)
+		memcpy(mNew, v->m, v->cnt * sizeof(item_t));
+
+	VECT_FREE(v->m);
+	v->m = mNew;
+	v->cap = szNewCap;
+	return 0;
+}
+
+int
+vect_append(vect_t *vect, item_t val)
+{
+	if (vect == NULL)
+		return -1;
+
+	if (vect->cnt + 1 > vect->cap)
+	{
+		if (vect->mem_is_outer)
+			return -1;
+		else
+			vect_reserve(vect, vect->cap + VECT_MEMALLOCSTEP);
+	}
+
+	vect->m[vect->cnt] = val;
+	vect->cnt++;
+	return 0;
+}
+
+void
+vect_print(const vect_t *a)
+{
+	for (size_t j = 0; j < a->cnt; j++)
+		printf("%" VECT_ITEM_FORMAT_SPECIFIER " ", a->m[j]);
+
+	printf("\n");
+}
+
+int
+vect_compare(const vect_t *a, const vect_t *b)
+{
+	if (a == NULL || b == NULL)
+		return -1;
+
+	if (a->cnt != b->cnt)
+		return -1;
+
+	for (size_t j = 0; j < a->cnt; j++)
+		if (a->m[j] != b->m[j])
+			return -1;
+
+	return 0;
+}
+
+int
+vect_insert(vect_t *v, size_t pos, item_t val)
+{
+	if (v->cap < v->cnt + 1 &&
+		(v->mem_is_outer || vect_reserve(v, v->cap + VECT_MEMALLOCSTEP) != 0))
+		return -1;
+
+	/*
+	 * If need, move right from pos including pos. Because
+	 * neither stdlib's nor POSIX's documentation defines the
+	 * behaviour of memmove in case of count=0, we check it by
+	 * ourselves.
+	 */
+	if (v->cnt - pos > 0)
+		memmove(&v->m[pos + 1], &v->m[pos], (v->cnt - pos) * sizeof(item_t));
+
+	v->m[pos] = val;
+	v->cnt++;
+	return 0;
+}
+
+void
+vect_clear(vect_t *v)
+{
+	if (v == NULL)
+		return;
+
+	if (!v->mem_is_outer)
+		VECT_FREE(v->m);
+
+	memset(v, 0, sizeof(vect_t));
+}
+
+usv_srch_res_t
+usv_search(const uniqsortvect_t *usv, item_t val)
+{
+	size_t i, l, g;
+	usv_srch_res_t res;
+
+	if (usv == NULL || (usv->m == NULL && ((usv->cnt != 0) || usv->cap != 0))) {
+		res.st = USV_SRCH_ERROR;
+		return res;
+	}
+
+	if (usv->cnt == 0) {
+		res.pos = 0;
+		res.st = USV_SRCH_EMPTY;
+		return res;
+	}
+
+	if (val < usv->m[0]) {
+		res.pos = 0;
+		res.st = USV_SRCH_NOT_FOUND_SMALLEST;
+		return res;
+	}
+
+	if (val > usv->m[usv->cnt - 1]) {
+		res.pos = usv->cnt - 1;
+		res.st = USV_SRCH_NOT_FOUND_LARGEST;
+		return res;
+	}
+
+	l = 0;
+	g = usv->cnt - 1;
+
+	while (g - l > 1) {
+		i = l + (g - l) / 2;
+		if (val == usv->m[i]) {
+			res.pos = i;
+			res.st = USV_SRCH_FOUND;
+			return res;
+		} else if (val > usv->m[i]) {
+			l = i;
+		} else // val <= usv->m[i]
+		{
+			g = i;
+		}
+	}
+	/*
+	 * When scopes l and g are neighbours (  g-l = 1)
+	 */
+	if (val == usv->m[g]) {
+		res.pos = g;
+		res.st = USV_SRCH_FOUND;
+		return res;
+	} else if (val == usv->m[l]) {
+		res.pos = l;
+		res.st = USV_SRCH_FOUND;
+		return res;
+	}
+
+	res.pos = g;
+	res.st = USV_SRCH_NOT_FOUND;
+	return res;
+}
+
+/*
+ * INSERT
+ * receives a value, checks whether an unique sorted values vector contains
+ * this value. If not, inserts new value, retaining sorted order.
+ */
+usv_ins_res_t
+usv_insert(uniqsortvect_t *a, item_t val)
+{
+	usv_srch_res_t search;
+	usv_ins_res_t insert;
+
+	Assert(a != NULL);
+
+	search = usv_search(a, val);
+	if (search.st == USV_SRCH_FOUND) {
+		insert.st = USV_INS_EXISTS;
+		insert.pos = search.pos;
+		return insert;
+	} else if (search.st == USV_SRCH_NOT_FOUND_SMALLEST ||
+			   search.st == USV_SRCH_NOT_FOUND) {
+		insert.pos = search.pos;
+	} else if (search.st == USV_SRCH_EMPTY ||
+			   search.st == USV_SRCH_NOT_FOUND_LARGEST) {
+		/* In case when value is more than largest: pos = a->cnt = search.g + 1.
+		 */
+		/* In case of empty vector: pos = a->cnt = 0. */
+		insert.pos = a->cnt;
+	} else /* USV_SRCH_ERROR or unknown result */
+	{
+		insert.st = USV_INS_ERROR;
+		return insert;
+	}
+
+	insert.st = vect_insert(a, insert.pos, val)
+	== 0 ? USV_INS_NEW : USV_INS_ERROR;
+
+	return insert;
+}
+
+#include "lib/vect_templ_undef.h"
diff --git a/src/backend/lib/vect_u16.c b/src/backend/lib/vect_u16.c
new file mode 100644
index 00000000000..0ab8e224c7a
--- /dev/null
+++ b/src/backend/lib/vect_u16.c
@@ -0,0 +1,8 @@
+/*
+ * File: vect_u16.c
+ */
+
+/* clang-format off */
+#include "lib/vect_u16_config.h"
+#include "vect_templ.c"
+/* clang-format on */
diff --git a/src/include/c.h b/src/include/c.h
index 88d13ec9993..1e48a52ae90 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -505,6 +505,10 @@ extern "C++"
 #define CppAsString(identifier) #identifier
 #define CppAsString2(x)			CppAsString(x)
 #define CppConcat(x, y)			x##y
+#define CppConcat2(x, y)		CppConcat(x, y)
+
+#define CppConcatTriple(x, y, z)	x##y##z
+#define CppConcatTriple2(a, b, c)	CppConcatTriple(a, b, c)
 
 /*
  * VA_ARGS_NARGS
diff --git a/src/include/lib/bitpack_staple_templ.h b/src/include/lib/bitpack_staple_templ.h
new file mode 100644
index 00000000000..5c9972e08cb
--- /dev/null
+++ b/src/include/lib/bitpack_staple_templ.h
@@ -0,0 +1,57 @@
+/*
+ * File: bitpack_staple_templ.h.h
+ */
+
+#include "c.h"
+
+/******************************************************************************
+ * NONREUSABLE CODE, allowed to be included only once
+ *
+ * This code should appear only once in a file (or in a chain of files)
+ * including this header with #include. So, we protect it from duplicates by
+ * means of macro
+ *
+ *****************************************************************************/
+#ifndef _BITPACK_STAPLE_TEMPL_H_UNIQUE_CODE_
+#define _BITPACK_STAPLE_TEMPL_H_UNIQUE_CODE_
+
+/* No code here yet */
+
+#endif /* _BITPACK_STAPLE_TEMPL_H_UNIQUE_CODE_ */
+
+/******************************************************************************
+ * End of Code, allowed to be included only once
+ *****************************************************************************/
+
+/******************************************************************************
+ * REUSABLE CODE
+ *
+ * This code can be reused with #include directive in a file if BITPACK_MARKER
+ * redefined. This allow creation of several types of vectors with different
+ * types of members.
+ *
+ *****************************************************************************/
+
+#ifndef BITPACK_ITEM_TYPE
+#error "BITPACK_ITEM_TYPE macro is indefined."
+#endif
+#ifndef BITPACK_MARKER
+#error "BITPACK_MARKER macro is indefined."
+#endif
+
+#define item_t		   BITPACK_ITEM_TYPE
+#define width_from_val CppConcatTriple2(width_, BITPACK_MARKER, _from_val)
+#define width_to_mask  CppConcatTriple2(width_, BITPACK_MARKER, _to_mask)
+#define bitpack_pack   CppConcatTriple2(bitpack_, BITPACK_MARKER, _pack)
+#define bitpack_unpack CppConcatTriple2(bitpack_, BITPACK_MARKER, _unpack)
+
+/******************************************************************************
+ * End of Reusable Code
+ *****************************************************************************/
+
+/*
+ * Don't forget to include this code in your file that uses this header
+ *
+ * #include "lib/bitpack_templ_undef.h"
+ *
+ */
diff --git a/src/include/lib/bitpack_templ.h b/src/include/lib/bitpack_templ.h
new file mode 100644
index 00000000000..b3a6e06c328
--- /dev/null
+++ b/src/include/lib/bitpack_templ.h
@@ -0,0 +1,14 @@
+/*
+ * bitpack_templ.h
+ *
+ */
+
+#include "bitpack_staple_templ.h"
+
+extern item_t width_from_val(item_t val);
+extern item_t width_to_mask(size_t width);
+extern size_t bitpack_pack(uint8_t *pack, size_t caret, item_t item,
+						   size_t szItemWidth);
+extern item_t bitpack_unpack(const uint8_t *pack, size_t *caret, size_t szItemWidth);
+
+#include "bitpack_templ_undef.h"
diff --git a/src/include/lib/bitpack_templ_undef.h b/src/include/lib/bitpack_templ_undef.h
new file mode 100644
index 00000000000..5bf864ffa15
--- /dev/null
+++ b/src/include/lib/bitpack_templ_undef.h
@@ -0,0 +1,5 @@
+#undef item_t
+#undef width_from_val
+#undef width_to_mask
+#undef bitpack_pack
+#undef bitpack_unpack
diff --git a/src/include/lib/bitpack_u16.h b/src/include/lib/bitpack_u16.h
new file mode 100644
index 00000000000..45fb6c4b17b
--- /dev/null
+++ b/src/include/lib/bitpack_u16.h
@@ -0,0 +1,12 @@
+/*
+ * bitpack.h
+ */
+#ifndef _BITPACK_U16_H_
+#define _BITPACK_U16_H_
+
+/* clang-format off */
+#include "bitpack_u16_config.h"
+#include "bitpack_templ.h"
+/* clang-format on */
+
+#endif /* _BITPACK_U16_H_ */
diff --git a/src/include/lib/bitpack_u16_config.h b/src/include/lib/bitpack_u16_config.h
new file mode 100644
index 00000000000..9e6c64d4fee
--- /dev/null
+++ b/src/include/lib/bitpack_u16_config.h
@@ -0,0 +1,6 @@
+/*
+ * File: vect_u16_config.h
+ */
+
+#define BITPACK_ITEM_TYPE uint16_t
+#define BITPACK_MARKER	  u16
diff --git a/src/include/lib/vect_templ.h b/src/include/lib/vect_templ.h
new file mode 100644
index 00000000000..8eec6f064b3
--- /dev/null
+++ b/src/include/lib/vect_templ.h
@@ -0,0 +1,27 @@
+/*
+ * File: vect_templ.h
+ */
+
+#include "vect_templ_staple.h"
+
+/*
+ * Vector's functions
+ * Keep this section equal to the same section in vect_templ.c
+ */
+extern int vect_init(vect_t *v, size_t cap, item_t external_memory[]);
+extern int vect_fill(vect_t *v, size_t cnt, const item_t *in);
+extern int vect_reserve(vect_t *v, size_t szNewCap);
+extern int vect_append(vect_t *vect, item_t val);
+extern void vect_print(const vect_t *a);
+extern int vect_compare(const vect_t *a, const vect_t *b);
+extern int vect_insert(vect_t *v, size_t pos, item_t val);
+extern void vect_clear(vect_t *v);
+
+/*
+ * Unique sorted vector's functions
+ * Keep this section equal to the same section in vect_templ.c
+ */
+extern usv_ins_res_t usv_insert(uniqsortvect_t *a, item_t val);
+extern usv_srch_res_t usv_search(const uniqsortvect_t *usv, item_t val);
+
+#include "vect_templ_undef.h"
\ No newline at end of file
diff --git a/src/include/lib/vect_templ_staple.h b/src/include/lib/vect_templ_staple.h
new file mode 100644
index 00000000000..b192c6d82a3
--- /dev/null
+++ b/src/include/lib/vect_templ_staple.h
@@ -0,0 +1,140 @@
+/*
+ * File: vect_staple_templ.h
+ */
+
+#include "c.h"
+
+/******************************************************************************
+ * NONREUSABLE CODE, allowed to be included only once
+ *
+ * This code should appear only once in a file (or in a chain of files)
+ * including this header with #include. So, we protect it from duplicates by
+ * means of macro
+ *
+ *****************************************************************************/
+#ifndef _VECT_STAPLE_TEMPL_H_UNIQUE_CODE_
+#define _VECT_STAPLE_TEMPL_H_UNIQUE_CODE_
+
+/*
+ * SEARCH in Vector of Unique Sorted members
+ */
+typedef enum
+{
+	USV_SRCH_ERROR = -1,
+	USV_SRCH_FOUND = 0,
+	USV_SRCH_EMPTY,
+	USV_SRCH_NOT_FOUND,
+	USV_SRCH_NOT_FOUND_SMALLEST,
+	USV_SRCH_NOT_FOUND_LARGEST
+} usv_srch_stat_t;
+
+typedef struct
+{
+	usv_srch_stat_t st;
+	size_t pos; /* position (index) of a member that is equal to searched value
+				 * or that is nearest greater member */
+} usv_srch_res_t;
+
+/*
+ * INSERT  in Vector of Unique Sorted members
+ */
+typedef enum
+{
+	USV_INS_ERROR = -1,
+	USV_INS_EXISTS = 0,
+	USV_INS_NEW
+} usv_ins_stat_t;
+
+typedef struct
+{
+	usv_ins_stat_t st;
+	size_t pos; /* position (index) of a member that was inserted or that proved
+				 * to be equal to inserted value
+				 */
+} usv_ins_res_t;
+
+#endif /* _VECT_STAPLE_TEMPL_H_UNIQUE_CODE_ */
+
+/******************************************************************************
+ * End of Code, allowed to be included only once
+ *****************************************************************************/
+
+/******************************************************************************
+ * REUSABLE CODE
+ *
+ * This code can be reused with #include directive in a file if VECT_MARKER
+ * redefined. This allow creation of several types of vectors with different
+ * types of members.
+ *
+ *****************************************************************************/
+
+#ifndef VECT_ITEM_TYPE
+#error "VECT_ITEM_TYPE macro is indefined."
+#endif
+
+#ifndef VECT_ITEM_FORMAT_SPECIFIER
+#error "VECT_ITEM_FORMAT_SPECIFIER macro is indefined."
+#endif
+
+#ifndef VECT_MARKER
+#error "VECT_MARKER macro is indefined."
+#endif
+
+#ifndef VECT_MEMALLOCSTEP
+#error "VECT_MEMALLOCSTEP macro is indefined."
+#endif
+
+#ifndef VECT_MALLOC
+#error "VECT_MALLOC macro is indefined."
+#endif
+
+#ifndef VECT_FREE
+#error "VECT_FREE macro is indefined."
+#endif
+
+/*
+ * The Vector type itself,
+ * The Vector of Unique Sorted Items type
+ * and the Item type
+ *
+ * In fact, vectors's names looks like vect_u16_t where:
+ *     vect_ - common prefix,
+ *     u16 - marker,
+ *     _t - suffix
+ */
+#define vect_t		   CppConcatTriple2(vect_, VECT_MARKER, _t)
+#define uniqsortvect_t CppConcatTriple2(uniqsortvect_, VECT_MARKER, _t)
+#define item_t		   VECT_ITEM_TYPE
+
+typedef struct
+{
+	size_t cnt;		   /* number of items */
+	size_t cap;		   /* capacity */
+	bool mem_is_outer; /* flag about an external memory is used */
+	item_t *m;		   /* items (members) */
+} vect_t;
+
+typedef vect_t uniqsortvect_t;
+
+#define vect_init		   CppConcatTriple2(vect_, VECT_MARKER, _init)
+#define vect_fill		   CppConcatTriple2(vect_, VECT_MARKER, _fill)
+#define vect_reserve	   CppConcatTriple2(vect_, VECT_MARKER, _reserve)
+#define vect_append		   CppConcatTriple2(vect_, VECT_MARKER, _append)
+#define vect_print		   CppConcatTriple2(vect_, VECT_MARKER, _print)
+#define vect_compare	   CppConcatTriple2(vect_, VECT_MARKER, _compare)
+#define vect_insert		   CppConcatTriple2(vect_, VECT_MARKER, _insert)
+#define vect_clear		   CppConcatTriple2(vect_, VECT_MARKER, _clear)
+
+#define usv_insert CppConcatTriple2(usv_, VECT_MARKER, _insert)
+#define usv_search CppConcatTriple2(usv_, VECT_MARKER, _search)
+
+/******************************************************************************
+ * End of Reusable Code
+ *****************************************************************************/
+
+/*
+ * Don't forget to include
+ * 		#include "vect_templ_undef.h"
+ * in your file that uses this header
+ *
+ */
diff --git a/src/include/lib/vect_templ_undef.h b/src/include/lib/vect_templ_undef.h
new file mode 100644
index 00000000000..59b69f18b99
--- /dev/null
+++ b/src/include/lib/vect_templ_undef.h
@@ -0,0 +1,25 @@
+/*
+ * File: vect_undef.h
+ */
+
+#undef vect_t
+#undef uniqsortvect_t
+#undef item_t
+
+#undef VECT_ITEM_TYPE
+#undef VECT_MARKER
+#undef VECT_CppConcatTriple2
+
+#undef vect_init
+#undef vect_fill
+#undef vect_reserve
+#undef vect_append
+#undef vect_print
+#undef vect_compare
+#undef vect_insert
+#undef vect_clear
+
+#undef usv_insert
+#undef usv_search
+
+#undef VECT_PRI_FORMAT_SPECIFIER
\ No newline at end of file
diff --git a/src/include/lib/vect_u16.h b/src/include/lib/vect_u16.h
new file mode 100644
index 00000000000..edf81a417f4
--- /dev/null
+++ b/src/include/lib/vect_u16.h
@@ -0,0 +1,34 @@
+/*
+ * File: vect_u16.h
+ */
+
+#ifndef _VECT_U16_H_
+#define _VECT_U16_H_
+
+/* clang-format off */
+#include "vect_u16_config.h"
+#include "vect_templ.h"
+/* clang-format on */
+
+/*
+ * Types are supposed to be created created by this file
+ *     vect_u16_t
+ *     item_u16_t
+ *     uniqsortvect_u16_t
+ */
+/*
+ * Functions are supposed to be created by this file
+ *     vect_u16_create
+ *     vect_u16_create_filled
+ *     vect_u16_reserve
+ *     vect_u16_append
+ *     vect_u16_destroy
+ *     vect_u16_print
+ *     vect_u16_compare
+ *     vect_u16_insert
+ *     vect_u16_clear
+ *     usv_u16_insert
+ *     usv_u16_search
+ */
+
+#endif //_VECT_U16_H_
diff --git a/src/include/lib/vect_u16_config.h b/src/include/lib/vect_u16_config.h
new file mode 100644
index 00000000000..13a93284e8f
--- /dev/null
+++ b/src/include/lib/vect_u16_config.h
@@ -0,0 +1,10 @@
+/*
+ * File: vect_u16_config.h
+ */
+
+#define VECT_ITEM_TYPE			   uint16_t
+#define VECT_ITEM_FORMAT_SPECIFIER PRIu16
+#define VECT_MARKER				   u16
+#define VECT_MEMALLOCSTEP		   5
+#define VECT_MALLOC				   malloc
+#define VECT_FREE				   free
diff --git a/src/test/Makefile b/src/test/Makefile
index 3eb0a06abb4..aba8db1f483 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -14,6 +14,7 @@ include $(top_builddir)/src/Makefile.global
 
 SUBDIRS = \
 	authentication \
+	dfor \
 	isolation \
 	modules \
 	perl \
diff --git a/src/test/dfor/.gitignore b/src/test/dfor/.gitignore
new file mode 100644
index 00000000000..0d77a51216b
--- /dev/null
+++ b/src/test/dfor/.gitignore
@@ -0,0 +1,3 @@
+test_bitpack_u16
+test_uniqsortvect_u16
+test_vect_u16
diff --git a/src/test/dfor/Makefile b/src/test/dfor/Makefile
new file mode 100644
index 00000000000..3b2c035927f
--- /dev/null
+++ b/src/test/dfor/Makefile
@@ -0,0 +1,53 @@
+#-------------------------------------------------------------------------
+# File: src/test/dfor/Makefile
+#-------------------------------------------------------------------------
+
+subdir = src/test/dfor
+top_builddir = ../../..
+dfor_dir := $(top_builddir)/src/backend/lib
+
+include $(dfor_dir)/Makefile.dfor
+
+# Ensure dependency tracking works
+OBJS += $(OBJS_DFOR)
+
+include $(top_builddir)/src/Makefile.global
+
+DEPDIR ?= .deps # This fixes a problem in some CI jobs
+
+# Object files of vect, bitpack and dfor used by these unit-tests are in the same
+# directory as this Makefile. Tests don't use ones from src/backend/lib and compile
+# different ones for themselves.
+$(info Use OBJS_DFOR=$(OBJS_DFOR) from current directory $(subdir). \
+       They are built on sources from $(dfor_dir))
+
+$(OBJS_DFOR): %.o: $(dfor_dir)/%.c
+	@if test ! -d $(DEPDIR); then mkdir -p $(DEPDIR); fi
+	$(CC) $(CFLAGS) $(CPPFLAGS) -DFRONTEND \
+		-c $< \
+		-MMD -MP -MF $(DEPDIR)/$(notdir $<:.c=.Po) \
+		-o $@
+
+LIBTAP_OBJS = $(top_builddir)/src/test/libtap/tap.o
+
+TESTS= test_vect_u16 \
+       test_uniqsortvect_u16 \
+       test_bitpack_u16
+
+$(TESTS:%=%.o): CPPFLAGS += -I$(top_builddir)/src/test -DFRONTEND
+
+all: $(TESTS)
+
+$(TESTS): %: %.o $(LIBTAP_OBJS) $(OBJS_DFOR)
+	$(CC) $(CFLAGS) $(CPPFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@$(X)
+
+check-unit: $(TESTS)
+	echo "# +++ Unit tests in $(subdir) +++" && \
+	cd $(top_builddir)/$(subdir) && \
+	   $(PROVE) $(PROVE_FLAGS) \
+	    -v $(addprefix ./,$(if $(PROVE_TESTS), $(PROVE_TESTS), $(TESTS)))
+
+check: check-unit
+
+clean distclean:
+	rm -rf $(TESTS) *.o
diff --git a/src/test/dfor/meson.build b/src/test/dfor/meson.build
new file mode 100644
index 00000000000..ce762c52430
--- /dev/null
+++ b/src/test/dfor/meson.build
@@ -0,0 +1,62 @@
+dfor_dir = join_paths(meson.project_source_root(), 'src/backend/lib')
+
+# Object files of vect, bitpack and dfor used by these unit-tests are in the same
+# directory as this meson.build. Tests don't use ones from src/backend/lib and
+# compile different ones for themselves. In Meson/Ninja build system we unite
+# them into a static library.
+
+dfor_sources = files(
+  join_paths(dfor_dir, 'vect_u16.c'),
+  join_paths(dfor_dir, 'bitpack_u16.c'),
+)
+
+dfor_test_lib = static_library(
+  'dfor_test_lib',
+  dfor_sources,
+  include_directories: [
+    include_directories('../../..'), # top_builddir
+    include_directories('../'),      # src/test
+    postgres_inc,                    # src/include here
+  ],
+  c_args: ['-DFRONTEND'],
+)
+
+# We also build libtap as a static library
+
+libtap = static_library(
+  'tap',
+  '../../test/libtap/tap.c',
+  include_directories:
+    include_directories('../../..'), # top_builddir
+)
+
+# Each test is an ELF executable
+
+test_names = [
+  'test_vect_u16',
+  'test_uniqsortvect_u16',
+  'test_bitpack_u16',
+]
+
+foreach t : test_names
+  exe = executable(
+    t,
+    t + '.c',
+    link_with: [
+      dfor_test_lib,
+      libtap,
+      common_static, # Provides pg_printf and other common utilities
+      pgport_static,    # Provides OS-portability functions
+    ],
+	dependencies: [os_deps, libintl],
+    include_directories: [
+      include_directories('../../..'), # top_builddir
+      include_directories('../'),      # src/test
+      postgres_inc,                    # src/include here
+    ],
+    # Backend code often requires these arguments to identify as backend
+    c_args: ['-DFRONTEND'],
+  )
+
+  test(t, exe, suite: 'dfor')
+endforeach
diff --git a/src/test/dfor/test.h b/src/test/dfor/test.h
new file mode 100644
index 00000000000..f6c54aad95f
--- /dev/null
+++ b/src/test/dfor/test.h
@@ -0,0 +1,31 @@
+
+/*
+ * test.h
+ */
+#ifndef _TEST_H_
+#define _TEST_H_
+
+#include <inttypes.h>
+#include <stdio.h>
+
+static inline void
+test_print_u8_array(size_t cnt, uint8_t arr[], const char *name)
+{
+	printf("%s(hex): { ", name);
+	for (size_t j = 0; j < cnt - 1; j++)
+		printf("%02" PRIx8 ", ", arr[j]);
+
+	printf("%02" PRIx8 " }\n", arr[cnt - 1]);
+}
+
+static inline void
+test_print_u16_array(size_t cnt, uint16_t arr[], const char *name)
+{
+	printf("%s(hex): { ", name);
+	for (size_t j = 0; j < cnt - 1; j++)
+		printf("%04" PRIx16 ", ", arr[j]);
+
+	printf("%04" PRIx16 "}\n", arr[cnt - 1]);
+}
+
+#endif /* _TEST_H_ */
\ No newline at end of file
diff --git a/src/test/dfor/test_bitpack_u16.c b/src/test/dfor/test_bitpack_u16.c
new file mode 100644
index 00000000000..da84bb2f22e
--- /dev/null
+++ b/src/test/dfor/test_bitpack_u16.c
@@ -0,0 +1,357 @@
+/*
+ * test_bitpack.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "lib/bitpack_u16.h"
+#include "lib/vect_u16.h"
+#include "libtap/tap.h"
+
+int
+main(void)
+{
+	plan(195);
+	printf("========================================\n");
+	printf("Test MASK AND WIDTH CALCULATION\n");
+	{
+		cmp_ok(1, "==", (uint16_t)width_u16_from_val(0x00),
+			   "Width of 00 is equal to 1 bit.");
+		cmp_ok(2, "==", (uint16_t)width_u16_from_val(0x02),
+			   "Width of 02 is equal to 2 bits.");
+		cmp_ok(2, "==", (uint16_t)width_u16_from_val(0x02),
+			   "Width of 02 is equal to 2 bits.");
+		cmp_ok(2, "==", (uint16_t)width_u16_from_val(0x03),
+			   "Width of 03 is equal to 2 bits.");
+		cmp_ok(3, "==", (uint16_t)width_u16_from_val(0x04),
+			   "Width of 04 is equal to 3 bits.");
+		cmp_ok(3, "==", (uint16_t)width_u16_from_val(0x05),
+			   "Width of 05 is equal to 3 bits.");
+		cmp_ok(4, "==", (uint16_t)width_u16_from_val(0x08),
+			   "Width of 08 is equal to 4 bits.");
+		cmp_ok(4, "==", (uint16_t)width_u16_from_val(0x0A),
+			   "Width of 10 is equal to 4 bits.");
+		cmp_ok(4, "==", (uint16_t)width_u16_from_val(0x0F),
+			   "Width of 15 is equal to 4 bits.");
+		cmp_ok(5, "==", (uint16_t)width_u16_from_val(0x10),
+			   "Width of 16 is equal to 5 bits.");
+		cmp_ok(5, "==", (uint16_t)width_u16_from_val(0x1F),
+			   "Width of 31 is equal to 5 bits.");
+		cmp_ok(6, "==", (uint16_t)width_u16_from_val(0x20),
+			   "Width of 32 is equal to 6 bits.");
+		cmp_ok(7, "==", (uint16_t)width_u16_from_val(0x40),
+			   "Width of 64 is equal to 7 bits.");
+		cmp_ok(8, "==", (uint16_t)width_u16_from_val(0x80),
+			   "Width of 128 is equal to 8 bits.");
+		cmp_ok(13, "==", (uint16_t)width_u16_from_val(0x1000),
+			   "Width of 0x01000 is equal to 13 bits.");
+		cmp_ok(16, "==", (uint16_t)width_u16_from_val(0x8ABC),
+			   "Width of 0x08ABC is equal to 15 bits.");
+
+		cmp_ok(0x1, "==", (uint16_t)width_u16_to_mask(1),
+			   "Mask from width 1 is 00000001(bin).");
+		cmp_ok(0x3, "==", (uint16_t)width_u16_to_mask(2),
+			   "Mask from width 2 is 00000011(bin).");
+		cmp_ok(0x7, "==", (uint16_t)width_u16_to_mask(3),
+			   "Mask from width 3 is 00000111(bin).");
+		cmp_ok(0x3FF, "==", (uint16_t)width_u16_to_mask(10),
+			   "Mask from width 10 is 0x3FF(bin).");
+		cmp_ok(0x7FFF, "==", (uint16_t)width_u16_to_mask(15),
+			   "Mask from width 15 is 0x7FFF(bin).");
+		cmp_ok(0xFFFF, "==", (uint16_t)width_u16_to_mask(16),
+			   "Mask from width 16 is 0xFFFF(bin).");
+	}
+	printf("Test MASK AND WIDTH CALCULATION PASSED\n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test BITPACK PACKING\n");
+	{
+#define SIZEOFPACK 60U
+		uint8_t pack[SIZEOFPACK];
+		size_t caret = 0;
+		memset(pack, 0, SIZEOFPACK);
+		/*
+		 * Since we implemented the nulifying of bits according to a mask (see
+		 * the bitpack function), we can use even a pack not prepared in advance
+		 * and comprising garbage. But we want to check value of each byte of
+		 * the pack in this test and we simplify this task by using a zeroed
+		 * pack.
+		 */
+
+		for (int j = 0; j < 8; j++) {
+			caret = bitpack_u16_pack(pack, caret, 1, 1);
+			caret = bitpack_u16_pack(pack, caret, 0, 1);
+		}
+		cmp_ok(16, "==", caret, "Caret = 16.");
+		cmp_ok(0x55, "==", pack[0], "Saved bit-by-bit: first byte is 0x55.");
+		cmp_ok(0x55, "==", pack[1], "Saved bit-by-bit: second byte is 0x55.");
+
+		for (int j = 0; j < 8; j++) {
+			caret = bitpack_u16_pack(pack, caret, 0x02 /* 10(bin) */, 2);
+		}
+
+		cmp_ok(32, "==", caret, "Caret = 32.");
+		cmp_ok(0xAA, "==", pack[2],
+			   "Saved with two-bit width: first byte is 0xAA.");
+		cmp_ok(0xAA, "==", pack[3],
+			   "Saved with two-bit width: second byte is 0xAA.");
+
+		for (int j = 0; j < 8; j++) {
+			caret = bitpack_u16_pack(pack, caret, 0x05 /* 101(bin) */, 3);
+			caret = bitpack_u16_pack(pack, caret, 0x02 /* 010(bin) */, 3);
+		}
+
+		cmp_ok(80, "==", caret, "Caret = 80.");
+		cmp_ok(0x55, "==", pack[4],
+			   "Saved with three-bit width: first byte is 0x55.");
+		cmp_ok(0x55, "==", pack[5],
+			   "Saved with three-bit width: second byte is 0x55.");
+		cmp_ok(0x55, "==", pack[6],
+			   "Saved with three-bit width: second byte is 0x55.");
+		cmp_ok(0x55, "==", pack[7],
+			   "Saved with three-bit width: first byte is 0x55.");
+		cmp_ok(0x55, "==", pack[8],
+			   "Saved with three-bit width: second byte is 0x55.");
+		cmp_ok(0x55, "==", pack[9],
+			   "Saved with three-bit width: second byte is 0x55.");
+
+		caret = bitpack_u16_pack(pack, caret, 0x0B, 4);
+		caret = bitpack_u16_pack(pack, caret, 0x0C, 4);
+		caret = bitpack_u16_pack(pack, caret, 0x0D, 4);
+		caret = bitpack_u16_pack(pack, caret, 0x0E, 4);
+
+		cmp_ok(96, "==", caret, "Caret = 96.");
+		cmp_ok(0xCB, "==", pack[10],
+			   "Saved with four-bit width: first byte is 0xCB.");
+		cmp_ok(0xED, "==", pack[11],
+			   "Saved with four-bit width: second byte is 0xED.");
+
+		for (int j = 0; j < 8; j++) {
+			caret = bitpack_u16_pack(pack, caret, 0x07 /* 00111b */, 5);
+		}
+
+		cmp_ok(136, "==", caret, "Caret = 136.");
+		cmp_ok(0xE7, "==", pack[12],
+			   "Saved with five-bit width: first byte is 0xE7.");
+		cmp_ok(0x9C, "==", pack[13],
+			   "Saved with five-bit width: second byte is 0x9C.");
+		cmp_ok(0x73, "==", pack[14],
+			   "Saved with five-bit width: third byte is 0x73.");
+		cmp_ok(0xCE, "==", pack[15],
+			   "Saved with five-bit width: fourth byte is 0xCE.");
+		cmp_ok(0x39, "==", pack[16],
+			   "Saved with five-bit width: fifth byte is 0x39.");
+
+		for (int j = 0; j < 4; j++)
+			caret = bitpack_u16_pack(pack, caret, 0x07 /* 000111b */, 6);
+
+		cmp_ok(160, "==", caret, "Caret = 160.");
+		cmp_ok(0xC7, "==", pack[17],
+			   "Saved with six-bit width: first byte is 0xC7.");
+		cmp_ok(0x71, "==", pack[18],
+			   "Saved with six-bit width: second byte is 0x71.");
+		cmp_ok(0x1C, "==", pack[19],
+			   "Saved with six-bit width: third byte is 0x1C.");
+
+		for (int j = 0; j < 8; j++)
+			caret = bitpack_u16_pack(pack, caret, 0x57 /* 1010111b */, 7);
+
+		cmp_ok(216, "==", caret, "Caret = 216.");
+		cmp_ok(0xD7, "==", pack[20],
+			   "Saved with seven-bit width: byte1 is 0xD7.");
+		cmp_ok(0xEB, "==", pack[21],
+			   "Saved with seven-bit width: byte2 is 0xEB.");
+		cmp_ok(0xF5, "==", pack[22],
+			   "Saved with seven-bit width: byte3 is 0xF5.");
+		cmp_ok(0x7A, "==", pack[23],
+			   "Saved with seven-bit width: byte4 is 0x7A.");
+		cmp_ok(0xBD, "==", pack[24],
+			   "Saved with seven-bit width: byte5 is 0xBD.");
+		cmp_ok(0x5E, "==", pack[25],
+			   "Saved with seven-bit width: byte6 is 0x5E.");
+		cmp_ok(0xAF, "==", pack[26],
+			   "Saved with seven-bit width: byte7 is 0xAF.");
+
+		caret = bitpack_u16_pack(pack, caret, 0xBA, 8);
+		caret = bitpack_u16_pack(pack, caret, 0xDC, 8);
+		caret = bitpack_u16_pack(pack, caret, 0xFE, 8);
+
+		cmp_ok(240, "==", caret, "Caret = 240.");
+		cmp_ok(0xBA, "==", pack[27],
+			   "Saved with eight-bit width: byte1 is 0xBA.");
+		cmp_ok(0xDC, "==", pack[28],
+			   "Saved with eight-bit width: byte2 is 0xDC.");
+		cmp_ok(0xFE, "==", pack[29],
+			   "Saved with eight-bit width: byte3 is 0xFE.");
+
+		caret = bitpack_u16_pack(
+			pack, caret, 0x00,
+			4); /* move to 4 bit for fun and again continue with 8-bit width */
+		caret = bitpack_u16_pack(pack, caret, 0x32, 8);
+		caret = bitpack_u16_pack(pack, caret, 0x54, 8);
+		caret = bitpack_u16_pack(pack, caret, 0x76, 8);
+		caret = bitpack_u16_pack(pack, caret, 0x98, 8);
+
+		cmp_ok(276, "==", caret, "Caret = 276.");
+		cmp_ok(0x20, "==", pack[30],
+			   "Saved with eight-bit width but shifted by 4: is 0x20.");
+		cmp_ok(0x43, "==", pack[31],
+			   "Saved with eight-bit width but shifted by 4: is 0x43.");
+		cmp_ok(0x65, "==", pack[32],
+			   "Saved with eight-bit width but shifted by 4: is 0x65.");
+		cmp_ok(0x87, "==", pack[33],
+			   "Saved with eight-bit width but shifted by 4: is 0x87.");
+		cmp_ok(0x09, "==", pack[34],
+			   "Saved with eight-bit width but shifted by 4: is 0x09.");
+
+		caret = bitpack_u16_pack(
+			pack, caret, 0x00,
+			4); /* move to 4 bit for fun and again continue with 8-bit width */
+		cmp_ok(280, "==", caret, "Caret = 280.");
+		cmp_ok(0x09, "==", pack[34],
+			   "Added padding 0x0, width=4. Byte in pack is still 0x09.");
+
+		for (int j = 0; j < 3; j++)
+			caret = bitpack_u16_pack(pack, caret, 0x1671 /* 1011001110001b */,
+									 13);
+
+		cmp_ok(319, "==", caret, "Caret = 319.");
+		cmp_ok(0x71, "==", pack[35], "Saved with thirteen-bit width: is 0x71.");
+		cmp_ok(0x36, "==", pack[36], "Saved with thirteen-bit width: is 0x36.");
+		cmp_ok(0xCE, "==", pack[37], "Saved with thirteen-bit width: is 0xCE.");
+		cmp_ok(0xC6, "==", pack[38], "Saved with thirteen-bit width: is 0xC6.");
+		cmp_ok(0x59, "==", pack[39], "Saved with thirteen-bit width: is 0x59.");
+
+		caret = bitpack_u16_pack(pack, caret, 0x1 /* PADDING */, 1);
+		cmp_ok(320, "==", caret, "Caret = 320.");
+		cmp_ok(0xD9, "==", pack[39],
+			   "After padding with 0x01, w=1: 0x59 -> 0xD9.");
+
+		for (int j = 0; j < 5; j++)
+			caret = bitpack_u16_pack(pack, caret, 0xCDEF, 16);
+
+		cmp_ok(400, "==", caret, "Caret = 400.");
+		for (int i = 40; i < 50;) {
+			cmp_ok(0xEF, "==", pack[i++], "Packed with width=16. 0xEF.");
+			cmp_ok(0xCD, "==", pack[i++], "Packed with width=16. 0xC.");
+		}
+
+		caret = bitpack_u16_pack(pack, caret,
+								 0x0 /* PADDING in order to shift by 1 bit*/,
+								 1);
+		cmp_ok(401, "==", caret, "Caret = 401.");
+
+		for (int j = 0; j < 3; j++)
+			caret = bitpack_u16_pack(pack, caret, 0x5555, 16);
+
+		cmp_ok(449, "==", caret, "Caret = 401.");
+		for (int i = 50; i < 56;)
+			cmp_ok(0xAA, "==", pack[i++],
+				   "16-bit value saved with shift by 1 bit 0x55->0xAA.");
+
+		cmp_ok(0x0, "==", pack[56], "1 higher bit is alone .");
+
+		printf("Test BITPACK PACKING PASSED\n");
+		printf("========================================\n\n");
+
+		printf("========================================\n");
+		printf("Test BITPACK UNPACKING\n");
+
+		caret = 0;
+
+		for (int j = 0; j < 8; j++) {
+			cmp_ok(0x01, "==", bitpack_u16_unpack(pack, &caret, 1));
+			cmp_ok(0x00, "==", bitpack_u16_unpack(pack, &caret, 1));
+		}
+		cmp_ok(caret, "==", 16);
+
+		for (int j = 0; j < 8; j++)
+			cmp_ok(0x02, "==", bitpack_u16_unpack(pack, &caret, 2));
+
+		cmp_ok(32, "==", caret, "Caret = 32.");
+
+		for (int j = 0; j < 8; j++) {
+			cmp_ok(0x05, "==", bitpack_u16_unpack(pack, &caret, 3));
+			cmp_ok(0x02, "==", bitpack_u16_unpack(pack, &caret, 3));
+		}
+		cmp_ok(80, "==", caret, "Caret = 80.");
+
+		cmp_ok(0x0B, "==", bitpack_u16_unpack(pack, &caret, 4));
+		cmp_ok(0x0C, "==", bitpack_u16_unpack(pack, &caret, 4));
+		cmp_ok(0x0D, "==", bitpack_u16_unpack(pack, &caret, 4));
+		cmp_ok(0x0E, "==", bitpack_u16_unpack(pack, &caret, 4));
+
+		cmp_ok(96, "==", caret, "Caret = 96.");
+
+		for (int j = 0; j < 8; j++)
+			cmp_ok(0x07, "==", bitpack_u16_unpack(pack, &caret, 5),
+				   "width=5, val=00111b");
+
+		cmp_ok(136, "==", caret, "Caret = 136.");
+
+		for (int j = 0; j < 4; j++)
+			cmp_ok(0x07, "==", bitpack_u16_unpack(pack, &caret, 6),
+				   "width=6, val=000111b");
+
+		cmp_ok(160, "==", caret, "Caret = 160.");
+
+		for (int j = 0; j < 8; j++)
+			cmp_ok(0x57, "==", bitpack_u16_unpack(pack, &caret, 7),
+				   "width=7, val=1010111b (0x57)");
+
+		cmp_ok(216, "==", caret, "Caret = 216.");
+
+		cmp_ok(0xBA, "==", bitpack_u16_unpack(pack, &caret, 8),
+			   "width=8, val=0xBA");
+		cmp_ok(0xDC, "==", bitpack_u16_unpack(pack, &caret, 8),
+			   "width=8, val=0xDC");
+		cmp_ok(0xFE, "==", bitpack_u16_unpack(pack, &caret, 8),
+			   "width=8, val=0xFE");
+
+		cmp_ok(240, "==", caret, "Caret = 240.");
+
+		cmp_ok(0x0, "==", bitpack_u16_unpack(pack, &caret, 4),
+			   "width=4, val=0x0, for fun");
+
+		cmp_ok(0x32, "==", bitpack_u16_unpack(pack, &caret, 8),
+			   "width=8, val=0x32");
+		cmp_ok(0x54, "==", bitpack_u16_unpack(pack, &caret, 8),
+			   "width=8, val=0x54");
+		cmp_ok(0x76, "==", bitpack_u16_unpack(pack, &caret, 8),
+			   "width=8, val=0x76");
+		cmp_ok(0x98, "==", bitpack_u16_unpack(pack, &caret, 8),
+			   "width=8, val=0x98");
+
+		cmp_ok(0x0, "==", bitpack_u16_unpack(pack, &caret, 4),
+			   "width=4, val=0x0, for fun padding again");
+
+		for (int j = 0; j < 3; j++)
+			cmp_ok(0x1671, "==", bitpack_u16_unpack(pack, &caret, 13),
+				   "width=13, val=0x1671 (1011001110001b)");
+
+		cmp_ok(319, "==", caret, "Caret = 319.");
+
+		cmp_ok(0x1, "==", bitpack_u16_unpack(pack, &caret, 1),
+			   "width=1, val=0x1");
+		cmp_ok(320, "==", caret, "Caret = 320.");
+
+		for (int j = 0; j < 5; j++)
+			cmp_ok(0xCDEF, "==", bitpack_u16_unpack(pack, &caret, 16),
+				   "18-bit value alligned with bytes in pack.");
+
+		cmp_ok(400, "==", caret, "Caret = 400.");
+		cmp_ok(0x0, "==", bitpack_u16_unpack(pack, &caret, 1),
+			   "1-bit width value (padding for shift).");
+		cmp_ok(401, "==", caret, "Caret = 401.");
+
+		for (int j = 0; j < 3; j++)
+			cmp_ok(0x5555, "==", bitpack_u16_unpack(pack, &caret, 16),
+				   "16-bit width value shifted by 1 bit.");
+
+		cmp_ok(449, "==", caret, "Caret = 449.");
+	}
+
+	done_testing();
+}
diff --git a/src/test/dfor/test_uniqsortvect_u16.c b/src/test/dfor/test_uniqsortvect_u16.c
new file mode 100644
index 00000000000..4ddce8b0b3d
--- /dev/null
+++ b/src/test/dfor/test_uniqsortvect_u16.c
@@ -0,0 +1,263 @@
+/*
+ * test_uniqsortvect.c
+ */
+
+#include "lib/vect_u16.h"
+#include "libtap/tap.h"
+
+int test_usv(size_t src_cnt, uint16_t *src_in, size_t expected_cnt,
+			 uint16_t *expected_in);
+
+int
+test_usv(size_t src_cnt, uint16_t *src_in, size_t expected_cnt,
+		 uint16_t *expected_in)
+{
+	int result = -1;
+	vect_u16_t src;
+	vect_u16_t expected;
+	uniqsortvect_u16_t x;
+
+	vect_u16_init(&src, src_cnt, NULL);
+	vect_u16_fill(&src, src_cnt, src_in);
+
+	vect_u16_init(&expected, 0, NULL);
+	vect_u16_fill(&expected, expected_cnt, expected_in);
+
+	vect_u16_init(&x, 0, NULL);
+
+	for (size_t i = 0; i < src_cnt; i++)
+		usv_u16_insert(&x, src.m[i]);
+
+	result = vect_u16_compare(&x, &expected);
+
+	vect_u16_clear(&x);
+	vect_u16_clear(&expected);
+	vect_u16_clear(&src);
+	return result;
+}
+
+int
+main(void)
+{
+	plan(56);
+
+	printf("========================================\n");
+	printf("Test CREATE AND DESTROY SORTED UNIQUE VECTOR (EMPTY)\n");
+	{
+		uniqsortvect_u16_t usv;
+		size_t capacity = 10;
+		vect_u16_init(&usv, capacity, NULL);
+		cmp_ok(usv.cap, "==", capacity,
+			   "Vectors capacity is equal to requested one");
+		cmp_ok(usv.cnt, "==", 0, "No members in vector");
+		ok(usv.m != NULL, "Array for members is reserved");
+
+		vect_u16_clear(&usv);
+	}
+	printf("Test CREATE AND DESTROY SORTED UNIQUE VECTOR (EMPTY) PASSED\n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test SEARCH IN UNIQUE SORT VECT\n");
+	{
+		uniqsortvect_u16_t usv;
+		usv_srch_res_t srch;
+		uint16_t input[4] = { 5, 10, 20, 30 };
+
+		vect_u16_init(&usv, 0, NULL);
+
+		for (size_t i = 0; i < 4; i++)
+			usv_u16_insert(&usv, input[i]);
+
+		srch = usv_u16_search(&usv, 0);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND_SMALLEST,
+			   "Not found, smallest");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 1);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND_SMALLEST,
+			   "Not found, smallest");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 5);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 6);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND, "Not found");
+		cmp_ok(srch.pos, "==", 1, "Pos =1");
+
+		srch = usv_u16_search(&usv, 10);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 1, "Pos =1");
+
+		srch = usv_u16_search(&usv, 15);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND, "Not found");
+		cmp_ok(srch.pos, "==", 2, "Pos =2");
+
+		srch = usv_u16_search(&usv, 20);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 2, "Pos =2");
+
+		srch = usv_u16_search(&usv, 25);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND, "Not found");
+		cmp_ok(srch.pos, "==", 3, "Pos =3");
+
+		srch = usv_u16_search(&usv, 30);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 3, "Pos =2");
+
+		srch = usv_u16_search(&usv, 45);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND_LARGEST, "Not found, largest");
+		cmp_ok(srch.pos, "==", 3, "Pos =3");
+
+		vect_u16_clear(&usv);
+	}
+	{
+		uniqsortvect_u16_t usv;
+		usv_srch_res_t srch;
+		uint16_t input[3] = { 5, 10, 20 };
+		uint16_t buf[3]; /* overindulge in testing the outer memory vector */
+
+		vect_u16_init(&usv, 3, buf);
+
+		for (size_t i = 0; i < 3; i++)
+			usv_u16_insert(&usv, input[i]);
+
+		srch = usv_u16_search(&usv, 0);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND_SMALLEST,
+			   "Not found, smallest");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 5);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 6);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND, "Not found");
+		cmp_ok(srch.pos, "==", 1, "Pos =1");
+
+		srch = usv_u16_search(&usv, 10);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 1, "Pos =1");
+
+		srch = usv_u16_search(&usv, 15);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND, "Not found");
+		cmp_ok(srch.pos, "==", 2, "Pos =2");
+
+		/*
+		 * When scopes l and g are neighbours (g-l=1) but
+		 * val==m[g] instead of val==m[l].
+		 */
+		srch = usv_u16_search(&usv, 20);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 2, "Pos =2");
+
+		srch = usv_u16_search(&usv, 21);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND_LARGEST, "Not found, largest");
+		cmp_ok(srch.pos, "==", 2, "Pos =2");
+
+		vect_u16_clear(&usv);
+	}
+	{ /* single member*/
+
+		uniqsortvect_u16_t usv;
+		usv_srch_res_t srch;
+
+		vect_u16_init(&usv, 3, NULL);
+
+		usv_u16_insert(&usv, 5); /* The only item in list is 5 */
+
+		srch = usv_u16_search(&usv, 0);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND_SMALLEST,
+			   "Not found, smallest");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 5);
+		cmp_ok(srch.st, "==", USV_SRCH_FOUND, "Found");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 6);
+		cmp_ok(srch.st, "==", USV_SRCH_NOT_FOUND_LARGEST, "Not found, largest");
+		cmp_ok(srch.pos, "==", 0, "Pos =2");
+
+		vect_u16_clear(&usv);
+	}
+	{ /* empty vector*/
+
+		uniqsortvect_u16_t usv;
+		usv_srch_res_t srch;
+
+		vect_u16_init(&usv, 1, NULL);
+
+		srch = usv_u16_search(&usv, 0);
+		cmp_ok(srch.st, "==", USV_SRCH_EMPTY, "Vector is empty.");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 4);
+		cmp_ok(srch.st, "==", USV_SRCH_EMPTY, "Vector is empty.");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 5);
+		cmp_ok(srch.st, "==", USV_SRCH_EMPTY, "Vector is empty.");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		srch = usv_u16_search(&usv, 6);
+		cmp_ok(srch.st, "==", USV_SRCH_EMPTY, "Vector is empty.");
+		cmp_ok(srch.pos, "==", 0, "Pos =0");
+
+		vect_u16_clear(&usv);
+	}
+	printf("Test SEARCH IN UNIQUE SORT VECT PASSED.\n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test ERROR ON NO VECTOR FOR SEARCHING\n");
+	{
+		usv_srch_res_t srch;
+		srch = usv_u16_search(NULL, 0);
+		cmp_ok(srch.st, "==", USV_SRCH_ERROR,
+			   "Error: no vector (empty pointer on vectror).");
+	}
+	{
+		uniqsortvect_u16_t usv;
+		usv_srch_res_t srch;
+		vect_u16_init(&usv, 0, NULL);
+
+		srch = usv_u16_search(&usv, 0);
+		cmp_ok(srch.st, "==", USV_SRCH_EMPTY,
+			   "Search in empty vector is not an error.");
+
+		vect_u16_clear(&usv);
+	}
+	printf("Test ERROR ON NO VECTOR FOR SEARCHING PASSED\n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test CREATED VECTORS ARE SORTED AND UNIQUE\n");
+	{
+		cmp_ok(
+			0, "==",
+			test_usv(10, (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, // src
+					 10,
+					 (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }), // expected
+			"Unique sorted vector remains the same.");
+
+		cmp_ok(0, "==",
+			   test_usv(10,
+						(uint16_t[]) { 0, 1, 2, 3, 4, 5, 3, 7, 5, 9 }, // src
+						8, (uint16_t[]) { 0, 1, 2, 3, 4, 5, 7, 9 }), // expected
+			   "Duplicates are removed.");
+
+		cmp_ok(
+			0, "==",
+			test_usv(10, (uint16_t[]) { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, // src
+					 10,
+					 (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }), // expected
+			"Unsorted became sorted.");
+	}
+	printf("Test CREATED VECTORS ARE SORTED AND UNIQUE PASSED\n");
+	printf("========================================\n\n");
+
+	done_testing();
+}
diff --git a/src/test/dfor/test_vect_u16.c b/src/test/dfor/test_vect_u16.c
new file mode 100644
index 00000000000..00efe7dccbe
--- /dev/null
+++ b/src/test/dfor/test_vect_u16.c
@@ -0,0 +1,168 @@
+/*
+ * test_vect_u16.c
+ */
+
+#include "libtap/tap.h"
+#include "lib/vect_u16.h"
+
+int
+main(void)
+{
+	plan(35);
+
+	printf("========================================\n");
+	printf("Test INIT AND CLEAR VECTOR\n");
+	{
+		vect_u16_t v;
+		size_t capacity = 10;
+		cmp_ok(0, "==", vect_u16_init(&v, capacity, NULL),
+			   "Result of vect_init is 0");
+
+		cmp_ok(v.cap, "==", capacity,
+			   "Vectors capacity is equal to requested one");
+		cmp_ok(v.cnt, "==", 0, "No members in vector");
+		ok(v.m != NULL, "Array for members is reserved");
+		cmp_ok(v.mem_is_outer, "==", false, "Vector does not use outer memory");
+
+		vect_u16_clear(&v);
+
+		cmp_ok(v.cap, "==", 0, "Vectors capacity is 0 after cleanup");
+		cmp_ok(v.cnt, "==", 0, "No members in vector after cleanup");
+		ok(v.m == NULL, "Array for members is absent");
+		cmp_ok(v.mem_is_outer, "==", false, "Vector does not use outer memory");
+	}
+	printf("Test INIT AND CLEAR VECTOR PASSED\n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test INIT AND FILL VECTOR\n");
+	{
+		vect_u16_t v;
+		size_t capacity = 10;
+		const uint16_t vals[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+		cmp_ok(0, "==", vect_u16_init(&v, capacity, NULL),
+			   "Result of vect_init is 0");
+		cmp_ok(0, "==", vect_u16_fill(&v, capacity, vals),
+			   "Result of vect_fill is 0");
+
+		cmp_ok(v.cap, "==", capacity,
+			   "Vectors capacity is equal to requested one");
+		ok(v.m != NULL, "Array for members is reserved");
+		cmp_ok(v.cnt, "==", capacity, "Members are in vector.");
+		{
+			int equal = 0;
+			for (size_t i = 0; i < capacity; i++) {
+				if (v.m[i] == i)
+					equal = equal + 1;
+				else
+					break;
+			}
+			cmp_ok(equal, "==", 10, "Members are correct");
+		}
+		vect_u16_clear(&v);
+	}
+	printf("Test INIT AND FILL VECTOR PASSED\n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test INIT AND FILL VECTOR with zero capcaity\n");
+	{
+		vect_u16_t v;
+		size_t capacity = 0;
+
+		cmp_ok(0, "==", vect_u16_init(&v, capacity, NULL),
+			   "Result of vect_init is 0");
+		cmp_ok(0, "==", vect_u16_fill(&v, capacity, NULL),
+			   "Result of vect_fill is 0");
+
+		cmp_ok(v.cap, "==", 0, "Vector's capacity is zero");
+		ok(v.m == NULL,
+		   "Pointer to members is NULL (array for members is not reserved)");
+		ok(v.cnt == 0, "Counter of members is zero.");
+		vect_u16_clear(&v);
+	}
+	{
+		vect_u16_t v;
+		size_t capacity = 10;
+		const uint16_t vals[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+		cmp_ok(0, "==", vect_u16_init(&v, 0, NULL), "Result of vect_init is 0");
+		cmp_ok(0, "==", vect_u16_fill(&v, capacity, vals),
+			   "Result of vect_fill is 0");
+
+		cmp_ok(v.cap, "==", capacity,
+			   "Vector's capacity is not zero after filling");
+		ok(v.m != NULL,
+		   "Pointer to members is not NULL fater filling (array for members has been reserved)");
+		ok(v.cnt == capacity, "Counter of members is not zero after filling.");
+		vect_u16_clear(&v);
+	}
+	printf("Test INIT AND FILL VECTOR with zero capcaity is finished\n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test COMPARE VECTORS\n");
+	{
+		vect_u16_t a, b, c, d;
+
+		uint16_t avals[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		uint16_t bvals[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		uint16_t cvals[] = { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		uint16_t dvals[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+		vect_u16_init(&a, 0, NULL);
+		vect_u16_init(&b, 0, NULL);
+		vect_u16_init(&c, 0, NULL);
+		vect_u16_init(&d, 0, NULL);
+
+		vect_u16_fill(&a, 10, avals);
+		vect_u16_fill(&b, 10, bvals);
+		vect_u16_fill(&c, 10, cvals);
+		vect_u16_fill(&d, 9, dvals);
+
+		cmp_ok(0, "==", vect_u16_compare(&a, &b), "Vectors are equal");
+		cmp_ok(-1, "==", vect_u16_compare(&a, &c),
+			   "Vectors are not equal because of value of members");
+		cmp_ok(-1, "==", vect_u16_compare(&a, &d),
+			   "Vectors are not equal because of number of members");
+	}
+	printf("Test COMPARE VECTORS is finished. \n");
+	printf("========================================\n\n");
+
+	printf("========================================\n");
+	printf("Test VECTOR WITH OUTER MEMORY\n");
+	{
+#define VECT_CAP 100
+		vect_u16_t vect;
+		uint16_t buf[VECT_CAP]; /* uint16_t is the item's type */
+		vect_u16_init(&vect, VECT_CAP, buf);
+		cmp_ok(
+			vect.cap, "==", VECT_CAP,
+			"Initialisation of vector having external memory resulted in proper capacity.");
+		cmp_ok(
+			vect.cnt, "==", 0,
+			"Initialisation of vector having external memory resulted in proper number of items.");
+		ok(((void *)vect.m == (void *)buf),
+		   "Initialisation of vector having external memory set buf to vect->m.");
+		ok(vect.mem_is_outer,
+		   "Initialisation of vector having external memory set mem_is_outer flag.");
+
+		for (size_t i = 0; i < VECT_CAP; i++)
+		{
+			if (vect_u16_append(&vect, i) != 0)
+				fail(
+					"ERROR: New value can't be appended into vector having external memory.");
+		}
+		pass(
+			"All values have been appended into vector having external memory.");
+
+		cmp_ok(vect.cnt, "==", VECT_CAP, "Vector is full.");
+		cmp_ok(vect_u16_append(&vect, VECT_CAP), "==", -1,
+			   "Once vector is full, extra item can't be appended.");
+	}
+	printf("Test VECTOR WITH OUTER MEMORY is finished\n");
+	printf("========================================\n");
+
+	done_testing();
+}
diff --git a/src/test/libtap/.gitignore b/src/test/libtap/.gitignore
new file mode 100644
index 00000000000..2c95d046c7d
--- /dev/null
+++ b/src/test/libtap/.gitignore
@@ -0,0 +1,13 @@
+/t/*
+!/t/*.*
+/t/*.exe
+/t/*.got
+*.a
+*.lo
+*.o
+*.so
+*.pc
+usr/
+*.sw?
+/.deps
+/.dirstamp
diff --git a/src/test/libtap/.travis.yml b/src/test/libtap/.travis.yml
new file mode 100644
index 00000000000..6f9809e1b99
--- /dev/null
+++ b/src/test/libtap/.travis.yml
@@ -0,0 +1,13 @@
+language: c
+
+compiler:
+  - gcc
+  - clang
+
+before_install: sudo apt-get install -y libtest-differences-perl
+
+install: make CC=$CC install
+
+script: make CC=$CC test
+
+after_script: make uninstall
diff --git a/src/test/libtap/COPYING b/src/test/libtap/COPYING
new file mode 100644
index 00000000000..65c5ca88a67
--- /dev/null
+++ b/src/test/libtap/COPYING
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/test/libtap/INSTALL b/src/test/libtap/INSTALL
new file mode 100644
index 00000000000..5b2c76df3d7
--- /dev/null
+++ b/src/test/libtap/INSTALL
@@ -0,0 +1,41 @@
+To install libtap on a Unix-like system:
+
+    $ make
+    $ make check
+    $ make install
+
+To compile with gcc -ansi, run:
+
+    $ ANSI=1 make
+
+To install to a different directory than /usr/local, supply the
+PREFIX variable to make:
+
+    $ PREFIX=/usr make install
+
+On Windows, the library can be created by first setting up the
+correct development environment variables. Usually this is done by
+running vcvars32.bat included in the Visual Studio distribution.
+You should also install gnu make which can be found at
+http://gnuwin32.sourceforge.net/packages/make.htm. Once this is
+done, you should be able to run the following:
+
+    > make -f Makefile.win
+
+If you want to use it directly in another project, you can copy tap.c
+and tap.h there and it shouldn't have a problem compiling.
+
+    $ ls
+    tap.c tap.h test.c
+    $ cat test.c
+    #include "tap.h"
+    int main () {
+        plan(1);
+        ok(50 + 5, "foo %s", "bar");
+        done_testing();
+    }
+    $ gcc test.c tap.c
+    $ a.out
+    1..1
+    ok 1 - foo bar
+
diff --git a/src/test/libtap/Makefile b/src/test/libtap/Makefile
new file mode 100644
index 00000000000..f020c2839a8
--- /dev/null
+++ b/src/test/libtap/Makefile
@@ -0,0 +1,73 @@
+CC ?= gcc
+CFLAGS += -Wall -I. -fPIC
+PREFIX ?= $(DESTDIR)/usr/local
+TESTS = $(patsubst %.c, %, $(wildcard t/*.c))
+
+ifdef ANSI
+	# -D_BSD_SOURCE for MAP_ANONYMOUS
+	CFLAGS += -ansi -D_BSD_SOURCE
+	LDLIBS += -lbsd-compat
+endif
+
+%:
+	$(CC) $(LDFLAGS) $(TARGET_ARCH) $(filter %.o %.a %.so, $^) $(LDLIBS) -o $@
+
+%.o:
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $(filter %.c, $^) $(LDLIBS) -o $@
+
+%.a:
+	$(AR) rcs $@ $(filter %.o, $^)
+
+%.so:
+	$(CC) -shared $(LDFLAGS) $(TARGET_ARCH) $(filter %.o, $^) $(LDLIBS) -o $@
+
+all: libtap.a libtap.so tap.pc tests
+
+tap.pc:
+	@echo generating tap.pc
+	@echo 'prefix='$(PREFIX) > tap.pc
+	@echo 'exec_prefix=$${prefix}' >> tap.pc
+	@echo 'libdir=$${prefix}/lib' >> tap.pc
+	@echo 'includedir=$${prefix}/include' >> tap.pc
+	@echo '' >> tap.pc
+	@echo 'Name: libtap' >> tap.pc
+	@echo 'Description: Write tests in C' >> tap.pc
+	@echo 'Version: 0.1.0' >> tap.pc
+	@echo 'URL: https://github.com/zorgnax/libtap' >> tap.pc
+	@echo 'Libs: -L$${libdir} -ltap' >> tap.pc
+	@echo 'Cflags: -I$${includedir}' >> tap.pc
+
+libtap.a: tap.o
+
+libtap.so: tap.o
+
+tap.o: tap.c tap.h
+
+tests: $(TESTS)
+
+$(TESTS): %: %.o libtap.a
+
+$(patsubst %, %.o, $(TESTS)): %.o: %.c tap.h
+	$(CC) $(CFLAGS) -O0 $(CPPFLAGS) $(TARGET_ARCH) -c $(filter %.c, $^) $(LDLIBS) -o $@
+
+clean:
+	rm -rf *.o t/*.o tap.pc libtap.a libtap.so $(TESTS)
+
+install: libtap.a tap.h libtap.so tap.pc
+	mkdir -p $(PREFIX)/lib $(PREFIX)/include $(PREFIX)/lib/pkgconfig
+	install -c libtap.a $(PREFIX)/lib
+	install -c libtap.so $(PREFIX)/lib
+	install -c tap.pc $(PREFIX)/lib/pkgconfig
+	install -c tap.h $(PREFIX)/include
+
+uninstall:
+	rm $(PREFIX)/lib/libtap.a $(PREFIX)/lib/libtap.so $(PREFIX)/include/tap.h
+
+dist:
+	rm libtap.zip
+	zip -r libtap *
+
+check test: all
+	./t/test
+
+.PHONY: all clean install uninstall dist check test tests
diff --git a/src/test/libtap/Makefile.win b/src/test/libtap/Makefile.win
new file mode 100644
index 00000000000..694d679a1b1
--- /dev/null
+++ b/src/test/libtap/Makefile.win
@@ -0,0 +1,37 @@
+CFLAGS = /Zi /Wall /wd4255 /wd4996 /wd4127 /wd4820 /wd4100 /wd4619 \
+		 /wd4514 /wd4668 /I.
+CC = cl /nologo
+TESTS = $(patsubst %.c, %.exe, $(wildcard t/*.c))
+
+%.exe:
+	$(CC) $(LDFLAGS) $(filter %.obj %.lib %.dll, $^) $(LDLIBS) /Fe $@
+
+%.o:
+	$(CC) $(CFLAGS) $(CPPFLAGS) /c $(filter %.c, $^) $(LDLIBS) /Fo $@
+
+%.lib:
+	lib /nologo /out:$@ $(filter %.obj, $^)
+
+%.dll:
+	lib /nologo /out:$@ $(filter %.obj, $^)
+
+all: tap.lib tests
+
+tap.lib: tap.obj
+
+tap.obj: tap.c tap.h
+
+tests: $(TESTS)
+
+$(TESTS): %.exe: %.obj tap.lib
+
+$(patsubst %.exe, %.obj, $(TESTS)): %.obj: %.c tap.h
+
+clean:
+	rm -rf *.obj t/*.obj tap.lib $(TESTS)
+
+check test: all
+	prove
+
+.PHONY: all clean check test tests
+
diff --git a/src/test/libtap/README.md b/src/test/libtap/README.md
new file mode 100644
index 00000000000..5332d526c08
--- /dev/null
+++ b/src/test/libtap/README.md
@@ -0,0 +1,268 @@
+NAME
+====
+
+libtap - Write tests in C
+
+SYNOPSIS
+========
+
+    #include <tap.h>
+
+    int main () {
+        plan(5);
+        int bronze = 1, silver = 2, gold = 3;
+        ok(bronze < silver, "bronze is less than silver");
+        ok(bronze > silver, "not quite");
+        is("gold", "gold", "gold is gold");
+        cmp_ok(silver, "<", gold, "%d <= %d", silver, gold);
+        like("platinum", ".*inum", "platinum matches .*inum");
+        done_testing();
+    }
+
+results in:
+
+    1..5
+    ok 1 - bronze is less than silver
+    not ok 2 - not quite
+    #   Failed test 'not quite'
+    #   at t/synopsis.c line 7.
+    ok 3 - gold is gold
+    ok 4 - 2 <= 3
+    ok 5 - platinum matches .*inum
+    # Looks like you failed 1 test of 5 run.
+
+DESCRIPTION
+===========
+
+tap is an easy to read and easy to write way of creating tests for
+your software. This library creates functions that can be used to
+generate it for your C programs. It is implemented using macros
+that include file and line info automatically, and makes it so that
+the format message of each test is optional. It is mostly based on
+the Test::More Perl module.
+
+INSTALL
+=======
+
+On **Unix** systems:
+
+    $ make
+    $ make install
+
+For more detailed installation instructions (eg, for **Windows**), see `INSTALL`.
+
+FUNCTIONS
+=========
+
+-   plan(tests)
+-   plan(NO_PLAN)
+-   plan(SKIP_ALL);
+-   plan(SKIP_ALL, fmt, ...)
+
+    Use this to start a series of tests. When you know how many tests there
+    will be, you can put a number as a number of tests you expect to run. If
+    you do not know how many tests there will be, you can use plan(NO_PLAN)
+    or not call this function. When you pass it a number of tests to run, a
+    message similar to the following will appear in the output:
+
+        1..5
+
+    If you pass it SKIP_ALL, the whole test will be skipped.
+
+-   ok(test)
+-   ok(test, fmt, ...)
+
+    Specify a test. the test can be any statement returning a true or false
+    value. You may optionally pass a format string describing the test.
+
+        ok(r = reader_new("Of Mice and Men"), "create a new reader");
+        ok(reader_go_to_page(r, 55), "can turn the page");
+        ok(r->page == 55, "page turned to the right one");
+
+    Should print out:
+
+        ok 1 - create a new reader
+        ok 2 - can turn the page
+        ok 3 - page turned to the right one
+
+    On failure, a diagnostic message will be printed out.
+
+        not ok 3 - page turned to the right one
+        #   Failed test 'page turned to the right one'
+        #   at reader.c line 13.
+
+-   is(got, expected)
+-   is(got, expected, fmt, ...)
+-   isnt(got, unexpected)
+-   isnt(got, unexpected, fmt, ...)
+
+    Tests that the string you got is what you expected. with isnt, it is the
+    reverse.
+
+        is("this", "that", "this is that");
+
+    prints:
+
+        not ok 1 - this is that
+        #   Failed test 'this is that'
+        #   at is.c line 6.
+        #          got: 'this'
+        #     expected: 'that'
+
+-   cmp_ok(a, op, b)
+-   cmp_ok(a, op, b, fmt, ...)
+
+    Compares two ints with any binary operator that doesn't require an lvalue.
+    This is nice to use since it provides a better error message than an
+    equivalent ok.
+
+        cmp_ok(420, ">", 666);
+
+    prints:
+
+        not ok 1
+        #   Failed test at cmpok.c line 5.
+        #     420
+        #         >
+        #     666
+
+-   cmp_mem(got, expected, n)
+-   cmp_mem(got, expected, n, fmt, ...)
+
+    Tests that the first n bytes of the memory you got is what you expected.
+    NULL pointers for got and expected are handled (if either is NULL,
+    the test fails), but you need to ensure n is not too large.
+
+        char *a = "foo";
+        char *b = "bar";
+        cmp_mem(a, b, 3)
+
+    prints
+
+        not ok 1
+        #   Failed test at t/cmp_mem.c line 9.
+        #     Difference starts at offset 0
+        #          got: 0x66
+        #     expected: 0x62
+
+-   like(got, expected)
+-   like(got, expected, fmt, ...)
+-   unlike(got, unexpected)
+-   unlike(got, unexpected, fmt, ...)
+
+    Tests that the string you got matches the expected extended POSIX regex.
+    unlike is the reverse. These macros are the equivalent of a skip on
+    Windows.
+
+        like("stranger", "^s.(r).*\\1$", "matches the regex");
+
+    prints:
+
+        ok 1 - matches the regex
+
+-   pass()
+-   pass(fmt, ...)
+-   fail()
+-   fail(fmt, ...)
+
+    Speciy that a test succeeded or failed. Use these when the statement is
+    longer than you can fit into the argument given to an ok() test.
+
+-   dies_ok(code)
+-   dies_ok(code, fmt, ...)
+-   lives_ok(code)
+-   lives_ok(code, fmt, ...)
+
+    Tests whether the given code causes your program to exit. The code gets
+    passed to a macro that will test it in a forked process. If the code
+    succeeds it will be executed in the parent process. You can test things
+    like passing a function a null pointer and make sure it doesnt
+    dereference it and crash.
+
+        dies_ok({abort();}, "abort does close your program");
+        dies_ok({int x = 0/0;}, "divide by zero crash");
+        lives_ok({pow(3.0, 5.0);}, "nothing wrong with taking 3**5");
+
+    On Windows, these macros are the equivalent of a skip.
+
+-   done_testing()
+
+    Summarizes the tests that occurred and exits the main function. If
+    there was no plan, it will print out the number of tests as.
+
+        1..5
+
+    It will also print a diagnostic message about how many
+    failures there were.
+
+        # Looks like you failed 2 tests of 3 run.
+
+    If all planned tests were successful, it will return 0. If any
+    test fails, it will return 1. If they all passed, but there
+    were missing tests, it will return 2.
+
+-   diag(fmt, ...)
+
+    print out a message to the tap output on stdout. Each line is
+    preceeded by a "# " so that you know its a diagnostic message.
+
+        diag("This is\na diag\nto describe\nsomething.");
+
+    prints:
+
+        # This is
+        # a diag
+        # to describe
+        # something
+
+    ok() and this function return an int so you can use it like:
+
+        ok(0) || diag("doh!");
+
+-   skip(test, n)
+-   skip(test, n, fmt, ...)
+-   end_skip
+
+    Skip a series of n tests if test is true. You may give a reason why you are
+    skipping them or not. The (possibly) skipped tests must occur between the
+    skip and end_skip macros.
+
+        skip(TRUE, 2);
+        ok(1);
+        ok(0);
+        end_skip;
+
+    prints:
+
+        ok 1 # skip
+        ok 2 # skip
+
+-   todo()
+-   todo(fmt, ...)
+-   end_todo
+
+    Specifies a series of tests that you expect to fail because they are not
+    yet implemented.
+
+        todo()
+        ok(0);
+        end_todo;
+
+    prints:
+
+        not ok 1 # TODO
+        #   Failed (TODO) test at todo.c line 7
+
+-   BAIL_OUT()
+-   BAIL_OUT(fmt, ...)
+
+    Immediately stops all testing.
+
+        BAIL_OUT("Can't go no further");
+
+    prints
+
+        Bail out!  Can't go no further
+
+    and exits with 255.
+
diff --git a/src/test/libtap/tap.c b/src/test/libtap/tap.c
new file mode 100644
index 00000000000..506e4000156
--- /dev/null
+++ b/src/test/libtap/tap.c
@@ -0,0 +1,421 @@
+/*
+libtap - Write tests in C
+Copyright 2012 Jake Gelbman <gelbman@gmail.com>
+This file is licensed under the LGPL
+*/
+
+#define _DEFAULT_SOURCE 1
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tap.h"
+
+#ifndef _WIN32
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <regex.h>
+
+#ifndef MAP_ANONYMOUS
+#ifdef MAP_ANON
+#define MAP_ANONYMOUS MAP_ANON
+#else
+#error "System does not support mapping anonymous pages"
+#endif
+#endif
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PRINTF_ATTR(fmtarg, firstvararg) __attribute__((format(printf, fmtarg, firstvararg)))
+#else
+#define PRINTF_ATTR(fmtarg, firstvararg)
+#endif
+
+static int expected_tests = NO_PLAN;
+static int failed_tests;
+static int current_test;
+static char *todo_mesg;
+
+static char *vstrdupf(const char *fmt, va_list args) PRINTF_ATTR(1,0);
+
+void tap_plan(int tests, const char *fmt, ...) PRINTF_ATTR(2, 3);
+
+int vok_at_loc(const char *file, int line, int test, const char *fmt,
+			   va_list args) PRINTF_ATTR(4,0);
+
+int ok_at_loc(const char *file, int line, int test, const char *fmt, ...)
+	PRINTF_ATTR(4, 5);
+
+int is_at_loc(const char *file, int line, const char *got, const char *expected,
+			  const char *fmt, ...) PRINTF_ATTR(5, 6);
+
+int isnt_at_loc(const char *file, int line, const char *got,
+				const char *expected, const char *fmt, ...)
+	PRINTF_ATTR(5, 6);
+
+int cmp_ok_at_loc(const char *file, int line, int a, const char *op, int b,
+				  const char *fmt, ...)
+	PRINTF_ATTR(6, 7);
+
+int cmp_mem_at_loc(const char *file, int line, const void *got,
+				   const void *expected, size_t n, const char *fmt, ...)
+	PRINTF_ATTR(6, 7);
+
+int diag(const char *fmt, ...) PRINTF_ATTR(1, 2);
+
+int bail_out(int ignore, const char *fmt, ...)
+	PRINTF_ATTR(2, 3);
+
+void tap_skip(int n, const char *fmt, ...)
+	PRINTF_ATTR(2, 3);
+
+void tap_todo(int ignore, const char *fmt, ...)
+	PRINTF_ATTR(2, 3);
+
+int like_at_loc(int for_match, const char *file, int line, const char *got,
+				const char *expected, const char *fmt, ...)
+	PRINTF_ATTR(6, 7);
+
+static char *
+vstrdupf(const char *fmt, va_list args)
+{
+	char *str;
+	int size;
+	va_list args2;
+	va_copy(args2, args);
+	if (!fmt)
+		fmt = "";
+	size = vsnprintf(NULL, 0, fmt, args2) + 2;
+	str = malloc(size);
+	if (!str) {
+		perror("malloc error");
+		exit(1);
+	}
+	vsprintf(str, fmt, args);
+	va_end(args2);
+	return str;
+}
+
+void
+tap_plan(int tests, const char *fmt, ...)
+{
+	expected_tests = tests;
+	if (tests == SKIP_ALL) {
+		char *why;
+		va_list args;
+		va_start(args, fmt);
+		why = vstrdupf(fmt, args);
+		va_end(args);
+		printf("1..0 ");
+		diag("SKIP %s\n", why);
+		exit(0);
+	}
+	if (tests != NO_PLAN) {
+		printf("1..%d\n", tests);
+	}
+}
+
+int
+vok_at_loc(const char *file, int line, int test, const char *fmt, va_list args)
+{
+	char *name = vstrdupf(fmt, args);
+	if (!test) {
+		printf("not ");
+	}
+	printf("ok %d", ++current_test);
+	if (*name)
+		printf(" - %s", name);
+	if (todo_mesg) {
+		printf(" # TODO");
+		if (*todo_mesg)
+			printf(" %s", todo_mesg);
+	}
+	printf("\n");
+	if (!test) {
+		printf("#   Failed ");
+		if (todo_mesg)
+			printf("(TODO) ");
+		printf("test ");
+		if (*name)
+			printf("'%s'\n#   ", name);
+		printf("at %s line %d.\n", file, line);
+		if (!todo_mesg)
+			failed_tests++;
+	}
+	free(name);
+	return test;
+}
+
+int
+ok_at_loc(const char *file, int line, int test, const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vok_at_loc(file, line, test, fmt, args);
+	va_end(args);
+	return test;
+}
+
+static int
+mystrcmp(const char *a, const char *b)
+{
+	return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b);
+}
+
+#define eq(a, b) (!mystrcmp(a, b))
+#define ne(a, b) (mystrcmp(a, b))
+
+int
+is_at_loc(const char *file, int line, const char *got, const char *expected,
+		  const char *fmt, ...)
+{
+	int test = eq(got, expected);
+	va_list args;
+	va_start(args, fmt);
+	vok_at_loc(file, line, test, fmt, args);
+	va_end(args);
+	if (!test) {
+		diag("         got: '%s'", got);
+		diag("    expected: '%s'", expected);
+	}
+	return test;
+}
+
+int
+isnt_at_loc(const char *file, int line, const char *got, const char *expected,
+			const char *fmt, ...)
+{
+	int test = ne(got, expected);
+	va_list args;
+	va_start(args, fmt);
+	vok_at_loc(file, line, test, fmt, args);
+	va_end(args);
+	if (!test) {
+		diag("         got: '%s'", got);
+		diag("    expected: anything else");
+	}
+	return test;
+}
+
+int
+cmp_ok_at_loc(const char *file, int line, int a, const char *op, int b,
+			  const char *fmt, ...)
+{
+	int test = eq(op, "||") ? a || b :
+		eq(op, "&&")		? a && b :
+		eq(op, "|")			? a | b :
+		eq(op, "^")			? a ^ b :
+		eq(op, "&")			? a & b :
+		eq(op, "==")		? a == b :
+		eq(op, "!=")		? a != b :
+		eq(op, "<")			? a < b :
+		eq(op, ">")			? a > b :
+		eq(op, "<=")		? a <= b :
+		eq(op, ">=")		? a >= b :
+		eq(op, "<<")		? a << b :
+		eq(op, ">>")		? a >> b :
+		eq(op, "+")			? a + b :
+		eq(op, "-")			? a - b :
+		eq(op, "*")			? a * b :
+		eq(op, "/")			? a / b :
+		eq(op, "%")			? a % b :
+							  diag("unrecognized operator '%s'", op);
+	va_list args;
+	va_start(args, fmt);
+	vok_at_loc(file, line, test, fmt, args);
+	va_end(args);
+	if (!test) {
+		diag("    %d", a);
+		diag("        %s", op);
+		diag("    %d", b);
+	}
+	return test;
+}
+
+static int
+find_mem_diff(const char *a, const char *b, size_t n, size_t *offset)
+{
+	size_t i;
+	if (a == b)
+		return 0;
+	if (!a || !b)
+		return 2;
+	for (i = 0; i < n; i++) {
+		if (a[i] != b[i]) {
+			*offset = i;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+int
+cmp_mem_at_loc(const char *file, int line, const void *got,
+			   const void *expected, size_t n, const char *fmt, ...)
+{
+	size_t offset;
+	int diff = find_mem_diff(got, expected, n, &offset);
+	va_list args;
+	va_start(args, fmt);
+	vok_at_loc(file, line, !diff, fmt, args);
+	va_end(args);
+	if (diff == 1) {
+		diag("    Difference starts at offset %lu", offset);
+		diag("         got: 0x%02x", ((const unsigned char *)got)[offset]);
+		diag("    expected: 0x%02x", ((const unsigned char *)expected)[offset]);
+	} else if (diff == 2) {
+		diag("         got: %s", got ? "not NULL" : "NULL");
+		diag("    expected: %s", expected ? "not NULL" : "NULL");
+	}
+	return !diff;
+}
+
+int
+diag(const char *fmt, ...)
+{
+	va_list args;
+	char *mesg, *line;
+	int i;
+	va_start(args, fmt);
+	if (!fmt) {
+		va_end(args);
+		return 0;
+	}
+	mesg = vstrdupf(fmt, args);
+	line = mesg;
+	for (i = 0; *line; i++) {
+		char c = mesg[i];
+		if (!c || c == '\n') {
+			mesg[i] = '\0';
+			printf("# %s\n", line);
+			if (!c)
+				break;
+			mesg[i] = c;
+			line = mesg + i + 1;
+		}
+	}
+	free(mesg);
+	va_end(args);
+	return 0;
+}
+
+int
+exit_status(void)
+{
+	int retval = 0;
+	if (expected_tests == NO_PLAN) {
+		printf("1..%d\n", current_test);
+	} else if (current_test != expected_tests) {
+		diag("Looks like you planned %d test%s but ran %d.", expected_tests,
+			 expected_tests > 1 ? "s" : "", current_test);
+		retval = 2;
+	}
+	if (failed_tests) {
+		diag("Looks like you failed %d test%s of %d run.", failed_tests,
+			 failed_tests > 1 ? "s" : "", current_test);
+		retval = 1;
+	}
+	return retval;
+}
+
+int
+bail_out(int ignore, const char *fmt, ...)
+{
+	va_list args;
+	(void)ignore;
+	va_start(args, fmt);
+	printf("Bail out!  ");
+	vprintf(fmt, args);
+	printf("\n");
+	va_end(args);
+	exit(255);
+	return 0;
+}
+
+void
+tap_skip(int n, const char *fmt, ...)
+{
+	char *why;
+	va_list args;
+	va_start(args, fmt);
+	why = vstrdupf(fmt, args);
+	va_end(args);
+	while (n-- > 0) {
+		printf("ok %d ", ++current_test);
+		diag("skip %s\n", why);
+	}
+	free(why);
+}
+
+void
+tap_todo(int ignore, const char *fmt, ...)
+{
+	va_list args;
+	(void)ignore;
+	va_start(args, fmt);
+	todo_mesg = vstrdupf(fmt, args);
+	va_end(args);
+}
+
+void
+tap_end_todo(void)
+{
+	free(todo_mesg);
+	todo_mesg = NULL;
+}
+
+#ifndef _WIN32
+/* Create a shared memory int to keep track of whether a piece of code executed
+dies. to be used in the dies_ok and lives_ok macros.  */
+int
+tap_test_died(int status)
+{
+	static int *test_died = NULL;
+	int prev;
+	if (!test_died) {
+		test_died = mmap(0, sizeof(int), PROT_READ | PROT_WRITE,
+						 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+		*test_died = 0;
+	}
+	prev = *test_died;
+	*test_died = status;
+	return prev;
+}
+
+int
+like_at_loc(int for_match, const char *file, int line, const char *got,
+			const char *expected, const char *fmt, ...)
+{
+	int test;
+	regex_t re;
+	va_list args;
+	int err = regcomp(&re, expected, REG_EXTENDED);
+	if (err) {
+		char errbuf[256];
+		regerror(err, &re, errbuf, sizeof errbuf);
+		fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n",
+				expected, errbuf, file, line);
+		exit(255);
+	}
+	err = regexec(&re, got, 0, NULL, 0);
+	regfree(&re);
+	test = for_match ? !err : err;
+	va_start(args, fmt);
+	vok_at_loc(file, line, test, fmt, args);
+	va_end(args);
+	if (!test) {
+		if (for_match) {
+			diag("                   '%s'", got);
+			diag("    doesn't match: '%s'", expected);
+		} else {
+			diag("                   '%s'", got);
+			diag("          matches: '%s'", expected);
+		}
+	}
+	return test;
+}
+#endif
diff --git a/src/test/libtap/tap.h b/src/test/libtap/tap.h
new file mode 100644
index 00000000000..e366a6affdc
--- /dev/null
+++ b/src/test/libtap/tap.h
@@ -0,0 +1,115 @@
+/*
+libtap - Write tests in C
+Copyright 2012 Jake Gelbman <gelbman@gmail.com>
+This file is licensed under the LGPL
+*/
+
+#ifndef __TAP_H__
+#define __TAP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy __va_copy
+#else
+#define va_copy(d, s) ((d) = (s))
+#endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+int     vok_at_loc      (const char *file, int line, int test, const char *fmt,
+                         va_list args);
+int     ok_at_loc       (const char *file, int line, int test, const char *fmt,
+                         ...);
+int     is_at_loc       (const char *file, int line, const char *got,
+                         const char *expected, const char *fmt, ...);
+int     isnt_at_loc     (const char *file, int line, const char *got,
+                         const char *expected, const char *fmt, ...);
+int     cmp_ok_at_loc   (const char *file, int line, int a, const char *op,
+                         int b, const char *fmt, ...);
+int     cmp_mem_at_loc  (const char *file, int line, const void *got,
+                         const void *expected, size_t n, const char *fmt, ...);
+int     bail_out        (int ignore, const char *fmt, ...);
+void    tap_plan        (int tests, const char *fmt, ...);
+int     diag            (const char *fmt, ...);
+int     exit_status     (void);
+void    tap_skip        (int n, const char *fmt, ...);
+void    tap_todo        (int ignore, const char *fmt, ...);
+void    tap_end_todo    (void);
+
+#define NO_PLAN          -1
+#define SKIP_ALL         -2
+#define ok(...)          ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define is(...)          is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define isnt(...)        isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define cmp_ok(...)      cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define cmp_mem(...)     cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define plan(...)        tap_plan(__VA_ARGS__, NULL)
+#define done_testing()   return exit_status()
+#define BAIL_OUT(...)    bail_out(0, "" __VA_ARGS__, NULL)
+#define pass(...)        ok(1, "" __VA_ARGS__)
+#define fail(...)        ok(0, "" __VA_ARGS__)
+
+#define skip(test, ...)  do {if (test) {tap_skip(__VA_ARGS__, NULL); break;}
+#define end_skip         } while (0)
+
+#define todo(...)        tap_todo(0, "" __VA_ARGS__, NULL)
+#define end_todo         tap_end_todo()
+
+#define dies_ok(...)     dies_ok_common(1, __VA_ARGS__)
+#define lives_ok(...)    dies_ok_common(0, __VA_ARGS__)
+
+#ifdef _WIN32
+#define like(...)        tap_skip(1, "like is not implemented on Windows")
+#define unlike(...)      tap_skip(1, "unlike is not implemented on Windows")
+#define dies_ok_common(...) \
+                         tap_skip(1, "Death detection is not supported on Windows")
+#else
+#define like(...)        like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL)
+#define unlike(...)      like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL)
+int     like_at_loc     (int for_match, const char *file, int line,
+                         const char *got, const char *expected,
+                         const char *fmt, ...);
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+int tap_test_died (int status);
+#define dies_ok_common(for_death, code, ...)                \
+    do {                                                    \
+        int cpid;                                           \
+        int it_died;                                        \
+        tap_test_died(1);                                   \
+        cpid = fork();                                      \
+        switch (cpid) {                                     \
+        case -1:                                            \
+            perror("fork error");                           \
+            exit(1);                                        \
+        case 0:                                             \
+            close(1);                                       \
+            close(2);                                       \
+            code                                            \
+            tap_test_died(0);                               \
+            exit(0);                                        \
+        }                                                   \
+        if (waitpid(cpid, NULL, 0) < 0) {                   \
+            perror("waitpid error");                        \
+            exit(1);                                        \
+        }                                                   \
+        it_died = tap_test_died(0);                         \
+        if (!it_died)                                       \
+            {code}                                          \
+        ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \
+    } while (0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/test/meson.build b/src/test/meson.build
index cd45cbf57fb..64fa751a5a5 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -8,6 +8,7 @@ subdir('postmaster')
 subdir('recovery')
 subdir('subscription')
 subdir('modules')
+subdir('dfor')
 
 if ssl.found()
   subdir('ssl')
-- 
2.53.0

