You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
8.5 KiB
310 lines
8.5 KiB
#ifndef RESPONSE_TEST |
|
#define RESPONSE_TEST value |
|
|
|
#include <unistd.h> |
|
#include <stdio.h> |
|
#include <sys/socket.h> |
|
#include <stdlib.h> |
|
#include <netinet/in.h> |
|
#include <arpa/inet.h> |
|
#include <netdb.h> |
|
#include <string.h> |
|
#include <stdbool.h> |
|
|
|
#include "munit/munit.h" |
|
#include "../src/readline.h" |
|
#include "../src/requestresponse.h" |
|
#include "../src/response.h" |
|
|
|
typedef struct { |
|
char *fullLine; |
|
float version; |
|
int statusCode; |
|
char *statusMessage; |
|
} firstLine; |
|
|
|
static firstLine line1Examples[] = { |
|
//Full Line, version status Code Status Message |
|
{ "HTTP/1.1 200 OK", 1.1, 200, "OK" }, |
|
{ "HTTP/2.0 404 Not Found", 2.0, 404, "Not Found" }, |
|
{ NULL, 0, 0, NULL } |
|
}; |
|
|
|
|
|
MunitResult testResponseNewStatus(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = newResponse(); |
|
responseBarebones(rsp); |
|
munit_assert_int( rsp->statusCode, ==, 200 ); |
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseNewStatusMessage(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = newResponse(); |
|
responseBarebones(rsp); |
|
munit_assert_string_equal( rsp->statusMessage, "OK" ); |
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseNewVersion(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = newResponse(); |
|
responseBarebones(rsp); |
|
munit_assert_float( rsp->version, ==, 1.1 ); |
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseSetBody(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = newResponse(); |
|
responseBarebones(rsp); |
|
responseSetBody( rsp, "Testing", 1 ); |
|
munit_assert_string_equal( rsp->body, "Testing" ); |
|
munit_assert_string_equal( getHeader( rsp->headers, "content-length" )->value, "7" ); |
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseToString(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = newResponse(); |
|
responseBarebones(rsp); |
|
munit_assert_string_equal( responseToString( rsp ), "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nContent-Type: text/plain\r\n\r\n" ); |
|
responseSetBody( rsp, "Testing", 1 ); |
|
munit_assert_string_equal( responseToString( rsp ), "HTTP/1.1 200 OK\r\nContent-Length: 7\r\nContent-Type: text/plain\r\n\r\nTesting\r\n" ); |
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseFirstLineStatusCode(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp; |
|
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){ |
|
rsp = newResponse(); |
|
responseFirstLine( rsp, line->fullLine ); |
|
munit_assert_int( rsp->statusCode, ==, line->statusCode ); |
|
free( rsp ); |
|
} |
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseFirstLineStatusMessage(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp; |
|
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){ |
|
rsp = newResponse(); |
|
responseFirstLine( rsp, line->fullLine ); |
|
munit_assert_string_equal( rsp->statusMessage, line->statusMessage ); |
|
free( rsp ); |
|
} |
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseFirstLineVersion(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp; |
|
for ( firstLine *line = line1Examples; line->fullLine != NULL; line++ ){ |
|
rsp = newResponse(); |
|
responseFirstLine( rsp, line->fullLine ); |
|
munit_assert_float( rsp->version, ==, line->version ); |
|
free( rsp ); |
|
} |
|
return MUNIT_OK; |
|
} |
|
|
|
static void* setupSocketTests(const MunitParameter params[], void* user_data) { |
|
int client_fd = 0; |
|
struct sockaddr_in address; |
|
memset( &address, 0, sizeof(address) ); |
|
struct hostent *host = gethostbyname("example.com"); |
|
Response *rsp = NULL; |
|
|
|
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0){ |
|
perror("socket failed"); |
|
return NULL; |
|
} |
|
|
|
|
|
address.sin_family = AF_INET; |
|
address.sin_port = htons( 80 ); |
|
// We want the request to go out to whatever the host was resolved to |
|
memcpy( &address.sin_addr, host->h_addr_list[0], host->h_length ); |
|
|
|
if((connect(client_fd, (struct sockaddr *)&address, sizeof(address)))<0) { |
|
perror("connect failed"); |
|
return NULL; |
|
} |
|
|
|
char *toSend = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"; |
|
|
|
if ( write( client_fd, toSend, strlen(toSend) ) != strlen(toSend) ){ |
|
perror( "Write Error" ); |
|
return NULL; |
|
} |
|
|
|
rsp = newResponseFromSocket( client_fd ); |
|
return rsp; |
|
} |
|
|
|
MunitResult testResponseFromSocketHeaderLength(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = ( Response * )user_data_or_fixture; |
|
if ( rsp == NULL ) return MUNIT_ERROR; |
|
|
|
//Check there are the right nubmer of haeders |
|
// Unfortunately it changes from request to request so this is a "loose" |
|
// check |
|
munit_assert_int( countHeaders( rsp->headers ), >, 7 ); |
|
|
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseFromSocketStatusCode(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = ( Response * )user_data_or_fixture; |
|
if ( rsp == NULL ) return MUNIT_ERROR; |
|
|
|
//Check there are the right nubmer of haeders |
|
munit_assert_int( rsp->statusCode, ==, 200 ); |
|
|
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testResponseFromSocketBody(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
Response *rsp = ( Response * )user_data_or_fixture; |
|
Header *contentLength = getHeader( rsp->headers, "content-length" ); |
|
unsigned int length = 0; |
|
|
|
if ( contentLength == NULL ) return MUNIT_ERROR; |
|
|
|
munit_assert_int( atoi( contentLength->value ), ==, strlen( (char *)rsp->body ) ); |
|
|
|
//Check there are the right nubmer of haeders |
|
munit_assert_int( rsp->statusCode, ==, 200 ); |
|
|
|
return MUNIT_OK; |
|
} |
|
|
|
MunitResult testConectionEstablished(const MunitParameter params[], |
|
void* user_data_or_fixture){ |
|
|
|
Response *rsp = newResponse(); |
|
connectionEstablished(rsp); |
|
|
|
munit_assert_string_equal( |
|
responseToString( rsp ), |
|
"HTTP/1.1 200 Connection Established\r\n\r\n" |
|
); |
|
|
|
return MUNIT_OK; |
|
} |
|
|
|
static MunitTest response_tests[] = { |
|
{ |
|
"/new/status", /* name */ |
|
testResponseNewStatus, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/new/statusMessage", /* name */ |
|
testResponseNewStatusMessage, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/new/version", /* name */ |
|
testResponseNewVersion, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/set/body", /* name */ |
|
testResponseSetBody, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/to/string", /* name */ |
|
testResponseToString, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/to/string/connectionEstablished", /* name */ |
|
testConectionEstablished, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/line1/statusCode", /* name */ |
|
testResponseFirstLineStatusCode, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/line1/statusMessage", /* name */ |
|
testResponseFirstLineStatusMessage, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/line1/version", /* name */ |
|
testResponseFirstLineVersion, /* test */ |
|
NULL, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/fromSocket/headerLength", /* name */ |
|
testResponseFromSocketHeaderLength, /* test */ |
|
setupSocketTests, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/fromSocket/statusCode", /* name */ |
|
testResponseFromSocketStatusCode, /* test */ |
|
setupSocketTests, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, { |
|
"/fromSocket/body", /* name */ |
|
testResponseFromSocketBody, /* test */ |
|
setupSocketTests, /* setup */ |
|
NULL, /* tear_down */ |
|
MUNIT_TEST_OPTION_NONE, /* options */ |
|
NULL /* parameters */ |
|
}, |
|
/* Mark the end of the array with an entry where the test |
|
* function is NULL */ |
|
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } |
|
}; |
|
|
|
MunitSuite response_test_suite = { |
|
"/response", /* name */ |
|
response_tests, /* tests */ |
|
NULL, /* suites */ |
|
1, /* iterations */ |
|
MUNIT_SUITE_OPTION_NONE /* options */ |
|
}; |
|
|
|
#ifndef MAINTEST |
|
#define MAINTEST |
|
|
|
int main (int argc, char* argv[]) { |
|
return munit_suite_main(&response_test_suite, NULL, argc, argv); |
|
} |
|
|
|
#endif /* ifndef MAINTEST */ |
|
|
|
#endif /* ifndef RESPONSE_TEST */
|
|
|