diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
commit | be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 (patch) | |
tree | 9754ff1ca740f6346cf8483ec915d4054bc5da2d /fluent-bit/tests/include/aws_client_mock.c | |
parent | Initial commit. (diff) | |
download | netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.tar.xz netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.zip |
Adding upstream version 1.44.3.upstream/1.44.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/tests/include/aws_client_mock.c')
-rw-r--r-- | fluent-bit/tests/include/aws_client_mock.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/fluent-bit/tests/include/aws_client_mock.c b/fluent-bit/tests/include/aws_client_mock.c new file mode 100644 index 00000000..84ee6a1e --- /dev/null +++ b/fluent-bit/tests/include/aws_client_mock.c @@ -0,0 +1,256 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "aws_client_mock.h" + +#include <fluent-bit/flb_aws_util.h> +#include <fluent-bit/flb_http_client.h> + +/* Vtable mocked methods */ +static struct flb_http_client *flb_aws_client_mock_vtable_request( + struct flb_aws_client *aws_client, int method, const char *uri, const char *body, + size_t body_len, struct flb_aws_header *dynamic_headers, size_t dynamic_headers_len); + +/* Protected structs */ + +/* flb_aws_client_mock pointer returned by mock_generator */ +static struct flb_aws_client_mock *flb_aws_client_mock_instance = NULL; + +/* Generator that returns clients with the test vtable */ +static struct flb_aws_client_generator mock_generator = { + .create = flb_aws_client_create_mock, +}; + +/* Test/mock flb_aws_client vtable */ +static struct flb_aws_client_vtable mock_client_vtable = { + .request = flb_aws_client_mock_vtable_request, +}; + +/* + * Configure generator + * Note: Automatically creates mock and wires to generator + * Destroys any existing mock in generator + */ +void flb_aws_client_mock_configure_generator( + struct flb_aws_client_mock_request_chain *request_chain) +{ + flb_aws_client_mock_destroy_generator(); + flb_aws_client_mock_instance = flb_aws_client_mock_create(request_chain); +} + +/* + * Clean up generator's memory + * Cleanup should be called on exiting generator + */ +void flb_aws_client_mock_destroy_generator() +{ + if (flb_aws_client_mock_instance != NULL) { + flb_aws_client_mock_destroy(flb_aws_client_mock_instance); + } +} + +/* Create Mock of flb_aws_client */ +struct flb_aws_client_mock *flb_aws_client_mock_create( + struct flb_aws_client_mock_request_chain *request_chain) +{ + struct flb_aws_client_mock *mock = flb_calloc(1, sizeof(struct flb_aws_client_mock)); + + /* Create a surrogate aws_client and copy to mock client */ + struct flb_aws_client *surrogate_aws_client = flb_aws_client_generator()->create(); + mock->super = *surrogate_aws_client; + mock->surrogate = surrogate_aws_client; + memset(mock->surrogate, 0, sizeof(struct flb_aws_client)); + + /* Switch vtable to mock vtable */ + mock->super.client_vtable = &mock_client_vtable; + mock->request_chain = request_chain; + mock->next_request_index = 0; + return mock; +} + +/* Destroy flb_aws_client_mock */ +void flb_aws_client_mock_destroy(struct flb_aws_client_mock *mock) +{ + /* Remove from generator registry if stored */ + if (flb_aws_client_mock_instance == mock) { + flb_aws_client_mock_instance = NULL; + } + + /* Resurrect surrogate, and destroy flb_aws_client */ + *mock->surrogate = mock->super; + flb_aws_client_destroy(mock->surrogate); + + /* Destroy mock flb_aws_client */ + flb_free(mock); +} + +/* Return a Mocked flb_aws_client, ready for injection */ +struct flb_aws_client *flb_aws_client_mock_context(struct flb_aws_client_mock *mock) +{ + return (struct flb_aws_client *)mock; +} + +/* Get the number of unused requests */ +int flb_aws_client_mock_count_unused_requests(struct flb_aws_client_mock *mock) +{ + return mock->request_chain->length - mock->next_request_index; +} + +/* Set flb_aws_client_mock_instance used in mock generator */ +void flb_aws_client_mock_set_generator_instance(struct flb_aws_client_mock *mock) +{ + flb_aws_client_mock_instance = mock; +} + +/* Set flb_aws_client_mock_instance used in mock generator */ +struct flb_aws_client_mock *flb_aws_client_mock_get_generator_instance( + struct flb_aws_client_mock *mock) +{ + return flb_aws_client_mock_instance = mock; +} + +/* Get generator used in mock */ +struct flb_aws_client_generator *flb_aws_client_get_mock_generator() +{ + return &mock_generator; +} + +/* Get the number of unused requests */ +int flb_aws_client_mock_generator_count_unused_requests() +{ + TEST_ASSERT(flb_aws_client_mock_instance != 0); + return flb_aws_client_mock_count_unused_requests(flb_aws_client_mock_instance); +} + +/* Return the mock instance */ +struct flb_aws_client *flb_aws_client_create_mock() +{ + TEST_CHECK(flb_aws_client_mock_instance != NULL); + TEST_MSG( + "[aws_mock_client] Must initialize flb_aws_client_mock_instance before calling " + "flb_aws_client_create_mock()"); + TEST_MSG( + "[aws_mock_client] This ouccurs when the generator is called, before tests are " + "initialized."); + + return flb_aws_client_mock_context(flb_aws_client_mock_instance); +} + +/* Mock request used by flb_aws_client mock */ +static struct flb_http_client *flb_aws_client_mock_vtable_request( + struct flb_aws_client *aws_client, int method, const char *uri, const char *body, + size_t body_len, struct flb_aws_header *dynamic_headers, size_t dynamic_headers_len) +{ + int h; + int i; + int ret; + + /* Get access to mock */ + struct flb_aws_client_mock *mock = (struct flb_aws_client_mock *)aws_client; + + /* Check that a response is left in the chain */ + ret = TEST_CHECK(mock->next_request_index < mock->request_chain->length); + if (!ret) { + TEST_MSG( + "[flb_aws_client_mock] %d mock responses provided. Attempting to call %d " + "times. Aborting.", + (int)mock->request_chain->length, (int)mock->next_request_index + 1); + return NULL; + } + struct flb_aws_client_mock_response *response = + &(mock->request_chain->responses[mock->next_request_index]); + struct flb_http_client *c = NULL; + + /* create an http client so that we can set the response */ + c = flb_calloc(1, sizeof(struct flb_http_client)); + if (!c) { + flb_errno(); + return NULL; + } + mk_list_init(&c->headers); + + /* Response configuration */ + for (i = 0; i < response->length; ++i) { + struct flb_aws_client_mock_response_config *response_config = + &(response->config_parameters[i]); + void *val1 = response_config->config_value; + void *val2 = response_config->config_value_2; + + /* Expectations */ + if (response_config->config_parameter == FLB_AWS_CLIENT_MOCK_EXPECT_HEADER) { + int header_found = FLB_FALSE; + /* Search for header in request */ + for (h = 0; h < dynamic_headers_len; ++h) { + ret = strncmp(dynamic_headers[h].key, (char *)val1, + dynamic_headers[h].key_len); + if (ret == 0) { + /* Check header value */ + ret = strncmp(dynamic_headers[h].val, (char *)val2, + dynamic_headers[h].val_len + 1); + TEST_CHECK(ret == 0); + TEST_MSG("[aws_mock_client] Expected Header: (%s: %s)", (char *)val1, + (char *)val2); + TEST_MSG("[aws_mock_client] Received Header: (%s: %s)", (char *)val1, + dynamic_headers[h].val); + + header_found = FLB_TRUE; + } + } + TEST_CHECK(header_found); + TEST_MSG("[aws_mock_client] Expected Header: (%s: %s)", (char *)val1, + (char *)val2); + TEST_MSG("[aws_mock_client] Header not received"); + } + else if (response_config->config_parameter == FLB_AWS_CLIENT_MOCK_EXPECT_METHOD) { + char *flb_http_methods[] = { + "FLB_HTTP_GET", "FLB_HTTP_POST", "FLB_HTTP_PUT", + "FLB_HTTP_HEAD", "FLB_HTTP_CONNECT", "FLB_HTTP_PATCH", + }; + + /* + * Check method is what is expected + * Typecast config value from void * -> int + */ + TEST_CHECK(method == (int)(uintptr_t)val1); + TEST_MSG("[aws_mock_client] Expected HTTP Method: %s", + flb_http_methods[(int)(uintptr_t)val1]); + TEST_MSG("[aws_mock_client] Received HTTP Method: %s", + flb_http_methods[method]); + } + else if (response_config->config_parameter == + FLB_AWS_CLIENT_MOCK_EXPECT_HEADER_COUNT) { + TEST_CHECK(dynamic_headers_len == (int)(uintptr_t)val1); + TEST_MSG("[aws_mock_client] Expected %d Headers", (int)(uintptr_t)val1); + TEST_MSG("[aws_mock_client] Received %d Headers", + (int)(uintptr_t)dynamic_headers_len); + } + else if (response_config->config_parameter == FLB_AWS_CLIENT_MOCK_EXPECT_URI) { + ret = strncmp(uri, (char *)val1, strlen((char *)val1) + 1); + TEST_CHECK(ret == 0); + TEST_MSG("[aws_mock_client] Expected URI: %s", (char *)val1); + TEST_MSG("[aws_mock_client] Received URI: %s", uri); + } + + /* Replace response client */ + else if (response_config->config_parameter == + FLB_AWS_CLIENT_MOCK_CONFIG_REPLACE) { + flb_http_client_destroy(c); + c = (struct flb_http_client *)val1; + } + + /* + * Response setters + * Set client fields using XMacro definitions + */ +#define EXPAND_CLIENT_RESPONSE_PARAMETER(lower, UPPER, type) \ + else if (response_config->config_parameter == FLB_AWS_CLIENT_MOCK_SET_##UPPER) \ + { \ + c->resp.lower = CONVERT_##type((char *)val1); \ + } +#include "aws_client_mock_client_resp.def" +#undef EXPAND_CLIENT_RESPONSE_PARAMETER + } + + /* Increment request */ + ++mock->next_request_index; + + return c; +}; |