diff --git a/config/common_base b/config/common_base
index f40354487..004b5e5d1 100644
--- a/config/common_base
+++ b/config/common_base
@@ -549,6 +549,11 @@ CONFIG_RTE_LIBRTE_SECURITY=y
 CONFIG_RTE_LIBRTE_COMPRESSDEV=y
 CONFIG_RTE_COMPRESS_MAX_DEVS=64
 
+#
+# Compile compressdev unit test
+#
+CONFIG_RTE_COMPRESSDEV_TEST=n
+
 #
 # Compile generic event device library
 #
diff --git a/test/test/Makefile b/test/test/Makefile
index a88cc38bf..0faa03bad 100644
--- a/test/test/Makefile
+++ b/test/test/Makefile
@@ -181,6 +181,10 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_pmd_ring_perf.c
 SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_blockcipher.c
 SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev.c
 
+ifeq ($(CONFIG_RTE_COMPRESSDEV_TEST),y)
+SRCS-$(CONFIG_RTE_LIBRTE_COMPRESSDEV) += test_compressdev.c
+endif
+
 ifeq ($(CONFIG_RTE_LIBRTE_EVENTDEV),y)
 SRCS-y += test_eventdev.c
 SRCS-y += test_event_ring.c
@@ -201,6 +205,11 @@ CFLAGS += $(WERROR_FLAGS)
 CFLAGS += -D_GNU_SOURCE
 
 LDLIBS += -lm
+ifeq ($(CONFIG_RTE_COMPRESSDEV_TEST),y)
+ifeq ($(CONFIG_RTE_LIBRTE_COMPRESSDEV),y)
+LDLIBS += -lz
+endif
+endif
 
 # Disable VTA for memcpy test
 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
diff --git a/test/test/meson.build b/test/test/meson.build
index eb3d87a4d..69d3fa699 100644
--- a/test/test/meson.build
+++ b/test/test/meson.build
@@ -235,6 +235,14 @@ if dpdk_conf.has('RTE_LIBRTE_KNI')
 endif
 
 test_dep_objs = []
+compress_test_dep = dependency('zlib', required: false)
+if compress_test_dep.found()
+	test_dep_objs += compress_test_dep
+	test_sources += 'test_compressdev.c'
+	test_deps += 'compressdev'
+	test_names += 'compressdev_autotest'
+endif
+
 foreach d:test_deps
 	def_lib = get_option('default_library')
 	test_dep_objs += get_variable(def_lib + '_rte_' + d)
