-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
aws: Add imds tests and mock flb_aws_client via flb_aws_client_mock s…
…truct Signed-off-by: Matthew Fala <[email protected]>
- Loading branch information
1 parent
aea8835
commit c7e97e3
Showing
4 changed files
with
1,304 additions
and
307 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
{ | ||
if (flb_aws_client_mock_instance != NULL) { | ||
flb_aws_client_mock_destroy(flb_aws_client_mock_instance); | ||
} | ||
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 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 (int 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 (int 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; | ||
}; |
Oops, something went wrong.