YAIP/tests/response.test.c
Jonathan Hodgson 6eaad263be Moves some logic out of proxy and into main
Also fixes some segfaults caused by trying to free memory that wasn't
allocated with strdup or malloc etc.

Fixes some tests
2022-01-19 12:56:11 +00:00

310 lines
8.5 KiB
C

#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 */