diff options
Diffstat (limited to 'fluent-bit/tests/internal/aws_compress.c')
-rw-r--r-- | fluent-bit/tests/internal/aws_compress.c | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/fluent-bit/tests/internal/aws_compress.c b/fluent-bit/tests/internal/aws_compress.c new file mode 100644 index 00000000..180a0985 --- /dev/null +++ b/fluent-bit/tests/internal/aws_compress.c @@ -0,0 +1,489 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#include <fluent-bit/flb_info.h> +#include <fluent-bit/flb_mem.h> +#include <fluent-bit/flb_utils.h> +#include <fluent-bit/flb_gzip.h> + +#include <fluent-bit/aws/flb_aws_compress.h> +#include "flb_tests_internal.h" + +#define FLB_AWS_COMPRESS_TEST_TYPE_COMPRESS 1 +#define FLB_AWS_COMPRESS_TEST_TYPE_B64_TRUNCATE 2 + +/* test case definition struct */ +struct flb_aws_test_case { + char* compression_keyword; + char* in_data; + char* expect_out_data_b64; + int expect_ret; +}; + +/* test loop function declarations */ +static unsigned char * base64_encode(const unsigned char *src, size_t len, + size_t *out_len); +static unsigned char * base64_decode(const unsigned char *src, size_t len, + size_t *out_len); +static void flb_aws_compress_general_test_cases(int test_type, + struct flb_aws_test_case *cases, + size_t max_out_len, + int(*decompress)(void *in_data, + size_t in_len, + void **out_data, + size_t *out_len)); +static void flb_aws_compress_test_cases(struct flb_aws_test_case *cases); +static void flb_aws_compress_truncate_b64_test_cases__gzip_decode( + struct flb_aws_test_case *cases, + size_t max_out_len); + +/** ------ Test Cases ------ **/ +void test_compression_gzip() +{ + struct flb_aws_test_case cases[] = + { + { + "gzip", + "hello hello hello hello hello hello", + "H4sIAAAAAAAA/8tIzcnJV8jARwIAVzdihSMAAAA=", + 0 + }, + { 0 } + }; + + flb_aws_compress_test_cases(cases); +} + +void test_b64_truncated_gzip() +{ +struct flb_aws_test_case cases[] = + { + { + "gzip", + "hello hello hello hello hello hello", + "hello hello hello hello hello hello", /* Auto decoded via gzip */ + 0 /* Expected ret */ + }, + { 0 } + }; + + flb_aws_compress_truncate_b64_test_cases__gzip_decode(cases, + 41); +} + +void test_b64_truncated_gzip_truncation() +{ +struct flb_aws_test_case cases[] = + { + { + "gzip", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp" + "or incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, qui" + "s nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequ" + "at. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum do" + "lore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proiden" + "t, sunt in culpa qui officia deserunt mollit anim id est laborum. xyz", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp" + "or incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, qui" + "s nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequ" + "at. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum do" + "lore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proiden" + "t, su[Truncated...]" + /*"nt in culpa qui officia deserunt mollit anim id est laborum. xyz",*/ + "", + 0 /* Expected ret */ + }, + { + "gzip", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp" + "or incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, qui" + "s nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequ" + "at. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum do" + "lore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proiden" + "t, sunt in culpa qui officia deserunt mollit anim id est laborum.", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp" + "or incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, qui" + "s nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequ" + "at. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum do" + "lore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proiden" + "t, sunt in culpa qui officia deserunt mollit anim id est laborum.", + 0 /* Expected ret */ + }, + { 0 } + }; + + flb_aws_compress_truncate_b64_test_cases__gzip_decode(cases, + 381); +} + +void test_b64_truncated_gzip_truncation_buffer_too_small() +{ +struct flb_aws_test_case cases[] = + { + { + "gzip", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp" + "or incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, qui" + "s nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequ" + "at. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum do" + "lore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proiden" + "t, sunt in culpa qui officia deserunt mollit anim id est laborum.", + "", + -1 /* Expected ret */ + }, + { + "gzip", + "", + "", + -1 /* Expected ret: Buffer too small */ + }, + { 0 } + }; + + flb_aws_compress_truncate_b64_test_cases__gzip_decode(cases, + 14); +} + +void test_b64_truncated_gzip_truncation_edge() +{ +struct flb_aws_test_case cases[] = + { + /*{ + "gzip", + "", + "", + 0 + }, *//* This test case fails, because GZIP can zip empty strings but not unzip */ + { + "gzip", + "[Truncated...]", /* Endless loop? */ + "", + -1 /* Expected ret */ + }, + { 0 } + }; + + flb_aws_compress_truncate_b64_test_cases__gzip_decode(cases, + 51); +} + +void test_b64_truncated_gzip_truncation_multi_rounds() +{ +struct flb_aws_test_case cases[] = + { + { + "gzip", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp" + "or incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, qui" + "s nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequ" + "at. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum do" + "lore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proiden" + "t, sunt in culpa qui officia deserunt mollit anim id est laborum." + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "", /* First half of the compression is heavy, the second half is light. */ + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp" + "or incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, qui" + "s nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequ" + "at. Duis aute irure dolor in reprehenderit in voluptate velit es" + "[Truncated...]", /* Bad estimation of resizing, 3 truncation iterations + * needed */ + 0 /* Expected ret */ + }, + { 0 } + }; + + flb_aws_compress_truncate_b64_test_cases__gzip_decode(cases, + 300); +} + +TEST_LIST = { + { "test_compression_gzip", test_compression_gzip }, + { "test_b64_truncated_gzip", test_b64_truncated_gzip }, + { "test_b64_truncated_gzip_truncation", test_b64_truncated_gzip_truncation }, + { "test_b64_truncated_gzip_truncation_buffer_too_small", + test_b64_truncated_gzip_truncation_buffer_too_small }, + { "test_b64_truncated_gzip_truncation_edge", + test_b64_truncated_gzip_truncation_edge }, + { "test_b64_truncated_gzip_truncation_multi_rounds", + test_b64_truncated_gzip_truncation_multi_rounds }, + { 0 } +}; + +/** ------ Helper Methods ------ **/ + +/* test case loop for flb_aws_compress */ +static void flb_aws_compress_test_cases(struct flb_aws_test_case *cases) +{ + flb_aws_compress_general_test_cases(FLB_AWS_COMPRESS_TEST_TYPE_COMPRESS, + cases, 0, NULL); +} + +/* test case loop for flb_aws_compress */ +static void flb_aws_compress_truncate_b64_test_cases__gzip_decode( + struct flb_aws_test_case *cases, + size_t max_out_len) +{ + flb_aws_compress_general_test_cases(FLB_AWS_COMPRESS_TEST_TYPE_B64_TRUNCATE, + cases, max_out_len, &flb_gzip_uncompress); +} + +/* General test case loop flb_aws_compress */ +static void flb_aws_compress_general_test_cases(int test_type, + struct flb_aws_test_case *cases, + size_t max_out_len, + int(*decompress)(void *in_data, + size_t in_len, + void **out_data, + size_t *out_len)) +{ + int ret; + size_t len; + int compression_type = FLB_AWS_COMPRESS_NONE; + unsigned char* out_data; + size_t out_data_len; + unsigned char* out_data_b64; + size_t out_data_b64_len; + struct flb_config *config; + struct flb_aws_test_case *tcase = cases; + + config = flb_config_init(); + + if (config == NULL) { + return; + } + + flb_config_exit(config); + + while (tcase->compression_keyword != 0) { + + size_t in_data_len = strlen(tcase->in_data); + compression_type = flb_aws_compression_get_type(tcase->compression_keyword); + + TEST_CHECK(compression_type != -1); + TEST_MSG("| flb_aws_get_compression_type: failed to get compression type for " + "keyword " + "%s", tcase->compression_keyword); + + if (test_type == FLB_AWS_COMPRESS_TEST_TYPE_COMPRESS) { + ret = flb_aws_compression_compress(compression_type, (void *) tcase->in_data, + in_data_len, (void **) &out_data, + &out_data_len); + } + else { + ret = flb_aws_compression_b64_truncate_compress(compression_type, max_out_len, + (void *) tcase->in_data, + in_data_len, + (void **) &out_data, + &out_data_len); + } + + TEST_CHECK(ret == tcase->expect_ret); + TEST_MSG("| Expected return value: %i", tcase->expect_ret); + TEST_MSG("| Produced return value: %i", ret); + + if (ret != 0) { + TEST_MSG("*- For input data: %s", tcase->in_data); + ++tcase; + continue; + } + + if (test_type == FLB_AWS_COMPRESS_TEST_TYPE_COMPRESS) { + out_data_b64 = base64_encode(out_data, out_data_len, &out_data_b64_len); + /* remove newline character which is a part of this encode algo */ + --out_data_b64_len; + flb_free(out_data); + out_data = NULL; + } + else { + /* decode b64 so we can compare plain text */ + out_data_b64 = base64_decode(out_data, out_data_len, &out_data_b64_len); + flb_free(out_data); + out_data = out_data_b64; + out_data_len = out_data_b64_len; + ret = decompress(out_data, out_data_len, (void *)&out_data_b64, + &out_data_b64_len); + flb_free(out_data); + out_data = NULL; + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("| Decompression failure"); + out_data_b64 = flb_malloc(1); /* placeholder malloc */ + } + } + + ret = memcmp(tcase->expect_out_data_b64, out_data_b64, out_data_b64_len); + TEST_CHECK(ret == 0); + TEST_MSG("| Expected output(%s): %s", + (test_type == FLB_AWS_COMPRESS_TEST_TYPE_COMPRESS) + ? "b64" : "decompressed", tcase->expect_out_data_b64); + TEST_MSG("| Produced output(%s): %s", + (test_type == FLB_AWS_COMPRESS_TEST_TYPE_COMPRESS) + ? "b64" : "decompressed", out_data_b64); + + len = strlen(tcase->expect_out_data_b64); + TEST_CHECK(len == out_data_b64_len); + TEST_MSG("| Expected length: %zu", len); + TEST_MSG("| Produced length: %zu", out_data_b64_len); + + TEST_MSG("*- For input data: %s", tcase->in_data); + + flb_free(out_data_b64); + ++tcase; + } +} + +/* B64 check script copied from Monkey Auth Plugin */ +/* Change log: + * Removed auto new line entry from every 72 characters to make consistant with + * the actual base64 conversion + */ +/* Copied from monkey/plugins/auth/base64.c */ + +#define __mem_alloc malloc +#define __mem_free free + +static const unsigned char base64_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + * base64_encode - Base64 encode + * @src: Data to be encoded + * @len: Length of the data to be encoded + * @out_len: Pointer to output length variable, or %NULL if not used + * Returns: Allocated buffer of out_len bytes of encoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. Returned buffer is + * nul terminated to make it easier to use as a C string. The nul terminator is + * not included in out_len. + */ +static unsigned char * base64_encode(const unsigned char *src, size_t len, + size_t *out_len) +{ + unsigned char *out, *pos; + const unsigned char *end, *in; + size_t olen; + size_t line_len; + + olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ + olen += olen / 72; /* line feeds */ + olen++; /* nul termination */ + if (olen < len) + return NULL; /* integer overflow */ + + out = __mem_alloc(olen); + + if (out == NULL) + return NULL; + + end = src + len; + in = src; + pos = out; + line_len = 0; + while (end - in >= 3) { + *pos++ = base64_table[in[0] >> 2]; + *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; + *pos++ = base64_table[in[2] & 0x3f]; + in += 3; + line_len += 4; + } + + if (end - in) { + *pos++ = base64_table[in[0] >> 2]; + if (end - in == 1) { + *pos++ = base64_table[(in[0] & 0x03) << 4]; + *pos++ = '='; + } else { + *pos++ = base64_table[((in[0] & 0x03) << 4) | + (in[1] >> 4)]; + *pos++ = base64_table[(in[1] & 0x0f) << 2]; + } + *pos++ = '='; + line_len += 4; + } + + if (line_len) + *pos++ = '\n'; + + *pos = '\0'; + if (out_len) + *out_len = pos - out; + return out; +} + +/** + * base64_decode - Base64 decode + * @src: Data to be decoded + * @len: Length of the data to be decoded + * @out_len: Pointer to output length variable + * Returns: Allocated buffer of out_len bytes of decoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. + */ +static unsigned char * base64_decode(const unsigned char *src, size_t len, + size_t *out_len) +{ + unsigned char dtable[256], *out, *pos, block[4], tmp; + size_t i, count, olen; + int pad = 0; + + memset(dtable, 0x80, 256); + for (i = 0; i < sizeof(base64_table) - 1; i++) + dtable[base64_table[i]] = (unsigned char) i; + dtable['='] = 0; + + count = 0; + for (i = 0; i < len; i++) { + if (dtable[src[i]] != 0x80) + count++; + } + + if (count == 0 || count % 4) + return NULL; + + olen = (count / 4 * 3) + 1; + pos = out = __mem_alloc(olen); + if (out == NULL) + return NULL; + + count = 0; + for (i = 0; i < len; i++) { + tmp = dtable[src[i]]; + if (tmp == 0x80) + continue; + + if (src[i] == '=') + pad++; + block[count] = tmp; + count++; + if (count == 4) { + *pos++ = (block[0] << 2) | (block[1] >> 4); + *pos++ = (block[1] << 4) | (block[2] >> 2); + *pos++ = (block[2] << 6) | block[3]; + count = 0; + if (pad) { + if (pad == 1) + pos--; + else if (pad == 2) + pos -= 2; + else { + /* Invalid padding */ + __mem_free(out); + return NULL; + } + break; + } + } + } + *pos = '\0'; + + *out_len = pos - out; + return out; +} + +/* End of copied base64.c from monkey */ |