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:
parent
2cc2bbe604
commit
ac3077c3ea
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user