Skip to content

Commit 51d580b

Browse files
authored
Add more unit tests for coverage (#175)
* Add unit test to cover httpParserOnStatusCompleteCallback, HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG and HTTP_REQUEST_NO_USER_AGENT_FLAG * Enforce 100 percent coverage in CI
1 parent dd62128 commit 51d580b

File tree

3 files changed

+191
-14
lines changed

3 files changed

+191
-14
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ jobs:
4141
uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main
4242
with:
4343
coverage-file: ./build/coverage.info
44+
branch-coverage-min: 100
45+
line-coverage-min: 100
4446

4547
complexity:
4648
runs-on: ubuntu-latest

test/unit-test/core_http_send_utest.c

Lines changed: 139 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575

7676
/* HTTP OK Status-Line. */
7777
#define HTTP_STATUS_LINE_OK "HTTP/1.1 200 OK\r\n"
78+
#define HTTP_STATUS_LINE_NO_REASON_PHRASE "HTTP/1.1 200\r\n"
7879
#define HTTP_STATUS_CODE_OK 200
7980

8081
/* Various header lines for test response templates. */
@@ -103,11 +104,26 @@
103104
HTTP_TEST_VARY_HEADER_LINE \
104105
HTTP_TEST_P3P_HEADER_LINE \
105106
HTTP_TEST_XSERVER_HEADER_LINE HTTP_HEADER_LINE_SEPARATOR
106-
#define HTTP_TEST_RESPONSE_HEAD_LENGTH ( sizeof( HTTP_TEST_RESPONSE_HEAD ) - 1U )
107-
#define HTTP_TEST_RESPONSE_HEAD_HEADER_COUNT 7
108-
#define HTTP_TEST_RESPONSE_HEAD_CONTENT_LENGTH 43
109-
#define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_FIELD_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_FIELD ) - 2U )
110-
#define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_VALUE_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_VALUE ) - 2U )
107+
#define HTTP_TEST_RESPONSE_HEAD_LENGTH ( sizeof( HTTP_TEST_RESPONSE_HEAD ) - 1U )
108+
#define HTTP_TEST_RESPONSE_HEAD_HEADER_COUNT 7
109+
#define HTTP_TEST_RESPONSE_HEAD_CONTENT_LENGTH 43
110+
#define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_FIELD_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_FIELD ) - 2U )
111+
#define HTTP_TEST_RESPONSE_HEAD_PARTIAL_HEADER_VALUE_LENGTH ( sizeof( HTTP_STATUS_LINE_OK ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_VALUE ) - 2U )
112+
113+
#define HTTP_TEST_RESPONSE_HEAD_2 \
114+
HTTP_STATUS_LINE_NO_REASON_PHRASE \
115+
HTTP_TEST_CONTENT_LENGTH_HEADER_LINE \
116+
HTTP_TEST_CONNECTION_CLOSE_HEADER_LINE \
117+
HTTP_TEST_DATE_HEADER_LINE \
118+
HTTP_TEST_ETAG_HEADER_LINE \
119+
HTTP_TEST_VARY_HEADER_LINE \
120+
HTTP_TEST_P3P_HEADER_LINE \
121+
HTTP_TEST_XSERVER_HEADER_LINE HTTP_HEADER_LINE_SEPARATOR
122+
#define HTTP_TEST_RESPONSE_HEAD_2_LENGTH ( sizeof( HTTP_TEST_RESPONSE_HEAD_2 ) - 1U )
123+
#define HTTP_TEST_RESPONSE_HEAD_2_HEADER_COUNT 7
124+
#define HTTP_TEST_RESPONSE_HEAD_2_CONTENT_LENGTH 43
125+
#define HTTP_TEST_RESPONSE_HEAD_2_PARTIAL_HEADER_FIELD_LENGTH ( sizeof( HTTP_STATUS_LINE_NO_REASON_PHRASE ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_FIELD ) - 2U )
126+
#define HTTP_TEST_RESPONSE_HEAD_2_PARTIAL_HEADER_VALUE_LENGTH ( sizeof( HTTP_STATUS_LINE_NO_REASON_PHRASE ) + sizeof( HTTP_TEST_CONTENT_LENGTH_PARTIAL_HEADER_VALUE ) - 2U )
111127

112128
/* Template HTTP PUT response. This has no body. */
113129
#define HTTP_TEST_RESPONSE_PUT \
@@ -235,6 +251,9 @@ static HTTPRequestHeaders_t requestHeaders = { 0 };
235251
/* Header parsing callback shared among the tests. */
236252
static HTTPClient_ResponseHeaderParsingCallback_t headerParsingCallback = { 0 };
237253

254+
/* Flag to indicate this callback is called. */
255+
static int statusCompleteCallbackFlag = 0;
256+
238257
/* A mocked timer query function that increments on every call. */
239258
static uint32_t getTestTime( void )
240259
{
@@ -432,6 +451,7 @@ static void helper_parse_status_line( const char ** pNext,
432451
const llhttp_settings_t * pSettings )
433452
{
434453
const char * pReasonPhraseStart = NULL;
454+
const char * pNextLineStart = NULL;
435455
size_t reasonPhraseStartLen = 0;
436456

437457
/* For purposes of unit testing the response is well formed in the non-error
@@ -440,17 +460,36 @@ static void helper_parse_status_line( const char ** pNext,
440460
* always string literals. strchr() should not be used in application code. */
441461
*pNext = strchr( *pNext, SPACE_CHARACTER ); /* Get the space before the status-code. */
442462
*pNext += SPACE_CHARACTER_LEN;
443-
*pNext = strchr( *pNext, SPACE_CHARACTER ); /* Get the space before the reason-phrase. */
444-
*pNext += SPACE_CHARACTER_LEN;
445-
pReasonPhraseStart = *pNext;
446-
*pNext = strstr( *pNext, HTTP_HEADER_LINE_SEPARATOR );
447-
reasonPhraseStartLen = ( size_t ) ( *pNext - pReasonPhraseStart );
463+
/* pNext points to the status code now. */
464+
465+
pReasonPhraseStart = strchr( *pNext, SPACE_CHARACTER );
466+
pReasonPhraseStart = &( pReasonPhraseStart[ SPACE_CHARACTER_LEN ] );
467+
468+
pNextLineStart = strstr( *pNext, HTTP_HEADER_LINE_SEPARATOR );
469+
pNextLineStart = &( pNextLineStart[ HTTP_HEADER_LINE_SEPARATOR_LEN ] );
470+
448471
pParser->status_code = 200;
449-
pSettings->on_status( pParser,
450-
pReasonPhraseStart,
451-
reasonPhraseStartLen );
452472

453-
*pNext += HTTP_HEADER_LINE_SEPARATOR_LEN;
473+
/* Check if the reason phrase exist in the header and call the corresponding callback.
474+
* Reason phrase "OK" exists in the response "HTTP/1.1 200 OK\r\n". The callback
475+
* on_status is called.
476+
* Reason phrase doesn't exist in the response "HTTP/1.1 200\r\n". The callback
477+
* on_status_complete is called. */
478+
if( pNextLineStart > pReasonPhraseStart )
479+
{
480+
reasonPhraseStartLen = ( size_t ) ( pNextLineStart - pReasonPhraseStart );
481+
reasonPhraseStartLen = reasonPhraseStartLen - HTTP_HEADER_LINE_SEPARATOR_LEN;
482+
pSettings->on_status( pParser,
483+
pReasonPhraseStart,
484+
reasonPhraseStartLen );
485+
*pNext = pNextLineStart;
486+
}
487+
else
488+
{
489+
statusCompleteCallbackFlag = 1;
490+
pSettings->on_status_complete( pParser );
491+
*pNext = pNextLineStart;
492+
}
454493
}
455494

456495
/* Mock helper that parses all of the headers starting from pNext. */
@@ -805,6 +844,7 @@ void setUp( void )
805844
response.pBuffer = httpBuffer;
806845
response.bufferLen = sizeof( httpBuffer );
807846
response.pHeaderParsingCallback = &headerParsingCallback;
847+
statusCompleteCallbackFlag = 0;
808848

809849
/* Ignore third-party init functions that return void. */
810850
llhttp_init_Ignore();
@@ -846,6 +886,72 @@ void test_HTTPClient_Send_HEAD_request_parse_whole_response( void )
846886

847887
/*-----------------------------------------------------------*/
848888

889+
/* Test successfully parsing a response to a HEAD request. The full response
890+
* message is present in the response buffer on the first network read. */
891+
void test_HTTPClient_Send_HEAD_request_no_parse_body( void )
892+
{
893+
HTTPStatus_t returnStatus = HTTPSuccess;
894+
895+
llhttp_execute_Stub( llhttp_execute_whole_response );
896+
897+
response.respOptionFlags |= HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG;
898+
899+
returnStatus = HTTPClient_Send( &transportInterface,
900+
&requestHeaders,
901+
NULL,
902+
0,
903+
&response,
904+
0 );
905+
TEST_ASSERT_EQUAL( HTTPSuccess, returnStatus );
906+
TEST_ASSERT_EQUAL( NULL, response.pBody );
907+
TEST_ASSERT_EQUAL( 0U, response.bodyLen );
908+
TEST_ASSERT_EQUAL( response.pBuffer + ( sizeof( HTTP_STATUS_LINE_OK ) - 1U ), response.pHeaders );
909+
TEST_ASSERT_EQUAL( HTTP_TEST_RESPONSE_HEAD_LENGTH - ( sizeof( HTTP_STATUS_LINE_OK ) - 1U ) - HTTP_HEADER_END_INDICATOR_LEN,
910+
response.headersLen );
911+
TEST_ASSERT_EQUAL( HTTP_STATUS_CODE_OK, response.statusCode );
912+
TEST_ASSERT_EQUAL( HTTP_TEST_RESPONSE_HEAD_CONTENT_LENGTH, response.contentLength );
913+
TEST_ASSERT_EQUAL( HTTP_TEST_RESPONSE_HEAD_HEADER_COUNT, response.headerCount );
914+
TEST_ASSERT_BITS_HIGH( HTTP_RESPONSE_CONNECTION_CLOSE_FLAG, response.respFlags );
915+
TEST_ASSERT_BITS_LOW( HTTP_RESPONSE_CONNECTION_KEEP_ALIVE_FLAG, response.respFlags );
916+
}
917+
918+
/*-----------------------------------------------------------*/
919+
920+
/* Test successfully parsing a response to a HEAD request. The full response
921+
* message is present in the response buffer on the first network read. The response
922+
* contains a status code but without a reason string. The on_status_complete is called
923+
* in this case. */
924+
void test_HTTPClient_Send_HEAD_request_parse_whole_response_no_reason_string( void )
925+
{
926+
HTTPStatus_t returnStatus = HTTPSuccess;
927+
928+
pNetworkData = ( uint8_t * ) HTTP_TEST_RESPONSE_HEAD_2;
929+
networkDataLen = HTTP_TEST_RESPONSE_HEAD_2_LENGTH;
930+
931+
llhttp_execute_Stub( llhttp_execute_whole_response );
932+
933+
returnStatus = HTTPClient_Send( &transportInterface,
934+
&requestHeaders,
935+
NULL,
936+
0,
937+
&response,
938+
0 );
939+
TEST_ASSERT_EQUAL( HTTPSuccess, returnStatus );
940+
TEST_ASSERT_EQUAL( NULL, response.pBody );
941+
TEST_ASSERT_EQUAL( 0U, response.bodyLen );
942+
TEST_ASSERT_EQUAL( response.pBuffer + ( sizeof( HTTP_STATUS_LINE_NO_REASON_PHRASE ) - 1U ), response.pHeaders );
943+
TEST_ASSERT_EQUAL( HTTP_TEST_RESPONSE_HEAD_2_LENGTH - ( sizeof( HTTP_STATUS_LINE_NO_REASON_PHRASE ) - 1U ) - HTTP_HEADER_END_INDICATOR_LEN,
944+
response.headersLen );
945+
TEST_ASSERT_EQUAL( HTTP_STATUS_CODE_OK, response.statusCode );
946+
TEST_ASSERT_EQUAL( HTTP_TEST_RESPONSE_HEAD_2_CONTENT_LENGTH, response.contentLength );
947+
TEST_ASSERT_EQUAL( HTTP_TEST_RESPONSE_HEAD_2_HEADER_COUNT, response.headerCount );
948+
TEST_ASSERT_BITS_HIGH( HTTP_RESPONSE_CONNECTION_CLOSE_FLAG, response.respFlags );
949+
TEST_ASSERT_BITS_LOW( HTTP_RESPONSE_CONNECTION_KEEP_ALIVE_FLAG, response.respFlags );
950+
TEST_ASSERT_EQUAL( 1, statusCompleteCallbackFlag );
951+
}
952+
953+
/*-----------------------------------------------------------*/
954+
849955
/* Test successfully parsing a response to a PUT request. The full response
850956
* message is present in the response buffer on the first network read. */
851957
void test_HTTPClient_Send_PUT_request_parse_whole_response( void )
@@ -1757,6 +1863,25 @@ void test_HTTPClient_Send_parsing_errors( void )
17571863
0 );
17581864
TEST_ASSERT_EQUAL( HTTPSecurityAlertInvalidContentLength, returnStatus );
17591865

1866+
httpParsingErrno = HPE_PAUSED;
1867+
returnStatus = HTTPClient_Send( &transportInterface,
1868+
&requestHeaders,
1869+
NULL,
1870+
0,
1871+
&response,
1872+
0 );
1873+
TEST_ASSERT_EQUAL( HTTPParserPaused, returnStatus );
1874+
1875+
httpParsingErrno = HPE_PAUSED;
1876+
response.respOptionFlags |= HTTP_RESPONSE_DO_NOT_PARSE_BODY_FLAG;
1877+
returnStatus = HTTPClient_Send( &transportInterface,
1878+
&requestHeaders,
1879+
NULL,
1880+
0,
1881+
&response,
1882+
0 );
1883+
TEST_ASSERT_EQUAL( HTTPNoResponse, returnStatus );
1884+
17601885
/* Use -1 to indicate an unknown error. */
17611886
httpParsingErrno = -1;
17621887
returnStatus = HTTPClient_Send( &transportInterface,

test/unit-test/core_http_utest.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ typedef struct _headers
7272
"%s: %s\r\n" \
7373
"%s: %s\r\n\r\n"
7474

75+
#define HTTP_TEST_HEADER_NO_USER_AGENT_FORMAT \
76+
"%s %s %s\r\n" \
77+
"%s: %s\r\n\r\n"
78+
7579
#define HTTP_TEST_EXTRA_HEADER_FORMAT \
7680
"%s %s %s\r\n" \
7781
"%s: %s\r\n" \
@@ -94,6 +98,19 @@ typedef struct _headers
9498
HTTP_TEST_HOST_VALUE_LEN + HTTP_HEADER_LINE_SEPARATOR_LEN + \
9599
HTTP_HEADER_LINE_SEPARATOR_LEN )
96100

101+
/* Length of the following template HTTP header.
102+
* <HTTP_METHOD_GET> <HTTP_TEST_REQUEST_PATH> <HTTP_PROTOCOL_VERSION> \r\n
103+
* <HTTP_HOST_FIELD>: <HTTP_TEST_HOST_VALUE> \r\n
104+
* \r\n
105+
* This is used to initialize the expectedHeader string. */
106+
#define HTTP_TEST_PREFIX_HEADER_NO_USER_AGENT_LEN \
107+
( HTTP_METHOD_GET_LEN + SPACE_CHARACTER_LEN + \
108+
HTTP_TEST_REQUEST_PATH_LEN + SPACE_CHARACTER_LEN + \
109+
HTTP_PROTOCOL_VERSION_LEN + HTTP_HEADER_LINE_SEPARATOR_LEN + \
110+
HTTP_HOST_FIELD_LEN + HTTP_HEADER_FIELD_SEPARATOR_LEN + \
111+
HTTP_TEST_HOST_VALUE_LEN + HTTP_HEADER_LINE_SEPARATOR_LEN + \
112+
HTTP_HEADER_LINE_SEPARATOR_LEN )
113+
97114
/* Add 1 because snprintf(...) writes a null byte at the end. */
98115
#define HTTP_TEST_INITIALIZED_HEADER_BUFFER_LEN \
99116
( HTTP_TEST_PREFIX_HEADER_LEN + 1 )
@@ -472,6 +489,39 @@ void test_Http_InitializeRequestHeaders_Happy_Path()
472489
expectedHeaders.dataLen );
473490
}
474491