diff --git a/test/test/test_compressdev.c b/test/test/test_compressdev.c
new file mode 100644
index 000000000..02fc6c3fa
--- /dev/null
+++ b/test/test/test_compressdev.c
@@ -0,0 +1,727 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+#include <string.h>
+#include <zlib.h>
+#include <math.h>
+
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_compressdev.h>
+
+#include "test_compressdev_test_buffer.h"
+#include "test.h"
+
+#define DEFAULT_WINDOW_SIZE 15
+#define DEFAULT_MEM_LEVEL 8
+#define MAX_DEQD_RETRIES 10
+#define DEQUEUE_WAIT_TIME 10000
+
+/*
+ * 30% extra size for compressed data compared to original data,
+ * in case data size cannot be reduced and it is actually bigger
+ * due to the compress block headers
+ */
+#define COMPRESS_BUF_SIZE_RATIO 1.3
+#define NUM_MBUFS 16
+#define NUM_OPS 16
+#define NUM_MAX_XFORMS 1
+#define NUM_MAX_INFLIGHT_OPS 128
+#define CACHE_SIZE 0
+
+#define DIV_CEIL(a, b)  ((a % b) ? ((a / b) + 1) : (a / b))
+
+const char *
+huffman_type_strings[] = {
+	[RTE_COMP_HUFFMAN_DEFAULT]	= "PMD default",
+	[RTE_COMP_HUFFMAN_FIXED]	= "Fixed",
+	[RTE_COMP_HUFFMAN_DYNAMIC]	= "Dynamic"
+};
+
+enum zlib_direction {
+	ZLIB_NONE,
+	ZLIB_COMPRESS,
+	ZLIB_DECOMPRESS,
+	ZLIB_ALL
+};
+
+struct comp_testsuite_params {
+	struct rte_mempool *mbuf_pool;
+	struct rte_mempool *op_pool;
+	struct rte_comp_xform def_comp_xform;
+	struct rte_comp_xform def_decomp_xform;
+};
+
+static struct comp_testsuite_params testsuite_params = { 0 };
+
+static void
+testsuite_teardown(void)
+{
+	struct comp_testsuite_params *ts_params = &testsuite_params;
+
+	rte_mempool_free(ts_params->mbuf_pool);
+	rte_mempool_free(ts_params->op_pool);
+}
+
+static int
+testsuite_setup(void)
+{
+	struct comp_testsuite_params *ts_params = &testsuite_params;
+	unsigned int i;
+
+	if (rte_compressdev_count() == 0) {
+		RTE_LOG(ERR, USER1, "Need at least one compress device\n");
+		return -EINVAL;
+	}
+
+	uint32_t max_buf_size = 0;
+	for (i = 0; i < RTE_DIM(compress_test_bufs); i++)
+		max_buf_size = RTE_MAX(max_buf_size,
+				strlen(compress_test_bufs[i]) + 1);
+
+	max_buf_size *= COMPRESS_BUF_SIZE_RATIO;
+	/*
+	 * Buffers to be used in compression and decompression.
+	 * Since decompressed data might be larger than
+	 * compressed data (due to block header),
+	 * buffers should be big enough for both cases.
+	 */
+	ts_params->mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool",
+			NUM_MBUFS,
+			CACHE_SIZE, 0,
+			max_buf_size + RTE_PKTMBUF_HEADROOM,
+			rte_socket_id());
+	if (ts_params->mbuf_pool == NULL) {
+		RTE_LOG(ERR, USER1, "Large mbuf pool could not be created\n");
+		goto exit;
+	}
+
+	ts_params->op_pool = rte_comp_op_pool_create("op_pool", NUM_OPS,
+						0, 0, rte_socket_id());
+	if (ts_params->op_pool == NULL) {
+		RTE_LOG(ERR, USER1, "Operation pool could not be created\n");
+		goto exit;
+	}
+
+	/* Initializes default values for compress/decompress xforms */
+	ts_params->def_comp_xform.next = NULL;
+	ts_params->def_comp_xform.type = RTE_COMP_COMPRESS;
+	ts_params->def_comp_xform.compress.algo = RTE_COMP_ALGO_DEFLATE,
+	ts_params->def_comp_xform.compress.deflate.huffman =
+						RTE_COMP_HUFFMAN_DEFAULT;
+	ts_params->def_comp_xform.compress.level = RTE_COMP_LEVEL_PMD_DEFAULT;
+	ts_params->def_comp_xform.compress.chksum = RTE_COMP_CHECKSUM_NONE;
+	ts_params->def_comp_xform.compress.window_size = DEFAULT_WINDOW_SIZE;
+
+	ts_params->def_decomp_xform.next = NULL;
+	ts_params->def_decomp_xform.type = RTE_COMP_DECOMPRESS;
+	ts_params->def_decomp_xform.decompress.algo = RTE_COMP_ALGO_DEFLATE,
+	ts_params->def_decomp_xform.decompress.chksum = RTE_COMP_CHECKSUM_NONE;
+	ts_params->def_decomp_xform.decompress.window_size = DEFAULT_WINDOW_SIZE;
+
+	return TEST_SUCCESS;
+
+exit:
+	testsuite_teardown();
+
+	return TEST_FAILED;
+}
+
+static int
+generic_ut_setup(void)
+{
+	/* Configure compressdev (one device, one queue pair) */
+	struct rte_compressdev_config config = {
+		.socket_id = rte_socket_id(),
+		.nb_queue_pairs = 1,
+		.max_nb_priv_xforms = NUM_MAX_XFORMS,
+		.max_nb_streams = 0
+	};
+
+	if (rte_compressdev_configure(0, &config) < 0) {
+		RTE_LOG(ERR, USER1, "Device configuration failed\n");
+		return -1;
+	}
+
+	if (rte_compressdev_queue_pair_setup(0, 0, NUM_MAX_INFLIGHT_OPS,
+			rte_socket_id()) < 0) {
+		RTE_LOG(ERR, USER1, "Queue pair setup failed\n");
+		return -1;
+	}
+
+	if (rte_compressdev_start(0) < 0) {
+		RTE_LOG(ERR, USER1, "Device could not be started\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+generic_ut_teardown(void)
+{
+	rte_compressdev_stop(0);
+}
+
+static int
+compare_buffers(const char *buffer1, uint32_t buffer1_len,
+		const char *buffer2, uint32_t buffer2_len)
+{
+	if (buffer1_len != buffer2_len) {
+		RTE_LOG(ERR, USER1, "Buffer lengths are different\n");
+		return -1;
+	}
+
+	if (memcmp(buffer1, buffer2, buffer1_len) != 0) {
+		RTE_LOG(ERR, USER1, "Buffers are different\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Maps compressdev and Zlib flush flags
+ */
+static int
+map_zlib_flush_flag(enum rte_comp_flush_flag flag)
+{
+	switch (flag) {
+	case RTE_COMP_FLUSH_NONE:
+		return Z_NO_FLUSH;
+	case RTE_COMP_FLUSH_SYNC:
+		return Z_SYNC_FLUSH;
+	case RTE_COMP_FLUSH_FULL:
+		return Z_FULL_FLUSH;
+	case RTE_COMP_FLUSH_FINAL:
+		return Z_FINISH;
+	/*
+	 * There should be only the values above,
+	 * so this should never happen
+	 */
+	default:
+		return -1;
+	}
+}
+
+static int
+compress_zlib(struct rte_comp_op *op,
+		const struct rte_comp_xform *xform, int mem_level)
+{
+	z_stream stream;
+	int zlib_flush;
+	int strategy, window_bits, comp_level;
+	int ret = -1;
+
+	/* initialize zlib stream */
+	stream.zalloc = Z_NULL;
+	stream.zfree = Z_NULL;
+	stream.opaque = Z_NULL;
+
+	if (xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_FIXED)
+		strategy = Z_FIXED;
+	else
+		strategy = Z_DEFAULT_STRATEGY;
+
+	/*
+	 * Window bits is the base two logarithm of the window size (in bytes).
+	 * When doing raw DEFLATE, this number will be negative.
+	 */
+	window_bits = -(xform->compress.window_size);
+
+	comp_level = xform->compress.level;
+
+	if (comp_level != RTE_COMP_LEVEL_NONE)
+		ret = deflateInit2(&stream, comp_level, Z_DEFLATED,
+			window_bits, mem_level, strategy);
+	else
+		ret = deflateInit(&stream, Z_NO_COMPRESSION);
+
+	if (ret != Z_OK) {
+		printf("Zlib deflate could not be initialized\n");
+		goto exit;
+	}
+
+	/* Assuming stateless operation */
+	stream.avail_in = op->src.length;
+	stream.next_in = rte_pktmbuf_mtod(op->m_src, uint8_t *);
+	stream.avail_out = op->m_dst->data_len;
+	stream.next_out = rte_pktmbuf_mtod(op->m_dst, uint8_t *);
+
+	/* Stateless operation, all buffer will be compressed in one go */
+	zlib_flush = map_zlib_flush_flag(op->flush_flag);
+	ret = deflate(&stream, zlib_flush);
+
+	if (stream.avail_in != 0) {
+		RTE_LOG(ERR, USER1, "Buffer could not be read entirely\n");
+		goto exit;
+	}
+
+	//TODO: This is only if flush final is used
+	if (ret != Z_STREAM_END)
+		goto exit;
+
+	op->consumed = op->src.length - stream.avail_in;
+	op->produced = op->m_dst->data_len - stream.avail_out;
+	op->status = RTE_COMP_OP_STATUS_SUCCESS;
+
+	deflateReset(&stream);
+
+	ret = 0;
+exit:
+	deflateEnd(&stream);
+
+	return ret;
+}
+
+static int
+decompress_zlib(struct rte_comp_op *op,
+		const struct rte_comp_xform *xform)
+{
+	z_stream stream;
+	int window_bits;
+	int zlib_flush;
+	int ret = TEST_FAILED;
+
+	/* initialize zlib stream */
+	stream.zalloc = Z_NULL;
+	stream.zfree = Z_NULL;
+	stream.opaque = Z_NULL;
+
+	/*
+	 * Window bits is the base two logarithm of the window size (in bytes).
+	 * When doing raw DEFLATE, this number will be negative.
+	 */
+	window_bits = -(xform->decompress.window_size);
+
+	ret = inflateInit2(&stream, window_bits);
+
+	if (ret != Z_OK) {
+		printf("Zlib deflate could not be initialized\n");
+		goto exit;
+	}
+
+	/* Assuming stateless operation */
+	stream.avail_in = op->src.length;
+	stream.next_in = rte_pktmbuf_mtod(op->m_src, uint8_t *);
+	stream.avail_out = op->m_dst->data_len;
+	stream.next_out = rte_pktmbuf_mtod(op->m_dst, uint8_t *);
+
+	/* Stateless operation, all buffer will be compressed in one go */
+	zlib_flush = map_zlib_flush_flag(op->flush_flag);
+	ret = inflate(&stream, zlib_flush);
+
+	if (stream.avail_in != 0) {
+		RTE_LOG(ERR, USER1, "Buffer could not be read entirely\n");
+		goto exit;
+	}
+
+	//TODO: This is only if flush final is used
+	if (ret != Z_STREAM_END)
+		goto exit;
+
+	op->consumed = op->src.length - stream.avail_in;
+	op->produced = op->m_dst->data_len - stream.avail_out;
+	op->status = RTE_COMP_OP_STATUS_SUCCESS;
+
+	inflateReset(&stream);
+
+	ret = 0;
+exit:
+	inflateEnd(&stream);
+
+	return ret;
+}
+
+/*
+ * Compresses and decompresses buffer with compressdev API and Zlib API
+ */
+static int
+test_deflate_comp_decomp(const char *test_buffer,
+		struct rte_comp_xform *compress_xform,
+		struct rte_comp_xform *decompress_xform,
+		enum rte_comp_op_type state,
+		enum zlib_direction zlib_dir)
+{
+	struct comp_testsuite_params *ts_params = &testsuite_params;
+	int ret_status = -1;
+	int ret;
+	struct rte_mbuf *comp_buf = NULL;
+	struct rte_mbuf *uncomp_buf = NULL;
+	struct rte_comp_op *op = NULL;
+	struct rte_comp_op *op_processed = NULL;
+	void *priv_xform = NULL;
+	uint16_t num_deqd;
+	unsigned int deqd_retries = 0;
+	char *data_ptr;
+
+	/* Prepare the source mbuf with the data */
+	uncomp_buf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	if (uncomp_buf == NULL) {
+		RTE_LOG(ERR, USER1,
+			"Source mbuf could not be allocated "
+			"from the mempool\n");
+		goto exit;
+	}
+
+	data_ptr = rte_pktmbuf_append(uncomp_buf, strlen(test_buffer) + 1);
+	snprintf(data_ptr, strlen(test_buffer) + 1, "%s", test_buffer);
+
+	/* Prepare the destination mbuf */
+	comp_buf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	if (comp_buf == NULL) {
+		RTE_LOG(ERR, USER1,
+			"Destination mbuf could not be allocated "
+			"from the mempool\n");
+		goto exit;
+	}
+
+	rte_pktmbuf_append(comp_buf,
+			strlen(test_buffer) * COMPRESS_BUF_SIZE_RATIO);
+
+	/* Build the compression operations */
+	op = rte_comp_op_alloc(ts_params->op_pool);
+	if (op == NULL) {
+		RTE_LOG(ERR, USER1,
+			"Compress operation could not be allocated "
+			"from the mempool\n");
+		goto exit;
+	}
+
+	op->m_src = uncomp_buf;
+	op->m_dst = comp_buf;
+	op->src.offset = 0;
+	op->src.length = rte_pktmbuf_pkt_len(uncomp_buf);
+	op->dst.offset = 0;
+	if (state == RTE_COMP_OP_STATELESS) {
+		//TODO: FULL or FINAL?
+		op->flush_flag = RTE_COMP_FLUSH_FINAL;
+	} else {
+		RTE_LOG(ERR, USER1,
+			"Stateful operations are not supported "
+			"in these tests yet\n");
+		goto exit;
+	}
+	op->input_chksum = 0;
+
+	/* Compress data (either with Zlib API or compressdev API */
+	if (zlib_dir == ZLIB_COMPRESS || zlib_dir == ZLIB_ALL) {
+		ret = compress_zlib(op,
+			(const struct rte_comp_xform *)&compress_xform,
+			DEFAULT_MEM_LEVEL);
+		if (ret < 0)
+			goto exit;
+
+		op_processed = op;
+	} else {
+		/* Create compress xform private data */
+		ret = rte_compressdev_private_xform_create(0,
+			(const struct rte_comp_xform *)compress_xform,
+			&priv_xform);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1,
+				"Compression private xform "
+				"could not be created\n");
+			goto exit;
+		}
+
+		/* Attach xform private data to operation */
+		op->private_xform = priv_xform;
+
+		/* Enqueue and dequeue all operations */
+		ret = rte_compressdev_enqueue_burst(0, 0, &op, 1);
+		if (ret == 0) {
+			RTE_LOG(ERR, USER1,
+				"The operation could not be enqueued\n");
+			goto exit;
+		}
+		do {
+			/*
+			 * If retrying a dequeue call, wait for 10 ms to allow
+			 * enough time to the driver to process the operations
+			 */
+			if (deqd_retries != 0) {
+				/*
+				 * Avoid infinite loop if not all the
+				 * operations get out of the device
+				 */
+				if (deqd_retries == MAX_DEQD_RETRIES) {
+					RTE_LOG(ERR, USER1,
+						"Not all operations could be "
+						"dequeued\n");
+					goto exit;
+				}
+				usleep(DEQUEUE_WAIT_TIME);
+			}
+			num_deqd = rte_compressdev_dequeue_burst(0, 0,
+					&op_processed, 1);
+
+			deqd_retries++;
+		} while (num_deqd < 1);
+
+		deqd_retries = 0;
+
+		/* Free compress private xform */
+		rte_compressdev_private_xform_free(0, priv_xform);
+		priv_xform = NULL;
+	}
+
+	enum rte_comp_huffman huffman_type =
+		compress_xform->compress.deflate.huffman;
+	RTE_LOG(DEBUG, USER1, "Buffer compressed from %u to %u bytes "
+			"(level = %u, huffman = %s)\n",
+			op_processed->consumed, op_processed->produced,
+			compress_xform->compress.level,
+			huffman_type_strings[huffman_type]);
+	RTE_LOG(DEBUG, USER1, "Compression ratio = %.2f",
+			(float)op_processed->produced /
+			op_processed->consumed * 100);
+	op = NULL;
+
+	/*
+	 * Check operation status and free source mbuf (destination mbuf and
+	 * compress operation information is needed for the decompression stage)
+	 */
+	if (op_processed->status != RTE_COMP_OP_STATUS_SUCCESS) {
+		RTE_LOG(ERR, USER1,
+			"Some operations were not successful\n");
+		goto exit;
+	}
+	rte_pktmbuf_free(uncomp_buf);
+	uncomp_buf = NULL;
+
+	/* Allocate buffer for decompressed data */
+	uncomp_buf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	if (uncomp_buf == NULL) {
+		RTE_LOG(ERR, USER1,
+			"Destination mbuf could not be allocated "
+			"from the mempool\n");
+		goto exit;
+	}
+
+	rte_pktmbuf_append(uncomp_buf, strlen(test_buffer) + 1);
+
+	/* Build the decompression operations */
+	op = rte_comp_op_alloc(ts_params->op_pool);
+	if (op == NULL) {
+		RTE_LOG(ERR, USER1,
+			"Decompress operation could not be allocated "
+			"from the mempool\n");
+		goto exit;
+	}
+
+	/* Source buffer is the compressed data from the previous operation */
+	op->m_src = op_processed->m_dst;
+	op->m_dst = uncomp_buf;
+	op->src.offset = 0;
+	/*
+	 * Set the length of the compressed data to the
+	 * number of bytes that were produced in the previous stage
+	 */
+	op->src.length = op_processed->produced;
+	op->dst.offset = 0;
+	if (state == RTE_COMP_OP_STATELESS) {
+		//TODO: FULL or FINAL?
+		op->flush_flag = RTE_COMP_FLUSH_FINAL;
+	} else {
+		RTE_LOG(ERR, USER1,
+			"Stateful operations are not supported "
+			"in these tests yet\n");
+		goto exit;
+	}
+	op->input_chksum = 0;
+
+	/*
+	 * Free the previous compress operation,
+	 * as it is not needed anymore
+	 */
+	rte_comp_op_free(op_processed);
+	op_processed = NULL;
+
+	/* Decompress data (either with Zlib API or compressdev API */
+	if (zlib_dir == ZLIB_DECOMPRESS || zlib_dir == ZLIB_ALL) {
+		ret = decompress_zlib(op,
+			(const struct rte_comp_xform *)&decompress_xform);
+		if (ret < 0)
+			goto exit;
+
+		op_processed = op;
+	} else {
+		num_deqd = 0;
+		/* Create decompress xform private data */
+		ret = rte_compressdev_private_xform_create(0,
+			(const struct rte_comp_xform *)decompress_xform,
+			&priv_xform);
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1,
+				"Decompression private xform "
+				"could not be created\n");
+			goto exit;
+		}
+
+		/* Attach xform private data to operation */
+		op->private_xform = priv_xform;
+
+		/* Enqueue and dequeue all operations */
+		ret = rte_compressdev_enqueue_burst(0, 0, &op, 1);
+		if (ret == 0) {
+			RTE_LOG(ERR, USER1,
+				"The operation could not be enqueued\n");
+			goto exit;
+		}
+		do {
+			/*
+			 * If retrying a dequeue call, wait for 10 ms to allow
+			 * enough time to the driver to process the operations
+			 */
+			if (deqd_retries != 0) {
+				/*
+				 * Avoid infinite loop if not all the
+				 * operations get out of the device
+				 */
+				if (deqd_retries == MAX_DEQD_RETRIES) {
+					RTE_LOG(ERR, USER1,
+						"Not all operations could be "
+						"dequeued\n");
+					goto exit;
+				}
+				usleep(DEQUEUE_WAIT_TIME);
+			}
+			num_deqd = rte_compressdev_dequeue_burst(0, 0,
+					&op_processed, 1);
+
+			deqd_retries++;
+		} while (num_deqd < 1);
+	}
+
+	RTE_LOG(DEBUG, USER1, "Buffer decompressed from %u to %u bytes\n",
+			op_processed->consumed, op_processed->produced);
+	op = NULL;
+	/*
+	 * Check operation status and free source mbuf (destination mbuf and
+	 * compress operation information is still needed)
+	 */
+	if (op_processed->status != RTE_COMP_OP_STATUS_SUCCESS) {
+		RTE_LOG(ERR, USER1,
+			"Some operations were not successful\n");
+		goto exit;
+	}
+	rte_pktmbuf_free(comp_buf);
+	comp_buf = NULL;
+
+	/*
+	 * Compare the original stream with the decompressed stream
+	 * (in size and the data)
+	 */
+	if (compare_buffers(test_buffer, strlen(test_buffer) + 1,
+			rte_pktmbuf_mtod(op_processed->m_dst, const char *),
+			op_processed->produced) < 0)
+		goto exit;
+
+	ret_status = 0;
+
+exit:
+	/* Free resources */
+	rte_pktmbuf_free(uncomp_buf);
+	rte_pktmbuf_free(comp_buf);
+	rte_comp_op_free(op);
+	rte_comp_op_free(op_processed);
+
+	if (priv_xform != NULL)
+		rte_compressdev_private_xform_free(0, priv_xform);
+
+	return ret_status;
+}
+
+static int
+test_compressdev_deflate_stateless_fixed(void)
+{
+	struct comp_testsuite_params *ts_params = &testsuite_params;
+	const char *test_buffer;
+	uint16_t i;
+	struct rte_comp_xform compress_xform;
+
+	memcpy(&compress_xform, &ts_params->def_comp_xform,
+			sizeof(struct rte_comp_xform));
+	compress_xform.compress.deflate.huffman = RTE_COMP_HUFFMAN_FIXED;
+
+	for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+		test_buffer = compress_test_bufs[i];
+
+		/* Compress with compressdev, decompress with Zlib */
+		if (test_deflate_comp_decomp(test_buffer,
+				&compress_xform,
+				&ts_params->def_decomp_xform,
+				RTE_COMP_OP_STATELESS,
+				ZLIB_DECOMPRESS) < 0)
+			return TEST_FAILED;
+
+		/* Compress with Zlib, decompress with compressdev */
+		if (test_deflate_comp_decomp(test_buffer,
+				&compress_xform,
+				&ts_params->def_decomp_xform,
+				RTE_COMP_OP_STATELESS,
+				ZLIB_COMPRESS) < 0)
+			return TEST_FAILED;
+	}
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_compressdev_deflate_stateless_dynamic(void)
+{
+	struct comp_testsuite_params *ts_params = &testsuite_params;
+	const char *test_buffer;
+	uint16_t i;
+	struct rte_comp_xform compress_xform;
+
+	memcpy(&compress_xform, &ts_params->def_comp_xform,
+			sizeof(struct rte_comp_xform));
+	compress_xform.compress.deflate.huffman = RTE_COMP_HUFFMAN_DYNAMIC;
+
+	for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+		test_buffer = compress_test_bufs[i];
+
+		/* Compress with compressdev, decompress with Zlib */
+		if (test_deflate_comp_decomp(test_buffer,
+				&compress_xform,
+				&ts_params->def_decomp_xform,
+				RTE_COMP_OP_STATELESS,
+				ZLIB_DECOMPRESS) < 0)
+			return TEST_FAILED;
+
+		/* Compress with Zlib, decompress with compressdev */
+		if (test_deflate_comp_decomp(test_buffer,
+				&compress_xform,
+				&ts_params->def_decomp_xform,
+				RTE_COMP_OP_STATELESS,
+				ZLIB_COMPRESS) < 0)
+			return TEST_FAILED;
+	}
+
+	return TEST_SUCCESS;
+}
+
+static struct unit_test_suite compressdev_testsuite  = {
+	.suite_name = "compressdev unit test suite",
+	.setup = testsuite_setup,
+	.teardown = testsuite_teardown,
+	.unit_test_cases = {
+		TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+			test_compressdev_deflate_stateless_fixed),
+		TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+			test_compressdev_deflate_stateless_dynamic),
+		TEST_CASES_END() /**< NULL terminate unit test array */
+	}
+};
+
+static int
+test_compressdev(void)
+{
+	return unit_test_suite_runner(&compressdev_testsuite);
+}
+
+REGISTER_TEST_COMMAND(compressdev_autotest, test_compressdev);
diff --git a/test/test/test_compressdev_test_buffer.h b/test/test/test_compressdev_test_buffer.h
new file mode 100644
index 000000000..c0492f89a
--- /dev/null
+++ b/test/test/test_compressdev_test_buffer.h
@@ -0,0 +1,295 @@
+#ifndef TEST_COMPRESSDEV_TEST_BUFFERS_H_
+#define TEST_COMPRESSDEV_TEST_BUFFERS_H_
+
+/*
+ * These test buffers are snippets obtained
+ * from the Canterbury and Calgary Corpus
+ * collection.
+ */
+
+/* Snippet of Alice's Adventures in Wonderland */
+static const char test_buf_alice[] =
+	"  Alice was beginning to get very tired of sitting by her sister\n"
+	"on the bank, and of having nothing to do:  once or twice she had\n"
+	"peeped into the book her sister was reading, but it had no\n"
+	"pictures or conversations in it, `and what is the use of a book,'\n"
+	"thought Alice `without pictures or conversation?'\n\n"
+	"  So she was considering in her own mind (as well as she could,\n"
+	"for the hot day made her feel very sleepy and stupid), whether\n"
+	"the pleasure of making a daisy-chain would be worth the trouble\n"
+	"of getting up and picking the daisies, when suddenly a White\n"
+	"Rabbit with pink eyes ran close by her.\n\n"
+	"  There was nothing so VERY remarkable in that; nor did Alice\n"
+	"think it so VERY much out of the way to hear the Rabbit say to\n"
+	"itself, `Oh dear!  Oh dear!  I shall be late!'  (when she thought\n"
+	"it over afterwards, it occurred to her that she ought to have\n"
+	"wondered at this, but at the time it all seemed quite natural);\n"
+	"but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-\n"
+	"POCKET, and looked at it, and then hurried on, Alice started to\n"
+	"her feet, for it flashed across her mind that she had never\n"
+	"before seen a rabbit with either a waistcoat-pocket, or a watch to\n"
+	"take out of it, and burning with curiosity, she ran across the\n"
+	"field after it, and fortunately was just in time to see it pop\n"
+	"down a large rabbit-hole under the hedge.\n\n"
+	"  In another moment down went Alice after it, never once\n"
+	"considering how in the world she was to get out again.\n\n"
+	"  The rabbit-hole went straight on like a tunnel for some way,\n"
+	"and then dipped suddenly down, so suddenly that Alice had not a\n"
+	"moment to think about stopping herself before she found herself\n"
+	"falling down a very deep well.\n\n"
+	"  Either the well was very deep, or she fell very slowly, for she\n"
+	"had plenty of time as she went down to look about her and to\n"
+	"wonder what was going to happen next.  First, she tried to look\n"
+	"down and make out what she was coming to, but it was too dark to\n"
+	"see anything; then she looked at the sides of the well, and\n"
+	"noticed that they were filled with cupboards and book-shelves;\n"
+	"here and there she saw maps and pictures hung upon pegs.  She\n"
+	"took down a jar from one of the shelves as she passed; it was\n"
+	"labelled `ORANGE MARMALADE', but to her great disappointment it\n"
+	"was empty:  she did not like to drop the jar for fear of killing\n"
+	"somebody, so managed to put it into one of the cupboards as she\n"
+	"fell past it.\n\n"
+	"  `Well!' thought Alice to herself, `after such a fall as this, I\n"
+	"shall think nothing of tumbling down stairs!  How brave they'll\n"
+	"all think me at home!  Why, I wouldn't say anything about it,\n"
+	"even if I fell off the top of the house!' (Which was very likely\n"
+	"true.)\n\n"
+	"  Down, down, down.  Would the fall NEVER come to an end!  `I\n"
+	"wonder how many miles I've fallen by this time?' she said aloud.\n"
+	"`I must be getting somewhere near the centre of the earth.  Let\n"
+	"me see:  that would be four thousand miles down, I think--' (for,\n"
+	"you see, Alice had learnt several things of this sort in her\n"
+	"lessons in the schoolroom, and though this was not a VERY good\n"
+	"opportunity for showing off her knowledge, as there was no one to\n"
+	"listen to her, still it was good practice to say it over) `--yes,\n"
+	"that's about the right distance--but then I wonder what Latitude\n"
+	"or Longitude I've got to?'  (Alice had no idea what Latitude was,\n"
+	"or Longitude either, but thought they were nice grand words to\n"
+	"say.)\n\n"
+	"  Presently she began again.  `I wonder if I shall fall right\n"
+	"THROUGH the earth!  How funny it'll seem to come out among the\n"
+	"people that walk with their heads downward!  The Antipathies, I\n"
+	"think--' (she was rather glad there WAS no one listening, this\n"
+	"time, as it didn't sound at all the right word) `--but I shall\n"
+	"have to ask them what the name of the country is, you know.\n"
+	"Please, Ma'am, is this New Zealand or Australia?' (and she tried\n"
+	"to curtsey as she spoke--fancy CURTSEYING as you're falling\n"
+	"through the air!  Do you think you could manage it?)  `And what\n"
+	"an ignorant little girl she'll think me for asking!  No, it'll\n"
+	"never do to ask:  perhaps I shall see it written up somewhere.'\n"
+	"  Down, down, down.  There was nothing else to do, so Alice soon\n"
+	"began talking again.  `Dinah'll miss me very much to-night, I\n"
+	"should think!'  (Dinah was the cat.)  `I hope they'll remember\n"
+	"her saucer of milk at tea-time.  Dinah my dear!  I wish you were\n"
+	"down here with me!  There are no mice in the air, I'm afraid, but\n"
+	"you might catch a bat, and that's very like a mouse, you know.\n"
+	"But do cats eat bats, I wonder?'  And here Alice began to get\n"
+	"rather sleepy, and went on saying to herself, in a dreamy sort of\n"
+	"way, `Do cats eat bats?  Do cats eat bats?' and sometimes, `Do\n"
+	"bats eat cats?' for, you see, as she couldn't answer either\n"
+	"question, it didn't much matter which way she put it.  She felt\n"
+	"that she was dozing off, and had just begun to dream that she\n"
+	"was walking hand in hand with Dinah, and saying to her very\n"
+	"earnestly, `Now, Dinah, tell me the truth:  did you ever eat a\n"
+	"bat?' when suddenly, thump! thump! down she came upon a heap of\n"
+	"sticks and dry leaves, and the fall was over.\n\n";
+
+/* Snippet of Shakespeare play */
+static const char test_buf_shakespeare[] =
+	"CHARLES	wrestler to Frederick.\n"
+	"\n"
+	"\n"
+	"OLIVER		|\n"
+	"		|\n"
+	"JAQUES (JAQUES DE BOYS:)  	|  sons of Sir Rowland de Boys.\n"
+	"		|\n"
+	"ORLANDO		|\n"
+	"\n"
+	"\n"
+	"ADAM	|\n"
+	"	|  servants to Oliver.\n"
+	"DENNIS	|\n"
+	"\n"
+	"\n"
+	"TOUCHSTONE	a clown.\n"
+	"\n"
+	"SIR OLIVER MARTEXT	a vicar.\n"
+	"\n"
+	"\n"
+	"CORIN	|\n"
+	"	|  shepherds.\n"
+	"SILVIUS	|\n"
+	"\n"
+	"\n"
+	"WILLIAM	a country fellow in love with Audrey.\n"
+	"\n"
+	"	A person representing HYMEN. (HYMEN:)\n"
+	"\n"
+	"ROSALIND	daughter to the banished duke.\n"
+	"\n"
+	"CELIA	daughter to Frederick.\n"
+	"\n"
+	"PHEBE	a shepherdess.\n"
+	"\n"
+	"AUDREY	a country wench.\n"
+	"\n"
+	"	Lords, pages, and attendants, &c.\n"
+	"	(Forester:)\n"
+	"	(A Lord:)\n"
+	"	(First Lord:)\n"
+	"	(Second Lord:)\n"
+	"	(First Page:)\n"
+	"	(Second Page:)\n"
+	"\n"
+	"\n"
+	"SCENE	Oliver's house; Duke Frederick's court; and the\n"
+	"	Forest of Arden.\n"
+	"\n"
+	"\n"
+	"\n"
+	"\n"
+	"	AS YOU LIKE IT\n"
+	"\n"
+	"\n"
+	"ACT I\n"
+	"\n"
+	"\n"
+	"\n"
+	"SCENE I	Orchard of Oliver's house.\n"
+	"\n"
+	"\n"
+	"	[Enter ORLANDO and ADAM]\n"
+	"\n"
+	"ORLANDO	As I remember, Adam, it was upon this fashion\n"
+	"	bequeathed me by will but poor a thousand crowns,\n"
+	"	and, as thou sayest, charged my brother, on his\n"
+	"	blessing, to breed me well: and there begins my\n"
+	"	sadness. My brother Jaques he keeps at school, and\n"
+	"	report speaks goldenly of his profit: for my part,\n"
+	"	he keeps me rustically at home, or, to speak more\n"
+	"	properly, stays me here at home unkept; for call you\n"
+	"	that keeping for a gentleman of my birth, that\n"
+	"	differs not from the stalling of an ox? His horses\n"
+	"	are bred better; for, besides that they are fair\n"
+	"	with their feeding, they are taught their manage,\n"
+	"	and to that end riders dearly hired: but I, his\n"
+	"	brother, gain nothing under him but growth; for the\n"
+	"	which his animals on his dunghills are as much\n"
+	"	bound to him as I. Besides this nothing that he so\n"
+	"	plentifully gives me, the something that nature gave\n"
+	"	me his countenance seems to take from me: he lets\n"
+	"	me feed with his hinds, bars me the place of a\n"
+	"	brother, and, as much as in him lies, mines my\n"
+	"	gentility with my education. This is it, Adam, that\n"
+	"	grieves me; and the spirit of my father, which I\n"
+	"	think is within me, begins to mutiny against this\n"
+	"	servitude: I will no longer endure it, though yet I\n"
+	"	know no wise remedy how to avoid it.\n"
+	"\n"
+	"ADAM	Yonder comes my master, your brother.\n"
+	"\n"
+	"ORLANDO	Go apart, Adam, and thou shalt hear how he will\n";
+
+/* Snippet of source code in Pascal */
+static const char test_buf_pascal[] =
+	"	Ptr    = 1..DMem;\n"
+	"	Loc    = 1..IMem;\n"
+	"	Loc0   = 0..IMem;\n"
+	"	EdgeT  = (hout,lin,hin,lout); {Warning this order is important in}\n"
+	"				      {predicates such as gtS,geS}\n"
+	"	CardT  = (finite,infinite);\n"
+	"	ExpT   = Minexp..Maxexp;\n"
+	"	ManT   = Mininf..Maxinf; \n"
+	"	Pflag  = (PNull,PSoln,PTrace,PPrint);\n"
+	"	Sreal  = record\n"
+	"		    edge:EdgeT;\n"
+	"		    cardinality:CardT;\n"
+	"		    exp:ExpT; {exponent}\n"
+	"		    mantissa:ManT;\n"
+	"		 end;\n"
+	"	Int    = record\n"
+	"		    hi:Sreal;\n"
+	"		    lo:Sreal;\n"
+	"	 end;\n"
+	"	Instr  = record\n"
+	"		    Code:OpType;\n"
+	"		    Pars: array[0..Par] of 0..DMem;\n"
+	"		 end;\n"
+	"	DataMem= record\n"
+	"		    D        :array [Ptr] of Int;\n"
+	"		    S        :array [Loc] of State;\n"
+	"		    LastHalve:Loc;\n"
+	"		    RHalve   :array [Loc] of real;\n"
+	"		 end;\n"
+	"	DataFlags=record\n"
+	"		    PF	     :array [Ptr] of Pflag;\n"
+	"		 end;\n"
+	"var\n"
+	"	Debug  : (none,activity,post,trace,dump);\n"
+	"	Cut    : (once,all);\n"
+	"	GlobalEnd,Verifiable:boolean;\n"
+	"	HalveThreshold:real;\n"
+	"	I      : array [Loc] of Instr; {Memory holding instructions}\n"
+	"	End    : Loc; {last instruction in I}\n"
+	"	ParN   : array [OpType] of -1..Par; {number of parameters for each \n"
+	"			opcode. -1 means no result}\n"
+	"        ParIntersect : array [OpType] of boolean ;\n"
+	"	DInit  : DataMem; {initial memory which is cleared and \n"
+	"				used in first call}\n"
+	"	DF     : DataFlags; {hold flags for variables, e.g. print/trace}\n"
+	"	MaxDMem:0..DMem;\n"
+	"	Shift  : array[0..Digits] of 1..maxint;{array of constant multipliers}\n"
+	"						{used for alignment etc.}\n"
+	"	Dummy  :Positive;\n"
+	"	{constant intervals and Sreals}\n"
+	"	PlusInfS,MinusInfS,PlusSmallS,MinusSmallS,ZeroS,\n"
+	"	PlusFiniteS,MinusFiniteS:Sreal;\n"
+	"	Zero,All,AllFinite:Int;\n"
+	"\n"
+	"procedure deblank;\n"
+	"var Ch:char;\n"
+	"begin\n"
+	"   while (not eof) and (input^ in [' ','	']) do read(Ch);\n"
+	"end;\n"
+	"\n"
+	"procedure InitialOptions;\n"
+	"\n"
+	"#include '/user/profs/cleary/bin/options.i';\n"
+	"\n"
+	"   procedure Option;\n"
+	"   begin\n"
+	"      case Opt of\n"
+	"      'a','A':Debug:=activity;\n"
+	"      'd','D':Debug:=dump;\n"
+	"      'h','H':HalveThreshold:=StringNum/100;\n"
+	"      'n','N':Debug:=none;\n"
+	"      'p','P':Debug:=post;\n"
+	"      't','T':Debug:=trace;\n"
+	"      'v','V':Verifiable:=true;\n"
+	"      end;\n"
+	"   end;\n"
+	"\n"
+	"begin\n"
+	"   Debug:=trace;\n"
+	"   Verifiable:=false;\n"
+	"   HalveThreshold:=67/100;\n"
+	"   Options;\n"
+	"   writeln(Debug);\n"
+	"   writeln('Verifiable:',Verifiable);\n"
+	"   writeln('Halve threshold',HalveThreshold);\n"
+	"end;{InitialOptions}\n"
+	"\n"
+	"procedure NormalizeUp(E,M:integer;var S:Sreal;var Closed:boolean);\n"
+	"begin\n"
+	"with S do\n"
+	"begin\n"
+	"   if M=0 then S:=ZeroS else\n"
+	"   if M>0 then\n";
+
+static const char * const compress_test_bufs[] = {
+	test_buf_alice,
+	test_buf_shakespeare,
+	test_buf_pascal
+};
+
+#endif /* TEST_COMPRESSDEV_TEST_BUFFERS_H_ */
