test/reduce: add compression algorithm

This is a really dumb algorithm but is simple to understand
for unit testing purposes.  It counts the number of consecutive
bytes with the same value, and then stores the number of bytes
with that value, and the byte value itself.  For example:

0xA1 0xA1 0xA2 0xA3 0xA3 0xA3 0xA3 0xA3 0xA3

would be compressed to:

0x02 0xA1 0x01 0xA2 0x06 0xA3

This will make it easy to generate specific data sequences
that compress to specific sizes to validate the different
compression paths through the reduce library.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I0d48f98c080b9cdacb25433f53f44df7ada78c0a

Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/449072
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: wuzhouhui <wuzhouhui@kingsoft.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Jim Harris 2019-01-02 10:13:36 -07:00
parent 2cc2bbe604
commit ac3077c3ea

View File

@ -1027,6 +1027,128 @@ overlapped(void)
backing_dev_destroy(&backing_dev);
}
static int
ut_compress(char *outbuf, uint32_t *compressed_len, char *inbuf, uint32_t inbuflen)
{
uint32_t len = 0;
uint8_t count;
char last;
while (true) {
if (inbuflen == 0) {
*compressed_len = len;
return 0;
}
if (*compressed_len < (len + 2)) {
return -ENOSPC;
}
last = *inbuf;
count = 1;
inbuflen--;
inbuf++;
while (inbuflen > 0 && *inbuf == last && count < UINT8_MAX) {
count++;
inbuflen--;
inbuf++;
}
outbuf[len] = count;
outbuf[len + 1] = last;
len += 2;
}
}
static int
ut_decompress(uint8_t *outbuf, uint32_t *compressed_len, uint8_t *inbuf, uint32_t inbuflen)
{
uint32_t len = 0;
SPDK_CU_ASSERT_FATAL(inbuflen % 2 == 0);
while (true) {
if (inbuflen == 0) {
*compressed_len = len;
return 0;
}
if ((len + inbuf[0]) > *compressed_len) {
return -ENOSPC;
}
memset(outbuf, inbuf[1], inbuf[0]);
outbuf += inbuf[0];
len += inbuf[0];
inbuflen -= 2;
inbuf += 2;
}
}
#define BUFSIZE 4096
static void
compress_algorithm(void)
{
uint8_t original_data[BUFSIZE];
uint8_t compressed_data[BUFSIZE];
uint8_t decompressed_data[BUFSIZE];
uint32_t compressed_len, decompressed_len, i;
int rc;
memset(original_data, 0xAA, BUFSIZE);
compressed_len = sizeof(compressed_data);
rc = ut_compress(compressed_data, &compressed_len, original_data, UINT8_MAX);
CU_ASSERT(rc == 0);
CU_ASSERT(compressed_len == 2);
CU_ASSERT(compressed_data[0] == UINT8_MAX);
CU_ASSERT(compressed_data[1] == 0xAA);
decompressed_len = sizeof(decompressed_data);
rc = ut_decompress(decompressed_data, &decompressed_len, compressed_data, compressed_len);
CU_ASSERT(rc == 0);
CU_ASSERT(decompressed_len == UINT8_MAX);
CU_ASSERT(memcmp(original_data, decompressed_data, decompressed_len) == 0);
compressed_len = sizeof(compressed_data);
rc = ut_compress(compressed_data, &compressed_len, original_data, UINT8_MAX + 1);
CU_ASSERT(rc == 0);
CU_ASSERT(compressed_len == 4);
CU_ASSERT(compressed_data[0] == UINT8_MAX);
CU_ASSERT(compressed_data[1] == 0xAA);
CU_ASSERT(compressed_data[2] == 1);
CU_ASSERT(compressed_data[3] == 0xAA);
decompressed_len = sizeof(decompressed_data);
rc = ut_decompress(decompressed_data, &decompressed_len, compressed_data, compressed_len);
CU_ASSERT(rc == 0);
CU_ASSERT(decompressed_len == UINT8_MAX + 1);
CU_ASSERT(memcmp(original_data, decompressed_data, decompressed_len) == 0);
for (i = 0; i < sizeof(original_data); i++) {
original_data[i] = i & 0xFF;
}
compressed_len = sizeof(compressed_data);
rc = ut_compress(compressed_data, &compressed_len, original_data, 2048);
CU_ASSERT(rc == 0);
CU_ASSERT(compressed_len == 4096);
CU_ASSERT(compressed_data[0] == 1);
CU_ASSERT(compressed_data[1] == 0);
CU_ASSERT(compressed_data[4094] == 1);
CU_ASSERT(compressed_data[4095] == 0xFF);
decompressed_len = sizeof(decompressed_data);
rc = ut_decompress(decompressed_data, &decompressed_len, compressed_data, compressed_len);
CU_ASSERT(rc == 0);
CU_ASSERT(decompressed_len == 2048);
CU_ASSERT(memcmp(original_data, decompressed_data, decompressed_len) == 0);
compressed_len = sizeof(compressed_data);
rc = ut_compress(compressed_data, &compressed_len, original_data, 2049);
CU_ASSERT(rc == -ENOSPC);
}
int
main(int argc, char **argv)
{
@ -1054,7 +1176,8 @@ main(int argc, char **argv)
CU_add_test(suite, "read_write", read_write) == NULL ||
CU_add_test(suite, "destroy", destroy) == NULL ||
CU_add_test(suite, "defer_bdev_io", defer_bdev_io) == NULL ||
CU_add_test(suite, "overlapped", overlapped) == NULL
CU_add_test(suite, "overlapped", overlapped) == NULL ||
CU_add_test(suite, "compress_algorithm", compress_algorithm) == NULL
) {
CU_cleanup_registry();
return CU_get_error();