492+
/**
493+
* @brief Test happy path with HTTP_REQUEST_NO_USER_AGENT_FLAG.
494+
*/
495+
void test_Http_InitializeRequestHeaders_no_user_agent_flag()
496+
{
497+
HTTPStatus_t httpStatus = HTTPSuccess;
498+
HTTPRequestHeaders_t requestHeaders = { 0 };
499+
HTTPRequestInfo_t requestInfo = { 0 };
500+
int numBytes = 0;
501+
502+
setupRequestInfo( &requestInfo );
503+
requestInfo.reqFlags |= HTTP_REQUEST_NO_USER_AGENT_FLAG;
504+
505+
expectedHeaders.dataLen = HTTP_TEST_PREFIX_HEADER_NO_USER_AGENT_LEN;
506+
setupBuffer( &requestHeaders );
507+
508+
/* Happy Path testing. */
509+
numBytes = snprintf( ( char * ) expectedHeaders.buffer, sizeof( expectedHeaders.buffer ),
510+
HTTP_TEST_HEADER_NO_USER_AGENT_FORMAT,
511+
HTTP_METHOD_GET, HTTP_TEST_REQUEST_PATH,
512+
HTTP_PROTOCOL_VERSION,
513+
HTTP_HOST_FIELD, HTTP_TEST_HOST_VALUE );
514+
/* Make sure that the entire pre-existing data was printed to the buffer. */
515+
TEST_ASSERT_GREATER_THAN( 0, numBytes );
516+
TEST_ASSERT_LESS_THAN( sizeof( expectedHeaders.buffer ), ( size_t ) numBytes );
517+
518+
httpStatus = HTTPClient_InitializeRequestHeaders( &requestHeaders, &requestInfo );
519+
TEST_ASSERT_EQUAL( HTTPSuccess, httpStatus );
520+
TEST_ASSERT_EQUAL( expectedHeaders.dataLen, requestHeaders.headersLen );
521+
TEST_ASSERT_EQUAL_MEMORY( expectedHeaders.buffer, requestHeaders.pBuffer,
522+
expectedHeaders.dataLen );
523+
}
524+
475525
/**
476526
* @brief Test NULL parameters, following order of else-if blocks in the HTTP library.
477527
*/

0 commit comments

Comments
 (0)